Fix subdomain DNS messaging for Ladill nameservers and retire pending-setup primaries.
Deploy Ladill Hosting / deploy (push) Successful in 47s
Deploy Ladill Hosting / deploy (push) Successful in 47s
Treat ns_auto domains as managed DNS, publish subdomain A records via PowerDNS without failing the UX when the local DNS registry is missing, and promote real linked domains over pending-setup.local placeholders. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -111,9 +111,161 @@ class HostingPanelDomainLinkingTest extends TestCase
|
||||
'hosting_account_id' => $account->id,
|
||||
'domain' => 'linked-example.com',
|
||||
'domain_id' => $domain->id,
|
||||
'type' => 'addon',
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_add_domain_promotes_over_pending_setup_placeholder(): void
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
||||
$product = HostingProduct::create([
|
||||
'name' => 'Growth Plan',
|
||||
'slug' => 'growth-placeholder-promote-test',
|
||||
'category' => 'shared',
|
||||
'type' => 'multi_domain',
|
||||
'price_monthly' => 10,
|
||||
'max_domains' => 8,
|
||||
]);
|
||||
|
||||
$node = HostingNode::create([
|
||||
'name' => 'Local Node',
|
||||
'hostname' => 'local-node',
|
||||
'ip_address' => '127.0.0.1',
|
||||
'type' => 'shared',
|
||||
'provider' => 'local',
|
||||
'status' => 'active',
|
||||
'ssh_port' => '22',
|
||||
]);
|
||||
|
||||
$account = HostingAccount::unguarded(function () use ($user, $node, $product) {
|
||||
return HostingAccount::create([
|
||||
'user_id' => $user->id,
|
||||
'hosting_product_id' => $product->id,
|
||||
'hosting_node_id' => $node->id,
|
||||
'username' => 'aminmohammedosei',
|
||||
'primary_domain' => 'pending-setup.local',
|
||||
'type' => 'shared',
|
||||
'status' => 'active',
|
||||
'php_version' => '8.2',
|
||||
]);
|
||||
});
|
||||
|
||||
HostedSite::create([
|
||||
'hosting_account_id' => $account->id,
|
||||
'domain' => 'pending-setup.local',
|
||||
'document_root' => '/home/aminmohammedosei/public_html',
|
||||
'type' => 'primary',
|
||||
'status' => 'active',
|
||||
'ssl_enabled' => false,
|
||||
]);
|
||||
|
||||
$provider = \Mockery::mock(SharedNodeProvider::class);
|
||||
$provider->shouldReceive('addSite')->once()->andReturn([
|
||||
'document_root' => '/home/aminmohammedosei/public_html/amenscientifichospital.com',
|
||||
'domain' => 'amenscientifichospital.com',
|
||||
]);
|
||||
$provider->shouldReceive('removeSite')->once()->andReturn(true);
|
||||
|
||||
$verification = \Mockery::mock(DomainVerificationService::class);
|
||||
$verification->shouldReceive('reprovision')->once();
|
||||
|
||||
$this->app->instance(SharedNodeProvider::class, $provider);
|
||||
$this->app->instance(DomainVerificationService::class, $verification);
|
||||
|
||||
$session = $this->app['session.store'];
|
||||
$session->start();
|
||||
|
||||
$request = Request::create('http://localhost/hosting/panel/' . $account->id . '/domains', 'POST', [
|
||||
'domain' => 'amenscientifichospital.com',
|
||||
], [], [], [
|
||||
'HTTP_REFERER' => 'http://localhost/hosting/accounts/' . $account->id,
|
||||
]);
|
||||
$request->setUserResolver(fn (): User => $user);
|
||||
$request->setLaravelSession($session);
|
||||
|
||||
$response = $this->app->make(HostingPanelController::class)->addDomain(
|
||||
$request,
|
||||
$account->fresh(['sites', 'node', 'product']),
|
||||
$this->app->make(DomainDnsBlueprintService::class),
|
||||
$this->app->make(DomainVerificationService::class),
|
||||
);
|
||||
|
||||
$this->assertSame(302, $response->getStatusCode());
|
||||
|
||||
$account->refresh();
|
||||
$this->assertSame('amenscientifichospital.com', $account->primary_domain);
|
||||
|
||||
$this->assertDatabaseHas('hosted_sites', [
|
||||
'hosting_account_id' => $account->id,
|
||||
'domain' => 'amenscientifichospital.com',
|
||||
'type' => 'primary',
|
||||
]);
|
||||
|
||||
$this->assertSoftDeleted('hosted_sites', [
|
||||
'hosting_account_id' => $account->id,
|
||||
'domain' => 'pending-setup.local',
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_account_page_heals_placeholder_primary_when_real_domain_already_linked(): void
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
|
||||
$product = HostingProduct::create([
|
||||
'name' => 'Growth Plan',
|
||||
'slug' => 'growth-heal-placeholder-test',
|
||||
'category' => 'shared',
|
||||
'type' => 'multi_domain',
|
||||
'price_monthly' => 10,
|
||||
'max_domains' => 8,
|
||||
]);
|
||||
|
||||
$node = HostingNode::create([
|
||||
'name' => 'Local Node',
|
||||
'hostname' => 'local-node',
|
||||
'ip_address' => '127.0.0.1',
|
||||
'type' => 'shared',
|
||||
'provider' => 'local',
|
||||
'status' => 'active',
|
||||
'ssh_port' => '22',
|
||||
]);
|
||||
|
||||
$account = HostingAccount::unguarded(function () use ($user, $node, $product) {
|
||||
return HostingAccount::create([
|
||||
'user_id' => $user->id,
|
||||
'hosting_product_id' => $product->id,
|
||||
'hosting_node_id' => $node->id,
|
||||
'username' => 'acctuser',
|
||||
'primary_domain' => 'pending-setup.local',
|
||||
'type' => 'shared',
|
||||
'status' => 'active',
|
||||
'php_version' => '8.2',
|
||||
]);
|
||||
});
|
||||
|
||||
HostedSite::create([
|
||||
'hosting_account_id' => $account->id,
|
||||
'domain' => 'amenscientifichospital.com',
|
||||
'document_root' => '/home/acctuser/public_html/amenscientifichospital.com',
|
||||
'type' => 'addon',
|
||||
'status' => 'active',
|
||||
'ssl_enabled' => false,
|
||||
]);
|
||||
|
||||
$request = Request::create('http://localhost/hosting/accounts/' . $account->id, 'GET');
|
||||
$request->setUserResolver(fn (): User => $user);
|
||||
|
||||
$html = $this->app->make(HostingProductController::class)
|
||||
->showAccount($request, $account)
|
||||
->render();
|
||||
|
||||
$account->refresh();
|
||||
$this->assertSame('amenscientifichospital.com', $account->primary_domain);
|
||||
$this->assertStringContainsString('amenscientifichospital.com', $html);
|
||||
$this->assertStringNotContainsString('pending-setup.local', $html);
|
||||
}
|
||||
|
||||
public function test_hosting_account_page_renders_linked_domains(): void
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
@@ -312,6 +464,10 @@ class HostingPanelDomainLinkingTest extends TestCase
|
||||
);
|
||||
|
||||
$this->assertSame(302, $response->getStatusCode());
|
||||
$this->assertSame(
|
||||
'Subdomain blog.primary.example.com created. DNS was updated on Ladill nameservers; SSL will provision automatically.',
|
||||
$session->get('success')
|
||||
);
|
||||
$this->assertDatabaseHas('hosted_sites', [
|
||||
'hosting_account_id' => $account->id,
|
||||
'domain' => 'blog.primary.example.com',
|
||||
@@ -323,6 +479,56 @@ class HostingPanelDomainLinkingTest extends TestCase
|
||||
$this->assertSame(5, $account->fresh()->maxSubdomainsLimit());
|
||||
}
|
||||
|
||||
public function test_add_subdomain_treats_ns_auto_as_managed_even_without_dns_mode(): void
|
||||
{
|
||||
[$user, $account, $parent] = $this->makeAccountWithPrimary(maxDomains: 1, withManagedDomain: true);
|
||||
|
||||
Domain::query()->whereKey($parent->domain_id)->update(['dns_mode' => null]);
|
||||
$parent->update(['domain_id' => null]);
|
||||
|
||||
$provider = \Mockery::mock(SharedNodeProvider::class);
|
||||
$provider->shouldReceive('addSite')->once()->andReturn([
|
||||
'document_root' => '/home/acctuser/public_html/data.primary.example.com',
|
||||
'domain' => 'data.primary.example.com',
|
||||
]);
|
||||
|
||||
$pdns = \Mockery::mock(\App\Services\Dns\PowerDnsClient::class);
|
||||
$pdns->shouldReceive('upsertRecords')->once()->andReturn(['status' => 'updated', 'count' => 1]);
|
||||
|
||||
$this->app->instance(SharedNodeProvider::class, $provider);
|
||||
$this->app->instance(\App\Services\Dns\PowerDnsClient::class, $pdns);
|
||||
|
||||
$session = $this->app['session.store'];
|
||||
$session->start();
|
||||
|
||||
$request = Request::create('http://localhost/hosting/panel/'.$account->id.'/domains/subdomains', 'POST', [
|
||||
'parent_site_id' => $parent->id,
|
||||
'subdomain' => 'data',
|
||||
], [], [], [
|
||||
'HTTP_REFERER' => 'http://localhost/hosting/panel/'.$account->id.'/domains',
|
||||
]);
|
||||
$request->setUserResolver(fn (): User => $user);
|
||||
$request->setLaravelSession($session);
|
||||
|
||||
$response = $this->app->make(HostingPanelController::class)->addSubdomain(
|
||||
$request,
|
||||
$account->fresh(['sites', 'product', 'node']),
|
||||
$this->app->make(\App\Services\Dns\PowerDnsClient::class),
|
||||
);
|
||||
|
||||
$this->assertSame(302, $response->getStatusCode());
|
||||
$this->assertSame(
|
||||
'Subdomain data.primary.example.com created. DNS was updated on Ladill nameservers; SSL will provision automatically.',
|
||||
$session->get('success')
|
||||
);
|
||||
$this->assertDatabaseHas('domains', [
|
||||
'host' => 'primary.example.com',
|
||||
'dns_mode' => 'managed',
|
||||
]);
|
||||
$this->assertStringNotContainsString('external DNS', (string) $session->get('success'));
|
||||
$this->assertStringNotContainsString('Point an A record', (string) $session->get('success'));
|
||||
}
|
||||
|
||||
public function test_subdomain_quota_is_max_domains_times_five(): void
|
||||
{
|
||||
[$user, $account, $parent] = $this->makeAccountWithPrimary(maxDomains: 1, withManagedDomain: false);
|
||||
|
||||
Reference in New Issue
Block a user