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) }