fix(permissions):修复后端权限漏洞
This commit is contained in:
1 parent
9d61abda86
commit
e703c9a044
21 files changed
+233
-136
No files matched your search
@@ -411,17 +411,24 @@ func (s *sAdmin) UpdateUserStatus(ctx context.Context, req *v1.AdminUserUpdateSt
|
||||
}
|
||||
|
||||
// UnlockUser 清除管理员的登录锁定状态(重置失败计数与锁定截止时间)。
|
||||
//
|
||||
// 解锁是本文件里唯一漏掉 assertCanManageAdminUser 的账号处置动作:锁定本身是暴力破解
|
||||
// 的防线,非超管若能解锁超级管理员账号,就等于可以无限次重置对方的失败计数继续爆破。
|
||||
func (s *sAdmin) UnlockUser(ctx context.Context, req *v1.AdminUserUnlockReq) (*v1.AdminUserUnlockRes, error) {
|
||||
var user *struct {
|
||||
Id int64 `json:"id"`
|
||||
Id int64 `json:"id"`
|
||||
Role string `json:"role"`
|
||||
}
|
||||
err := dao.SysAdminUsers.Ctx(ctx).Where("id", req.Id).Scan(&user)
|
||||
err := dao.SysAdminUsers.Ctx(ctx).Where("id", req.Id).Fields("id, role").Scan(&user)
|
||||
if err = common.IgnoreScanNoRows(err); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if user == nil {
|
||||
return nil, common.NewNotFoundError("管理员")
|
||||
}
|
||||
if err := assertCanManageAdminUser(ctx, req.Id, user.Role); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = dao.SysAdminUsers.Ctx(ctx).Where("id", req.Id).Data(map[string]interface{}{
|
||||
"failed_attempts": 0,
|
||||
|
||||
@@ -133,7 +133,7 @@ var predefinedPermissionGroups = []v1.PermissionGroup{
|
||||
Name: "member",
|
||||
Label: "成员管理",
|
||||
Permissions: []string{
|
||||
"member:view", "member:import", "member:model_scope",
|
||||
"member:view", "member:import", "member:manage", "member:model_scope",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -272,62 +272,6 @@ func (s *sAdmin) UpdateUserPermissions(ctx context.Context, req *v1.AdminPermiss
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// UpdateUserDataScopes updates data scopes for an admin user.
|
||||
func (s *sAdmin) UpdateUserDataScopes(ctx context.Context, req *v1.AdminDataScopeUpdateReq) (*v1.AdminDataScopeUpdateRes, error) {
|
||||
// Check if target is super_admin
|
||||
var user *struct {
|
||||
Role string `json:"role"`
|
||||
}
|
||||
err := dao.SysAdminUsers.Ctx(ctx).
|
||||
Where("id", req.Id).Scan(&user)
|
||||
if err = common.IgnoreScanNoRows(err); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if user == nil {
|
||||
return nil, common.NewNotFoundError("用户")
|
||||
}
|
||||
if user.Role == "super_admin" {
|
||||
return nil, common.NewBadRequestError("超级管理员无需配置数据范围")
|
||||
}
|
||||
if err := assertCanManageAdminUser(ctx, req.Id, user.Role); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 事务采用 ctx 传播式写法:闭包内统一使用 dao.Xxx.Ctx(ctx),事务由 ctx 自动挂载。
|
||||
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
|
||||
// Delete existing data scopes
|
||||
_, err := dao.SysAdminDataScopes.Ctx(ctx).
|
||||
Where("admin_user_id", req.Id).
|
||||
Delete()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Insert new data scopes
|
||||
if len(req.DataScopes) > 0 {
|
||||
data := make([]do.SysAdminDataScopes, len(req.DataScopes))
|
||||
for i, sc := range req.DataScopes {
|
||||
data[i] = do.SysAdminDataScopes{
|
||||
AdminUserId: req.Id,
|
||||
ScopeType: sc.ScopeType,
|
||||
ScopeValue: sc.ScopeValue,
|
||||
}
|
||||
}
|
||||
_, err = dao.SysAdminDataScopes.Ctx(ctx).Data(data).Insert()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// tierLabels 是档位的中文标签,随元数据下发给前端,避免前端硬编码一份。
|
||||
var tierLabels = map[string]string{
|
||||
TierNone: "无",
|
||||
@@ -393,6 +337,11 @@ func HasPermission(ctx context.Context, userID int64, role string, permission st
|
||||
|
||||
// GetDataScopes returns data scopes for an admin user.
|
||||
// super_admin always returns "all".
|
||||
//
|
||||
// ⚠️ 当前无调用方:数据范围只被存储与回显,没有任何查询按它过滤,配置了也不生效。
|
||||
// 写接口已随之下线(见 api/admin/v1/permission.go)。要让这个特性真正成立,
|
||||
// 必须先把它接进各列表查询的 WHERE 条件,再恢复配置入口 —— 在那之前不要仅凭
|
||||
// 本函数存在就认为数据范围已被强制执行。
|
||||
func GetDataScopes(ctx context.Context, userID int64, role string) ([]v1.DataScopeItem, error) {
|
||||
if role == "super_admin" {
|
||||
return []v1.DataScopeItem{{ScopeType: "all"}}, nil
|
||||
|
||||
@@ -47,8 +47,8 @@ var tierPermissions = map[string]map[string][]string{
|
||||
},
|
||||
"member": {
|
||||
TierRead: {"member:view"},
|
||||
TierOperate: {"member:view", "member:import"},
|
||||
TierFull: {"member:view", "member:import", "member:model_scope"},
|
||||
TierOperate: {"member:view", "member:import", "member:manage"},
|
||||
TierFull: {"member:view", "member:import", "member:manage", "member:model_scope"},
|
||||
},
|
||||
"channel": {
|
||||
TierRead: {"channel:view"},
|
||||
@@ -137,6 +137,7 @@ var dangerousPermissions = map[string]string{
|
||||
"user:create": "可创建管理员账号",
|
||||
"user:edit": "可修改管理员账号与其角色(含提权)",
|
||||
"user:delete": "可删除管理员账号",
|
||||
"member:manage": "可重置任意租户成员的密码(等同接管该成员账号)",
|
||||
}
|
||||
|
||||
// tierOrder 定义档位由低到高的顺序,用于「权限点集合 → 档位」的反向推导。
|
||||
|
||||
@@ -30,7 +30,7 @@ var builtinRoleDefaults = map[string][]string{
|
||||
"channel:view", "channel:create", "channel:edit", "channel:test", "channel:delete",
|
||||
"model:view", "model:create", "model:edit", "model:delete",
|
||||
"tenant:view", "tenant:create", "tenant:edit", "tenant:suspend", "tenant:delete", "tenant:close",
|
||||
"member:view", "member:import", "member:model_scope",
|
||||
"member:view", "member:import", "member:manage", "member:model_scope",
|
||||
"plan:view", "plan:create", "plan:edit", "plan:delete",
|
||||
"billing:view", "billing:export", "billing:refund",
|
||||
"order:view", "order:refund",
|
||||
@@ -52,7 +52,7 @@ var builtinRoleDefaults = map[string][]string{
|
||||
"channel:view", "channel:create", "channel:edit", "channel:test", "channel:delete",
|
||||
"model:view", "model:create", "model:edit", "model:delete",
|
||||
"tenant:view", "tenant:create", "tenant:edit", "tenant:suspend",
|
||||
"member:view", "member:import", "member:model_scope",
|
||||
"member:view", "member:import", "member:manage", "member:model_scope",
|
||||
"plan:view", "plan:create", "plan:edit", "plan:delete",
|
||||
"billing:view",
|
||||
"order:view",
|
||||
|
||||
Reference in new issue
Block a user