Files
laravel_swoole/app/Services/Auth/PermissionCacheService.php
2026-02-08 22:38:13 +08:00

257 lines
7.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
namespace App\Services\Auth;
use App\Models\Auth\User;
use App\Models\Auth\Role;
use App\Models\Auth\Permission;
use Illuminate\Support\Facades\Cache;
class PermissionCacheService
{
protected $cachePrefix = 'permission:';
protected $cacheMinutes = 60; // 缓存60分钟
/**
* 获取用户的权限列表(带缓存)
*/
public function getUserPermissions(int $userId): array
{
$cacheKey = $this->getUserPermissionsCacheKey($userId);
return Cache::remember($cacheKey, now()->addMinutes($this->cacheMinutes), function() use ($userId) {
$user = User::find($userId);
if (!$user) {
return [];
}
$permissions = [];
foreach ($user->roles as $role) {
foreach ($role->permissions as $permission) {
$permissions[$permission->id] = [
'id' => $permission->id,
'name' => $permission->name,
'code' => $permission->code,
'type' => $permission->type,
'route' => $permission->route,
];
}
}
return array_values($permissions);
});
}
/**
* 获取用户的权限编码列表(带缓存)
*/
public function getUserPermissionCodes(int $userId): array
{
$cacheKey = $this->getUserPermissionCodesCacheKey($userId);
return Cache::remember($cacheKey, now()->addMinutes($this->cacheMinutes), function() use ($userId) {
$permissions = $this->getUserPermissions($userId);
return array_column($permissions, 'code');
});
}
/**
* 获取用户的菜单树(带缓存)
*/
public function getUserMenuTree(int $userId): array
{
$cacheKey = $this->getUserMenuTreeCacheKey($userId);
return Cache::remember($cacheKey, now()->addMinutes($this->cacheMinutes), function() use ($userId) {
$user = User::find($userId);
if (!$user) {
return [];
}
// 获取用户的所有权限ID
$permissionIds = [];
foreach ($user->roles as $role) {
foreach ($role->permissions as $permission) {
$permissionIds[] = $permission->id;
}
}
// 获取菜单类型的权限
$permissions = Permission::whereIn('id', $permissionIds)
->whereIn('type', ['menu', 'api'])
->where('status', 1)
->orderBy('sort', 'asc')
->get();
return $this->buildMenuTree($permissions->toArray());
});
}
/**
* 检查用户是否有某个权限(带缓存)
*/
public function userHasPermission(int $userId, string $permissionCode): bool
{
$codes = $this->getUserPermissionCodes($userId);
return in_array($permissionCode, $codes);
}
/**
* 获取角色的权限列表(带缓存)
*/
public function getRolePermissions(int $roleId): array
{
$cacheKey = $this->getRolePermissionsCacheKey($roleId);
return Cache::remember($cacheKey, now()->addMinutes($this->cacheMinutes), function() use ($roleId) {
$role = Role::find($roleId);
if (!$role) {
return [];
}
return $role->permissions->map(function($permission) {
return [
'id' => $permission->id,
'name' => $permission->name,
'code' => $permission->code,
'type' => $permission->type,
];
})->toArray();
});
}
/**
* 清除用户权限缓存
*/
public function clearUserPermissionCache(int $userId): void
{
Cache::forget($this->getUserPermissionsCacheKey($userId));
Cache::forget($this->getUserPermissionCodesCacheKey($userId));
Cache::forget($this->getUserMenuTreeCacheKey($userId));
}
/**
* 清除角色权限缓存
*/
public function clearRolePermissionCache(int $roleId): void
{
Cache::forget($this->getRolePermissionsCacheKey($roleId));
// 清除所有拥有该角色的用户权限缓存
$role = Role::find($roleId);
if ($role) {
foreach ($role->users as $user) {
$this->clearUserPermissionCache($user->id);
}
}
}
/**
* 清除所有权限缓存
*/
public function clearAllPermissionCache(): void
{
if (Cache::getStore() instanceof \Illuminate\Cache\RedisStore) {
$redis = Cache::getStore()->connection();
$keys = $redis->keys($this->cachePrefix . '*');
if (!empty($keys)) {
$redis->del($keys);
}
}
}
/**
* 清除指定用户的权限缓存(当用户角色变化时调用)
*/
public function onUserRolesChanged(int $userId): void
{
$this->clearUserPermissionCache($userId);
}
/**
* 清除角色的用户缓存(当角色权限变化时调用)
*/
public function onRolePermissionsChanged(int $roleId): void
{
$this->clearRolePermissionCache($roleId);
}
/**
* 清除权限的所有缓存(当权限本身变化时调用)
*/
public function onPermissionChanged(int $permissionId): void
{
// 清除所有缓存,因为权限变化可能影响所有用户
$this->clearAllPermissionCache();
}
/**
* 构建菜单树
*/
protected function buildMenuTree(array $permissions, int $parentId = 0): array
{
$tree = [];
foreach ($permissions as $permission) {
if ($permission['parent_id'] == $parentId) {
$node = [
'id' => $permission['id'],
'name' => $permission['name'],
'code' => $permission['code'],
'type' => $permission['type'],
'route' => $permission['route'],
'component' => $permission['component'],
'meta' => json_decode($permission['meta'] ?? '{}', true),
'sort' => $permission['sort'],
'children' => $this->buildMenuTree($permissions, $permission['id']),
];
// 如果没有子节点移除children字段
if (empty($node['children'])) {
unset($node['children']);
}
$tree[] = $node;
}
}
// 按sort排序
usort($tree, function($a, $b) {
return $a['sort'] <=> $b['sort'];
});
return $tree;
}
/**
* 生成用户权限缓存键
*/
protected function getUserPermissionsCacheKey(int $userId): string
{
return $this->cachePrefix . 'user:' . $userId . ':permissions';
}
/**
* 生成用户权限编码缓存键
*/
protected function getUserPermissionCodesCacheKey(int $userId): string
{
return $this->cachePrefix . 'user:' . $userId . ':permission_codes';
}
/**
* 生成用户菜单树缓存键
*/
protected function getUserMenuTreeCacheKey(int $userId): string
{
return $this->cachePrefix . 'user:' . $userId . ':menu_tree';
}
/**
* 生成角色权限缓存键
*/
protected function getRolePermissionsCacheKey(int $roleId): string
{
return $this->cachePrefix . 'role:' . $roleId . ':permissions';
}
}