fix: impersonation UX — banner contrast, route blocking, nav filtering

- Banner: white elevated button for contrast, fixed 48px height,
  layout top padding offset so content isn't obscured
- Middleware: allow GET me/profile (viewing), block mutations only;
  add auth/refresh to blocked routes
- Navigation: hide Platform section during impersonation; hide
  org-dependent items when impersonated user has no organisation
- Test: add read-only routes allowed test, auth/refresh blocked test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-16 02:51:50 +02:00
parent 4df668b5b8
commit 67ce1e9d9d
4 changed files with 64 additions and 37 deletions

View File

@@ -391,6 +391,7 @@ class AdminImpersonationTest extends TestCase
['POST', '/api/v1/auth/mfa/setup/totp'],
['GET', '/api/v1/auth/mfa/status'],
['GET', '/api/v1/auth/trusted-devices'],
['POST', '/api/v1/auth/refresh'],
];
foreach ($sensitiveRoutes as [$method, $url]) {
@@ -406,6 +407,23 @@ class AdminImpersonationTest extends TestCase
}
}
public function test_read_only_routes_allowed_during_impersonation(): void
{
Sanctum::actingAs($this->superAdmin);
$this->postJson(
"/api/v1/admin/impersonate/{$this->targetUser->id}",
$this->startPayload(),
)->assertOk();
// GET /auth/me should be allowed (profile viewing)
$response = $this->withHeader('X-Impersonate-User', $this->targetUser->id)
->getJson('/api/v1/auth/me');
$response->assertOk();
$response->assertJsonPath('data.id', $this->targetUser->id);
}
public function test_ip_change_terminates_session(): void
{
Sanctum::actingAs($this->superAdmin);