CluPilotCloud/tests/Feature/Security/SecurityConsoleTest.php

130 lines
5.5 KiB
PHP

<?php
use App\Livewire\Admin\ConfirmReleaseBlock;
use App\Livewire\Admin\CustomerDetail;
use App\Livewire\Admin\HostDetail;
use App\Livewire\Admin\Overview;
use App\Models\Customer;
use App\Models\Host;
use App\Models\Instance;
use App\Models\Operator;
use App\Models\SecurityBlock;
use Livewire\Livewire;
use Spatie\Permission\Models\Role;
/**
* Task 6, Schritt 4: dieselben Sperr-Zeilen in der Konsole, hinter der
* jeweiligen Berechtigung — hosts.manage auf der Host-Detailseite,
* instances.manage auf der Kundenseite (Instanz eines Kunden). Beide teilen
* sich EIN Modal (App\Livewire\Admin\ConfirmReleaseBlock), das nach dem
* Subjekt der Sperre autorisiert.
*/
it('zeigt einem Betreiber mit hosts.manage die Sperre eines Hosts und laesst ihn sie aufheben', function () {
$host = Host::factory()->active()->create();
$block = SecurityBlock::factory()->forHost($host)->create(['ip' => '203.0.113.20']);
Livewire::actingAs(operator('Admin'), 'operator')
->test(HostDetail::class, ['host' => $host])
->assertSee('203.0.113.20')
->call('onSecurityBlockReleaseConfirmed', $block->uuid)
->assertDispatched('notify');
expect($block->fresh()->released_at)->not->toBeNull();
});
it('verweigert das Aufheben einer Host-Sperre ohne hosts.manage', function () {
$host = Host::factory()->active()->create();
$block = SecurityBlock::factory()->forHost($host)->create();
Livewire::actingAs(operator('Read-only'), 'operator')
->test(HostDetail::class, ['host' => $host])
->call('onSecurityBlockReleaseConfirmed', $block->uuid)
->assertForbidden();
expect($block->fresh()->released_at)->toBeNull();
});
it('laesst eine Host-Sperre nicht ueber die Instanz-Seite eines Kunden aufheben', function () {
// Zwei getrennte Subjekte, zwei getrennte Pruefungen: CustomerDetail darf
// nur Sperren an EIGENEN Instanzen aufheben, nie eine Host-Sperre — auch
// nicht mit instances.manage.
$host = Host::factory()->active()->create();
$block = SecurityBlock::factory()->forHost($host)->create();
$customer = Customer::factory()->create();
Instance::factory()->for($customer)->create();
Livewire::actingAs(operator('Admin'), 'operator')
->test(CustomerDetail::class, ['uuid' => $customer->uuid])
->call('onSecurityBlockReleaseConfirmed', $block->uuid);
expect($block->fresh()->released_at)->toBeNull();
});
it('zeigt einem Betreiber mit instances.manage die Sperre einer Kunden-Instanz und laesst ihn sie aufheben', function () {
$customer = Customer::factory()->create();
$instance = Instance::factory()->for($customer)->create();
$block = SecurityBlock::factory()->for($instance)->create(['ip' => '198.51.100.42']);
Livewire::actingAs(operator('Support'), 'operator')
->test(CustomerDetail::class, ['uuid' => $customer->uuid])
->call('onSecurityBlockReleaseConfirmed', $block->uuid)
->assertDispatched('notify');
expect($block->fresh()->released_at)->not->toBeNull();
});
it('verweigert das Aufheben einer Instanz-Sperre ohne instances.manage', function () {
// Keine der fuenf mitgelieferten Rollen eignet sich hier: Owner, Admin und
// Support tragen instances.manage genau wie customers.manage (dieselbe
// Begruendung wie bei instances.restart), Billing und Read-only haben
// nicht einmal customers.manage und koennten die Seite gar nicht oeffnen.
// Also die eigene, engere Rolle, die die Rollen-Konsole genau dafuer
// vorsieht (Muster: tests/Feature/Admin/RoleManagementTest.php).
$role = Role::findOrCreate('Kundendienst-eng', 'operator');
$role->syncPermissions(['console.view', 'customers.manage']);
$support = Operator::factory()->create(['password' => 'password']);
$support->assignRole($role);
$customer = Customer::factory()->create();
$instance = Instance::factory()->for($customer)->create();
$block = SecurityBlock::factory()->for($instance)->create();
Livewire::actingAs($support, 'operator')
->test(CustomerDetail::class, ['uuid' => $customer->uuid])
->call('onSecurityBlockReleaseConfirmed', $block->uuid)
->assertForbidden();
expect($block->fresh()->released_at)->toBeNull();
});
it('autorisiert das geteilte Konsolen-Modal nach dem Subjekt der Sperre', function () {
$host = Host::factory()->active()->create();
$hostBlock = SecurityBlock::factory()->forHost($host)->create();
$customer = Customer::factory()->create();
$instance = Instance::factory()->for($customer)->create();
$instanceBlock = SecurityBlock::factory()->for($instance)->create();
// hosts.manage oeffnet die Host-Sperre, aber nicht die Instanz-Sperre.
Livewire::actingAs(operator('Admin'), 'operator')
->test(ConfirmReleaseBlock::class, ['uuid' => $hostBlock->uuid])
->assertSee($hostBlock->ip);
Livewire::actingAs(operator('Read-only'), 'operator')
->test(ConfirmReleaseBlock::class, ['uuid' => $instanceBlock->uuid])
->assertForbidden();
});
it('zeigt auf der Uebersicht einen Hinweis, solange irgendwo eine Sperre aktiv ist', function () {
Livewire::actingAs(operator('Owner'), 'operator')
->test(Overview::class)
->assertDontSee(__('admin.notice.security_blocks', ['n' => 1]));
$instance = Instance::factory()->create();
SecurityBlock::factory()->for($instance)->create();
Livewire::actingAs(operator('Owner'), 'operator')
->test(Overview::class)
->assertSee(__('admin.notice.security_blocks', ['n' => 1]));
});