package controllers import ( "errors" "time" "github.com/gofiber/fiber/v3" "gorm.io/gorm" "server/internal/models" ) type AdminController struct{} func NewAdminController() *AdminController { return &AdminController{} } // Typescript: interface type ListUsersRequest struct { Page int `json:"page" validate:"omitempty,min=1"` PageSize int `json:"pageSize" validate:"omitempty,min=1,max=100"` } // Typescript: interface type BlockUserRequest struct { 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 := 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 := dbFromCtx(c) if err != nil { return err } var list []models.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") } // Map to short representation short := make([]models.UserShort, 0, len(list)) for i := range list { short = append(short, models.ToUserShort(&list[i])) } return c.JSON(fiber.Map{ "data": fiber.Map{ "page": req.Page, "pageSize": req.PageSize, "items": short, }, "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 := validateStruct(&req); err != nil { return err } db, err := dbFromCtx(c) if err != nil { return err } uuid := c.Params("uuid") if uuid == "" { return fiber.NewError(fiber.StatusBadRequest, "invalid user uuid") } var user models.User if err := db.Preload("Details").Preload("Preferences").Where("uuid = ?", uuid).First(&user).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": user.Status = models.UserStatusDisabled case "unblock": user.Status = models.UserStatusActive default: return fiber.NewError(fiber.StatusBadRequest, "invalid action") } user.UpdatedAt = time.Now().UTC() if err := db.Save(&user).Error; err != nil { return fiber.NewError(fiber.StatusInternalServerError, "failed to update user status") } return c.JSON(success(models.ToUserShort(&user))) }