quzuu-api-test / controllers /user_controller.go
lifedebugger's picture
Deploy files from GitHub repository
a57273b
package controllers
import (
"strconv"
"abdanhafidz.com/go-boilerplate/models/dto"
entity "abdanhafidz.com/go-boilerplate/models/entity"
http_error "abdanhafidz.com/go-boilerplate/models/error"
"abdanhafidz.com/go-boilerplate/services"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)
type UserController interface {
ListUsers(ctx *gin.Context)
CreateUser(ctx *gin.Context)
BulkCreateUsers(ctx *gin.Context)
UpdateUser(ctx *gin.Context)
DeleteUser(ctx *gin.Context)
}
type userController struct {
accountService services.AccountService
}
func NewUserController(accountService services.AccountService) UserController {
return &userController{accountService}
}
// ListUsers godoc
// @Summary List All Users with Pagination
// @Description Retrieve a paginated list of all users with optional role filter. Supports pagination parameters (page, limit) and can filter by user role.
// @Tags Super Admin Users Management
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param page query int false "Page number for pagination. Minimum value is 1. Default is 1."
// @Param limit query int false "Number of items per page. Minimum 1, Maximum 50. Default is 10."
// @Param role query string false "Filter users by role. Allowed values: user, admin, super_admin. Leave empty for no filter."
// @Success 200 {object} dto.SuccessResponse[[]dto.UserResponse]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/super-admin/users [get]
func (c *userController) ListUsers(ctx *gin.Context) {
limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10"))
page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
role := ctx.DefaultQuery("role", "")
search := ctx.DefaultQuery("search", "")
if limit < 1 {
limit = 10
} else if limit > 50 {
limit = 50
}
if page < 1 {
page = 1
}
validRoles := map[string]bool{
"user": true,
"admin": true,
"super_admin": true,
}
if role != "" && !validRoles[role] {
ResponseJSON(ctx, gin.H{}, []dto.UserResponse{}, http_error.BAD_REQUEST_ERROR)
return
}
offset := (page - 1) * limit
p := entity.Pagination{
Limit: limit,
Offset: offset,
Role: role,
Search: search,
}
accounts, total, err := c.accountService.GetAllAccountsWithPagination(ctx.Request.Context(), p)
if err != nil {
ResponseJSON(ctx, gin.H{}, []dto.UserResponse{}, err)
return
}
var users []dto.UserResponse
for _, acc := range accounts {
fullName := ""
if acc.AccountDetail != nil && acc.AccountDetail.FullName != nil {
fullName = *acc.AccountDetail.FullName
}
users = append(users, dto.UserResponse{
Id: acc.Id,
Username: acc.Username,
Email: acc.Email,
FullName: fullName,
Role: acc.Role,
IsEmailVerified: acc.IsEmailVerified,
IsDetailCompleted: acc.IsDetailCompleted,
CreatedAt: acc.CreatedAt,
})
}
var totalPages int
if total == 0 {
totalPages = 1
} else {
totalPages = int((total + int64(limit) - 1) / int64(limit))
}
if page > totalPages {
page = totalPages
}
meta := gin.H{
"totalItems": total,
"totalPages": totalPages,
"currentPage": page,
"limit": limit,
}
ResponseJSON(ctx, meta, users, nil)
}
// CreateUser godoc
// @Summary Create Single User
// @Description Create a new user account by providing user details
// @Tags Super Admin Users Management
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body dto.CreateUserRequest true "Create User Request"
// @Success 200 {object} dto.SuccessResponse[dto.UserResponse]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/super-admin/users [post]
func (c *userController) CreateUser(ctx *gin.Context) {
req := RequestJSON[dto.CreateUserRequest](ctx)
account, err := c.accountService.Create(ctx.Request.Context(), req.Name, req.Email, req.Username, req.Password, req.Role)
if err != nil {
ResponseJSON(ctx, req, dto.UserResponse{}, err)
return
}
if req.Role != "" && req.Role != "user" {
account.Role = req.Role
account.IsEmailVerified = true
account, _ = c.accountService.UpdateUserRole(ctx.Request.Context(), account)
err = c.accountService.SetEmailVerified(ctx.Request.Context(), account.Id, true)
if err != nil {
ResponseJSON(ctx, req, dto.UserResponse{}, err)
return
}
}
res := dto.UserResponse{
Id: account.Id,
Username: account.Username,
Email: account.Email,
Role: account.Role,
IsEmailVerified: account.IsEmailVerified,
IsDetailCompleted: account.IsDetailCompleted,
CreatedAt: account.CreatedAt,
}
ResponseJSON(ctx, req, res, nil)
}
// BulkCreateUsers godoc
// @Summary Bulk Create Users
// @Description Create multiple user accounts at once
// @Tags Super Admin Users Management
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param requests body []dto.CreateUserRequest true "Bulk Create User Requests"
// @Success 200 {object} dto.SuccessResponse[dto.CreateUserRequest]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Router /api/v1/super-admin/users/bulk [post]
func (c *userController) BulkCreateUsers(ctx *gin.Context) {
var requests []dto.CreateUserRequest
if err := ctx.ShouldBindJSON(&requests); err != nil {
ResponseJSON(ctx, requests, dto.CreateUserRequest{}, http_error.BAD_REQUEST_ERROR)
ctx.Abort()
return
}
response, err := c.accountService.BulkCreateAccounts(ctx.Request.Context(), requests)
ResponseJSON(ctx, gin.H{"count": len(requests)}, response, err)
}
// GetUserById godoc
// @Summary Edit User
// @Description Update user information by ID
// @Tags Super Admin Users Management
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path string true "User ID"
// @Param request body dto.UpdateUserRequest true "Update User Request"
// @Success 200 {object} dto.SuccessResponse[dto.UserResponse]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Failure 404 {object} dto.ErrorResponse
// @Router /api/v1/super-admin/users/{id} [put]
func (c *userController) UpdateUser(ctx *gin.Context) {
idParam := ctx.Param("id")
userId, err := uuid.Parse(idParam)
if err != nil {
ResponseJSON(ctx, gin.H{"id": idParam}, dto.UserResponse{}, http_error.INVALID_TOKEN)
return
}
req := RequestJSON[dto.UpdateUserRequest](ctx)
account, err := c.accountService.GetById(ctx.Request.Context(), userId)
if err != nil {
ResponseJSON(ctx, gin.H{"id": userId}, dto.UserResponse{}, err)
return
}
if account.Role == "super_admin" || account.Role == "admin" {
account.IsEmailVerified = true
err = c.accountService.SetEmailVerified(ctx.Request.Context(), account.Id, true)
if err != nil {
ResponseJSON(ctx, req, dto.UserResponse{}, err)
return
}
}
// Update fields if provided
if req.Email != "" {
account.Email = req.Email
}
if req.Username != "" {
account.Username = req.Username
}
if req.Role != "" {
account.Role = req.Role
}
if req.Password != "" {
account.Password = req.Password
}
if req.Password != "" {
account, err = c.accountService.Update(ctx.Request.Context(), account)
} else {
account, err = c.accountService.UpdateUserRole(ctx.Request.Context(), account)
}
if err != nil {
ResponseJSON(ctx, req, dto.UserResponse{}, err)
return
}
res := dto.UserResponse{
Id: account.Id,
Username: account.Username,
Email: account.Email,
Role: account.Role,
IsEmailVerified: account.IsEmailVerified,
IsDetailCompleted: account.IsDetailCompleted,
CreatedAt: account.CreatedAt,
}
ResponseJSON(ctx, req, res, nil)
}
// DeleteUser godoc
// @Summary Delete User
// @Description Delete a user account by ID
// @Tags Super Admin Users Management
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path string true "User ID"
// @Success 200 {object} dto.SuccessResponse[any]
// @Failure 400 {object} dto.ErrorResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Failure 404 {object} dto.ErrorResponse
// @Router /api/v1/super-admin/users/{id} [delete]
func (c *userController) DeleteUser(ctx *gin.Context) {
idParam := ctx.Param("id")
userId, err := uuid.Parse(idParam)
if err != nil {
ResponseJSON[any](ctx, gin.H{"id": idParam}, nil, http_error.INVALID_TOKEN)
return
}
_, err = c.accountService.GetById(ctx.Request.Context(), userId)
if err != nil {
ResponseJSON[any](ctx, gin.H{"id": userId}, nil, err)
return
}
err = c.accountService.DeleteAccount(ctx.Request.Context(), userId)
if err != nil {
ResponseJSON[any](ctx, gin.H{"id": userId}, nil, err)
return
}
ResponseJSON(ctx, gin.H{"id": userId}, gin.H{"message": "User deleted successfully"}, nil)
}