120 lines
4.4 KiB
PHP
120 lines
4.4 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Permissions;
|
|
|
|
use App\Actions\Permissions\PermissionService;
|
|
use App\Enums\Permission;
|
|
use App\Models\Project;
|
|
use App\Models\Team;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Tests\TestCase;
|
|
|
|
class PermissionServiceTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
/**
|
|
* Ensure direct project permissions expand through the configured hierarchy.
|
|
*/
|
|
public function test_direct_project_permissions_expand_through_hierarchy(): void
|
|
{
|
|
$service = app(PermissionService::class);
|
|
$user = User::factory()->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));
|
|
}
|
|
}
|