- Add admin handlers and services for users, posts, comments, groups, and dashboard - Implement role permission management with ability to view and update permissions - Add database seeding for roles and Casbin permission policies - Upgrade Casbin from v2 to v3 with GORM adapter for persistent policy storage - Add admin-specific repository methods with filtering and pagination - Register new admin API routes under /api/v1/admin/*
203 lines
4.9 KiB
Go
203 lines
4.9 KiB
Go
package handler
|
|
|
|
import (
|
|
"strconv"
|
|
|
|
"carrot_bbs/internal/dto"
|
|
"carrot_bbs/internal/pkg/response"
|
|
"carrot_bbs/internal/service"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// AdminGroupHandler 管理端群组处理器
|
|
type AdminGroupHandler struct {
|
|
adminGroupService service.AdminGroupService
|
|
}
|
|
|
|
// NewAdminGroupHandler 创建管理端群组处理器
|
|
func NewAdminGroupHandler(adminGroupService service.AdminGroupService) *AdminGroupHandler {
|
|
return &AdminGroupHandler{
|
|
adminGroupService: adminGroupService,
|
|
}
|
|
}
|
|
|
|
// GetGroupList 获取群组列表
|
|
// GET /api/v1/admin/groups
|
|
func (h *AdminGroupHandler) GetGroupList(c *gin.Context) {
|
|
// 解析分页参数
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
|
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
|
|
|
if page <= 0 {
|
|
page = 1
|
|
}
|
|
if pageSize <= 0 || pageSize > 100 {
|
|
pageSize = 20
|
|
}
|
|
|
|
// 获取筛选参数
|
|
keyword := c.Query("keyword")
|
|
status := c.Query("status")
|
|
ownerID := c.Query("owner_id")
|
|
startDate := c.Query("start_date")
|
|
endDate := c.Query("end_date")
|
|
|
|
groups, total, err := h.adminGroupService.GetGroupList(c.Request.Context(), page, pageSize, keyword, status, ownerID, startDate, endDate)
|
|
if err != nil {
|
|
response.InternalServerError(c, "failed to get group list")
|
|
return
|
|
}
|
|
|
|
response.Paginated(c, groups, total, page, pageSize)
|
|
}
|
|
|
|
// GetGroupDetail 获取群组详情
|
|
// GET /api/v1/admin/groups/:id
|
|
func (h *AdminGroupHandler) GetGroupDetail(c *gin.Context) {
|
|
groupID := c.Param("id")
|
|
if groupID == "" {
|
|
response.BadRequest(c, "group id is required")
|
|
return
|
|
}
|
|
|
|
groupDetail, err := h.adminGroupService.GetGroupDetail(c.Request.Context(), groupID)
|
|
if err != nil {
|
|
response.NotFound(c, "group not found")
|
|
return
|
|
}
|
|
|
|
response.Success(c, groupDetail)
|
|
}
|
|
|
|
// GetGroupMembers 获取群组成员列表
|
|
// GET /api/v1/admin/groups/:id/members
|
|
func (h *AdminGroupHandler) GetGroupMembers(c *gin.Context) {
|
|
groupID := c.Param("id")
|
|
if groupID == "" {
|
|
response.BadRequest(c, "group id is required")
|
|
return
|
|
}
|
|
|
|
// 解析分页参数
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
|
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
|
|
|
if page <= 0 {
|
|
page = 1
|
|
}
|
|
if pageSize <= 0 || pageSize > 100 {
|
|
pageSize = 20
|
|
}
|
|
|
|
members, err := h.adminGroupService.GetGroupMembers(c.Request.Context(), groupID, page, pageSize)
|
|
if err != nil {
|
|
response.HandleError(c, err, "failed to get group members")
|
|
return
|
|
}
|
|
|
|
response.Success(c, members)
|
|
}
|
|
|
|
// DeleteGroup 解散群组
|
|
// DELETE /api/v1/admin/groups/:id
|
|
func (h *AdminGroupHandler) DeleteGroup(c *gin.Context) {
|
|
groupID := c.Param("id")
|
|
if groupID == "" {
|
|
response.BadRequest(c, "group id is required")
|
|
return
|
|
}
|
|
|
|
err := h.adminGroupService.DeleteGroup(c.Request.Context(), groupID)
|
|
if err != nil {
|
|
response.HandleError(c, err, "failed to delete group")
|
|
return
|
|
}
|
|
|
|
response.Success(c, dto.SuccessResponse{
|
|
Success: true,
|
|
Message: "group deleted successfully",
|
|
})
|
|
}
|
|
|
|
// UpdateGroupStatus 更新群组状态
|
|
// PUT /api/v1/admin/groups/:id/status
|
|
func (h *AdminGroupHandler) UpdateGroupStatus(c *gin.Context) {
|
|
groupID := c.Param("id")
|
|
if groupID == "" {
|
|
response.BadRequest(c, "group id is required")
|
|
return
|
|
}
|
|
|
|
var req dto.AdminUpdateGroupStatusRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "invalid request body: "+err.Error())
|
|
return
|
|
}
|
|
|
|
// 验证状态值
|
|
if req.Status != "active" && req.Status != "dissolved" {
|
|
response.BadRequest(c, "invalid status value, must be 'active' or 'dissolved'")
|
|
return
|
|
}
|
|
|
|
groupDetail, err := h.adminGroupService.UpdateGroupStatus(c.Request.Context(), groupID, req.Status)
|
|
if err != nil {
|
|
response.HandleError(c, err, "failed to update group status")
|
|
return
|
|
}
|
|
|
|
response.Success(c, groupDetail)
|
|
}
|
|
|
|
// RemoveMember 移除群组成员
|
|
// DELETE /api/v1/admin/groups/:id/members/:userId
|
|
func (h *AdminGroupHandler) RemoveMember(c *gin.Context) {
|
|
groupID := c.Param("id")
|
|
userID := c.Param("userId")
|
|
|
|
if groupID == "" {
|
|
response.BadRequest(c, "group id is required")
|
|
return
|
|
}
|
|
if userID == "" {
|
|
response.BadRequest(c, "user id is required")
|
|
return
|
|
}
|
|
|
|
err := h.adminGroupService.RemoveMember(c.Request.Context(), groupID, userID)
|
|
if err != nil {
|
|
response.HandleError(c, err, "failed to remove member")
|
|
return
|
|
}
|
|
|
|
response.Success(c, dto.SuccessResponse{
|
|
Success: true,
|
|
Message: "member removed successfully",
|
|
})
|
|
}
|
|
|
|
// TransferOwner 转让群主
|
|
// PUT /api/v1/admin/groups/:id/transfer
|
|
func (h *AdminGroupHandler) TransferOwner(c *gin.Context) {
|
|
groupID := c.Param("id")
|
|
if groupID == "" {
|
|
response.BadRequest(c, "group id is required")
|
|
return
|
|
}
|
|
|
|
var req dto.AdminTransferGroupOwnerRequest
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
response.BadRequest(c, "invalid request body: "+err.Error())
|
|
return
|
|
}
|
|
|
|
groupDetail, err := h.adminGroupService.TransferOwner(c.Request.Context(), groupID, req.NewOwnerID)
|
|
if err != nil {
|
|
response.HandleError(c, err, "failed to transfer owner")
|
|
return
|
|
}
|
|
|
|
response.Success(c, groupDetail)
|
|
}
|