181 lines
6.6 KiB
PHP
181 lines
6.6 KiB
PHP
<?php
|
||||
|
|
declare(strict_types=1);
|
|||
|
|
/**
|
|||
|
|
*+------------------
|
|||
|
|
* madong
|
|||
|
|
*+------------------
|
|||
|
|
* Copyright (c) https://gitee.com/motion-code All rights reserved.
|
|||
|
|
*+------------------
|
|||
|
|
* Author: Mr. April (405784684@qq.com)
|
|||
|
|
*+------------------
|
|||
|
|
* Official Website: http://www.madong.tech
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
namespace app\service\admin\system;
|
|||
|
|
|
|||
|
|
use app\dao\system\RoleMenuDao;
|
|||
|
|
use core\base\BaseService;
|
|||
|
|
use core\exception\handler\AdminException;
|
|||
|
|
use support\Container;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @method getColumn(int[]|string[] $array, string $string)
|
|||
|
|
*/
|
|||
|
|
class RoleMenuService extends BaseService
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
public function __construct(RoleMenuDao $dao)
|
|||
|
|
{
|
|||
|
|
$this->dao = $dao;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 更新设置角色权限
|
|||
|
|
*
|
|||
|
|
* @param $data
|
|||
|
|
*
|
|||
|
|
* @throws \core\exception\handler\AdminException
|
|||
|
|
*/
|
|||
|
|
// public function save($data): void
|
|||
|
|
// {
|
|||
|
|
// try {
|
|||
|
|
// $this->transaction(function () use ($data) {
|
|||
|
|
// $roleId = $data['role_id'] ?? '';
|
|||
|
|
// $newPermissions = $data['menu_id'] ?? [];
|
|||
|
|
// if (empty($roleId)) {
|
|||
|
|
// throw new AdminException('参数错误缺少role_id', ['errorCode' => -1]);
|
|||
|
|
// }
|
|||
|
|
//
|
|||
|
|
// // 1. 获取角色模型(确保角色存在)
|
|||
|
|
// /** @var SysRoleService $roleService */
|
|||
|
|
// $roleService = Container::make(SysRoleService::class);
|
|||
|
|
// $roleModel = $roleService->get($roleId);
|
|||
|
|
// if (!$roleModel) {
|
|||
|
|
// throw new AdminException('角色不存在', ['errorCode' => -1]);
|
|||
|
|
// }
|
|||
|
|
//
|
|||
|
|
// // 2. 同步 role_menu 关联关系(自动处理新增/删除,无需手动计算差异)
|
|||
|
|
// // 假设 SysRole 模型定义了 roleMenus 关联(hasMany: SysRoleMenu)
|
|||
|
|
// $roleModel->menus()->sync($newPermissions);
|
|||
|
|
//
|
|||
|
|
// // 3. 获取同步后的菜单ID(从关联关系中直接获取,确保数据一致性)
|
|||
|
|
// $syncedMenuIds = $roleModel->menus()->pluck('menu_id')->toArray();
|
|||
|
|
//
|
|||
|
|
// // 4. 构建 Casbin 策略(基于同步后的最新菜单权限)
|
|||
|
|
// $casbinRoleId = PolicyPrefix::ROLE->value . $roleId;
|
|||
|
|
// $domain = '*';
|
|||
|
|
//
|
|||
|
|
// // 4.1 获取菜单详情(用于构建策略)
|
|||
|
|
// /** @var SysMenuService $menuService */
|
|||
|
|
// $menuService = Container::make(SysMenuService::class);
|
|||
|
|
// $menuDetails = $menuService->selectList(['id' => $syncedMenuIds], '*', 0, 0, 'sort', [], true)->toArray();
|
|||
|
|
//
|
|||
|
|
// $incomingPolicies = [];
|
|||
|
|
// foreach ($menuDetails as $menu) {
|
|||
|
|
// if (empty($menu['code'])) continue;
|
|||
|
|
// $incomingPolicies[] = [
|
|||
|
|
// $casbinRoleId, // sub (角色标识)
|
|||
|
|
// $domain, // dom (租户域)
|
|||
|
|
// $menu['code'], // obj (权限码)
|
|||
|
|
// '*', // act (操作类型)
|
|||
|
|
// $menu['methods'], // method (HTTP方法)
|
|||
|
|
// PolicyPrefix::MENU->value . $menu['id'], // trace_id
|
|||
|
|
// ];
|
|||
|
|
// }
|
|||
|
|
//
|
|||
|
|
// // 4.2 更新 Casbin 策略
|
|||
|
|
// $currentCasbinPolicies = Permission::getImplicitResourcesForUser($casbinRoleId, $domain);
|
|||
|
|
// /** @var SysCasbinService $casbinService */
|
|||
|
|
// $casbinService = Container::make(SysCasbinService::class);
|
|||
|
|
// $casbinService->updateCasbinPolicies($currentCasbinPolicies, $incomingPolicies);
|
|||
|
|
//
|
|||
|
|
// });
|
|||
|
|
// } catch (\Throwable $e) {
|
|||
|
|
// throw new AdminException($e->getMessage());
|
|||
|
|
// }
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 更新设置角色权限(含事务封装)
|
|||
|
|
*
|
|||
|
|
* @param $data
|
|||
|
|
*
|
|||
|
|
* @throws \core\exception\handler\AdminException
|
|||
|
|
*/
|
|||
|
|
public function save($data): void
|
|||
|
|
{
|
|||
|
|
try {
|
|||
|
|
$this->transaction(function () use ($data) {
|
|||
|
|
$this->saveWithoutTransaction($data);
|
|||
|
|
});
|
|||
|
|
} catch (\Throwable $e) {
|
|||
|
|
throw new AdminException($e->getMessage());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 无事务版本:核心业务逻辑(供内部/外部事务复用)
|
|||
|
|
*
|
|||
|
|
* @param array $data
|
|||
|
|
*
|
|||
|
|
* @throws \core\exception\handler\AdminException
|
|||
|
|
*/
|
|||
|
|
public function saveWithoutTransaction(array $data): void
|
|||
|
|
{
|
|||
|
|
try {
|
|||
|
|
$roleId = $data['role_id'] ?? '';
|
|||
|
|
$newPermissions = $data['menu_id'] ?? [];
|
|||
|
|
if (empty($roleId)) {
|
|||
|
|
throw new AdminException('参数错误缺少role_id');
|
|||
|
|
}
|
|||
|
|
// 1. 获取角色模型(确保角色存在)
|
|||
|
|
/** @var RoleService $roleService */
|
|||
|
|
$roleService = Container::make(RoleService::class);
|
|||
|
|
$roleModel = $roleService->get($roleId);
|
|||
|
|
if (!$roleModel) {
|
|||
|
|
throw new AdminException('角色不存在');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2. 同步 role_menu 关联关系(自动处理新增/删除,无需手动计算差异)
|
|||
|
|
$roleModel->menus()->sync($newPermissions);
|
|||
|
|
|
|||
|
|
// 3. 清理相关用户的权限缓存
|
|||
|
|
$this->clearUserPermissionCacheByRole($roleId);
|
|||
|
|
|
|||
|
|
} catch (\Throwable $e) {
|
|||
|
|
throw new AdminException($e->getMessage());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 清理拥有此角色的用户的权限缓存
|
|||
|
|
*
|
|||
|
|
* @param string|int $roleId 角色ID
|
|||
|
|
*/
|
|||
|
|
private function clearUserPermissionCacheByRole(string|int $roleId): void
|
|||
|
|
{
|
|||
|
|
try {
|
|||
|
|
// 获取拥有此角色的所有用户
|
|||
|
|
/** @var \app\service\admin\system\AdminRoleService $adminRoleService */
|
|||
|
|
$adminRoleService = Container::make(\app\service\admin\system\AdminRoleService::class);
|
|||
|
|
|
|||
|
|
// 获取拥有此角色的用户ID列表
|
|||
|
|
$userIds = \app\model\system\AdminRole::where('role_id', $roleId)
|
|||
|
|
->pluck('admin_id')
|
|||
|
|
->toArray();
|
|||
|
|
|
|||
|
|
if (!empty($userIds)) {
|
|||
|
|
// 清理这些用户的权限缓存
|
|||
|
|
$currentUser = Container::make(\app\adminapi\CurrentUser::class);
|
|||
|
|
foreach ($userIds as $userId) {
|
|||
|
|
$currentUser->clearCache($userId);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} catch (\Throwable $e) {
|
|||
|
|
// 缓存清理失败不影响主要业务,记录日志即可
|
|||
|
|
\core\logger\Logger::error("清理角色{$roleId}的用户权限缓存失败: " . $e->getMessage());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|