create(); $this->actingAs($user); expect(TenantResource::canCreate())->toBeFalse(); }); it('cannot be created via CRUD (onboarding wizard is the only path)', function () { [$user] = createUserWithTenant(role: 'manager'); $this->actingAs($user); expect(TenantResource::canCreate())->toBeFalse(); }); it('can be edited by managers (TENANT_MANAGE)', function () { [$user, $tenant] = createUserWithTenant(role: 'manager'); $this->actingAs($user); expect(TenantResource::canEdit($tenant))->toBeTrue(); }); it('cannot be deleted by managers (TENANT_DELETE)', function () { [$user, $tenant] = createUserWithTenant(role: 'manager'); $this->actingAs($user); expect(TenantResource::canDelete($tenant))->toBeFalse(); }); it('can be deleted by owners (TENANT_DELETE)', function () { [$user, $tenant] = createUserWithTenant(role: 'owner'); $this->actingAs($user); expect(TenantResource::canDelete($tenant))->toBeTrue(); }); it('cannot edit tenants it cannot access', function () { [$user] = createUserWithTenant(role: 'manager'); $otherTenant = Tenant::factory()->create(); $this->actingAs($user); expect(TenantResource::canEdit($otherTenant))->toBeFalse(); }); it('does not grant lifecycle mutation abilities for inaccessible tenants regardless of lifecycle state', function (\Closure $tenantFactory): void { [$user] = createUserWithTenant(role: 'owner', ensureDefaultMicrosoftProviderConnection: false); $otherTenant = $tenantFactory(); $this->actingAs($user); expect(TenantResource::canEdit($otherTenant))->toBeFalse() ->and(TenantResource::canDelete($otherTenant))->toBeFalse(); })->with([ 'draft' => [fn (): Tenant => Tenant::factory()->draft()->create()], 'onboarding' => [fn (): Tenant => Tenant::factory()->onboarding()->create()], 'active' => [fn (): Tenant => Tenant::factory()->active()->create()], 'archived' => [fn (): Tenant => Tenant::factory()->archived()->create()], ]); it('keeps onboarding and archived tenants manageable when the actor is entitled', function () { $onboardingTenant = Tenant::factory()->onboarding()->create(); [$user, $onboardingTenant] = createUserWithTenant( tenant: $onboardingTenant, role: 'manager', ensureDefaultMicrosoftProviderConnection: false, ); $archivedTenant = Tenant::factory()->archived()->create([ 'workspace_id' => (int) $onboardingTenant->workspace_id, ]); createUserWithTenant( tenant: $archivedTenant, user: $user, role: 'manager', workspaceRole: 'manager', ensureDefaultMicrosoftProviderConnection: false, ); $archivedTenant = Tenant::withTrashed()->findOrFail((int) $archivedTenant->getKey()); $this->actingAs($user); expect(TenantResource::canEdit($onboardingTenant))->toBeTrue() ->and(TenantResource::canEdit($archivedTenant))->toBeTrue() ->and(TenantResource::canDelete($onboardingTenant))->toBeFalse() ->and(TenantResource::canDelete($archivedTenant))->toBeFalse(); }); });