From e9bf6017ea092ab52273afb1634049ccd909db24 Mon Sep 17 00:00:00 2001 From: Hemachandar Date: Tue, 13 Jan 2026 22:23:30 +0530 Subject: [PATCH] Handle NS record flow and auto-verification of sub-domains --- .../components/domains/nameserverTable.svelte | 29 +++++++-- .../domains/add-domain/+page.svelte | 26 ++++++-- .../add-domain/verify-[domain]/+page.svelte | 58 ++++++++---------- .../domains/retryDomainModal.svelte | 56 ++++++++++-------- .../function-[function]/domains/table.svelte | 2 +- .../settings/domains/add-domain/+page.svelte | 26 ++++++-- .../add-domain/verify-[domain]/+page.svelte | 54 +++++++---------- .../settings/domains/retryDomainModal.svelte | 56 ++++++++++-------- .../settings/domains/table.svelte | 2 +- .../domains/add-domain/+page.svelte | 26 ++++++-- .../add-domain/verify-[domain]/+page.svelte | 59 ++++++++----------- .../domains/retryDomainModal.svelte | 56 ++++++++++-------- .../sites/site-[site]/domains/table.svelte | 2 +- 13 files changed, 250 insertions(+), 202 deletions(-) diff --git a/src/lib/components/domains/nameserverTable.svelte b/src/lib/components/domains/nameserverTable.svelte index a08de4208..37ff46823 100644 --- a/src/lib/components/domains/nameserverTable.svelte +++ b/src/lib/components/domains/nameserverTable.svelte @@ -3,8 +3,15 @@ import { Badge, Layout, Typography, Table, InteractiveText } from '@appwrite.io/pink-svelte'; - export let domain: string; - export let verified = undefined; + let { + domain, + verified = undefined, + ruleStatus = undefined + }: { + domain: string; + verified?: boolean; + ruleStatus?: 'created' | 'verifying' | 'unverified' | 'verified'; + } = $props(); const nameserverList = $regionalConsoleVariables?._APP_DOMAINS_NAMESERVERS ? $regionalConsoleVariables?._APP_DOMAINS_NAMESERVERS?.split(',') @@ -16,10 +23,20 @@ {domain} - {#if verified === true} - - {:else if verified === false} - + {#if verified !== undefined} + {#if ruleStatus === 'created'} + + {:else if ruleStatus === 'verifying'} + + {:else if ruleStatus === 'unverified'} + + {:else if verified === true} + + {/if} {/if} diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte index 89f2bb4c2..6a9d3183a 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte @@ -48,16 +48,24 @@ async function addDomain() { const apexDomain = getApexDomain(domainName); - let domain = data.domainsList.domains.find((d: Models.Domain) => d.domain === apexDomain); + const domain = data.domainsList.domains.find((d: Models.Domain) => d.domain === apexDomain); if (apexDomain && !domain && isCloud) { try { - domain = await sdk.forConsole.domains.create({ + await sdk.forConsole.domains.create({ teamId: $project.teamId, domain: apexDomain }); } catch (error) { - // Apex domain creation error needs to be silent. + // apex might already be added on organization level, skip. + const alreadyAdded = error?.type === 'domain_already_exists'; + if (!alreadyAdded) { + addNotification({ + type: 'error', + message: error.message + }); + return; + } } } @@ -89,12 +97,18 @@ functionId: page.params.function }); } - if (rule?.status === 'verified') { + + await invalidate(Dependencies.FUNCTION_DOMAINS); + + const verified = rule?.status !== 'created'; + if (verified) { + addNotification({ + type: 'success', + message: 'Domain verified successfully' + }); await goto(routeBase); - await invalidate(Dependencies.FUNCTION_DOMAINS); } else { await goto(`${routeBase}/add-domain/verify-${domainName}?rule=${rule.$id}`); - await invalidate(Dependencies.FUNCTION_DOMAINS); } } catch (error) { addNotification({ diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte index 41d1b541e..fa97bd5cc 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte @@ -11,7 +11,6 @@ } from '@appwrite.io/pink-svelte'; import { Button, Form } from '$lib/elements/forms'; import { sdk } from '$lib/stores/sdk'; - import { organization } from '$lib/stores/organization'; import { addNotification } from '$lib/stores/notifications'; import { goto, invalidate } from '$app/navigation'; import { Dependencies } from '$lib/constants'; @@ -23,6 +22,7 @@ import NameserverTable from '$lib/components/domains/nameserverTable.svelte'; import RecordTable from '$lib/components/domains/recordTable.svelte'; import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; + import { getApexDomain } from '$lib/helpers/tlds.js'; let { data } = $props(); @@ -54,41 +54,30 @@ } async function verify() { - const isNewDomain = - data.domainsList.domains.find((rule) => rule.domain === data.proxyRule.domain) === - undefined; try { - if (selectedTab !== 'nameserver') { - const ruleData = await sdk - .forProject(page.params.region, page.params.project) - .proxy.updateRuleVerification({ ruleId }); - verified = ruleData.status === 'verified'; + const apexDomain = getApexDomain(data.proxyRule.domain); + const domain = data.domainsList.domains.find((d) => d.domain === apexDomain); - // This means domain verification using DNS records hasn't succeeded and the rule is still in initial state. - if (ruleData.status === 'created') { - throw new Error( - 'Domain verification failed. Please check your domain settings or try again later' - ); - } - } else if (isNewDomain && isCloud) { - const domainData = await sdk.forConsole.domains.create({ - teamId: $organization.$id, - domain: data.proxyRule.domain - }); - verified = domainData.nameservers.toLowerCase() === 'appwrite'; - } - - if (verified) { - addNotification({ - type: 'success', - message: 'Domain added successfully' - }); - } else { - addNotification({ - type: 'info', - message: 'Verification in progress' + if (isCloud && domain) { + await sdk.forConsole.domains.updateNameservers({ + domainId: domain.$id }); } + } catch (error) { + // Ignore error + } + + try { + await sdk + .forProject(page.params.region, page.params.project) + .proxy.updateRuleVerification({ ruleId }); + + verified = true; + addNotification({ + type: 'success', + message: 'Domain verified successfully' + }); + await goto(routeBase); await invalidate(Dependencies.DOMAINS); await invalidate(Dependencies.FUNCTION_DOMAINS); @@ -172,7 +161,10 @@ {#if selectedTab === 'nameserver'} - + {:else} (getDefaultTab()); let error = $state(null); - let verified = $state(false); + let verified: boolean | undefined = $state(undefined); function getDefaultTab() { return showCNAMETab ? 'cname' : showATab ? 'a' : showAAAATab ? 'aaaa' : 'nameserver'; } async function retryProxyRule() { + error = null; + try { - error = null; - const proxyRule = await sdk + const apexDomain = getApexDomain(selectedProxyRule.domain); + const domain = domainsList?.domains.find((d) => d.domain === apexDomain); + if (isCloud && domain) { + await sdk.forConsole.domains.updateNameservers({ + domainId: domain.$id + }); + } + } catch (error) { + // Ignore error + } + + try { + await sdk .forProject(page.params.region, page.params.project) .proxy.updateRuleVerification({ ruleId: selectedProxyRule.$id }); - verified = proxyRule.status === 'verified'; + verified = true; + addNotification({ + type: 'success', + message: 'Domain verified successfully' + }); + await invalidate(Dependencies.FUNCTION_DOMAINS); - - // This means domain verification using DNS records hasn't succeeded and the rule is still in initial state. - if (proxyRule.status === 'created') { - throw new Error( - 'Domain verification failed. Please check your domain settings or try again later' - ); - } - - if (verified) { - addNotification({ - type: 'success', - message: `${selectedProxyRule.domain} has been verified` - }); - } else { - addNotification({ - type: 'info', - message: 'Verification in progress' - }); - } show = false; trackEvent(Submit.DomainUpdateVerification); } catch (e) { + verified = false; error = e.message ?? 'Domain verification failed. Please check your domain settings or try again later'; @@ -130,7 +133,10 @@ {#if selectedTab === 'nameserver'} - + {:else} + {/if} {#if showLogs} diff --git a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte index 2f4250d19..eb2b2a214 100644 --- a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte @@ -30,16 +30,24 @@ async function addDomain() { const apexDomain = getApexDomain(domainName); - let domain = data.domainsList.domains.find((d: Models.Domain) => d.domain === apexDomain); + const domain = data.domainsList.domains.find((d: Models.Domain) => d.domain === apexDomain); if (apexDomain && !domain && isCloud) { try { - domain = await sdk.forConsole.domains.create({ + await sdk.forConsole.domains.create({ teamId: $project.teamId, domain: apexDomain }); } catch (error) { - // Apex domain creation error needs to be silent. + // apex might already be added on organization level, skip. + const alreadyAdded = error?.type === 'domain_already_exists'; + if (!alreadyAdded) { + addNotification({ + type: 'error', + message: error.message + }); + return; + } } } @@ -47,12 +55,18 @@ const rule = await sdk .forProject(page.params.region, page.params.project) .proxy.createAPIRule({ domain: domainName.toLocaleLowerCase() }); - if (rule?.status === 'verified') { + + await invalidate(Dependencies.DOMAINS); + + const verified = rule?.status !== 'created'; + if (verified) { + addNotification({ + type: 'success', + message: 'Domain verified successfully' + }); await goto(routeBase); - await invalidate(Dependencies.DOMAINS); } else { await goto(`${routeBase}/add-domain/verify-${domainName}?rule=${rule.$id}`); - await invalidate(Dependencies.DOMAINS); } } catch (error) { addNotification({ diff --git a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte index f0312de38..73f27dc72 100644 --- a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte @@ -11,7 +11,6 @@ } from '@appwrite.io/pink-svelte'; import { Button, Form } from '$lib/elements/forms'; import { sdk } from '$lib/stores/sdk'; - import { organization } from '$lib/stores/organization'; import { addNotification } from '$lib/stores/notifications'; import { goto, invalidate } from '$app/navigation'; import { Dependencies } from '$lib/constants'; @@ -23,6 +22,7 @@ import NameserverTable from '$lib/components/domains/nameserverTable.svelte'; import RecordTable from '$lib/components/domains/recordTable.svelte'; import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; + import { getApexDomain } from '$lib/helpers/tlds.js'; let { data } = $props(); @@ -55,41 +55,29 @@ } async function verify() { - const isNewDomain = - data.domainsList.domains.find((rule) => rule.domain === data.proxyRule.domain) === - undefined; try { - if (selectedTab !== 'nameserver') { - const ruleData = await sdk - .forProject(page.params.region, page.params.project) - .proxy.updateRuleVerification({ ruleId }); - verified = ruleData.status === 'verified'; - - // This means domain verification using DNS records hasn't succeeded and the rule is still in initial state. - if (ruleData.status === 'created') { - throw new Error( - 'Domain verification failed. Please check your domain settings or try again later' - ); - } - } else if (isNewDomain && isCloud) { - const domainData = await sdk.forConsole.domains.create({ - teamId: $organization.$id, - domain: data.proxyRule.domain - }); - verified = domainData.nameservers.toLowerCase() === 'appwrite'; - } - - if (verified) { - addNotification({ - type: 'success', - message: 'Domain added successfully' - }); - } else { - addNotification({ - type: 'info', - message: 'Verification in progress' + const apexDomain = getApexDomain(data.proxyRule.domain); + const domain = data.domainsList.domains.find((d) => d.domain === apexDomain); + if (isCloud && domain) { + await sdk.forConsole.domains.updateNameservers({ + domainId: domain.$id }); } + } catch (error) { + // Ignore error + } + + try { + await sdk + .forProject(page.params.region, page.params.project) + .proxy.updateRuleVerification({ ruleId }); + + verified = true; + addNotification({ + type: 'success', + message: 'Domain verified successfully' + }); + await goto(routeBase); await invalidate(Dependencies.DOMAINS); } catch (error) { diff --git a/src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte b/src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte index bd77890a8..2c345047a 100644 --- a/src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte +++ b/src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte @@ -13,13 +13,16 @@ import { Divider, Tabs } from '@appwrite.io/pink-svelte'; import NameserverTable from '$lib/components/domains/nameserverTable.svelte'; import RecordTable from '$lib/components/domains/recordTable.svelte'; + import { getApexDomain } from '$lib/helpers/tlds'; let { show = $bindable(), - selectedProxyRule + selectedProxyRule, + domainsList }: { show: boolean; selectedProxyRule: Models.ProxyRule; + domainsList?: Models.DomainsList; } = $props(); const showCNAMETab = $derived( @@ -40,43 +43,43 @@ let selectedTab = $state<'cname' | 'nameserver' | 'a' | 'aaaa'>(getDefaultTab()); let error = $state(null); - let verified = $state(false); + let verified: boolean | undefined = $state(undefined); function getDefaultTab() { return showCNAMETab ? 'cname' : showATab ? 'a' : showAAAATab ? 'aaaa' : 'nameserver'; } async function retryDomain() { + error = null; + try { - error = null; - const proxyRule = await sdk + const apexDomain = getApexDomain(selectedProxyRule.domain); + const domain = domainsList?.domains.find((d) => d.domain === apexDomain); + if (isCloud && domain) { + await sdk.forConsole.domains.updateNameservers({ + domainId: domain.$id + }); + } + } catch (error) { + // Ignore error + } + + try { + await sdk .forProject(page.params.region, page.params.project) .proxy.updateRuleVerification({ ruleId: selectedProxyRule.$id }); - verified = proxyRule.status === 'verified'; + verified = true; + addNotification({ + type: 'success', + message: 'Domain verified successfully' + }); + await invalidate(Dependencies.DOMAINS); - - // This means domain verification using DNS records hasn't succeeded and the rule is still in initial state. - if (proxyRule.status === 'created') { - throw new Error( - 'Domain verification failed. Please check your domain settings or try again later' - ); - } - - if (verified) { - addNotification({ - type: 'success', - message: `${selectedProxyRule.domain} has been verified` - }); - } else { - addNotification({ - type: 'info', - message: 'Verification in progress' - }); - } show = false; trackEvent(Submit.DomainUpdateVerification); } catch (e) { + verified = false; error = e.message ?? 'Domain verification failed. Please check your domain settings or try again later'; @@ -130,7 +133,10 @@ {#if selectedTab === 'nameserver'} - + {:else} + {/if} {#if showLogs} diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte index b4288a1f9..d511fc88f 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte @@ -58,16 +58,24 @@ async function addDomain() { const apexDomain = getApexDomain(domainName); const isSiteDomain = domainName.endsWith($regionalConsoleVariables._APP_DOMAIN_SITES); - let domain = data.domainsList.domains.find((d) => d.domain === apexDomain); + const domain = data.domainsList.domains.find((d) => d.domain === apexDomain); if (isCloud && apexDomain && !domain && !isSiteDomain) { try { - domain = await sdk.forConsole.domains.create({ + await sdk.forConsole.domains.create({ teamId: $project.teamId, domain: apexDomain }); } catch (error) { - // Apex domain creation error needs to be silent. + // apex might already be added on organization level, skip. + const alreadyAdded = error?.type === 'domain_already_exists'; + if (!alreadyAdded) { + addNotification({ + type: 'error', + message: error.message + }); + return; + } } } @@ -99,12 +107,18 @@ siteId: page.params.site }); } - if (rule?.status === 'verified') { + + await invalidate(Dependencies.SITES_DOMAINS); + + const verified = rule?.status !== 'created'; + if (verified) { + addNotification({ + type: 'success', + message: 'Domain added successfully' + }); await goto(routeBase); - await invalidate(Dependencies.SITES_DOMAINS); } else { await goto(`${routeBase}/add-domain/verify-${domainName}?rule=${rule.$id}`); - await invalidate(Dependencies.SITES_DOMAINS); } } catch (error) { addNotification({ diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte index 80fba1842..424749bbb 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte @@ -11,7 +11,6 @@ } from '@appwrite.io/pink-svelte'; import { Button, Form } from '$lib/elements/forms'; import { sdk } from '$lib/stores/sdk'; - import { organization } from '$lib/stores/organization'; import { addNotification } from '$lib/stores/notifications'; import { goto, invalidate } from '$app/navigation'; import { Dependencies } from '$lib/constants'; @@ -23,6 +22,7 @@ import RecordTable from '$lib/components/domains/recordTable.svelte'; import NameserverTable from '$lib/components/domains/nameserverTable.svelte'; import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; + import { getApexDomain } from '$lib/helpers/tlds.js'; let { data } = $props(); @@ -54,41 +54,29 @@ } async function verify() { - const isNewDomain = - data.domainsList.domains.findIndex((rule) => rule.domain === data.proxyRule.domain) === - -1; try { - if (selectedTab !== 'nameserver') { - const ruleData = await sdk - .forProject(page.params.region, page.params.project) - .proxy.updateRuleVerification({ ruleId }); - verified = ruleData.status === 'verified'; - - // This means domain verification using DNS records hasn't succeeded and the rule is still in initial state. - if (ruleData.status === 'created') { - throw new Error( - 'Domain verification failed. Please check your domain settings or try again later' - ); - } - } else if (isNewDomain && isCloud) { - const domainData = await sdk.forConsole.domains.create({ - teamId: $organization.$id, - domain: data.proxyRule.domain - }); - verified = domainData.nameservers.toLowerCase() === 'appwrite'; - } - - if (verified) { - addNotification({ - type: 'success', - message: 'Domain added successfully' - }); - } else { - addNotification({ - type: 'info', - message: 'Verification in progress' + const apexDomain = getApexDomain(data.proxyRule.domain); + const domain = data.domainsList.domains.find((d) => d.domain === apexDomain); + if (isCloud && domain) { + await sdk.forConsole.domains.updateNameservers({ + domainId: domain.$id }); } + } catch (error) { + // Ignore error + } + + try { + await sdk + .forProject(page.params.region, page.params.project) + .proxy.updateRuleVerification({ ruleId }); + + verified = true; + addNotification({ + type: 'success', + message: 'Domain verified successfully' + }); + await goto(routeBase); await invalidate(Dependencies.DOMAINS); await invalidate(Dependencies.SITES_DOMAINS); @@ -172,7 +160,10 @@ {#if selectedTab === 'nameserver'} - + {:else} (getDefaultTab()); let error = $state(null); - let verified = $state(false); + let verified: boolean | undefined = $state(undefined); function getDefaultTab() { return showCNAMETab ? 'cname' : showATab ? 'a' : showAAAATab ? 'aaaa' : 'nameserver'; } async function retryDomain() { + error = null; + try { - error = null; - const proxyRule = await sdk + const apexDomain = getApexDomain(selectedProxyRule.domain); + const domain = domainsList?.domains.find((d) => d.domain === apexDomain); + if (isCloud && domain) { + await sdk.forConsole.domains.updateNameservers({ + domainId: domain.$id + }); + } + } catch (error) { + // Ignore error + } + + try { + await sdk .forProject(page.params.region, page.params.project) .proxy.updateRuleVerification({ ruleId: selectedProxyRule.$id }); - verified = proxyRule.status === 'verified'; + verified = true; + addNotification({ + type: 'success', + message: 'Domain verified successfully' + }); + await invalidate(Dependencies.SITES_DOMAINS); - - // This means domain verification using DNS records hasn't succeeded and the rule is still in initial state. - if (proxyRule.status === 'created') { - throw new Error( - 'Domain verification failed. Please check your domain settings or try again later' - ); - } - - if (verified) { - addNotification({ - type: 'success', - message: `${selectedProxyRule.domain} has been verified` - }); - } else { - addNotification({ - type: 'info', - message: 'Verification in progress' - }); - } show = false; trackEvent(Submit.DomainUpdateVerification); } catch (e) { + verified = false; error = e.message ?? 'Domain verification failed. Please check your domain settings or try again later'; @@ -130,7 +133,10 @@ {#if selectedTab === 'nameserver'} - + {:else} + {/if} {#if showLogs}