diff --git a/app/Livewire/Admin/Vpn.php b/app/Livewire/Admin/Vpn.php index 72f15a7..7835dc1 100644 --- a/app/Livewire/Admin/Vpn.php +++ b/app/Livewire/Admin/Vpn.php @@ -159,6 +159,11 @@ class Vpn extends Component ApplyVpnPeer::dispatch($peer->public_key, $peer->allowed_ip, true); + // Whatever was on screen belongs to the previous access. Leaving it up + // after creating another one would present the wrong private config + // under the new name — and someone would hand it out. + $this->dismissConfig(); + // Only a key we generated can be turned into a ready-to-use config. if ($keypair !== null) { $config = $this->clientConfig($keypair, $peer->allowed_ip); diff --git a/tests/Feature/Admin/VpnTest.php b/tests/Feature/Admin/VpnTest.php index fa943e2..cd26c30 100644 --- a/tests/Feature/Admin/VpnTest.php +++ b/tests/Feature/Admin/VpnTest.php @@ -692,3 +692,25 @@ it('stops serving a revealed config once the access is revoked', function () { $modal->call('toggleQr')->assertForbidden(); expect(App\Services\Wireguard\ConfigHandoff::get($token))->toBeNull(); }); + +it('never leaves the previous config on screen after another access is created', function () { + vpnHub(); + Queue::fake(); + $owner = operator('Owner'); + + $component = Livewire::actingAs($owner)->test(Vpn::class) + ->set('name', 'Erster')->set('ownerId', $owner->id) + ->call('create'); + $firstToken = $component->get('configToken'); + expect(App\Services\Wireguard\ConfigHandoff::get($firstToken))->toContain('PrivateKey'); + + // Second access brings its own key, so there is no config to show — the + // first one must not stay up wearing the second one's name. + $component->set('name', 'Zweiter')->set('publicKey', Keypair::generate()->publicKey) + ->call('create') + ->assertHasNoErrors(); + + expect($component->get('configToken'))->toBeNull() + ->and($component->get('newConfigName'))->toBeNull() + ->and(App\Services\Wireguard\ConfigHandoff::get($firstToken))->toBeNull(); +});