Some checks are pending
Main Confidence / confidence (push) Waiting to run
## Summary - add a shared provider target-scope descriptor, normalizer, identity-context metadata, and surface-summary layer - update provider connection list, detail, create, edit, and onboarding surfaces to use neutral target-scope vocabulary while keeping Microsoft identity contextual - align provider connection audit and resolver output with the neutral target-scope contract and add focused guard/unit/feature coverage for regressions ## Validation - browser smoke: opened the tenant-scoped provider connection list, drilled into detail, and verified the edit/create surfaces in local admin context ## Notes - this PR comes from the session branch created for the active feature work - no additional runtime or persistence layer was introduced in this slice Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #274
122 lines
4.0 KiB
PHP
122 lines
4.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Filament\Resources\ProviderConnectionResource\Pages\CreateProviderConnection;
|
|
use App\Models\AuditLog;
|
|
use App\Models\ProviderConnection;
|
|
use App\Models\Tenant;
|
|
use App\Models\User;
|
|
use Filament\Facades\Filament;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Livewire\Livewire;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
it('keeps provider connection identity audit payloads aligned across consent and migration flows', function (): void {
|
|
config()->set('graph.client_id', 'platform-client-id');
|
|
config()->set('graph.client_secret', 'platform-client-secret');
|
|
|
|
$user = User::factory()->create();
|
|
$tenant = Tenant::factory()->create([
|
|
'tenant_id' => 'identity-audit-tenant-id',
|
|
]);
|
|
|
|
[$user, $tenant] = createUserWithTenant(tenant: $tenant, user: $user, role: 'owner', ensureDefaultMicrosoftProviderConnection: false);
|
|
|
|
$response = $this->actingAs($user)->get(route('admin.consent.start', [
|
|
'tenant' => $tenant->external_id,
|
|
]));
|
|
|
|
$response->assertRedirect();
|
|
|
|
$state = session('tenant_onboard_state');
|
|
|
|
$this->get(route('admin.consent.callback', [
|
|
'tenant' => $tenant->tenant_id,
|
|
'state' => $state,
|
|
'admin_consent' => 'True',
|
|
]))->assertSuccessful();
|
|
|
|
$this->artisan('tenantpilot:provider-connections:classify', ['--write' => true])
|
|
->assertSuccessful();
|
|
|
|
$logs = AuditLog::query()
|
|
->where('tenant_id', (int) $tenant->getKey())
|
|
->whereIn('action', [
|
|
'provider_connection.consent_started',
|
|
'provider_connection.consent_result',
|
|
'provider_connection.migration_classification_applied',
|
|
])
|
|
->orderBy('id')
|
|
->get();
|
|
|
|
expect($logs)->toHaveCount(3);
|
|
|
|
foreach ($logs as $log) {
|
|
expect($log->resource_type)->toBe('provider_connection')
|
|
->and($log->resource_id)->not->toBeNull();
|
|
|
|
$metadata = is_array($log->metadata) ? $log->metadata : [];
|
|
|
|
expect($metadata)->toHaveKeys([
|
|
'provider_connection_id',
|
|
'provider',
|
|
'connection_type',
|
|
'source',
|
|
]);
|
|
}
|
|
});
|
|
|
|
it('records provider connection create audits with neutral target-scope metadata', function (): void {
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner', ensureDefaultMicrosoftProviderConnection: false);
|
|
|
|
$this->actingAs($user);
|
|
$tenant->makeCurrent();
|
|
Filament::setTenant($tenant, true);
|
|
|
|
Livewire::actingAs($user)
|
|
->test(CreateProviderConnection::class)
|
|
->fillForm([
|
|
'display_name' => 'Audit target scope connection',
|
|
'entra_tenant_id' => '88888888-8888-8888-8888-888888888888',
|
|
'is_default' => true,
|
|
])
|
|
->call('create')
|
|
->assertHasNoFormErrors();
|
|
|
|
$connection = ProviderConnection::query()
|
|
->where('tenant_id', (int) $tenant->getKey())
|
|
->where('display_name', 'Audit target scope connection')
|
|
->firstOrFail();
|
|
|
|
$log = AuditLog::query()
|
|
->where('tenant_id', (int) $tenant->getKey())
|
|
->where('action', 'provider_connection.created')
|
|
->where('resource_id', (string) $connection->getKey())
|
|
->firstOrFail();
|
|
|
|
$metadata = is_array($log->metadata) ? $log->metadata : [];
|
|
|
|
expect($metadata)->toHaveKeys([
|
|
'provider_connection_id',
|
|
'provider',
|
|
'target_scope',
|
|
'provider_identity_context',
|
|
'connection_type',
|
|
])
|
|
->and($metadata)->not->toHaveKey('entra_tenant_id')
|
|
->and($metadata['target_scope'])->toMatchArray([
|
|
'provider' => 'microsoft',
|
|
'scope_kind' => 'tenant',
|
|
'scope_identifier' => '88888888-8888-8888-8888-888888888888',
|
|
'shared_label' => 'Target scope',
|
|
])
|
|
->and($metadata['provider_identity_context'][0] ?? [])->toMatchArray([
|
|
'provider' => 'microsoft',
|
|
'detail_key' => 'microsoft_tenant_id',
|
|
'detail_label' => 'Microsoft tenant ID',
|
|
'detail_value' => '88888888-8888-8888-8888-888888888888',
|
|
]);
|
|
});
|