fix: keep existing SSH keys out of onboarding state

This commit is contained in:
Andras Bacsai
2026-09-28 10:22:44 +02:00
parent 7e4fbc3499
commit 6656ab5ea6
2 changed files with 77 additions and 11 deletions
+8 -11
View File
@@ -133,12 +133,10 @@ class Index extends Component
}
if ($this->selectedExistingPrivateKey) {
$this->createdPrivateKey = PrivateKey::where('team_id', currentTeam()->id)
->where('id', $this->selectedExistingPrivateKey)
->first();
$this->createdPrivateKey = PrivateKey::ownedByCurrentTeam(['team_id'])
->find($this->selectedExistingPrivateKey);
if ($this->createdPrivateKey) {
$this->privateKey = $this->createdPrivateKey->private_key;
$this->publicKey = $this->createdPrivateKey->getPublicKey();
$this->authorize('update', $this->createdPrivateKey);
}
}
@@ -249,9 +247,9 @@ class Index extends Component
return;
}
$this->createdPrivateKey = PrivateKey::ownedByCurrentTeam()->findOrFail($this->selectedExistingPrivateKey);
$this->authorize('view', $this->createdPrivateKey);
$this->privateKey = $this->createdPrivateKey->private_key;
$this->createdPrivateKey = PrivateKey::ownedByCurrentTeam(['team_id'])->findOrFail($this->selectedExistingPrivateKey);
$this->authorize('update', $this->createdPrivateKey);
$this->privateKey = null;
$this->currentState = 'create-server';
}
@@ -305,14 +303,13 @@ class Index extends Component
$this->validate();
$this->privateKey = formatPrivateKey($this->privateKey);
$foundServer = Server::whereIp($this->remoteServerHost)->first();
if ($foundServer) {
return $this->dispatch('error', 'A server with this IP/Domain already exists.');
}
$privateKeyId = $this->createdPrivateKey?->id ?? $this->selectedExistingPrivateKey;
$this->createdPrivateKey = PrivateKey::ownedByCurrentTeam()->findOrFail($privateKeyId);
$this->authorize('view', $this->createdPrivateKey);
$this->createdPrivateKey = PrivateKey::ownedByCurrentTeam(['team_id'])->findOrFail($privateKeyId);
$this->authorize('update', $this->createdPrivateKey);
try {
$this->createdServer = Team::createServerWithinLimit(currentTeam()->id, [
@@ -151,6 +151,75 @@ test('a client supplied private key identifier from another team is rejected by
->call('selectExistingPrivateKey');
})->throws(ModelNotFoundException::class);
test('a member cannot load a team private key through onboarding query parameters', function () {
$member = User::factory()->create();
$member->teams()->attach($this->otherTeam, ['role' => 'member']);
$this->otherTeam->update(['show_boarding' => false]);
actAsBoardingUser($member, $this->otherTeam);
Livewire::test(Index::class, [
'selectedServerType' => 'remote',
'selectedExistingPrivateKey' => $this->otherKey->id,
])->assertForbidden();
});
test('a member cannot select a team private key through an onboarding action', function () {
$member = User::factory()->create();
$member->teams()->attach($this->otherTeam, ['role' => 'member']);
$this->otherTeam->update(['show_boarding' => false]);
actAsBoardingUser($member, $this->otherTeam);
Livewire::test(Index::class)
->set('selectedExistingPrivateKey', $this->otherKey->id)
->call('selectExistingPrivateKey')
->assertForbidden();
});
test('an owner can select an existing key without exposing its private value', function () {
actAsBoardingUser($this->otherOwner, $this->otherTeam);
$component = Livewire::test(Index::class)
->set('selectedExistingPrivateKey', $this->otherKey->id)
->call('selectExistingPrivateKey')
->assertOk()
->assertSet('createdPrivateKey.id', $this->otherKey->id)
->assertSet('privateKey', null);
expect($component->get('createdPrivateKey')->getAttributes())->not->toHaveKey('private_key');
});
test('an owner can resume onboarding with an existing key without exposing its private value', function () {
actAsBoardingUser($this->otherOwner, $this->otherTeam);
$component = Livewire::test(Index::class, [
'selectedServerType' => 'remote',
'selectedExistingPrivateKey' => $this->otherKey->id,
])
->assertOk()
->assertSet('createdPrivateKey.id', $this->otherKey->id)
->assertSet('privateKey', null);
expect($component->get('createdPrivateKey')->getAttributes())->not->toHaveKey('private_key');
});
test('an owner can create a server with an existing key without loading its private value', function () {
actAsBoardingUser($this->otherOwner, $this->otherTeam);
Livewire::test(Index::class)
->set('selectedExistingPrivateKey', $this->otherKey->id)
->call('selectExistingPrivateKey')
->set('remoteServerName', 'Existing key server')
->set('remoteServerHost', '192.0.2.51')
->set('remoteServerPort', 22)
->set('remoteServerUser', 'root')
->call('saveServer')
->assertOk()
->assertSet('currentState', 'validate-server')
->assertSet('privateKey', null);
expect(Server::query()->where('ip', '192.0.2.51')->firstOrFail()->private_key_id)->toBe($this->otherKey->id);
});
test('a hydrated server model from another team is forbidden before use', function () {
actAsBoardingUser($this->rootOwner, $this->rootTeam);