go-quasar-partial-ssr/backend/internal/http/controllers/admin.go

120 lines
2.8 KiB
Go

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