139 lines
4.9 KiB
PHP
139 lines
4.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Filament\Pages\Findings\FindingsIntakeQueue;
|
|
use App\Filament\Resources\FindingResource;
|
|
use App\Models\Finding;
|
|
use App\Models\Tenant;
|
|
use App\Models\User;
|
|
use App\Models\Workspace;
|
|
use App\Models\WorkspaceMembership;
|
|
use App\Support\Workspaces\WorkspaceContext;
|
|
use Livewire\Livewire;
|
|
|
|
it('redirects intake visits without workspace context into the existing workspace chooser flow', function (): void {
|
|
$user = User::factory()->create();
|
|
|
|
$workspaceA = Workspace::factory()->create();
|
|
$workspaceB = Workspace::factory()->create();
|
|
|
|
WorkspaceMembership::factory()->create([
|
|
'workspace_id' => (int) $workspaceA->getKey(),
|
|
'user_id' => (int) $user->getKey(),
|
|
'role' => 'owner',
|
|
]);
|
|
|
|
WorkspaceMembership::factory()->create([
|
|
'workspace_id' => (int) $workspaceB->getKey(),
|
|
'user_id' => (int) $user->getKey(),
|
|
'role' => 'owner',
|
|
]);
|
|
|
|
$this->actingAs($user)
|
|
->get(FindingsIntakeQueue::getUrl(panel: 'admin'))
|
|
->assertRedirect('/admin/choose-workspace');
|
|
});
|
|
|
|
it('returns 404 for users outside the active workspace on the intake route', function (): void {
|
|
$user = User::factory()->create();
|
|
$workspace = Workspace::factory()->create();
|
|
|
|
WorkspaceMembership::factory()->create([
|
|
'workspace_id' => (int) Workspace::factory()->create()->getKey(),
|
|
'user_id' => (int) $user->getKey(),
|
|
'role' => 'owner',
|
|
]);
|
|
|
|
$this->actingAs($user)
|
|
->withSession([WorkspaceContext::SESSION_KEY => (int) $workspace->getKey()])
|
|
->get(FindingsIntakeQueue::getUrl(panel: 'admin'))
|
|
->assertNotFound();
|
|
});
|
|
|
|
it('returns 403 for workspace members with no currently viewable findings scope anywhere', function (): void {
|
|
$user = User::factory()->create();
|
|
$workspace = Workspace::factory()->create();
|
|
|
|
WorkspaceMembership::factory()->create([
|
|
'workspace_id' => (int) $workspace->getKey(),
|
|
'user_id' => (int) $user->getKey(),
|
|
'role' => 'owner',
|
|
]);
|
|
|
|
Tenant::factory()->create([
|
|
'workspace_id' => (int) $workspace->getKey(),
|
|
'status' => 'active',
|
|
]);
|
|
|
|
$this->actingAs($user)
|
|
->withSession([WorkspaceContext::SESSION_KEY => (int) $workspace->getKey()])
|
|
->get(FindingsIntakeQueue::getUrl(panel: 'admin'))
|
|
->assertForbidden();
|
|
});
|
|
|
|
it('suppresses hidden-tenant findings and keeps their detail route not found', function (): void {
|
|
$visibleTenant = Tenant::factory()->create(['status' => 'active']);
|
|
[$user, $visibleTenant] = createUserWithTenant($visibleTenant, role: 'readonly', workspaceRole: 'readonly');
|
|
|
|
$hiddenTenant = Tenant::factory()->create([
|
|
'status' => 'active',
|
|
'workspace_id' => (int) $visibleTenant->workspace_id,
|
|
]);
|
|
|
|
$visibleFinding = Finding::factory()->for($visibleTenant)->create([
|
|
'workspace_id' => (int) $visibleTenant->workspace_id,
|
|
'status' => Finding::STATUS_TRIAGED,
|
|
'assignee_user_id' => null,
|
|
]);
|
|
|
|
$hiddenFinding = Finding::factory()->for($hiddenTenant)->create([
|
|
'workspace_id' => (int) $hiddenTenant->workspace_id,
|
|
'status' => Finding::STATUS_NEW,
|
|
'assignee_user_id' => null,
|
|
]);
|
|
|
|
$this->actingAs($user);
|
|
setAdminPanelContext();
|
|
session()->put(WorkspaceContext::SESSION_KEY, (int) $visibleTenant->workspace_id);
|
|
|
|
Livewire::actingAs($user)
|
|
->test(FindingsIntakeQueue::class)
|
|
->assertCanSeeTableRecords([$visibleFinding])
|
|
->assertCanNotSeeTableRecords([$hiddenFinding]);
|
|
|
|
$this->actingAs($user)
|
|
->withSession([WorkspaceContext::SESSION_KEY => (int) $visibleTenant->workspace_id])
|
|
->get(FindingResource::getUrl('view', ['record' => $hiddenFinding], panel: 'tenant', tenant: $hiddenTenant))
|
|
->assertNotFound();
|
|
});
|
|
|
|
it('keeps inspect access while disabling claim for members without assign capability', function (): void {
|
|
$tenant = Tenant::factory()->create(['status' => 'active']);
|
|
[$user, $tenant] = createUserWithTenant($tenant, role: 'readonly', workspaceRole: 'readonly');
|
|
|
|
$finding = Finding::factory()->for($tenant)->create([
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'status' => Finding::STATUS_NEW,
|
|
'assignee_user_id' => null,
|
|
]);
|
|
|
|
$this->actingAs($user);
|
|
setAdminPanelContext();
|
|
session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id);
|
|
|
|
Livewire::actingAs($user)
|
|
->test(FindingsIntakeQueue::class)
|
|
->assertCanSeeTableRecords([$finding])
|
|
->assertTableActionVisible('claim', $finding)
|
|
->assertTableActionDisabled('claim', $finding)
|
|
->callTableAction('claim', $finding);
|
|
|
|
expect($finding->refresh()->assignee_user_id)->toBeNull();
|
|
|
|
$this->actingAs($user)
|
|
->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
|
|
->get(FindingResource::getUrl('view', ['record' => $finding], panel: 'tenant', tenant: $tenant))
|
|
->assertOk();
|
|
});
|