Skip to content

Commit ecebc05

Browse files
Daffa FawwazDaffa Fawwaz
authored andcommitted
feat: doc-swagger/feedback
1 parent 347b1ec commit ecebc05

39 files changed

+3618
-330
lines changed

api/handlers/auth_handler.go

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package handlers
22

33
import (
4+
"api-shiners/api/handlers/dto"
45
"api-shiners/pkg/auth"
56
"api-shiners/pkg/utils"
67
"context"
@@ -10,7 +11,6 @@ import (
1011
"github.com/gofiber/fiber/v2"
1112
)
1213

13-
// AuthController handles authentication related endpoints
1414
type AuthController struct {
1515
authService auth.AuthService
1616
}
@@ -19,17 +19,16 @@ func NewAuthController(authService auth.AuthService) AuthController {
1919
return AuthController{authService: authService}
2020
}
2121

22-
// ==================== REGISTER ====================
2322

24-
// Register godoc
2523
// @Summary Register a new user
26-
// @Description Create a new user account
24+
// @Description Membuat akun user baru
2725
// @Tags Auth
2826
// @Accept json
2927
// @Produce json
30-
// @Param request body auth.RegisterRequest true "Register Request"
31-
// @Success 201 {object} map[string]interface{}
32-
// @Failure 400 {object} map[string]interface{}
28+
// @Param request body dto.RegisterRequest true "Register Request"
29+
// @Success 201 {object} dto.RegisterResponse
30+
// @Failure 400 {object} utils.ErrorResponse
31+
// @Failure 500 {object} utils.ErrorResponse
3332
// @Router /api/auth/register [post]
3433
func (ctrl *AuthController) Register(c *fiber.Ctx) error {
3534
var req auth.RegisterRequest
@@ -45,49 +44,53 @@ func (ctrl *AuthController) Register(c *fiber.Ctx) error {
4544
return utils.Success(c, http.StatusCreated, "User registered successfully", createdUser, nil)
4645
}
4746

48-
// ==================== LOGIN ====================
4947

50-
// Login godoc
5148
// @Summary Login user
52-
// @Description Authenticate user and return JWT token
49+
// @Description Autentikasi user dan mendapatkan JWT token
5350
// @Tags Auth
5451
// @Accept json
5552
// @Produce json
56-
// @Param request body auth.LoginRequest true "Login Request"
57-
// @Success 200 {object} map[string]interface{}
58-
// @Failure 401 {object} map[string]interface{}
53+
// @Param request body dto.LoginRequest true "Login Request"
54+
// @Success 200 {object} dto.LoginResponse
55+
// @Failure 400 {object} utils.ErrorResponse
56+
// @Failure 401 {object} utils.ErrorResponse
5957
// @Router /api/auth/login [post]
6058
func (ctrl *AuthController) Login(c *fiber.Ctx) error {
6159
var req auth.LoginRequest
6260
if err := c.BodyParser(&req); err != nil {
6361
return utils.Error(c, http.StatusBadRequest, "Invalid request body", "BadRequestException", nil)
6462
}
6563

66-
token, exp, err := ctrl.authService.Login(context.Background(), req)
64+
user, token, exp, permissions, err := ctrl.authService.LoginCore(context.Background(), req)
6765
if err != nil {
6866
return utils.Error(c, http.StatusUnauthorized, err.Error(), "UnauthorizedException", nil)
6967
}
7068

7169
data := fiber.Map{
72-
"token": token,
73-
"expires_in": exp.Format(time.RFC3339),
74-
"token_type": "Bearer",
70+
"token": token,
71+
"expires_in": exp.Format(time.RFC3339),
72+
"token_type": "Bearer",
73+
"user": fiber.Map{
74+
"id": user.ID,
75+
"name": user.Name,
76+
"role": user.Roles,
77+
"permissions": permissions,
78+
},
7579
}
7680

7781
return utils.Success(c, http.StatusOK, "Login successful", data, nil)
7882
}
7983

80-
// ==================== LOGOUT ====================
8184

82-
// Logout godoc
8385
// @Summary Logout user
84-
// @Description Invalidate user token
86+
// @Description Mengakhiri sesi dan menonaktifkan token
8587
// @Tags Auth
8688
// @Accept json
8789
// @Produce json
8890
// @Security BearerAuth
89-
// @Success 200 {object} map[string]interface{}
90-
// @Failure 400 {object} map[string]interface{}
91+
// @Success 200 {object} dto.GenericResponse
92+
// @Failure 400 {object} utils.ErrorResponse
93+
// @Failure 401 {object} utils.ErrorResponse
9194
// @Router /api/auth/logout [post]
9295
func (ctrl *AuthController) Logout(c *fiber.Ctx) error {
9396
token := c.Get("Authorization")
@@ -107,22 +110,19 @@ func (ctrl *AuthController) Logout(c *fiber.Ctx) error {
107110
return utils.Success(c, http.StatusOK, "Logout successful", nil, nil)
108111
}
109112

110-
// ==================== FORGOT PASSWORD ====================
111113

112-
// ForgotPassword godoc
113114
// @Summary Request password reset
114-
// @Description Generate reset token and send it to user's email
115+
// @Description Generate reset token dan kirim ke email user
115116
// @Tags Auth
116117
// @Accept json
117118
// @Produce json
118-
// @Param request body map[string]string true "Email Request"
119-
// @Success 200 {object} map[string]interface{}
120-
// @Failure 400 {object} map[string]interface{}
119+
// @Param request body dto.ForgotPasswordRequest true "Forgot Password Request"
120+
// @Success 200 {object} dto.GenericResponse
121+
// @Failure 400 {object} utils.ErrorResponse
122+
// @Failure 500 {object} utils.ErrorResponse
121123
// @Router /api/auth/forgot-password [post]
122124
func (ctrl *AuthController) ForgotPassword(c *fiber.Ctx) error {
123-
var req struct {
124-
Email string `json:"email"`
125-
}
125+
var req dto.ForgotPasswordRequest
126126
if err := c.BodyParser(&req); err != nil || req.Email == "" {
127127
return utils.Error(c, http.StatusBadRequest, "Email is required", "BadRequestException", nil)
128128
}
@@ -134,27 +134,23 @@ func (ctrl *AuthController) ForgotPassword(c *fiber.Ctx) error {
134134

135135
return utils.Success(c, http.StatusOK, "Password reset token generated", fiber.Map{
136136
"email": req.Email,
137-
"token": token, // tampilkan untuk testing
137+
"token": token, // ditampilkan untuk keperluan testing
138138
}, nil)
139139
}
140140

141-
// ==================== RESET PASSWORD ====================
142141

143-
// ResetPassword godoc
144142
// @Summary Reset user password
145-
// @Description Reset password using valid reset token
143+
// @Description Reset password menggunakan reset token yang valid
146144
// @Tags Auth
147145
// @Accept json
148146
// @Produce json
149-
// @Param request body map[string]string true "Reset Password Request"
150-
// @Success 200 {object} map[string]interface{}
151-
// @Failure 400 {object} map[string]interface{}
147+
// @Param request body dto.ResetPasswordRequest true "Reset Password Request"
148+
// @Success 200 {object} dto.GenericResponse
149+
// @Failure 400 {object} utils.ErrorResponse
150+
// @Failure 500 {object} utils.ErrorResponse
152151
// @Router /api/auth/reset-password [post]
153152
func (ctrl *AuthController) ResetPassword(c *fiber.Ctx) error {
154-
var req struct {
155-
Token string `json:"token"`
156-
NewPassword string `json:"new_password"`
157-
}
153+
var req dto.ResetPasswordRequest
158154
if err := c.BodyParser(&req); err != nil || req.Token == "" || req.NewPassword == "" {
159155
return utils.Error(c, http.StatusBadRequest, "Token and new password required", "BadRequestException", nil)
160156
}

api/handlers/dto/auth_request.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package dto
2+
3+
// RegisterRequest — payload untuk registrasi user
4+
type RegisterRequest struct {
5+
Name string `json:"name" example:"John Doe"`
6+
Email string `json:"email" example:"[email protected]"`
7+
Password string `json:"password" example:"strongpassword123"`
8+
}
9+
10+
// RegisterResponse — response sukses registrasi
11+
type RegisterResponse struct {
12+
ID string `json:"id" example:"a3b2c1d4-56ef-7890-gh12-ijk345lmn678"`
13+
Name string `json:"name" example:"John Doe"`
14+
Email string `json:"email" example:"[email protected]"`
15+
}
16+
17+
// LoginRequest — payload login user
18+
type LoginRequest struct {
19+
Email string `json:"email" example:"[email protected]"`
20+
Password string `json:"password" example:"strongpassword123"`
21+
}
22+
23+
// LoginResponse — response sukses login
24+
type LoginResponse struct {
25+
Token string `json:"token" example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"`
26+
ExpiresIn string `json:"expires_in" example:"2025-10-18T15:04:05Z"`
27+
TokenType string `json:"token_type" example:"Bearer"`
28+
User interface{} `json:"user"`
29+
}
30+
31+
// ForgotPasswordRequest — payload untuk lupa password
32+
type ForgotPasswordRequest struct {
33+
Email string `json:"email" example:"[email protected]"`
34+
}
35+
36+
// ResetPasswordRequest — payload untuk reset password
37+
type ResetPasswordRequest struct {
38+
Token string `json:"token" example:"123456"`
39+
NewPassword string `json:"new_password" example:"newStrongPassword123"`
40+
}
41+
42+
// GenericResponse — response umum (sukses tanpa data)
43+
type GenericResponse struct {
44+
Message string `json:"message" example:"Operation successful"`
45+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package dto
2+
3+
type CreateQuestionRequest struct {
4+
Question string `json:"question" example:"Apa pendapat Anda tentang pelatihan ini?"`
5+
}
6+
7+
type SubmitAnswerRequest struct {
8+
QuestionID string `json:"question_id" example:"b5a1c6c3-1234-4bcd-9123-a12b34cd56ef"`
9+
Answer string `json:"answer" example:"Sangat bermanfaat dan jelas"`
10+
}

api/handlers/dto/user_request.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package dto
2+
3+
// ==================== REQUEST DTO ====================
4+
5+
type SetRoleRequest struct {
6+
Role string `json:"role" example:"ADMIN"`
7+
}
8+
9+
// ==================== RESPONSE DTO ====================
10+
11+
type UserResponse struct {
12+
ID string `json:"id"`
13+
Name string `json:"name"`
14+
Email string `json:"email"`
15+
IsActive bool `json:"is_active"`
16+
Role string `json:"role,omitempty"`
17+
}
18+
19+
type UserRoleResponse struct {
20+
ID string `json:"id"`
21+
Name string `json:"name"`
22+
Email string `json:"email"`
23+
Role string `json:"role"`
24+
}
25+
26+
type UserStatusResponse struct {
27+
ID string `json:"id"`
28+
Name string `json:"name"`
29+
Email string `json:"email"`
30+
IsActive bool `json:"is_active"`
31+
}
32+
33+
type UserProfileResponse struct {
34+
ID string `json:"id"`
35+
Name string `json:"name"`
36+
Email string `json:"email"`
37+
IsActive bool `json:"is_active"`
38+
Roles []string `json:"roles"`
39+
}
40+
41+
// ==================== PAGINATION META ====================
42+
43+
// MetaResponse digunakan untuk metadata pagination di response
44+
type MetaResponse struct {
45+
Page int `json:"page" example:"1"`
46+
PerPage int `json:"per_page" example:"10"`
47+
Total int `json:"total" example:"100"`
48+
}
49+
50+
// ==================== PAGINATED RESPONSE ====================
51+
52+
type PaginatedUsersResponse struct {
53+
Data []UserResponse `json:"data"`
54+
Meta MetaResponse `json:"meta"`
55+
}

0 commit comments

Comments
 (0)