fix(admin): the admin password is shown once, and means it
The handoff stayed in the cache for its full ten minutes, so any replayed component request could fetch the plaintext again — "shown once" was a figure of speech. It is consumed on the first read and the token dropped; the payload reaches the view and nothing else. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>feat/portal-design
parent
d40113be8e
commit
55b1a1468f
|
|
@ -82,9 +82,21 @@ class InstanceAdminAccess extends ModalComponent
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
$payload = null;
|
$payload = null;
|
||||||
|
|
||||||
if ($this->token !== null) {
|
if ($this->token !== null) {
|
||||||
$raw = ConfigHandoff::get($this->token);
|
$raw = ConfigHandoff::get($this->token);
|
||||||
$payload = $raw === null ? null : json_decode($raw, true);
|
|
||||||
|
if ($raw !== null) {
|
||||||
|
// Consumed on the first read: leaving it in the cache would make
|
||||||
|
// "shown once" a figure of speech — any replayed component
|
||||||
|
// request could fetch the password again for ten minutes. The
|
||||||
|
// payload lives in a local variable, so it reaches the view and
|
||||||
|
// nothing else.
|
||||||
|
ConfigHandoff::forget($this->token);
|
||||||
|
$this->token = null;
|
||||||
|
$this->waiting = false;
|
||||||
|
$payload = json_decode($raw, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return view('livewire.admin.instance-admin-access', [
|
return view('livewire.admin.instance-admin-access', [
|
||||||
|
|
|
||||||
|
|
@ -114,3 +114,25 @@ it('tells the console when Proxmox is unreachable', function () {
|
||||||
// Otherwise the modal polls forever with a spinner.
|
// Otherwise the modal polls forever with a spinner.
|
||||||
expect(json_decode(ConfigHandoff::get('handoff-throw'), true))->toBe(['error' => 'failed']);
|
expect(json_decode(ConfigHandoff::get('handoff-throw'), true))->toBe(['error' => 'failed']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('shows the password once and not a second time', function () {
|
||||||
|
$pve = new FakeProxmoxClient;
|
||||||
|
app()->instance(ProxmoxClient::class, $pve);
|
||||||
|
$instance = adminAccessInstance();
|
||||||
|
$owner = operator('Owner');
|
||||||
|
$owner->forceFill(['password' => Hash::make('geheim-1234')])->save();
|
||||||
|
|
||||||
|
$modal = Livewire\Livewire::actingAs($owner)
|
||||||
|
->test(InstanceAdminAccess::class, ['uuid' => $instance->uuid])
|
||||||
|
->set('password', 'geheim-1234')
|
||||||
|
->call('request'); // sync queue: the job runs immediately
|
||||||
|
|
||||||
|
$token = $modal->get('token');
|
||||||
|
$modal->assertSee(__('instances.admin_ready'));
|
||||||
|
|
||||||
|
// "Shown once" has to mean it: a replayed request must not fetch it again.
|
||||||
|
expect(ConfigHandoff::get($token ?? 'none'))->toBeNull()
|
||||||
|
->and($modal->get('token'))->toBeNull();
|
||||||
|
|
||||||
|
$modal->call('$refresh')->assertDontSee(__('instances.admin_ready'));
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue