103 lines
3.1 KiB
PHP
103 lines
3.1 KiB
PHP
<?php
|
|
|
|
use App\Models\Permission;
|
|
use App\Models\Role;
|
|
use App\Models\User;
|
|
|
|
function makeImpersonator(): User
|
|
{
|
|
$admin = User::factory()->create(['is_active' => true]);
|
|
$perm = Permission::firstOrCreate(['name' => 'impersonate users', 'guard_name' => 'web']);
|
|
$admin->givePermissionTo($perm);
|
|
|
|
return $admin;
|
|
}
|
|
|
|
test('guest cannot start impersonation', function () {
|
|
$target = User::factory()->create();
|
|
|
|
$this->post("/impersonate/{$target->id}")->assertRedirect('/login');
|
|
});
|
|
|
|
test('user without permission cannot start impersonation', function () {
|
|
$admin = User::factory()->create();
|
|
$target = User::factory()->create();
|
|
|
|
$this->actingAs($admin)->post("/impersonate/{$target->id}")->assertForbidden();
|
|
});
|
|
|
|
test('cannot impersonate self', function () {
|
|
$admin = makeImpersonator();
|
|
|
|
$this->actingAs($admin)
|
|
->post("/impersonate/{$admin->id}")
|
|
->assertForbidden();
|
|
});
|
|
|
|
test('cannot impersonate an inactive user', function () {
|
|
$admin = makeImpersonator();
|
|
$target = User::factory()->create(['is_active' => false]);
|
|
|
|
$this->actingAs($admin)
|
|
->post("/impersonate/{$target->id}")
|
|
->assertForbidden();
|
|
});
|
|
|
|
test('cannot impersonate a Developer (Super Admin)', function () {
|
|
$admin = makeImpersonator();
|
|
$dev = User::factory()->create(['is_active' => true]);
|
|
Role::firstOrCreate(['name' => 'Developer', 'guard_name' => 'web']);
|
|
$dev->assignRole('Developer');
|
|
|
|
$this->actingAs($admin)
|
|
->post("/impersonate/{$dev->id}")
|
|
->assertForbidden();
|
|
});
|
|
|
|
test('start switches the authenticated user and stashes original id', function () {
|
|
$admin = makeImpersonator();
|
|
$target = User::factory()->create(['is_active' => true]);
|
|
|
|
$this->actingAs($admin)
|
|
->post("/impersonate/{$target->id}")
|
|
->assertRedirect(route('dashboard', absolute: false))
|
|
->assertSessionHas('impersonator_id', $admin->id);
|
|
|
|
expect(auth()->id())->toBe($target->id);
|
|
});
|
|
|
|
test('cannot start a second impersonation while already impersonating', function () {
|
|
$admin = makeImpersonator();
|
|
$first = User::factory()->create(['is_active' => true]);
|
|
$first->givePermissionTo('impersonate users'); // edge case: target also has permission
|
|
$second = User::factory()->create(['is_active' => true]);
|
|
|
|
$this->actingAs($admin)->post("/impersonate/{$first->id}");
|
|
|
|
$this->post("/impersonate/{$second->id}")
|
|
->assertRedirect()
|
|
->assertSessionHas('error');
|
|
|
|
expect(auth()->id())->toBe($first->id);
|
|
});
|
|
|
|
test('stop without an active session returns 403', function () {
|
|
$admin = makeImpersonator();
|
|
|
|
$this->actingAs($admin)->post('/impersonate/stop')->assertForbidden();
|
|
});
|
|
|
|
test('stop restores the original super admin', function () {
|
|
$admin = makeImpersonator();
|
|
$target = User::factory()->create(['is_active' => true]);
|
|
|
|
$this->actingAs($admin)->post("/impersonate/{$target->id}");
|
|
expect(auth()->id())->toBe($target->id);
|
|
|
|
$this->post('/impersonate/stop')
|
|
->assertRedirect(route('users', absolute: false));
|
|
|
|
expect(auth()->id())->toBe($admin->id);
|
|
expect(session()->has('impersonator_id'))->toBeFalse();
|
|
});
|