Files
mygo/internal/handler/admin.go
T

112 lines
2.8 KiB
Go

package handler
import (
"net/http"
"strconv"
"time"
"github.com/gin-gonic/gin"
"github.com/dhao2001/mygo/internal/api"
"github.com/dhao2001/mygo/internal/model"
"github.com/dhao2001/mygo/internal/repository"
)
// AdminHandler handles admin-only endpoints for user management.
type AdminHandler struct {
userRepo repository.UserRepository
}
// NewAdminHandler creates an AdminHandler.
func NewAdminHandler(userRepo repository.UserRepository) *AdminHandler {
return &AdminHandler{userRepo: userRepo}
}
// adminUserResponse exposes all user fields, including status, for admin views.
type adminUserResponse struct {
ID string `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
IsAdmin bool `json:"is_admin"`
Status string `json:"status"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// adminUserListResponse wraps a paginated list of admin user views.
type adminUserListResponse struct {
Users []adminUserResponse `json:"users"`
Total int64 `json:"total"`
}
func toAdminResponse(u *model.User) adminUserResponse {
return adminUserResponse{
ID: u.ID,
Username: u.Username,
Email: u.Email,
IsAdmin: u.IsAdmin,
Status: u.Status,
CreatedAt: u.CreatedAt,
UpdatedAt: u.UpdatedAt,
}
}
// DeleteUser handles DELETE /api/v1/admin/users/:id — soft-deletes a user.
func (h *AdminHandler) DeleteUser(c *gin.Context) {
id := c.Param("id")
if err := h.userRepo.Delete(c.Request.Context(), id); err != nil {
api.RespondError(c, err)
return
}
c.Status(http.StatusNoContent)
}
// GetUser handles GET /api/v1/admin/users/:id — returns a user including deleted.
func (h *AdminHandler) GetUser(c *gin.Context) {
id := c.Param("id")
user, err := h.userRepo.FindByIDIncludeDeleted(c.Request.Context(), id)
if err != nil {
api.RespondError(c, err)
return
}
c.JSON(http.StatusOK, toAdminResponse(user))
}
// ListUsers handles GET /api/v1/admin/users — returns a paginated list of all users.
func (h *AdminHandler) ListUsers(c *gin.Context) {
offset, err := strconv.Atoi(c.DefaultQuery("offset", "0"))
if err != nil || offset < 0 {
api.Error(c, http.StatusBadRequest, "invalid offset")
return
}
limit, err := strconv.Atoi(c.DefaultQuery("limit", "50"))
if err != nil || limit < 1 {
api.Error(c, http.StatusBadRequest, "invalid limit")
return
}
if limit > 200 {
limit = 200
}
users, total, err := h.userRepo.ListIncludeDeleted(c.Request.Context(), offset, limit)
if err != nil {
api.RespondError(c, err)
return
}
items := make([]adminUserResponse, 0, len(users))
for i := range users {
items = append(items, toAdminResponse(&users[i]))
}
c.JSON(http.StatusOK, adminUserListResponse{
Users: items,
Total: total,
})
}