This commit is contained in:
walkor 2022-12-23 14:39:57 +08:00
parent df1f319e57
commit e5c648a57f
4 changed files with 83 additions and 16 deletions

View File

@ -5,13 +5,13 @@ namespace plugin\admin\app\common;
use plugin\admin\app\model\Admin; use plugin\admin\app\model\Admin;
use plugin\admin\app\model\AdminRole; use plugin\admin\app\model\AdminRole;
use plugin\admin\app\model\Role; use plugin\admin\app\model\Role;
use plugin\admin\app\model\Rule;
class Auth class Auth
{ {
/** /**
* 获取权限范围内的所有角色id * 获取权限范围内的所有角色id
* @param bool $with_self * @param bool $with_self
* @param array $admin_ids
* @return array * @return array
*/ */
public static function getScopeRoleIds(bool $with_self = false): array public static function getScopeRoleIds(bool $with_self = false): array
@ -34,10 +34,9 @@ class Auth
/** /**
* 获取权限范围内的所有管理员id * 获取权限范围内的所有管理员id
* @param bool $with_self * @param bool $with_self
* @param array $admin_ids
* @return array * @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); $role_ids = static::getScopeRoleIds($with_self);
return AdminRole::whereIn('role_id', $role_ids)->pluck('admin_id')->toArray(); return AdminRole::whereIn('role_id', $role_ids)->pluck('admin_id')->toArray();

View File

@ -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 * @param int $type
* @return array|null * @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) { if ($type === static::EXCLUDE_ANCESTORS) {
$items = []; $items = [];
$include = array_unique($include); $include = array_unique($include);
@ -130,13 +131,15 @@ class Tree
$max_depth = 100; $max_depth = 100;
while ($max_depth-- > 0 && $item[$this->pidName] && isset($hash_tree[$item[$this->pidName]])) { while ($max_depth-- > 0 && $item[$this->pidName] && isset($hash_tree[$item[$this->pidName]])) {
$last_item = $item; $last_item = $item;
$item = $hash_tree[$item[$this->pidName]]; $pid = $item[$this->pidName];
$item = $hash_tree[$pid];
$item_id = $item['id']; $item_id = $item['id'];
if (empty($map[$item_id])) { if (empty($map[$item_id])) {
$map[$item_id] = 1; $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; $items[$item['id']] = $item;
} }

View File

@ -74,6 +74,7 @@ class RoleController extends Crud
if (!Auth::isSupperAdmin() && !in_array($pid, Auth::getScopeRoleIds(true))) { if (!Auth::isSupperAdmin() && !in_array($pid, Auth::getScopeRoleIds(true))) {
return $this->json(1, '父级角色组超出权限范围'); return $this->json(1, '父级角色组超出权限范围');
} }
$this->checkRules($pid, $data['rules'] ?? '');
$id = $this->doInsert($data); $id = $this->doInsert($data);
return $this->json(0, 'ok', ['id' => $id]); 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)) { if (!$is_supper_admin && !in_array($id, $descendant_role_ids)) {
return $this->json(1, '无数据权限'); return $this->json(1, '无数据权限');
} }
// id为1的权限权限固定为*
if (isset($data['rules']) && $id == 1) { $role = Role::find($id);
$data['rules'] = '*'; if (!$role) {
return $this->json(1, '数据不存在');
} }
// id为1的上级pid固定为0 $is_supper_role = $role->rules === '*';
if (isset($data['pid']) && $id == 1) {
$data['pid'] = 0; // 超级角色组不允许更改rules pid 字段
if ($is_supper_role) {
unset($data['rules'], $data['pid']);
} }
if (key_exists('pid', $data)) { if (key_exists('pid', $data)) {
@ -118,9 +122,31 @@ class RoleController extends Crud
if (!$is_supper_admin && !in_array($pid, Auth::getScopeRoleIds(true))) { if (!$is_supper_admin && !in_array($pid, Auth::getScopeRoleIds(true))) {
return $this->json(1, '父级超出权限范围'); return $this->json(1, '父级超出权限范围');
} }
} else {
$pid = $role->pid;
}
if (!$is_supper_role) {
$this->checkRules($pid, $data['rules'] ?? '');
} }
$this->doUpdate($id, $data); $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); return $this->json(0);
} }
@ -179,5 +205,37 @@ class RoleController extends Crud
return $this->json(0, 'ok', $tree->getTree($include)); 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('数据超出权限范围');
}
}
}
} }

View File

@ -27,5 +27,12 @@ class Role extends Base
*/ */
protected $primaryKey = 'id'; protected $primaryKey = 'id';
/**
* @return mixed
*/
public function getRuleIds()
{
return $this->rules ? explode(',', $this->rules) : [];
}
} }