diff --git a/src/plugin/admin/app/common/Auth.php b/src/plugin/admin/app/common/Auth.php index 87c11de..c25f237 100644 --- a/src/plugin/admin/app/common/Auth.php +++ b/src/plugin/admin/app/common/Auth.php @@ -5,13 +5,13 @@ namespace plugin\admin\app\common; use plugin\admin\app\model\Admin; use plugin\admin\app\model\AdminRole; use plugin\admin\app\model\Role; +use plugin\admin\app\model\Rule; class Auth { /** * 获取权限范围内的所有角色id * @param bool $with_self - * @param array $admin_ids * @return array */ public static function getScopeRoleIds(bool $with_self = false): array @@ -34,10 +34,9 @@ class Auth /** * 获取权限范围内的所有管理员id * @param bool $with_self - * @param array $admin_ids * @return array */ - public static function getScopeAdminIds(bool $with_self = false, array $admin_ids = []): array + public static function getScopeAdminIds(bool $with_self = false): array { $role_ids = static::getScopeRoleIds($with_self); return AdminRole::whereIn('role_id', $role_ids)->pluck('admin_id')->toArray(); diff --git a/src/plugin/admin/app/common/Tree.php b/src/plugin/admin/app/common/Tree.php index 56707fd..5dfc53a 100644 --- a/src/plugin/admin/app/common/Tree.php +++ b/src/plugin/admin/app/common/Tree.php @@ -8,12 +8,12 @@ class Tree /** * 获取完整的树结构,包含祖先节点 */ - const INCLUDE_ANCESTORS = 0; + const INCLUDE_ANCESTORS = 1; /** * 获取部分树,不包含祖先节点 */ - const EXCLUDE_ANCESTORS = 1; + const EXCLUDE_ANCESTORS = 0; /** * 数据 @@ -103,8 +103,9 @@ class Tree * @param int $type * @return array|null */ - public function getTree(array $include = [], int $type = 0): ?array + public function getTree(array $include = [], int $type = 1): ?array { + // $type === static::EXCLUDE_ANCESTORS if ($type === static::EXCLUDE_ANCESTORS) { $items = []; $include = array_unique($include); @@ -130,13 +131,15 @@ class Tree $max_depth = 100; while ($max_depth-- > 0 && $item[$this->pidName] && isset($hash_tree[$item[$this->pidName]])) { $last_item = $item; - $item = $hash_tree[$item[$this->pidName]]; + $pid = $item[$this->pidName]; + $item = $hash_tree[$pid]; $item_id = $item['id']; if (empty($map[$item_id])) { $map[$item_id] = 1; - $item['children'] = []; + $hash_tree[$pid]['children'] = []; } - $item['children'][$last_item['id']] = $last_item; + $hash_tree[$pid]['children'][$last_item['id']] = $last_item; + $item = $hash_tree[$pid]; } $items[$item['id']] = $item; } diff --git a/src/plugin/admin/app/controller/RoleController.php b/src/plugin/admin/app/controller/RoleController.php index 070c2ec..2d665fe 100644 --- a/src/plugin/admin/app/controller/RoleController.php +++ b/src/plugin/admin/app/controller/RoleController.php @@ -74,6 +74,7 @@ class RoleController extends Crud if (!Auth::isSupperAdmin() && !in_array($pid, Auth::getScopeRoleIds(true))) { return $this->json(1, '父级角色组超出权限范围'); } + $this->checkRules($pid, $data['rules'] ?? ''); $id = $this->doInsert($data); return $this->json(0, 'ok', ['id' => $id]); @@ -98,13 +99,16 @@ class RoleController extends Crud if (!$is_supper_admin && !in_array($id, $descendant_role_ids)) { return $this->json(1, '无数据权限'); } - // id为1的权限权限固定为* - if (isset($data['rules']) && $id == 1) { - $data['rules'] = '*'; + + $role = Role::find($id); + if (!$role) { + return $this->json(1, '数据不存在'); } - // id为1的上级pid固定为0 - if (isset($data['pid']) && $id == 1) { - $data['pid'] = 0; + $is_supper_role = $role->rules === '*'; + + // 超级角色组不允许更改rules pid 字段 + if ($is_supper_role) { + unset($data['rules'], $data['pid']); } if (key_exists('pid', $data)) { @@ -118,9 +122,31 @@ class RoleController extends Crud if (!$is_supper_admin && !in_array($pid, Auth::getScopeRoleIds(true))) { return $this->json(1, '父级超出权限范围'); } + } else { + $pid = $role->pid; + } + + if (!$is_supper_role) { + $this->checkRules($pid, $data['rules'] ?? ''); } $this->doUpdate($id, $data); + + // 删除所有子角色组中已经不存在的权限 + if (!$is_supper_role) { + $tree = new Tree(Role::select(['id', 'pid'])->get()); + $descendant_roles = $tree->getDescendant([$id]); + $descendant_role_ids = array_column($descendant_roles, 'id'); + $rule_ids = $data['rules'] ? explode(',', $data['rules']) : []; + foreach ($descendant_role_ids as $role_id) { + $tmp_role = Role::find($role_id); + $tmp_rule_ids = $role->getRuleIds(); + $tmp_rule_ids = array_intersect($rule_ids, $tmp_rule_ids); + $tmp_role->rules = implode(',', $tmp_rule_ids); + $tmp_role->save(); + } + } + return $this->json(0); } @@ -179,5 +205,37 @@ class RoleController extends Crud return $this->json(0, 'ok', $tree->getTree($include)); } + /** + * 检查权限字典是否合法 + * @param int $role_id + * @param $rule_ids + * @return void + * @throws BusinessException + */ + protected function checkRules(int $role_id, $rule_ids) + { + if ($rule_ids) { + $rule_ids = explode(',', $rule_ids); + if (in_array('*', $rule_ids)) { + throw new BusinessException('非法数据'); + } + $rule_exists = Rule::whereIn('id', $rule_ids)->pluck('id'); + if (count($rule_exists) != count($rule_ids)) { + throw new BusinessException('权限不存在'); + } + $rule_id_string = Role::where('id', $role_id)->value('rules'); + if ($rule_id_string === '') { + throw new BusinessException('数据超出权限范围'); + } + if ($rule_id_string === '*') { + return; + } + $legal_rule_ids = explode(',', $rule_id_string); + if (array_diff($rule_ids, $legal_rule_ids)) { + throw new BusinessException('数据超出权限范围'); + } + } + } + } diff --git a/src/plugin/admin/app/model/Role.php b/src/plugin/admin/app/model/Role.php index 9968055..bf77d88 100644 --- a/src/plugin/admin/app/model/Role.php +++ b/src/plugin/admin/app/model/Role.php @@ -27,5 +27,12 @@ class Role extends Base */ protected $primaryKey = 'id'; - + /** + * @return mixed + */ + public function getRuleIds() + { + return $this->rules ? explode(',', $this->rules) : []; + } + }