create(); $project = Project::factory()->create(); $service->sync($user, $project, [Permission::ProjectWrite]); $this->assertTrue($service->allows($user, Permission::ProjectRead, $project)); $this->assertTrue($service->allows($user, Permission::ProjectWrite, $project)); $this->assertFalse($service->allows($user, Permission::ProjectAdmin, $project)); } /** * Ensure project permissions assigned to teams are inherited by team members. */ public function test_team_project_permissions_are_inherited_by_members(): void { $service = app(PermissionService::class); $user = User::factory()->create(); $team = Team::factory()->create(); $project = Project::factory()->create(); $team->users()->attach($user); $service->sync($team, $project, [Permission::ProjectRead]); $this->assertTrue($service->allows($user, Permission::ProjectRead, $project)); } /** * Ensure user and team permissions are combined instead of one replacing the other. */ public function test_direct_user_permissions_are_combined_with_inherited_team_permissions(): void { $service = app(PermissionService::class); $user = User::factory()->create(); $team = Team::factory()->create(); $project = Project::factory()->create(); $team->users()->attach($user); $service->sync($team, $project, [Permission::ProjectWrite]); $service->sync($user, $project, [Permission::ProjectRead]); $this->assertTrue($service->allows($user, Permission::ProjectWrite, $project)); $this->assertTrue($service->allows($user, Permission::ProjectRead, $project)); } /** * Ensure team-scoped permissions are granted directly to users and do not come from membership alone. */ public function test_team_permissions_only_apply_when_directly_assigned_to_the_user(): void { $service = app(PermissionService::class); $manager = User::factory()->create(); $member = User::factory()->create(); $team = Team::factory()->create(); $team->users()->attach([$manager->id, $member->id]); $service->sync($manager, $team, [Permission::TeamManage]); $this->assertTrue($service->allows($manager, Permission::TeamManage, $team)); $this->assertFalse($service->allows($member, Permission::TeamManage, $team)); } /** * Ensure global admins can perform global, project, and team-scoped actions. */ public function test_global_admin_overrides_every_scope(): void { $service = app(PermissionService::class); $admin = User::factory()->create(); $project = Project::factory()->create(); $team = Team::factory()->create(); $service->sync($admin, null, [Permission::GlobalAdmin]); $this->assertTrue($service->allows($admin, Permission::ProjectCreate)); $this->assertTrue($service->allows($admin, Permission::ProjectAdmin, $project)); $this->assertTrue($service->allows($admin, Permission::TeamManage, $team)); } /** * Ensure the service can surface accessible project ids and manageable team ids. */ public function test_scope_lookup_helpers_return_expected_ids(): void { $service = app(PermissionService::class); $user = User::factory()->create(); $team = Team::factory()->create(); $project = Project::factory()->create(); $team->users()->attach($user); $service->sync($team, $project, [Permission::ProjectRead]); $service->sync($user, $team, [Permission::TeamManage]); $this->assertSame([$project->id], $service->viewableProjectIds($user)); $this->assertSame([$team->id], $service->manageableTeamIds($user)); $this->assertTrue($service->canManageAnyTeam($user)); } }