WaterEnterprise::class, 'enterprise_member' => WaterEnterprise::class, 'driver' => WaterDriver::class, 'agent' => WaterAgent::class, ]; public static function roles(): array { return array_keys(self::ROLE_MODELS); } public static function resourceModel(string $role): ?string { return self::ROLE_MODELS[$role] ?? null; } public function __construct(public readonly Principal $actor) { } private function grants() { if (!MiniUser::query()->where('id', $this->actor->userId)->where('status', 1)->exists()) { throw new ApiException(40101, '登录状态已失效', 401); } return MiniGrant::query()->where('user_id', $this->actor->userId)->where('status', 1); } public function identities(): array { $rows = []; foreach ($this->grants()->orderBy('id')->get() as $grant) { $model = self::resourceModel($grant->role); if (!$model) { continue; } $resource = $model::query()->where('id', $grant->resource_id)->where('status', 1)->first(); if ($resource) { $rows[] = [ 'role' => $grant->role, 'resource_id' => (int) $resource->id, 'name' => $resource->name, ]; } } if (count($rows) > 1) { throw new ApiException(40903, '账号绑定了多个业务身份,请联系管理员处理', 409); } return $rows; } public function enterprise(int $id, bool $write = false): WaterEnterprise { $roles = $write ? ['enterprise_admin'] : ['enterprise_admin', 'enterprise_member']; if (!$this->grants()->whereIn('role', $roles)->where('resource_id', $id)->exists()) { $this->deny(); } $row = WaterEnterprise::query()->where('id', $id)->where('status', 1)->first(); if (!$row) { $this->deny(); } return $row; } public function isEnterpriseAdmin(int $id): bool { return $this->grants()->where([ 'role' => 'enterprise_admin', 'resource_id' => $id, ])->exists(); } public function resource(string $role, int $id) { if (!in_array($role, ['driver', 'agent'], true) || !$this->grants()->where([ 'role' => $role, 'resource_id' => $id, ])->exists()) { $this->deny(); } $model = self::resourceModel($role); $row = $model::query()->where('id', $id)->where('status', 1)->first(); if (!$row) { $this->deny(); } return $row; } public function driverTask(int $driver, int $task): WaterDelivery { $this->resource('driver', $driver); $row = WaterDelivery::query()->where('id', $task)->where('driver_id', $driver)->first(); if (!$row) { throw new ApiException(40401, '配送任务不存在', 404); } return $row; } public function enterpriseTask(int $enterprise, int $task): WaterDelivery { $this->enterprise($enterprise); $row = WaterDelivery::query()->where('id', $task)->where('enterprise_id', $enterprise)->first(); if (!$row) { throw new ApiException(40401, '配送任务不存在', 404); } return $row; } public function agentIds(int $id): array { $this->resource('agent', $id); $ids = [$id]; $frontier = [$id]; // Existing hierarchy is limited to three levels. Refuse malformed cycles rather than widening scope. for ($depth = 0;$depth < 3 && $frontier;$depth++) { $next = WaterAgent::query()->whereIn('parent_id', $frontier)->where('status', 1)->pluck('id')->map(fn ($v) => (int) $v)->all(); if (array_intersect($next, $ids) || ($depth === 2 && $next)) { throw new ApiException(40903, '代理关系异常,请联系管理员', 409); } $ids = array_merge($ids, $next); $frontier = $next; } return $ids; } private function deny(): never { throw new ApiException(40301, '无权访问该业务身份或资源已停用', 403); } }