69 lines
2.8 KiB
PHP
Executable File
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); }
|
|
}
|
|
}
|
|
}
|