权限管理与测试
This commit is contained in:
@@ -2,10 +2,11 @@
|
||||
|
||||
namespace plugin\admin\app\common;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use InvalidArgumentException;
|
||||
use plugin\admin\app\model\OpmMwPermissionRule;
|
||||
use support\Db;
|
||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||
|
||||
/**
|
||||
* 数据权限规则服务类
|
||||
@@ -62,40 +63,75 @@ class DataPermissionService
|
||||
* 3. 收集查询中所有表别名;
|
||||
* 4. 逐条应用权限规则;
|
||||
*
|
||||
* @param Builder|string $query 查询对象
|
||||
* @return Builder
|
||||
* @param QueryBuilder|EloquentBuilder $query 查询对象
|
||||
* @return QueryBuilder|EloquentBuilder
|
||||
*/
|
||||
public function apply(Builder|string $query): Builder
|
||||
public function apply(QueryBuilder|EloquentBuilder $query): QueryBuilder|EloquentBuilder
|
||||
{
|
||||
// 兼容传入 Builder 的情况;这里统一取底层 Query Builder
|
||||
$baseQuery = $query->getQuery();
|
||||
// 统一拿 baseQuery(核心修复点)
|
||||
if ($query instanceof EloquentBuilder) {
|
||||
$baseQuery = $query->getQuery();
|
||||
$tableRaw = $query->getModel()->getTable();
|
||||
} else {
|
||||
$baseQuery = $query;
|
||||
$tableRaw = $query->from;
|
||||
}
|
||||
|
||||
// 解析主表名和主表别名,例如:table as t => [table, t]
|
||||
[$fromTable, $fromAlias] = $this->parseTableAlias((string)($baseQuery->from ?? ''));
|
||||
// 解析主表 & 别名
|
||||
[$fromTable, $fromAlias] = $this->parseTableAlias((string)($tableRaw ?? ''));
|
||||
|
||||
// 如果无法识别主表,直接返回,不处理
|
||||
if ($fromTable === '') {
|
||||
return $query;
|
||||
}
|
||||
|
||||
// 加载该主表对应的启用规则
|
||||
// 加载规则
|
||||
$rules = $this->loadRules($fromTable);
|
||||
|
||||
// 没有规则则不做任何限制
|
||||
if (empty($rules)) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
// 获取查询里所有表的别名映射,后续用于拼字段
|
||||
// 获取所有表别名
|
||||
$tableAliases = $this->getAllTableAliases($baseQuery);
|
||||
|
||||
// 逐条应用规则
|
||||
// 应用规则
|
||||
foreach ($rules as $rule) {
|
||||
$query = $this->applySingleRule($query, $rule, $fromAlias, $tableAliases);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
// public function apply(EloquentBuilder $query): Builder
|
||||
// {
|
||||
// // 兼容传入 Builder 的情况;这里统一取底层 Query Builder
|
||||
// $baseQuery = $query->getQuery();
|
||||
//
|
||||
// // 解析主表名和主表别名,例如:table as t => [table, t]
|
||||
// [$fromTable, $fromAlias] = $this->parseTableAlias((string)($baseQuery->from ?? ''));
|
||||
//
|
||||
// // 如果无法识别主表,直接返回,不处理
|
||||
// if ($fromTable === '') {
|
||||
// return $query;
|
||||
// }
|
||||
//
|
||||
// // 加载该主表对应的启用规则
|
||||
// $rules = $this->loadRules($fromTable);
|
||||
//
|
||||
// // 没有规则则不做任何限制
|
||||
// if (empty($rules)) {
|
||||
// return $query;
|
||||
// }
|
||||
//
|
||||
// // 获取查询里所有表的别名映射,后续用于拼字段
|
||||
// $tableAliases = $this->getAllTableAliases($baseQuery);
|
||||
//
|
||||
// // 逐条应用规则
|
||||
// foreach ($rules as $rule) {
|
||||
// $query = $this->applySingleRule($query, $rule, $fromAlias, $tableAliases);
|
||||
// }
|
||||
//
|
||||
// return $query;
|
||||
// }
|
||||
|
||||
/**
|
||||
* 加载指定表的启用权限规则
|
||||
@@ -131,18 +167,18 @@ class DataPermissionService
|
||||
* 5. 得到完整字段名;
|
||||
* 6. 根据 action 生成 where 条件。
|
||||
*
|
||||
* @param Builder $query 查询对象
|
||||
* @param QueryBuilder|EloquentBuilder $query 查询对象
|
||||
* @param array $rule 单条规则
|
||||
* @param string $mainAlias 主表别名
|
||||
* @param array $tableAliases 查询内所有表别名映射
|
||||
* @return Builder
|
||||
* @return QueryBuilder|EloquentBuilder
|
||||
*/
|
||||
protected function applySingleRule(
|
||||
Builder $query,
|
||||
QueryBuilder|EloquentBuilder $query,
|
||||
array $rule,
|
||||
string $mainAlias,
|
||||
array $tableAliases
|
||||
): Builder
|
||||
): QueryBuilder|EloquentBuilder
|
||||
{
|
||||
$field = trim((string)($rule['field'] ?? ''));
|
||||
$adminAttr = trim((string)($rule['admin_attr'] ?? ''));
|
||||
@@ -197,6 +233,66 @@ class DataPermissionService
|
||||
return $this->buildCondition($query, $fullField, $action, $resolvedValues[0]);
|
||||
}
|
||||
|
||||
// protected function applySingleRule(
|
||||
// Builder $query,
|
||||
// array $rule,
|
||||
// string $mainAlias,
|
||||
// array $tableAliases
|
||||
// ): Builder
|
||||
// {
|
||||
// $field = trim((string)($rule['field'] ?? ''));
|
||||
// $adminAttr = trim((string)($rule['admin_attr'] ?? ''));
|
||||
// $adminAttrMap = trim((string)($rule['admin_attr_map'] ?? ''));
|
||||
// $action = strtolower(trim((string)($rule['action'] ?? 'in')));
|
||||
// $fieldTable = trim((string)($rule['field_table'] ?? ''));
|
||||
//
|
||||
// // 规则字段或管理员属性为空,视为无效规则,直接跳过
|
||||
// if ($field === '' || $adminAttr === '') {
|
||||
// return $query;
|
||||
// }
|
||||
//
|
||||
// // 校验字段写法是否合法
|
||||
// $this->validateFieldPath($field, '规则字段');
|
||||
//
|
||||
// // 如果配置了字段所属表,也要校验
|
||||
// if ($fieldTable !== '') {
|
||||
// $this->validateIdentifierPath($fieldTable, '字段所属表');
|
||||
// }
|
||||
//
|
||||
// // 取管理员对应属性值
|
||||
// $rawValue = $this->admin[$adminAttr] ?? '';
|
||||
//
|
||||
// // * 表示不受限制
|
||||
// if ($rawValue === '*') {
|
||||
// return $query;
|
||||
// }
|
||||
//
|
||||
// // 解析管理员属性值,必要时通过映射转换成目标值
|
||||
// $resolvedValues = $this->resolveAdminAttrValue($rawValue, $adminAttrMap);
|
||||
//
|
||||
// // 如果最终解析不到任何可用值,则直接返回空结果
|
||||
// if (empty($resolvedValues) && !in_array('0', $resolvedValues, true)) {
|
||||
// return $query->whereRaw('1 = 0');
|
||||
// }
|
||||
//
|
||||
// // 获取规则字段的完整字段名,如 dept.id / t.organ_id
|
||||
// $fullField = $this->getFullFieldName($field, $mainAlias, $tableAliases, $fieldTable);
|
||||
//
|
||||
// // in / not in 这类操作符需要数组值
|
||||
// if ($this->isArrayOperator($action)) {
|
||||
// return $this->buildCondition($query, $fullField, $action, $resolvedValues);
|
||||
// }
|
||||
//
|
||||
// // 单值操作符只能对应一个结果,否则说明配置有问题
|
||||
// if (count($resolvedValues) !== 1) {
|
||||
// throw new InvalidArgumentException(
|
||||
// "规则配置错误:操作符 {$action} 只能对应单个值,但当前解析出 " . count($resolvedValues) . " 个值"
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// return $this->buildCondition($query, $fullField, $action, $resolvedValues[0]);
|
||||
// }
|
||||
|
||||
/**
|
||||
* 解析管理员属性值
|
||||
*
|
||||
@@ -293,13 +389,13 @@ class DataPermissionService
|
||||
* 1. 数组型条件:in / not in
|
||||
* 2. 单值条件:= / > / < / like / is null 等
|
||||
*
|
||||
* @param Builder $query 查询对象
|
||||
* @param QueryBuilder|EloquentBuilder $query 查询对象
|
||||
* @param string $field 完整字段名
|
||||
* @param string $action 操作符
|
||||
* @param mixed $value 条件值
|
||||
* @return Builder
|
||||
* @return QueryBuilder|EloquentBuilder
|
||||
*/
|
||||
protected function buildCondition(Builder $query, string $field, string $action, $value): Builder
|
||||
protected function buildCondition(QueryBuilder|EloquentBuilder $query, string $field, string $action, $value): QueryBuilder|EloquentBuilder
|
||||
{
|
||||
// 数组条件
|
||||
if (is_array($value)) {
|
||||
@@ -326,6 +422,33 @@ class DataPermissionService
|
||||
};
|
||||
}
|
||||
|
||||
// protected function buildCondition(Builder $query, string $field, string $action, $value): Builder
|
||||
// {
|
||||
// // 数组条件
|
||||
// if (is_array($value)) {
|
||||
// return match ($action) {
|
||||
// 'in' => $query->whereIn($field, $value),
|
||||
// 'not in', '<>in' => $query->whereNotIn($field, $value),
|
||||
// default => throw new InvalidArgumentException("不支持的数组操作符:{$action}"),
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// // 单值条件
|
||||
// return match ($action) {
|
||||
// '=', 'eq' => $query->where($field, '=', $value),
|
||||
// '>', 'gt' => $query->where($field, '>', $value),
|
||||
// '<', 'lt' => $query->where($field, '<', $value),
|
||||
// '>=', 'gte' => $query->where($field, '>=', $value),
|
||||
// '<=', 'lte' => $query->where($field, '<=', $value),
|
||||
// '<>', '!=', 'ne' => $query->where($field, '<>', $value),
|
||||
// 'like' => $query->where($field, 'like', $this->normalizeLikeValue((string)$value)),
|
||||
// 'not like' => $query->where($field, 'not like', $this->normalizeLikeValue((string)$value)),
|
||||
// 'is null' => $query->whereNull($field),
|
||||
// 'is not null' => $query->whereNotNull($field),
|
||||
// default => throw new InvalidArgumentException("不支持的操作符:{$action}"),
|
||||
// };
|
||||
// }
|
||||
|
||||
/**
|
||||
* 获取完整字段名
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user