124 lines
4.5 KiB
PHP
124 lines
4.5 KiB
PHP
<?php
|
|
|
|
use App\Models\BackupItem;
|
|
use App\Models\BackupSchedule;
|
|
use App\Models\BackupSet;
|
|
use App\Models\EntraGroup;
|
|
use App\Models\EntraRoleDefinition;
|
|
use App\Models\Finding;
|
|
use App\Models\InventoryItem;
|
|
use App\Models\InventoryLink;
|
|
use App\Models\Policy;
|
|
use App\Models\PolicyVersion;
|
|
use App\Models\RestoreRun;
|
|
use App\Models\Tenant;
|
|
use App\Models\TenantPermission;
|
|
use App\Models\Workspace;
|
|
use App\Support\WorkspaceIsolation\WorkspaceIsolationViolation;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
it('enforces tenant workspace binding for tenant-owned models even when events are disabled', function (): void {
|
|
$workspaceA = Workspace::factory()->create();
|
|
$workspaceB = Workspace::factory()->create();
|
|
|
|
$tenant = Tenant::factory()->create([
|
|
'workspace_id' => $workspaceA->getKey(),
|
|
]);
|
|
|
|
$policy = Policy::factory()->create([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'workspace_id' => $workspaceA->getKey(),
|
|
]);
|
|
|
|
$backupSet = BackupSet::factory()->create([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'workspace_id' => $workspaceA->getKey(),
|
|
]);
|
|
|
|
$cases = [
|
|
'policies' => fn (int $workspaceId) => Policy::factory()->make([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'workspace_id' => $workspaceId,
|
|
]),
|
|
'policy_versions' => fn (int $workspaceId) => PolicyVersion::factory()->make([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'workspace_id' => $workspaceId,
|
|
'policy_id' => $policy->getKey(),
|
|
]),
|
|
'backup_sets' => fn (int $workspaceId) => BackupSet::factory()->make([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'workspace_id' => $workspaceId,
|
|
]),
|
|
'backup_items' => fn (int $workspaceId) => BackupItem::factory()->make([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'workspace_id' => $workspaceId,
|
|
'backup_set_id' => $backupSet->getKey(),
|
|
'policy_id' => $policy->getKey(),
|
|
]),
|
|
'restore_runs' => fn (int $workspaceId) => RestoreRun::factory()->make([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'workspace_id' => $workspaceId,
|
|
'backup_set_id' => $backupSet->getKey(),
|
|
]),
|
|
'backup_schedules' => fn (int $workspaceId) => BackupSchedule::make([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'workspace_id' => $workspaceId,
|
|
'name' => 'Weekly backup',
|
|
'is_enabled' => true,
|
|
'timezone' => 'UTC',
|
|
'frequency' => 'daily',
|
|
'time_of_day' => '00:00:00',
|
|
'days_of_week' => null,
|
|
'policy_types' => ['settingsCatalogPolicy'],
|
|
'include_foundations' => true,
|
|
'retention_keep_last' => 30,
|
|
]),
|
|
'inventory_items' => fn (int $workspaceId) => InventoryItem::factory()->make([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'workspace_id' => $workspaceId,
|
|
]),
|
|
'inventory_links' => fn (int $workspaceId) => InventoryLink::factory()->make([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'workspace_id' => $workspaceId,
|
|
]),
|
|
'entra_groups' => fn (int $workspaceId) => EntraGroup::factory()->make([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'workspace_id' => $workspaceId,
|
|
]),
|
|
'findings' => fn (int $workspaceId) => Finding::factory()->make([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'workspace_id' => $workspaceId,
|
|
]),
|
|
'entra_role_definitions' => fn (int $workspaceId) => EntraRoleDefinition::factory()->make([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'workspace_id' => $workspaceId,
|
|
]),
|
|
'tenant_permissions' => fn (int $workspaceId) => TenantPermission::make([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'workspace_id' => $workspaceId,
|
|
'permission_key' => 'test.permission.'.uniqid(),
|
|
'status' => 'missing',
|
|
]),
|
|
];
|
|
|
|
foreach ($cases as $table => $makeModel) {
|
|
$model = $makeModel((int) $workspaceA->getKey());
|
|
|
|
($model::class)::withoutEvents(function () use ($model): void {
|
|
$model->save();
|
|
});
|
|
|
|
$this->assertDatabaseHas($table, [
|
|
'tenant_id' => $tenant->getKey(),
|
|
'workspace_id' => $workspaceA->getKey(),
|
|
]);
|
|
|
|
$mismatched = $makeModel((int) $workspaceB->getKey());
|
|
|
|
expect(fn () => $mismatched->save())
|
|
->toThrow(WorkspaceIsolationViolation::class);
|
|
}
|
|
});
|