Files
zyt/server/app/adminapi/service/AdminAccessSyncService.php
2026-11-06 13:37:12 +08:00

69 lines
2.8 KiB
PHP
Executable File

<?php
declare(strict_types=1);
namespace app\adminapi\service;
use app\common\cache\AdminAuthCache;
use app\common\cache\AdminTokenCache;
use app\common\model\auth\Admin;
use app\common\model\auth\AdminRole;
use app\common\model\auth\AdminSession;
use app\common\model\auth\SystemMenu;
use app\common\model\auth\SystemRoleMenu;
use think\facade\Log;
/** 原账号变更:事务内锁账号并撤销会话,提交成功后才清缓存。 */
final class AdminAccessSyncService
{
public static function ids(array $ids): array
{
$ids = array_values(array_unique(array_filter(array_map('intval', $ids), static fn (int $id): bool => $id > 0)));
sort($ids, SORT_NUMERIC);
return $ids;
}
public static function roleAdminIds(array $roleIds): array
{
return $roleIds === [] ? [] : self::ids(AdminRole::whereIn('role_id', $roleIds)->column('admin_id'));
}
/** 菜单父节点变更也影响只获授子节点的账号。 */
public static function menuAdminIds(int $menuId): array
{
$menuIds = [$menuId];
$rows = SystemMenu::field('id,pid')->select()->toArray();
do {
$count = count($menuIds);
foreach ($rows as $row) {
if (in_array((int) $row['pid'], $menuIds, true)) { $menuIds[] = (int) $row['id']; }
}
$menuIds = self::ids($menuIds);
} while (count($menuIds) !== $count);
return self::roleAdminIds(self::ids(SystemRoleMenu::whereIn('menu_id', $menuIds)->column('role_id')));
}
/** 调用者必须已开启事务;与密码登录、SSO签发和续期共用账号锁。 */
public static function revoke(array $adminIds): array
{
$adminIds = self::ids($adminIds);
if ($adminIds === []) { return []; }
Admin::whereIn('id', $adminIds)->order('id')->lock(true)->field('id')->select();
$tokens = AdminSession::whereIn('admin_id', $adminIds)->column('token');
AdminSession::whereIn('admin_id', $adminIds)->update(['expire_time' => time() - 1, 'update_time' => time()]);
return $tokens;
}
public static function clearCommitted(array $adminIds, array $tokens): void
{
// DB是有效性的准绳;缓存故障不能把已提交操作伪报失败,也不能恢复旧会话。
foreach ($tokens as $token) {
try { (new AdminTokenCache())->deleteAdminInfo((string) $token); }
catch (\Throwable $error) { Log::warning('账号变更已提交,会话缓存清理失败'); }
}
foreach (self::ids($adminIds) as $adminId) {
try { (new AdminAuthCache($adminId))->clearAuthCache(); }
catch (\Throwable $error) { Log::warning('账号变更已提交,权限缓存清理失败:admin_id=' . $adminId); }
}
}
}