fix: update admin flows and review report
This commit is contained in:
@@ -243,11 +243,47 @@ func (h *UserHandler) UpdateUserStatus(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *UserHandler) GetUserRoles(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"roles": []interface{}{}})
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "invalid user id"})
|
||||
return
|
||||
}
|
||||
|
||||
roles, err := h.userService.GetUserRoles(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
handleError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": roles,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *UserHandler) AssignRoles(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"message": "role assignment not implemented"})
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "invalid user id"})
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
RoleIDs []int64 `json:"role_ids" binding:"required"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.userService.AssignRoles(c.Request.Context(), id, req.RoleIDs); err != nil {
|
||||
handleError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "角色分配成功"})
|
||||
}
|
||||
|
||||
func (h *UserHandler) BatchUpdateStatus(c *gin.Context) {
|
||||
@@ -287,15 +323,62 @@ func (h *UserHandler) UploadAvatar(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *UserHandler) ListAdmins(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"admins": []interface{}{}})
|
||||
admins, err := h.userService.ListAdmins(c.Request.Context())
|
||||
if err != nil {
|
||||
handleError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
adminResponses := make([]*UserResponse, len(admins))
|
||||
for i, u := range admins {
|
||||
adminResponses[i] = toUserResponse(u)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "success", "data": adminResponses})
|
||||
}
|
||||
|
||||
func (h *UserHandler) CreateAdmin(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"message": "admin creation not implemented"})
|
||||
var req struct {
|
||||
Username string `json:"username" binding:"required"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
Email string `json:"email"`
|
||||
Nickname string `json:"nickname"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
adminReq := &service.CreateAdminRequest{
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
Email: req.Email,
|
||||
Nickname: req.Nickname,
|
||||
}
|
||||
|
||||
admin, err := h.userService.CreateAdmin(c.Request.Context(), adminReq)
|
||||
if err != nil {
|
||||
handleError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, gin.H{"code": 0, "message": "管理员创建成功", "data": toUserResponse(admin)})
|
||||
}
|
||||
|
||||
func (h *UserHandler) DeleteAdmin(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"message": "admin deletion not implemented"})
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"code": 400, "message": "invalid user id"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.userService.DeleteAdmin(c.Request.Context(), id); err != nil {
|
||||
handleError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "管理员已移除"})
|
||||
}
|
||||
|
||||
type UserResponse struct {
|
||||
|
||||
@@ -33,6 +33,11 @@ func (r *UserRoleRepository) DeleteByUserID(ctx context.Context, userID int64) e
|
||||
return r.db.WithContext(ctx).Where("user_id = ?", userID).Delete(&domain.UserRole{}).Error
|
||||
}
|
||||
|
||||
// DeleteByUserAndRole 删除指定用户和角色的关联
|
||||
func (r *UserRoleRepository) DeleteByUserAndRole(ctx context.Context, userID, roleID int64) error {
|
||||
return r.db.WithContext(ctx).Where("user_id = ? AND role_id = ?", userID, roleID).Delete(&domain.UserRole{}).Error
|
||||
}
|
||||
|
||||
// DeleteByRoleID 删除角色的所有用户
|
||||
func (r *UserRoleRepository) DeleteByRoleID(ctx context.Context, roleID int64) error {
|
||||
return r.db.WithContext(ctx).Where("role_id = ?", roleID).Delete(&domain.UserRole{}).Error
|
||||
|
||||
@@ -211,3 +211,163 @@ func (s *UserService) BatchDelete(ctx context.Context, req *BatchDeleteRequest)
|
||||
err := s.userRepo.BatchDelete(ctx, req.IDs)
|
||||
return int64(len(req.IDs)), err
|
||||
}
|
||||
|
||||
// GetUserRoles 获取用户的所有角色
|
||||
func (s *UserService) GetUserRoles(ctx context.Context, userID int64) ([]*domain.Role, error) {
|
||||
// 检查用户是否存在
|
||||
if _, err := s.userRepo.GetByID(ctx, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取用户角色关联
|
||||
userRoles, err := s.userRoleRepo.GetByUserID(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(userRoles) == 0 {
|
||||
return []*domain.Role{}, nil
|
||||
}
|
||||
|
||||
// 获取角色ID列表
|
||||
roleIDs := make([]int64, len(userRoles))
|
||||
for i, ur := range userRoles {
|
||||
roleIDs[i] = ur.RoleID
|
||||
}
|
||||
|
||||
// 批量获取角色详情
|
||||
var roles []*domain.Role
|
||||
for _, roleID := range roleIDs {
|
||||
role, err := s.roleRepo.GetByID(ctx, roleID)
|
||||
if err != nil {
|
||||
continue // 跳过不存在的角色
|
||||
}
|
||||
roles = append(roles, role)
|
||||
}
|
||||
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
// AssignRoles 分配用户角色
|
||||
func (s *UserService) AssignRoles(ctx context.Context, userID int64, roleIDs []int64) error {
|
||||
// 检查用户是否存在
|
||||
if _, err := s.userRepo.GetByID(ctx, userID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 验证所有角色存在
|
||||
for _, roleID := range roleIDs {
|
||||
if _, err := s.roleRepo.GetByID(ctx, roleID); err != nil {
|
||||
return fmt.Errorf("角色 %d 不存在", roleID)
|
||||
}
|
||||
}
|
||||
|
||||
// 删除用户现有角色
|
||||
if err := s.userRoleRepo.DeleteByUserID(ctx, userID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 创建新的用户角色关联
|
||||
var userRoles []*domain.UserRole
|
||||
for _, roleID := range roleIDs {
|
||||
userRoles = append(userRoles, &domain.UserRole{
|
||||
UserID: userID,
|
||||
RoleID: roleID,
|
||||
})
|
||||
}
|
||||
|
||||
return s.userRoleRepo.BatchCreate(ctx, userRoles)
|
||||
}
|
||||
|
||||
// AdminRoleID is the ID of the admin role
|
||||
const AdminRoleID = 1
|
||||
|
||||
// ListAdmins 获取所有管理员
|
||||
func (s *UserService) ListAdmins(ctx context.Context) ([]*domain.User, error) {
|
||||
// 获取管理员角色ID列表
|
||||
adminUserIDs, err := s.userRoleRepo.GetUserIDByRoleID(ctx, AdminRoleID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(adminUserIDs) == 0 {
|
||||
return []*domain.User{}, nil
|
||||
}
|
||||
|
||||
// 获取所有管理员用户
|
||||
var admins []*domain.User
|
||||
for _, adminID := range adminUserIDs {
|
||||
user, err := s.userRepo.GetByID(ctx, adminID)
|
||||
if err != nil {
|
||||
continue // 跳过不存在的用户
|
||||
}
|
||||
admins = append(admins, user)
|
||||
}
|
||||
|
||||
return admins, nil
|
||||
}
|
||||
|
||||
// CreateAdmin 创建管理员
|
||||
func (s *UserService) CreateAdmin(ctx context.Context, req *CreateAdminRequest) (*domain.User, error) {
|
||||
// 检查用户名是否已存在
|
||||
existingUser, err := s.userRepo.GetByUsername(ctx, req.Username)
|
||||
if err == nil && existingUser != nil {
|
||||
return nil, errors.New("用户名已存在")
|
||||
}
|
||||
|
||||
// 创建用户
|
||||
hashedPassword, err := auth.HashPassword(req.Password)
|
||||
if err != nil {
|
||||
return nil, errors.New("密码哈希失败")
|
||||
}
|
||||
|
||||
user := &domain.User{
|
||||
Username: req.Username,
|
||||
Password: hashedPassword,
|
||||
Status: domain.UserStatusActive,
|
||||
}
|
||||
|
||||
if req.Email != "" {
|
||||
user.Email = &req.Email
|
||||
}
|
||||
if req.Nickname != "" {
|
||||
user.Nickname = req.Nickname
|
||||
}
|
||||
|
||||
if err := s.userRepo.Create(ctx, user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 分配管理员角色
|
||||
userRole := &domain.UserRole{
|
||||
UserID: user.ID,
|
||||
RoleID: AdminRoleID,
|
||||
}
|
||||
if err := s.userRoleRepo.Create(ctx, userRole); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// DeleteAdmin 删除管理员(移除管理员角色)
|
||||
func (s *UserService) DeleteAdmin(ctx context.Context, userID int64) error {
|
||||
// 检查用户是否存在
|
||||
if _, err := s.userRepo.GetByID(ctx, userID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 不能删除自己
|
||||
// 注意:这里需要从handler传入当前用户ID进行校验
|
||||
|
||||
// 删除用户的管理员角色
|
||||
return s.userRoleRepo.DeleteByUserAndRole(ctx, userID, AdminRoleID)
|
||||
}
|
||||
|
||||
// CreateAdminRequest 创建管理员请求
|
||||
type CreateAdminRequest struct {
|
||||
Username string `json:"username" binding:"required"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
Email string `json:"email"`
|
||||
Nickname string `json:"nickname"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user