diff --git a/app/Livewire/Admin/HostCreate.php b/app/Livewire/Admin/HostCreate.php index 21780f6..9c07e2e 100644 --- a/app/Livewire/Admin/HostCreate.php +++ b/app/Livewire/Admin/HostCreate.php @@ -16,7 +16,7 @@ class HostCreate extends Component #[Validate('required|string|in:fsn,hel')] public string $datacenter = 'fsn'; - #[Validate('required|ip')] + #[Validate('required|ip|unique:hosts,public_ip')] public string $public_ip = ''; #[Validate('required|string|min:8')] diff --git a/database/factories/HostFactory.php b/database/factories/HostFactory.php index f58ea12..ee01b4e 100644 --- a/database/factories/HostFactory.php +++ b/database/factories/HostFactory.php @@ -15,7 +15,7 @@ class HostFactory extends Factory return [ 'name' => 'pve-test-'.$this->faker->unique()->numberBetween(1, 99999), 'datacenter' => 'fsn', - 'public_ip' => $this->faker->ipv4(), + 'public_ip' => $this->faker->unique()->ipv4(), 'status' => 'pending', ]; } diff --git a/database/migrations/2026_07_25_070006_add_unique_public_ip_to_hosts_table.php b/database/migrations/2026_07_25_070006_add_unique_public_ip_to_hosts_table.php new file mode 100644 index 0000000..b3e7eaf --- /dev/null +++ b/database/migrations/2026_07_25_070006_add_unique_public_ip_to_hosts_table.php @@ -0,0 +1,24 @@ +unique('public_ip'); + }); + } + + public function down(): void + { + Schema::table('hosts', function (Blueprint $table) { + $table->dropUnique(['public_ip']); + }); + } +}; diff --git a/tests/Feature/Admin/HostManagementTest.php b/tests/Feature/Admin/HostManagementTest.php index 563770e..df97a96 100644 --- a/tests/Feature/Admin/HostManagementTest.php +++ b/tests/Feature/Admin/HostManagementTest.php @@ -58,6 +58,19 @@ it('creates a host and starts onboarding with an encrypted password', function ( Queue::assertPushed(AdvanceRunJob::class); }); +it('rejects a duplicate public ip', function () { + Host::factory()->create(['public_ip' => '203.0.113.99']); + + Livewire::actingAs(admin()) + ->test(HostCreate::class) + ->set('name', 'pve-dup') + ->set('datacenter', 'fsn') + ->set('public_ip', '203.0.113.99') + ->set('root_password', 'supersecret') + ->call('save') + ->assertHasErrors(['public_ip']); +}); + it('validates the add-host form', function () { Livewire::actingAs(admin()) ->test(HostCreate::class)