Files
webman-buildadmin-mall/extend/ba/Auth.php

188 lines
5.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace ba;
use Throwable;
use support\think\Db;
/**
* 权限规则类Webman 迁移版)
*/
class Auth
{
protected array $config = [
'auth_group' => 'admin_group',
'auth_group_access' => 'admin_group_access',
'auth_rule' => 'admin_rule',
];
protected array $children = [];
public function __construct(array $config = [])
{
$this->config = array_merge($this->config, $config);
}
public function __get($name): mixed
{
return $this->config[$name] ?? null;
}
public function getMenus(int $uid): array
{
$this->children = [];
$originAuthRules = $this->getOriginAuthRules($uid);
foreach ($originAuthRules as $rule) {
$this->children[$rule['pid']][] = $rule;
}
if (!isset($this->children[0])) {
return [];
}
return $this->getChildren($this->children[0]);
}
private function getChildren(array $rules): array
{
foreach ($rules as $key => $rule) {
if (array_key_exists($rule['id'], $this->children)) {
$rules[$key]['children'] = $this->getChildren($this->children[$rule['id']]);
}
}
return $rules;
}
public function check(string $name, int $uid, string $relation = 'or', string $mode = 'url'): bool
{
$ruleList = $this->getRuleList($uid);
if (in_array('*', $ruleList)) {
return true;
}
if ($name) {
$name = strtolower($name);
$name = str_contains($name, ',') ? explode(',', $name) : [$name];
}
$list = [];
$requestParams = [];
if ($mode === 'url' && function_exists('request')) {
$req = request();
$requestParams = $req ? array_merge($req->get(), $req->post()) : [];
$requestParams = json_decode(strtolower(json_encode($requestParams, JSON_UNESCAPED_UNICODE)), true) ?? [];
}
foreach ($ruleList as $rule) {
$query = preg_replace('/^.+\?/U', '', $rule);
if ($mode === 'url' && $query !== $rule) {
parse_str($query, $param);
$intersect = array_intersect_assoc($requestParams, $param);
$rule = preg_replace('/\?.*$/U', '', $rule);
if (in_array($rule, $name) && $intersect == $param) {
$list[] = $rule;
}
} elseif (in_array($rule, $name)) {
$list[] = $rule;
} else {
// 仅勾选父级菜单(如 auth/admin允许访问子路径auth/admin/index、add 等)
$baseRule = preg_replace('/\?.*$/U', '', $rule);
foreach ((array) $name as $n) {
if ($baseRule !== '' && str_starts_with((string) $n, $baseRule . '/')) {
$list[] = $rule;
break;
}
}
}
}
if ($relation === 'or' && !empty($list)) {
return true;
}
$diff = array_diff($name, $list);
if ($relation === 'and' && empty($diff)) {
return true;
}
return false;
}
public function getRuleList(int $uid): array
{
$ids = $this->getRuleIds($uid);
if (empty($ids)) {
return [];
}
$originAuthRules = $this->getOriginAuthRules($uid);
$rules = [];
if (in_array('*', $ids)) {
$rules[] = '*';
}
foreach ($originAuthRules as $rule) {
$rules[$rule['id']] = strtolower($rule['name']);
}
return array_unique($rules);
}
public function getOriginAuthRules(int $uid): array
{
$ids = $this->getRuleIds($uid);
if (empty($ids)) {
return [];
}
$where = [['status', '=', '1']];
if (!in_array('*', $ids)) {
$where[] = ['id', 'in', $ids];
}
$rules = Db::name($this->config['auth_rule'])
->withoutField(['remark', 'status', 'weigh', 'update_time', 'create_time'])
->where($where)
->order('weigh desc,id asc')
->select()
->toArray();
foreach ($rules as $key => $rule) {
if (!empty($rule['keepalive'])) {
$rules[$key]['keepalive'] = $rule['name'];
}
}
return $rules;
}
public function getRuleIds(int $uid): array
{
$groups = $this->getGroups($uid);
$ids = [];
foreach ($groups as $g) {
$ids = array_merge($ids, explode(',', trim($g['rules'] ?? '', ',')));
}
return array_unique($ids);
}
public function getGroups(int $uid): array
{
$dbName = $this->config['auth_group_access'] ?: 'user';
if ($this->config['auth_group_access']) {
$userGroups = Db::name($dbName)
->alias('aga')
->join($this->config['auth_group'] . ' ag', 'aga.group_id = ag.id', 'LEFT')
->field('aga.uid,aga.group_id,ag.id,ag.pid,ag.name,ag.rules')
->where("aga.uid='$uid' and ag.status='1'")
->select()
->toArray();
} else {
$userGroups = Db::name($dbName)
->alias('u')
->join($this->config['auth_group'] . ' ag', 'u.group_id = ag.id', 'LEFT')
->field('u.id as uid,u.group_id,ag.id,ag.name,ag.rules')
->where("u.id='$uid' and ag.status='1'")
->select()
->toArray();
}
return $userGroups;
}
}