go-quasar-partial-ssr/backend/internal/admin/controller.go

180 lines
4.4 KiB
Go

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))
}
func (ac *AdminController) UpdateUser(c fiber.Ctx) error {
var req users.UpdateUserRequest
if err := c.Bind().Body(&req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, "invalid payload")
}
if err := validation.ValidateStruct(&req); err != nil {
return err
}
user, err := users.UpdateUser(req)
if err != nil {
return err
}
return c.JSON(responses.Success(user))
}
// UpdateUserDetails replaces user fields and synchronizes details/preferences.
func (ac *AdminController) UpdateUserDetails(c fiber.Ctx) error {
var req users.UpdateUserDetailsRequest
if err := c.Bind().Body(&req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, "invalid payload")
}
if err := validation.ValidateStruct(&req); err != nil {
return err
}
err := users.UpdateUserDetails(req)
if err != nil {
return err
}
user, err := users.GetUserByID(req.UserID)
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, "invalid user id")
}
return c.JSON(responses.Success(user))
}
// UpdateUserPreferences replaces user fields and synchronizes details/preferences.
func (ac *AdminController) UpdateUserPreferences(c fiber.Ctx) error {
var req users.UpdateUserPreferencesRequest
if err := c.Bind().Body(&req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, "invalid payload")
}
if err := validation.ValidateStruct(&req); err != nil {
return err
}
err := users.UpdateUserPreferences(req)
if err != nil {
return err
}
user, err := users.GetUserByID(req.UserID)
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, "invalid user id")
}
return c.JSON(responses.Success(user))
}