This commit is contained in:
2025-08-13 18:31:52 +08:00
parent 17ad88608b
commit 275713f893
77 changed files with 10658 additions and 178 deletions

316
extend/ba/Auth.php Normal file
View File

@@ -0,0 +1,316 @@
<?php
namespace ba;
use app\common\library\DatabaseRoute;
use Throwable;
use think\facade\Db;
/**
* 权限规则类
*/
class Auth
{
/**
* 默认配置
* @var array|string[]
*/
protected array $config = [
'auth_group' => 'admin_group', // 用户组数据表名
'auth_group_access' => 'admin_group_access', // 用户-用户组关系表
'auth_rule' => 'admin_rule', // 权限规则表
];
protected object $db;
/**
* 子菜单规则数组
* @var array
*/
protected array $children = [];
/**
* 构造方法
* @param array $config
*/
public function __construct(array $config = [])
{
$this->config = array_merge($this->config, $config);
$this->db = Db::connect(config('database.search_library'));
}
/**
* 魔术方法-获取当前配置
* @param $name
* @return mixed
*/
public function __get($name): mixed
{
return $this->config[$name];
}
/**
* 获取菜单规则列表
* @access public
* @param int $uid 用户ID
* @return array
* @throws Throwable
*/
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]);
}
/**
* 获取传递的菜单规则的子规则
* @param array $rules 菜单规则
* @return array
*/
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;
}
/**
* 检查是否有某权限
* @param string $name 菜单规则的 name可以传递两个以','号隔开
* @param int $uid 用户ID
* @param string $relation 如果出现两个 name,是两个都通过(and)还是一个通过即可(or)
* @param string $mode 如果不使用 url 则菜单规则name匹配到即通过
* @return bool
* @throws Throwable
*/
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);
if (str_contains($name, ',')) {
$name = explode(',', $name);
} else {
$name = [$name];
}
}
$list = []; //保存验证通过的规则名
if ('url' == $mode) {
$REQUEST = json_decode(strtolower(json_encode(request()->param(), JSON_UNESCAPED_UNICODE)), true);
}
foreach ($ruleList as $rule) {
$query = preg_replace('/^.+\?/U', '', $rule);
if ('url' == $mode && $query != $rule) {
parse_str($query, $param); //解析规则中的param
$intersect = array_intersect_assoc($REQUEST, $param);
$rule = preg_replace('/\?.*$/U', '', $rule);
if (in_array($rule, $name) && $intersect == $param) {
// 如果节点相符且url参数满足
$list[] = $rule;
}
} elseif (in_array($rule, $name)) {
$list[] = $rule;
}
}
if ('or' == $relation && !empty($list)) {
return true;
}
$diff = array_diff($name, $list);
if ('and' == $relation && empty($diff)) {
return true;
}
return false;
}
/**
* 获得权限规则列表
* @param int $uid 用户id
* @return array
* @throws Throwable
*/
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);
}
/**
* 获得权限规则原始数据
* @param int $uid 用户id
* @return array
* @throws Throwable
*/
public function getOriginAuthRules(int $uid): array
{
$ids = $this->getRuleIds($uid);
if (empty($ids)) return [];
$where = [];
$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;
}
/**
* 获取权限规则ids
* @param int $uid
* @return array
* @throws Throwable
*/
public function getRuleIds(int $uid): array
{
// 用户的组别和规则ID
$groups = $this->getGroups($uid);
$ids = [];
foreach ($groups as $g) {
$ids = array_merge($ids, explode(',', trim($g['rules'], ',')));
}
return array_unique($ids);
}
/**
* 获取用户所有分组和对应权限规则
* @param int $uid
* @return array
* @throws Throwable
*/
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;
}
/**
* 获取角色系统规则
* @param 角色
*/
public function getMenu($role):array
{
$role_menu = $this->db->name('sys_role_menu')->where('role_id', $role['role_id'])->field('menu_id')->select()->toArray();
$ids = [];
foreach ($role_menu as $k => $v) {
$ids[] = $v['menu_id'];
}
return $this->db->name('sys_menu')->whereIn('menu_id', $ids)->select()->toArray();
}
/**
* 获取用户角色
* @return void
*/
public function getUserRole($uid):array
{
return $this->db->name('sys_user_role')->where('user_id', $uid)->find();
}
/**
* 获取用户所有菜单
*/
public function getUserMenus($uid):array
{
return $this->getMenu($this->getUserRole($uid));
}
/**
* 验证权限
* @return void
*/
public function checkMenus($url, $uid):bool
{
$menus = $this->getUserMenus($uid);
$file = root_path() . '/jsondata/peion.json';
// 检查数组
$par_info = get_file_info($file);
$par_info = json_decode($par_info, true);
// 超管拥有全部权限
if($uid == 1) {
return true;
}
foreach ($par_info as $k => $v) {
if(!empty($v['peion']) && strpos($url, $v['peion']) !== false) {
if($v['url'] == '*') {
return true;
}
foreach ($menus as $mk => $mv) {
if($mv['url'] == $v['url'] || $mv['perms'] == $v['url']) {
return true;
}
}
}
}
return false;
}
}