Files
datahub/backend/app/Service/ScopeTableManager.php
2026-03-09 14:15:29 +08:00

100 lines
2.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Service;
use App\Model\User;
use Swoole\Table;
class ScopeTableManager
{
protected Table $table;
public function __construct(protected ScopeBitmapService $bitmapService)
{
$this->initTable();
}
/**
* 初始化 Swoole\Table
*/
protected function initTable(): void
{
$this->table = new Table(1024);
$this->table->column('role', Table::TYPE_STRING, 32);
$this->table->column('scope', Table::TYPE_STRING, 4096);
$this->table->column('version', Table::TYPE_INT, 8);
$this->table->create();
}
public function getTable(): Table
{
return $this->table;
}
/**
* 获取用户 scope 数据,未命中时懒加载
*
* @param int $user_id
* @return array{role: string, scope: string, version: int}|null
*/
public function getUserScope(int $user_id): ?array
{
$key = (string) $user_id;
$row = $this->table->get($key);
if ($row !== false) {
return $row;
}
// Table 未命中,从数据库加载
return $this->rebuildUserScope($user_id);
}
/**
* 重建用户 scope 并写入 Table
*
* @param int $user_id
* @return array{role: string, scope: string, version: int}|null
*/
public function rebuildUserScope(int $user_id): ?array
{
$user = User::query()->with('role')->find($user_id);
if (!$user || !$user->role) {
return null;
}
$role_name = $user->role->name;
// administrator 不需要 bitmap
if ($role_name === 'administrator') {
$bitmap = '';
} elseif ($role_name === 'developer') {
$bitmap = $this->bitmapService->buildForDeveloper($user_id);
} else {
$bitmap = $this->bitmapService->buildForUser($user_id);
}
$data = [
'role' => $role_name,
'scope' => $bitmap,
'version' => time(),
];
$this->table->set((string) $user_id, $data);
return $data;
}
/**
* 清除用户 scope(权限变更时先清再重建)
*
* @param int $user_id
* @return void
*/
public function invalidateUser(int $user_id): void
{
$this->table->del((string) $user_id);
}
}