File size: 3,961 Bytes
92bfa2a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12690b4
 
 
 
 
 
 
 
 
 
92bfa2a
4a66f20
 
 
 
92bfa2a
 
 
 
12690b4
 
 
 
 
 
 
 
 
 
92bfa2a
4a66f20
 
 
 
92bfa2a
 
 
 
12690b4
 
 
 
 
 
 
 
 
 
 
 
92bfa2a
4a66f20
 
 
 
92bfa2a
4a66f20
 
 
92bfa2a
 
 
 
12690b4
 
 
 
 
 
 
 
 
 
 
92bfa2a
4a66f20
 
 
 
92bfa2a
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package controllers

import (
	"abdanhafidz.com/go-boilerplate/models/dto"
	entity "abdanhafidz.com/go-boilerplate/models/entity"
	"abdanhafidz.com/go-boilerplate/services"
	"github.com/gin-gonic/gin"
)

type AuthenticationController interface {
	SignUp(ctx *gin.Context)
	SignIn(ctx *gin.Context)
	ChangePassword(ctx *gin.Context)
	UpdateUserRole(ctx *gin.Context)
}

type authenticationController struct {
	userService services.UserService
}

func NewAuthenticationController(userService services.UserService) AuthenticationController {
	return &authenticationController{
		userService: userService,
	}
}

// SignUp godoc
// @Summary      Sign Up
// @Description  Register a new user with name, email, username and password.
// @Tags         Auth
// @Accept       json
// @Produce      json
// @Param        request  body      dto.SignUpRequest  true  "Sign Up Data"
// @Success      200      {object}  entity.User
// @Failure      400      {object}  dto.ErrorResponse
// @Router       /api/v1/authentication/register [post]
func (c *authenticationController) SignUp(ctx *gin.Context) {
	req, err := RequestJSON[dto.SignUpRequest](ctx)
	if err != nil {
		return
	}
	res, err := c.userService.Create(ctx.Request.Context(), req.Name, req.Email, req.Username, req.Password)
	ResponseJSON(ctx, req, res, err)
}

// SignIn godoc
// @Summary      Sign In
// @Description  Authenticate user via email/username and password.
// @Tags         Auth
// @Accept       json
// @Produce      json
// @Param        request  body      dto.SignInRequest  true  "Sign In Data"
// @Success      200      {object}  dto.AuthenticatedUser
// @Failure      401      {object}  dto.ErrorResponse
// @Router       /api/v1/authentication/login [post]
func (c *authenticationController) SignIn(ctx *gin.Context) {
	req, err := RequestJSON[dto.SignInRequest](ctx)
	if err != nil {
		return
	}
	res, err := c.userService.Validate(ctx, req.EmailorUsername, req.Password)
	ResponseJSON(ctx, req, res, err)
}

// ChangePassword godoc
// @Summary      Change Password
// @Description  Update password for the logged-in user.
// @Tags         Auth
// @Accept       json
// @Produce      json
// @Param        request  body      dto.ChangePasswordRequest  true  "Password Change Data"
// @Success      200      {object}  dto.AuthenticatedUser
// @Failure      400      {object}  dto.ErrorResponse
// @Failure      401      {object}  dto.ErrorResponse
// @Security     BearerAuth
// @Router       /api/v1/authentication/change-password [put]
func (c *authenticationController) ChangePassword(ctx *gin.Context) {
	req, err := RequestJSON[dto.ChangePasswordRequest](ctx)
	if err != nil {
		return
	}
	userId := ParseUserId(ctx)
	if userId == "" {
		return
	}
	res, err := c.userService.ChangePassword(ctx.Request.Context(), userId, req.OldPassword, req.NewPassword)
	ResponseJSON(ctx, req, res, err)
}

// UpdateUserRole godoc
// @Summary      Update User Role (Legacy)
// @Description  Update user role. Note: This is an older endpoint, consider using /api/v1/users/me/roles instead.
// @Tags         Users
// @Accept       json
// @Produce      json
// @Param        userId   path      string  true  "User ID"
// @Param        request  body      dto.UpdateUserRoleRequest  true  "Role Update Data"
// @Success      200      {object}  entity.User
// @Failure      400      {object}  dto.ErrorResponse
// @Router       /api/v1/authentication/role/{userId} [put]
func (c *authenticationController) UpdateUserRole(ctx *gin.Context) {
	req, err := RequestJSON[dto.UpdateUserRoleRequest](ctx)
	if err != nil {
		return
	}
	userId := ctx.Param("userId")
	user, err := c.userService.GetById(ctx.Request.Context(), userId)
	if err != nil {
		ResponseJSON(ctx, req, entity.User{}, err)
		return
	}

	// For now, don't implement full Role update logic (requires roles association in schema)
	// Just stub it
	res, err := c.userService.Update(ctx.Request.Context(), user)
	ResponseJSON(ctx, req, res, err)
}