更新bug
This commit is contained in:
@@ -19,8 +19,8 @@ use think\facade\Config;
|
||||
* - DEPT (3) = 仅本部门(取 admin 全部部门的并集,不含子孙)
|
||||
* - SELF (4) = 仅本人
|
||||
*
|
||||
* 多角色时取「最严格」可见范围 = data_scope 最大值(1=全部 … 4=仅本人),
|
||||
* 与常见「数据权限取交集」一致,避免挂了一个「全部」角色就把其它角色的部门范围冲掉。
|
||||
* 多角色时,2/3/4 范围按授权并集取最宽范围;迁移期遗留的普通 scope=1 角色不会
|
||||
* 自动冲掉有限范围。只有明确的管理员角色、root 或 exempt_roles 才能在组合角色中放开全部。
|
||||
* root 管理员固定为 ALL。未挂任何部门时,范围退化为 SELF(可由 config 关闭)。
|
||||
*
|
||||
* 关键返回:`getVisibleAdminIds` 返回 int[](可见 admin_id 集合)或 null(ALL = 不过滤)。
|
||||
@@ -32,6 +32,9 @@ class DataScopeService
|
||||
public const SCOPE_DEPT = 3;
|
||||
public const SCOPE_SELF = 4;
|
||||
|
||||
/** @var string[] 明确允许在多角色组合中放开全部数据的内置角色名。 */
|
||||
private const ALL_SCOPE_ROLE_NAMES = ['管理员', '系统管理员'];
|
||||
|
||||
/**
|
||||
* 计算当前 admin 的有效数据范围。
|
||||
*/
|
||||
@@ -51,18 +54,59 @@ class DataScopeService
|
||||
if ($roleIds === []) {
|
||||
return self::SCOPE_SELF;
|
||||
}
|
||||
$scopes = SystemRole::whereIn('id', $roleIds)
|
||||
$roleRows = SystemRole::whereIn('id', $roleIds)
|
||||
->whereNull('delete_time')
|
||||
->column('data_scope');
|
||||
$scopes = array_values(array_filter(array_map('intval', $scopes), static function (int $v): bool {
|
||||
return $v >= self::SCOPE_ALL && $v <= self::SCOPE_SELF;
|
||||
}));
|
||||
// 角色存在但库中无有效 data_scope(缺失/脏数据/已删角色):宁可收窄到「仅本人」,避免误放开到全站
|
||||
if ($scopes === []) {
|
||||
->field('id,name,data_scope')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
return self::mergeRoleScopes($roleRows);
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并多个角色的数据范围。
|
||||
*
|
||||
* 历史迁移曾把全部旧角色默认成 scope=1;如果账号同时具有有限范围角色,普通的
|
||||
* scope=1 视为功能角色而不参与放大,防止“医生 + 医助”等组合意外获得全站数据。
|
||||
* 2/3/4 是嵌套授权,取最小值即可表达多个有效数据角色的可见范围并集。
|
||||
*
|
||||
* @param array<int,array<string,mixed>> $roleRows
|
||||
*/
|
||||
private static function mergeRoleScopes(array $roleRows): int
|
||||
{
|
||||
$validRows = [];
|
||||
foreach ($roleRows as $roleRow) {
|
||||
$scope = (int) ($roleRow['data_scope'] ?? 0);
|
||||
if ($scope < self::SCOPE_ALL || $scope > self::SCOPE_SELF) {
|
||||
continue;
|
||||
}
|
||||
$validRows[] = [
|
||||
'name' => trim((string) ($roleRow['name'] ?? '')),
|
||||
'scope' => $scope,
|
||||
];
|
||||
}
|
||||
// 角色存在但库中无有效 data_scope(缺失/脏数据/已删角色):宁可收窄到本人。
|
||||
if ($validRows === []) {
|
||||
return self::SCOPE_SELF;
|
||||
}
|
||||
|
||||
return (int) max($scopes);
|
||||
foreach ($validRows as $roleRow) {
|
||||
if ($roleRow['scope'] === self::SCOPE_ALL
|
||||
&& in_array($roleRow['name'], self::ALL_SCOPE_ROLE_NAMES, true)) {
|
||||
return self::SCOPE_ALL;
|
||||
}
|
||||
}
|
||||
|
||||
$boundedScopes = array_column(array_values(array_filter(
|
||||
$validRows,
|
||||
static fn (array $roleRow): bool => $roleRow['scope'] > self::SCOPE_ALL
|
||||
)), 'scope');
|
||||
if ($boundedScopes !== []) {
|
||||
return (int) min($boundedScopes);
|
||||
}
|
||||
|
||||
// 只有普通 scope=1 角色时保持原有“全部数据”行为。
|
||||
return self::SCOPE_ALL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user