package admin import ( "errors" "time" "github.com/gofiber/fiber/v3" "gorm.io/gorm" "server/internal/db" "server/internal/responses" users "server/internal/user" "server/internal/validation" ) type AdminController struct{} func NewAdminController() *AdminController { return &AdminController{} } type ListUsersRequest struct { Page int `json:"page" validate:"omitempty,min=1"` PageSize int `json:"pageSize" validate:"omitempty,min=1,max=100"` } type ListUsersResponse struct { Items []users.User `json:"items"` Page int `json:"page" ` PageSize int `json:"pageSize" ` } type BlockUserRequest struct { UUID string `json:"uuid" validate:"required,uuid4"` Action string `json:"action" validate:"required,oneof=block unblock"` } // ListUsers returns a paginated list of users (requires admin permissions). func (ac *AdminController) ListUsers(c fiber.Ctx) error { var req ListUsersRequest if err := c.Bind().Body(&req); err != nil { return fiber.NewError(fiber.StatusBadRequest, "invalid payload") } if err := validation.ValidateStruct(&req); err != nil { return err } if req.Page <= 0 { req.Page = 1 } if req.PageSize <= 0 || req.PageSize > 100 { req.PageSize = 20 } db, err := db.DBFromCtx(c) if err != nil { return err } var list []users.User offset := (req.Page - 1) * req.PageSize if err := db.Preload("Details").Preload("Preferences"). Limit(req.PageSize). Offset(offset). Find(&list).Error; err != nil { return fiber.NewError(fiber.StatusInternalServerError, "failed to load users") } return c.JSON(fiber.Map{ "data": fiber.Map{ "page": req.Page, "pageSize": req.PageSize, "items": list, }, "error": nil, }) } // BlockUser blocks or unblocks a user account by UUID. func (ac *AdminController) BlockUser(c fiber.Ctx) error { var req BlockUserRequest if err := c.Bind().Body(&req); err != nil { return fiber.NewError(fiber.StatusBadRequest, "invalid payload") } if err := validation.ValidateStruct(&req); err != nil { return err } db, err := db.DBFromCtx(c) if err != nil { return err } var u users.User if err := db.Preload("Details").Preload("Preferences").Where("uuid = ?", req.UUID).First(&u).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return fiber.NewError(fiber.StatusNotFound, "user not found") } return fiber.NewError(fiber.StatusInternalServerError, "failed to load user") } switch req.Action { case "block": u.Status = users.UserStatusDisabled case "unblock": u.Status = users.UserStatusActive default: return fiber.NewError(fiber.StatusBadRequest, "invalid action") } now := time.Now().UTC() u.UpdatedAt = &now if err := db.Save(&u).Error; err != nil { return fiber.NewError(fiber.StatusInternalServerError, "failed to update user status") } return c.JSON(responses.Success(u)) }