CluPilotCloud/tests/Feature/ImpersonationTest.php

80 lines
2.7 KiB
PHP

<?php
use App\Models\Customer;
use App\Models\Operator;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\URL;
it('hands over a signed link instead of relying on a shared cookie', function () {
$operator = Operator::factory()->role('Owner')->create();
$customer = Customer::factory()->create();
$response = $this->actingAs($operator, 'operator')
->post(route('admin.impersonate', $customer));
// The console and the portal are different hosts in exclusive mode, and a
// session cookie is host-bound — so the handover cannot be a cookie.
$response->assertRedirectContains('signature=');
});
it('signs the customer in on the web guard when the link is followed', function () {
$operator = Operator::factory()->role('Owner')->create();
$customer = Customer::factory()->create();
$user = $customer->ensureUser();
$url = URL::temporarySignedRoute('impersonate.enter', now()->addSeconds(60), [
'customer' => $customer->uuid, 'operator' => $operator->uuid,
]);
$this->get($url)->assertRedirect(route('dashboard'));
expect(Auth::guard('web')->id())->toBe($user->id);
});
it('refuses the same link twice', function () {
$operator = Operator::factory()->role('Owner')->create();
$customer = Customer::factory()->create();
$user = $customer->ensureUser();
$url = URL::temporarySignedRoute('impersonate.enter', now()->addSeconds(60), [
'customer' => $customer->uuid, 'operator' => $operator->uuid,
]);
$this->get($url)->assertRedirect(route('dashboard'));
Auth::guard('web')->logout();
// A link that still works after use is a password with an expiry date.
$this->get($url)->assertForbidden();
});
it('refuses an expired link', function () {
$operator = Operator::factory()->role('Owner')->create();
$customer = Customer::factory()->create();
$user = $customer->ensureUser();
$url = URL::temporarySignedRoute('impersonate.enter', now()->subSecond(), [
'customer' => $customer->uuid, 'operator' => $operator->uuid,
]);
$this->get($url)->assertForbidden();
});
it('leaves the operator session untouched, so leaving returns to the console', function () {
$operator = Operator::factory()->role('Owner')->create();
$customer = Customer::factory()->create();
$user = $customer->ensureUser();
$url = URL::temporarySignedRoute('impersonate.enter', now()->addSeconds(60), [
'customer' => $customer->uuid, 'operator' => $operator->uuid,
]);
$this->actingAs($operator, 'operator')->get($url);
expect(Auth::guard('operator')->check())->toBeTrue();
$this->post(route('impersonate.leave'));
expect(Auth::guard('web')->check())->toBeFalse()
->and(Auth::guard('operator')->check())->toBeTrue();
});