diff --git a/app/Livewire/Server/New/ByIp.php b/app/Livewire/Server/New/ByIp.php
index f5ea2ae80..a85306f6b 100644
--- a/app/Livewire/Server/New/ByIp.php
+++ b/app/Livewire/Server/New/ByIp.php
@@ -3,6 +3,7 @@
namespace App\Livewire\Server\New;
use App\Enums\ProxyTypes;
+use App\Models\PrivateKey;
use App\Models\Server;
use App\Models\Team;
use App\Rules\ValidServerIp;
@@ -84,11 +85,51 @@ protected function messages(): array
]);
}
+ public function getListeners(): array
+ {
+ return [
+ 'privateKeyCreated' => 'handlePrivateKeyCreated',
+ ];
+ }
+
public function setPrivateKey(string $private_key_id)
{
$this->private_key_id = $private_key_id;
}
+ public function generatePrivateKey(string $type): void
+ {
+ try {
+ $this->authorize('create', PrivateKey::class);
+
+ if (! in_array($type, ['ed25519', 'rsa'], true)) {
+ $this->dispatch('error', 'Invalid private key type.');
+
+ return;
+ }
+
+ $keyData = PrivateKey::generateNewKeyPair($type);
+ $privateKey = PrivateKey::createAndStore([
+ 'name' => $keyData['name'],
+ 'description' => $keyData['description'],
+ 'private_key' => $keyData['private_key'],
+ 'team_id' => currentTeam()->id,
+ ]);
+
+ $this->handlePrivateKeyCreated($privateKey->id);
+ $this->dispatch('success', 'Private key created successfully.');
+ } catch (\Throwable $e) {
+ handleError($e, $this);
+ }
+ }
+
+ public function handlePrivateKeyCreated($keyId): void
+ {
+ $this->private_keys = PrivateKey::ownedAndOnlySShKeys()->where('id', '!=', 0)->get();
+ $this->private_key_id = $keyId;
+ $this->resetErrorBag('private_key_id');
+ }
+
public function instantSave()
{
// $this->dispatch('success', 'Application settings updated!');
diff --git a/resources/views/livewire/server/new/by-ip.blade.php b/resources/views/livewire/server/new/by-ip.blade.php
index e41342ca2..39d9ca0fe 100644
--- a/resources/views/livewire/server/new/by-ip.blade.php
+++ b/resources/views/livewire/server/new/by-ip.blade.php
@@ -16,16 +16,65 @@
Non-root user is experimental:
docs.
-
-
- @foreach ($private_keys as $key)
- @if ($loop->first)
-
- @else
-
- @endif
- @endforeach
-
+
+
+
+
+ @foreach ($private_keys as $key)
+
+ @endforeach
+
+
+ @can('create', App\Models\PrivateKey::class)
+
+ @endcan
+
'file']);
+ Storage::fake('ssh-keys');
+
+ InstanceSettings::forceCreate(['id' => 0, 'is_api_enabled' => true]);
+
+ $this->team = Team::factory()->create();
+ $this->user = User::factory()->create();
+ $this->team->members()->attach($this->user->id, ['role' => 'owner']);
+
+ session(['currentTeam' => $this->team]);
+
+ $this->actingAs($this->user);
+
+ $this->existingPrivateKey = PrivateKey::withoutEvents(fn () => PrivateKey::forceCreate([
+ 'uuid' => (string) new Cuid2,
+ 'name' => 'Existing SSH Key',
+ 'description' => 'Existing SSH Key',
+ 'private_key' => 'test-private-key',
+ 'team_id' => $this->team->id,
+ ]));
+});
+
+it('generates and preselects a new private key without clearing server form data', function () {
+ $component = Livewire::test(ByIp::class, [
+ 'private_keys' => collect([$this->existingPrivateKey]),
+ 'limit_reached' => false,
+ ])
+ ->set('name', 'Production Server')
+ ->set('description', 'Deploy target')
+ ->set('ip', '192.0.2.50')
+ ->set('user', 'deploy.user')
+ ->set('port', 2222)
+ ->set('is_build_server', true)
+ ->call('generatePrivateKey', 'ed25519')
+ ->assertHasNoErrors()
+ ->assertSet('name', 'Production Server')
+ ->assertSet('description', 'Deploy target')
+ ->assertSet('ip', '192.0.2.50')
+ ->assertSet('user', 'deploy.user')
+ ->assertSet('port', 2222)
+ ->assertSet('is_build_server', true);
+
+ $newPrivateKeyId = $component->get('private_key_id');
+
+ expect($newPrivateKeyId)->not->toBe($this->existingPrivateKey->id)
+ ->and(PrivateKey::find($newPrivateKeyId))->not->toBeNull()
+ ->and($component->get('private_keys')->pluck('id'))->toContain($newPrivateKeyId);
+});
+
+it('preselects a manually added private key without clearing server form data', function () {
+ $manualPrivateKey = PrivateKey::withoutEvents(fn () => PrivateKey::forceCreate([
+ 'uuid' => (string) new Cuid2,
+ 'name' => 'Manual SSH Key',
+ 'description' => 'Manual SSH Key',
+ 'private_key' => 'manual-test-private-key',
+ 'team_id' => $this->team->id,
+ ]));
+
+ Livewire::test(ByIp::class, [
+ 'private_keys' => collect([$this->existingPrivateKey]),
+ 'limit_reached' => false,
+ ])
+ ->set('name', 'Production Server')
+ ->set('description', 'Deploy target')
+ ->set('ip', '192.0.2.51')
+ ->set('user', 'deploy.user')
+ ->set('port', 2222)
+ ->set('is_build_server', true)
+ ->call('handlePrivateKeyCreated', $manualPrivateKey->id)
+ ->assertSet('private_key_id', $manualPrivateKey->id)
+ ->assertSet('name', 'Production Server')
+ ->assertSet('description', 'Deploy target')
+ ->assertSet('ip', '192.0.2.51')
+ ->assertSet('user', 'deploy.user')
+ ->assertSet('port', 2222)
+ ->assertSet('is_build_server', true)
+ ->assertSee('Manual SSH Key');
+});