load(); \support\App::loadAllConfig(['route']); use app\miniapi\exception\ApiException; use app\miniapi\model\MiniAudit; use app\miniapi\model\MiniGrant; use app\miniapi\model\MiniUser; use app\miniapi\service\IdentityManagement; use plugin\saiadmin\app\model\water\WaterAgent; use plugin\saiadmin\app\model\water\WaterDriver; use plugin\saiadmin\app\model\water\WaterEnterprise; $checks = 0; function check(bool $ok, string $label): void { global $checks; $checks++; if (!$ok) { throw new RuntimeException($label); } } function reject(callable $action, int $code): void { try { $action(); } catch (ApiException $error) { check($error->getCode() === $code, 'Expected rejection ' . $code . ' got ' . $error->getCode()); return; } throw new RuntimeException('Missing rejection'); } $db = (new MiniUser())->getConnection(); $db->beginTransaction(); $now = date('Y-m-d H:i:s'); $rand = bin2hex(random_bytes(4)); $baseUserId = (int) MiniUser::query()->insertGetId([ 'appid' => 'wechat-app-fixture-' . $rand, 'openid' => 'openid-fixture-' . $rand, 'nickname' => 'identity-test', 'status' => 1, 'created_at' => $now, 'updated_at' => $now, ]); $opId = (int) WaterEnterprise::query()->insertGetId([ 'name' => 'identity-test-' . $rand, 'contact' => 'fixture', 'phone' => '139' . str_pad((string) random_int(0, 99999999), 8, '0', STR_PAD_LEFT), 'region' => '', 'address' => 'fixture', 'agent_id' => 0, 'status' => 1, 'created_at' => $now, 'updated_at' => $now, ]); $driverId = (int) WaterDriver::query()->insertGetId([ 'name' => 'fixture-driver-' . $rand, 'phone' => '138' . str_pad((string) random_int(0, 99999999), 8, '0', STR_PAD_LEFT), 'region' => '', 'vehicle' => '', 'capacity' => 100, 'status' => 1, 'created_at' => $now, 'updated_at' => $now, ]); $agentId = (int) WaterAgent::query()->insertGetId([ 'name' => 'fixture-agent-' . $rand, 'contact' => 'fixture', 'phone' => '137' . str_pad((string) random_int(0, 99999999), 8, '0', STR_PAD_LEFT), 'region' => '', 'address' => '', 'status' => 1, 'created_at' => $now, 'updated_at' => $now, ]); try { $service = new IdentityManagement(); reject(fn () => $service->users(2, []), 40301); reject(fn () => $service->grant(0, []), 40301); reject(fn () => $service->grant(1, [ 'user_id' => $baseUserId, 'role' => 'enterprise_admin', 'resource_id' => 999999, 'status' => 1, ]), 40401); reject(fn () => $service->grant(1, [ 'user_id' => 999999, 'role' => 'enterprise_admin', 'resource_id' => $opId, 'status' => 1, ]), 40401); reject(fn () => $service->grant(1, [ 'user_id' => $baseUserId, 'role' => 'warehouse_keeper', 'resource_id' => $opId, 'status' => 1, ]), 42201); $first = $service->grant(1, [ 'user_id' => $baseUserId, 'role' => 'enterprise_admin', 'resource_id' => $opId, 'status' => 1, ]); check(isset($first['id']) && $first['status'] === 1, 'first grant stored'); check(MiniGrant::query()->where('user_id', $baseUserId)->where('role', 'enterprise_admin')->count() === 1, 'one grant row'); $service->grant(1, [ 'user_id' => $baseUserId, 'role' => 'enterprise_admin', 'resource_id' => $opId, 'status' => 0, ]); check(MiniGrant::query()->where('user_id', $baseUserId)->where('role', 'enterprise_admin')->count() === 1, 'toggling status must not create a new row'); $service->grant(1, [ 'user_id' => $baseUserId, 'role' => 'driver', 'resource_id' => $driverId, 'status' => 1, ]); $service->grant(1, [ 'user_id' => $baseUserId, 'role' => 'agent', 'resource_id' => $agentId, 'status' => 1, ]); check(MiniGrant::query()->where('user_id', $baseUserId)->count() === 3, 'multiple roles coexist'); $list = $service->users(1, ['page' => 1, 'page_size' => 20]); check(is_int($list['total']) && $list['total'] >= 1, 'users list returns total'); $found = false; foreach ($list['items'] as $row) { if ((int) $row['id'] === $baseUserId) { $found = true; break; } } check($found, 'newly inserted user appears in listing'); $auditCount = (int) MiniAudit::query()->where('action', 'identity.grant')->count(); check($auditCount >= 3, 'audit rows written for grant operations'); $users = $service->users(1, ['user_id' => $baseUserId, 'page' => 1, 'page_size' => 5]); check($users['total'] === 1, 'user_id filter narrows list to one'); check(count($users['items'][0]['grants']) === 3, 'grants included in user detail'); } finally { MiniGrant::query()->where('user_id', $baseUserId)->delete(); MiniAudit::query()->where('action', 'identity.grant')->where('created_at', '>=', date('Y-m-d H:i:s', time() - 600))->delete(); if ($agentId) { WaterAgent::query()->where('id', $agentId)->delete(); } if ($driverId) { WaterDriver::query()->where('id', $driverId)->delete(); } if ($opId) { WaterEnterprise::query()->where('id', $opId)->delete(); } if ($baseUserId) { MiniUser::query()->where('id', $baseUserId)->delete(); } $db->rollBack(); } echo 'PASS: ' . $checks . ' identity management checks, database changes rolled back.' . PHP_EOL;