feat: 角色等级体系与权限管控实施
- 数据库:auth_roles 表新增 level 字段(1=超管, 10=管理员, 100=普通用户) - 后端:新增 GetAllRoles/GetUserMaxLevel/SetUserRoles/FindByCodeList DAO 方法 - 后端:SetRolesRequest 替换 AssignRoleRequest,AdminUserInfo.Roles 改为 []RoleInfo - 后端:所有管理操作(禁用/启用/角色分配/创建用户)强制层级权限校验 - 后端:PUT /users/:id/roles(批量设置角色)+ GET /roles(角色列表) - 前端:角色管理改为 Checkbox Group 多选,高等级角色禁用 - 前端:禁用/启用按钮受角色层级约束,列表页操作按钮权限管控 - 前端:创建用户对话框角色选项根据操作者等级动态过滤 - 文档:API 文档、设计方案、集成规范、进度文档同步更新 Made-with: Cursor
This commit is contained in:
@@ -2,6 +2,7 @@ package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
|
||||
"github.com/echochat/backend/app/auth/model"
|
||||
"github.com/echochat/backend/pkg/logs"
|
||||
@@ -117,3 +118,87 @@ func (d *RoleDAO) RemoveUserRoles(ctx context.Context, userID int64) error {
|
||||
Where("user_id = ?", userID).
|
||||
Delete(&model.UserRole{}).Error
|
||||
}
|
||||
|
||||
// GetAllRoles 获取所有角色列表(按 level 升序排列)
|
||||
func (d *RoleDAO) GetAllRoles(ctx context.Context) ([]model.Role, error) {
|
||||
funcName := "dao.role_dao.GetAllRoles"
|
||||
logs.Debug(ctx, funcName, "获取所有角色列表")
|
||||
|
||||
var roles []model.Role
|
||||
err := d.db.WithContext(ctx).Order("level ASC").Find(&roles).Error
|
||||
if err != nil {
|
||||
logs.Error(ctx, funcName, "获取所有角色失败", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
// GetUserMaxLevel 获取用户的最高权限等级(最小 level 值)
|
||||
// 如果用户无角色,返回 math.MaxInt32 表示无权限
|
||||
func (d *RoleDAO) GetUserMaxLevel(ctx context.Context, userID int64) (int, error) {
|
||||
funcName := "dao.role_dao.GetUserMaxLevel"
|
||||
logs.Debug(ctx, funcName, "获取用户最高权限等级", zap.Int64("user_id", userID))
|
||||
|
||||
var minLevel *int
|
||||
err := d.db.WithContext(ctx).
|
||||
Model(&model.UserRole{}).
|
||||
Joins("JOIN auth_roles ON auth_roles.id = auth_user_roles.role_id").
|
||||
Where("auth_user_roles.user_id = ?", userID).
|
||||
Select("MIN(auth_roles.level)").
|
||||
Scan(&minLevel).Error
|
||||
if err != nil {
|
||||
logs.Error(ctx, funcName, "获取用户权限等级失败", zap.Error(err))
|
||||
return 0, err
|
||||
}
|
||||
if minLevel == nil {
|
||||
return math.MaxInt32, nil
|
||||
}
|
||||
return *minLevel, nil
|
||||
}
|
||||
|
||||
// SetUserRoles 事务内先清除再批量设置用户角色
|
||||
func (d *RoleDAO) SetUserRoles(ctx context.Context, userID int64, roleIDs []int) error {
|
||||
funcName := "dao.role_dao.SetUserRoles"
|
||||
logs.Info(ctx, funcName, "设置用户角色",
|
||||
zap.Int64("user_id", userID),
|
||||
zap.Ints("role_ids", roleIDs),
|
||||
)
|
||||
|
||||
return d.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Where("user_id = ?", userID).Delete(&model.UserRole{}).Error; err != nil {
|
||||
logs.Error(ctx, funcName, "清除用户角色失败", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
if len(roleIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
userRoles := make([]model.UserRole, 0, len(roleIDs))
|
||||
for _, rid := range roleIDs {
|
||||
userRoles = append(userRoles, model.UserRole{
|
||||
UserID: userID,
|
||||
RoleID: rid,
|
||||
})
|
||||
}
|
||||
if err := tx.Create(&userRoles).Error; err != nil {
|
||||
logs.Error(ctx, funcName, "批量设置用户角色失败", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// FindByCodeList 按角色代码列表批量查询角色
|
||||
func (d *RoleDAO) FindByCodeList(ctx context.Context, codes []string) ([]model.Role, error) {
|
||||
funcName := "dao.role_dao.FindByCodeList"
|
||||
logs.Debug(ctx, funcName, "批量查询角色", zap.Strings("codes", codes))
|
||||
|
||||
var roles []model.Role
|
||||
err := d.db.WithContext(ctx).Where("code IN ?", codes).Find(&roles).Error
|
||||
if err != nil {
|
||||
logs.Error(ctx, funcName, "批量查询角色失败", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
return roles, nil
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ type Role struct {
|
||||
ID int `json:"id" gorm:"primaryKey;autoIncrement"` // 角色唯一标识,自增主键
|
||||
Code string `json:"code" gorm:"uniqueIndex;size:50;not null"` // 角色代码,全局唯一,如 user/admin/super_admin(对应 constants.RoleCode*)
|
||||
Name string `json:"name" gorm:"size:50;not null"` // 角色中文显示名称,如「普通用户」「管理员」
|
||||
Level int `json:"level" gorm:"not null;default:100"` // 角色等级,值越小权限越高:1=超管, 10=管理员, 100=普通用户
|
||||
Description string `json:"description" gorm:"size:200;default:''"` // 角色描述说明,用于后台管理界面展示
|
||||
CreatedAt time.Time `json:"created_at" gorm:"not null;autoCreateTime;type:timestamp(0)"` // 创建时间,由 GORM 自动填充,精确到秒
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user