guard('jwt')->login($user); } protected function authHeaders(User $user): array { return ['Authorization' => 'Bearer ' . $this->getAuthToken($user)]; } protected function createTestUser(string $role_name, array $overrides = []): User { $role = Role::query()->where('name', $role_name)->firstOrFail(); $suffix = bin2hex(random_bytes(4)); return User::query()->create(array_merge([ 'username' => 'perm_test_' . $suffix, 'email' => 'perm_test_' . $suffix . '@example.com', 'password' => 'Pass_' . $suffix, 'status' => 1, 'role_id' => $role->id, ], $overrides)); } // ========== Step 1: 路由访问检查 ========== public function test_administrator_bypasses_route_check(): void { $user = $this->createTestUser('administrator'); $response = $this->get('/api/v1/users', [], $this->authHeaders($user)); $response->assertStatus(200); $response->assertJsonPath('code', 0); } public function test_non_admin_without_route_group_returns_403(): void { $user = $this->createTestUser('accessor'); // accessor 没有路由组授权,应返回 403 $response = $this->get('/api/v1/users', [], $this->authHeaders($user)); $response->assertStatus(403); } public function test_route_group_authorization_allows_access(): void { $user = $this->createTestUser('developer'); $route = Route::query() ->where('method', 'GET') ->where('path', '/api/v1/users') ->first(); if (!$route) { $this->markTestSkipped('routes 表中无 GET /api/v1/users 路由'); } // 创建路由组并授权 $group = RouteGroup::query()->create([ 'name' => 'test_user_mgmt_' . uniqid(), 'label' => '用户管理测试', ]); $old_group_id = $route->group_id; $route->group_id = $group->id; $route->save(); Db::table('role_route_groups')->insert([ 'role_id' => $user->role_id, 'group_id' => $group->id, ]); $response = $this->get('/api/v1/users', [], $this->authHeaders($user)); $response->assertStatus(200); // 清理 Db::table('role_route_groups') ->where('role_id', $user->role_id) ->where('group_id', $group->id) ->delete(); $route->group_id = $old_group_id; $route->save(); $group->delete(); } public function test_override_allows_access_bypassing_group(): void { $user = $this->createTestUser('accessor'); $route = Route::query() ->where('method', 'GET') ->where('path', '/api/v1/users') ->first(); if (!$route) { $this->markTestSkipped('routes 表中无 GET /api/v1/users 路由'); } // 设置 override 为允许(无需路由组) RoleRouteOverride::query()->create([ 'role_id' => $user->role_id, 'route_id' => $route->id, 'allowed' => true, ]); $response = $this->get('/api/v1/users', [], $this->authHeaders($user)); $response->assertStatus(200); // 清理 RoleRouteOverride::query() ->where('role_id', $user->role_id) ->where('route_id', $route->id) ->delete(); } public function test_override_deny_overrides_group_auth(): void { $user = $this->createTestUser('developer'); $route = Route::query() ->where('method', 'GET') ->where('path', '/api/v1/users') ->first(); if (!$route) { $this->markTestSkipped('routes 表中无 GET /api/v1/users 路由'); } // 先授权路由组 $group = RouteGroup::query()->create([ 'name' => 'test_override_deny_' . uniqid(), 'label' => '覆盖拒绝测试', ]); $old_group_id = $route->group_id; $route->group_id = $group->id; $route->save(); Db::table('role_route_groups')->insert([ 'role_id' => $user->role_id, 'group_id' => $group->id, ]); // 设置 override 为拒绝(优先级高于 group) RoleRouteOverride::query()->create([ 'role_id' => $user->role_id, 'route_id' => $route->id, 'allowed' => false, ]); $response = $this->get('/api/v1/users', [], $this->authHeaders($user)); $response->assertStatus(403); // 清理 RoleRouteOverride::query() ->where('role_id', $user->role_id) ->where('route_id', $route->id) ->delete(); Db::table('role_route_groups') ->where('role_id', $user->role_id) ->where('group_id', $group->id) ->delete(); $route->group_id = $old_group_id; $route->save(); $group->delete(); } // ========== Step 2: 数据范围检查 ========== public function test_user_without_role_returns_403(): void { $suffix = bin2hex(random_bytes(4)); $user = User::query()->create([ 'username' => 'norole_' . $suffix, 'email' => 'norole_' . $suffix . '@example.com', 'password' => 'Pass_' . $suffix, 'status' => 1, 'role_id' => null, ]); $response = $this->get('/api/v1/users', [], $this->authHeaders($user)); $response->assertStatus(403); } public function test_accessor_with_store_scope_and_override(): void { $user = $this->createTestUser('accessor'); $route = Route::query() ->where('method', 'GET') ->where('path', '/api/v1/users') ->first(); if (!$route) { $this->markTestSkipped('routes 表中无 GET /api/v1/users 路由'); } // 授权路由访问 RoleRouteOverride::query()->create([ 'role_id' => $user->role_id, 'route_id' => $route->id, 'allowed' => true, ]); // 添加 store scope $store = Store::query()->first(); if ($store) { UserDataScope::query()->create([ 'user_id' => $user->id, 'scope_type' => 'store', 'scope_id' => $store->id, ]); } $response = $this->get('/api/v1/users', [], $this->authHeaders($user)); $response->assertStatus(200); // 清理 RoleRouteOverride::query() ->where('role_id', $user->role_id) ->where('route_id', $route->id) ->delete(); UserDataScope::query()->where('user_id', $user->id)->delete(); } public function test_administrator_scope_type_is_all(): void { $user = $this->createTestUser('administrator'); // administrator 应有 scope_type='all',可以正常访问 $response = $this->get('/api/v1/users', [], $this->authHeaders($user)); $response->assertStatus(200); $response->assertJsonPath('code', 0); } }