Skip to content

Commit 06d34f2

Browse files
hmacrMeldiron
andauthored
Fix custom domain flow (#2783)
* Fix custom domain flow * Failing test fix * lint --------- Co-authored-by: Matej Bačo <matejbaco2000@gmail.com>
1 parent 006a6ac commit 06d34f2

9 files changed

Lines changed: 271 additions & 127 deletions

File tree

src/lib/components/domains/nameserverTable.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
{#if verified === true}
2020
<Badge variant="secondary" type="success" size="xs" content="Verified" />
2121
{:else if verified === false}
22-
<Badge variant="secondary" type="warning" size="xs" content="Verification failed" />
22+
<Badge variant="secondary" type="error" size="xs" content="Verification failed" />
2323
{/if}
2424
</Layout.Stack>
2525
<Typography.Text variant="m-400">

src/lib/components/domains/recordTable.svelte

Lines changed: 114 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,56 @@
99
Alert
1010
} from '@appwrite.io/pink-svelte';
1111
import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store';
12+
import { getSubdomain } from '$lib/helpers/tlds';
13+
import { isCloud } from '$lib/system';
1214
13-
export let domain: string;
14-
export let verified = undefined;
15-
export let variant: 'cname' | 'a' | 'aaaa';
16-
export let service: 'sites' | 'general' = 'general';
15+
let {
16+
domain,
17+
verified = undefined,
18+
variant,
19+
service = 'general',
20+
ruleStatus = undefined,
21+
onNavigateToNameservers = () => {},
22+
onNavigateToA = () => {},
23+
onNavigateToAAAA = () => {}
24+
}: {
25+
domain: string;
26+
verified?: boolean;
27+
variant: 'cname' | 'a' | 'aaaa';
28+
service?: 'sites' | 'functions' | 'general';
29+
ruleStatus?: 'created' | 'verifying' | 'unverified' | 'verified';
30+
onNavigateToNameservers?: () => void;
31+
onNavigateToA?: () => void;
32+
onNavigateToAAAA?: () => void;
33+
} = $props();
1734
18-
let subdomain = domain?.split('.')?.slice(0, -2)?.join('.');
35+
const subdomain = $derived(getSubdomain(domain));
36+
const caaText = $derived(
37+
$regionalConsoleVariables._APP_DOMAIN_TARGET_CAA?.includes(' ')
38+
? $regionalConsoleVariables._APP_DOMAIN_TARGET_CAA
39+
: `0 issue "${$regionalConsoleVariables._APP_DOMAIN_TARGET_CAA}"`
40+
);
41+
const aTabVisible = $derived(
42+
!isCloud &&
43+
Boolean($regionalConsoleVariables._APP_DOMAIN_TARGET_A) &&
44+
$regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1'
45+
);
46+
const aaaaTabVisible = $derived(
47+
!isCloud &&
48+
Boolean($regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA) &&
49+
$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1'
50+
);
1951
2052
function setTarget() {
2153
switch (variant) {
2254
case 'cname':
23-
return service === 'general'
24-
? $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME
25-
: $regionalConsoleVariables._APP_DOMAIN_SITES;
55+
if (service === 'sites') {
56+
return $regionalConsoleVariables._APP_DOMAIN_SITES;
57+
} else if (service === 'functions') {
58+
return $regionalConsoleVariables._APP_DOMAIN_FUNCTIONS;
59+
} else {
60+
return $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME;
61+
}
2662
case 'a':
2763
return $regionalConsoleVariables._APP_DOMAIN_TARGET_A;
2864
case 'aaaa':
@@ -37,42 +73,90 @@
3773
<Typography.Text variant="l-500" color="--fgcolor-neutral-primary">
3874
{domain}
3975
</Typography.Text>
40-
{#if verified === true}
41-
<Badge variant="secondary" type="success" size="xs" content="Verified" />
42-
{:else if verified === false}
43-
<Badge variant="secondary" type="warning" size="xs" content="Verification failed" />
76+
{#if verified !== undefined}
77+
{#if ruleStatus === 'created'}
78+
<Badge
79+
variant="secondary"
80+
type="error"
81+
size="xs"
82+
content="Verification failed" />
83+
{:else if ruleStatus === 'verifying'}
84+
<Badge variant="secondary" size="xs" content="Generating certificate" />
85+
{:else if ruleStatus === 'unverified'}
86+
<Badge
87+
variant="secondary"
88+
type="error"
89+
size="xs"
90+
content="Certificate generation failed" />
91+
{:else if verified === true}
92+
<Badge variant="secondary" type="success" size="xs" content="Verified" />
93+
{/if}
4494
{/if}
4595
</Layout.Stack>
4696
<Typography.Text variant="m-400">
47-
Add the following record on your DNS provider. Note that DNS changes may take time to
48-
propagate fully.
97+
Add the following {$regionalConsoleVariables._APP_DOMAIN_TARGET_CAA
98+
? 'records'
99+
: 'record'} on your DNS provider. Note that DNS changes may take up to 48 hours to propagate
100+
fully.
49101
</Typography.Text>
50102
</Layout.Stack>
51103

52-
<Table.Root columns={3} let:root>
104+
<Table.Root
105+
columns={[
106+
{ id: 'type', width: { min: 150 } },
107+
{ id: 'name', width: { min: 80 } },
108+
{ id: 'value', width: { min: 100 } }
109+
]}
110+
let:root>
53111
<svelte:fragment slot="header" let:root>
54-
<Table.Header.Cell {root}>Type</Table.Header.Cell>
55-
<Table.Header.Cell {root}>Name</Table.Header.Cell>
56-
<Table.Header.Cell {root}>Value</Table.Header.Cell>
112+
<Table.Header.Cell column="type" {root}>Type</Table.Header.Cell>
113+
<Table.Header.Cell column="name" {root}>Name</Table.Header.Cell>
114+
<Table.Header.Cell column="value" {root}>Value</Table.Header.Cell>
57115
</svelte:fragment>
58116
<Table.Row.Base {root}>
59-
<Table.Cell {root}>{variant.toUpperCase()}</Table.Cell>
60-
<Table.Cell {root}>{subdomain || '@'}</Table.Cell>
61-
<Table.Cell {root}>
117+
<Table.Cell column="type" {root}>{variant.toUpperCase()}</Table.Cell>
118+
<Table.Cell column="name" {root}>{subdomain || '@'}</Table.Cell>
119+
<Table.Cell column="value" {root}>
62120
<InteractiveText variant="copy" isVisible text={setTarget()} />
63121
</Table.Cell>
64122
</Table.Row.Base>
123+
{#if $regionalConsoleVariables._APP_DOMAIN_TARGET_CAA}
124+
<Table.Row.Base {root}>
125+
<Table.Cell column="type" {root}>
126+
<Layout.Stack gap="s" direction="row" alignItems="center">
127+
<span>CAA</span>
128+
<Badge variant="secondary" size="xs" content="Recommended" />
129+
</Layout.Stack>
130+
</Table.Cell>
131+
<Table.Cell column="name" {root}>@</Table.Cell>
132+
<Table.Cell column="value" {root}>
133+
<InteractiveText variant="copy" isVisible text={caaText} />
134+
</Table.Cell>
135+
</Table.Row.Base>
136+
{/if}
65137
</Table.Root>
66138
<Layout.Stack gap="s" direction="row" alignItems="center">
67-
{#if variant === 'cname'}
68-
<Alert.Inline>
69-
If your domain uses CAA records, ensure certainly.com is authorized — otherwise, SSL
70-
setup may fail. A list of all domain providers and their DNS setting is available <Link
71-
variant="muted"
72-
external
73-
href="https://appwrite.io/docs/advanced/platform/custom-domains">here</Link
74-
>.
75-
</Alert.Inline>
139+
{#if variant === 'cname' && !subdomain}
140+
{#if isCloud}
141+
<Alert.Inline>
142+
Since <Badge variant="secondary" size="s" content={domain} /> is an apex domain, CNAME
143+
record is only supported by certain providers. If yours doesn't, please verify using
144+
<Link variant="muted" on:click={onNavigateToNameservers}>nameservers</Link> instead.
145+
</Alert.Inline>
146+
{:else if aTabVisible || aaaaTabVisible}
147+
<Alert.Inline>
148+
Since <Badge variant="secondary" size="s" content={domain} /> is an apex domain, CNAME
149+
record is only supported by certain providers. If yours doesn't, please verify using
150+
{#if aTabVisible}
151+
<Link variant="muted" on:click={onNavigateToA}>A record</Link>
152+
{#if aaaaTabVisible}
153+
or <Link variant="muted" on:click={onNavigateToAAAA}>AAAA record</Link
154+
>{/if}
155+
{:else if aaaaTabVisible}
156+
<Link variant="muted" on:click={onNavigateToAAAA}>AAAA record</Link>
157+
{/if} instead.
158+
</Alert.Inline>
159+
{/if}
76160
{:else}
77161
<Typography.Text variant="m-400" color="--fgcolor-neutral-secondary">
78162
A list of all domain providers and their DNS setting is available <Link

src/lib/components/navbar.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@
326326
]} />
327327

328328
{#if dailyCredits !== null}
329-
<Typography.Caption>
329+
<Typography.Caption variant="400">
330330
{dailyCredits} daily and {monthlyCredits} monthly
331331
credits
332332
</Typography.Caption>

src/lib/helpers/tlds.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,12 @@ export function isASubdomain(domain: string | null): boolean {
1818

1919
return !!subdomain;
2020
}
21+
22+
/**
23+
* Returns the subdomain part from a full domain string.
24+
*/
25+
export function getSubdomain(domain: string): string {
26+
if (!domain) return '';
27+
28+
return parse(domain, { allowPrivateDomains: true }).subdomain || '';
29+
}

src/lib/studio/domains/add/view.svelte

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
}: {
2525
show: boolean;
2626
siteId: string;
27-
onDomainAdded: (rule: string, domain: Models.Domain, verified: boolean) => void;
27+
onDomainAdded: (rule: Models.ProxyRule, domain: Models.Domain, verified: boolean) => void;
2828
} = $props();
2929
3030
let domainName = $state('');
@@ -84,9 +84,15 @@
8484
siteId
8585
});
8686
87-
const verified = rule?.status === 'verified';
88-
onDomainAdded(rule.$id, domain, verified);
89-
if (verified) await invalidate(Dependencies.SITES_DOMAINS);
87+
const verified = rule?.status !== 'created';
88+
if (verified) {
89+
await invalidate(Dependencies.SITES_DOMAINS);
90+
addNotification({
91+
type: 'success',
92+
message: 'Domain verified successfully'
93+
});
94+
}
95+
onDomainAdded(rule, domain, verified);
9096
9197
show = false;
9298
} catch (error) {

src/lib/studio/domains/manage/table.svelte

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -108,27 +108,46 @@
108108
</Table.Row.Base>
109109
{/each}
110110
{:else if proxyRules && proxyRules.total > 0}
111-
{#each proxyRules.rules as rule}
111+
{#each proxyRules.rules as proxyRule}
112+
{@const isRetryable =
113+
proxyRule.status === 'created' || proxyRule.status === 'unverified'}
112114
<Table.Row.Base {root}>
113115
<Table.Cell column="domain" {root}>
114116
<Layout.Stack direction="row" gap="xs" alignItems="center">
115-
<Link external variant="quiet" href={`${$regionalProtocol}${rule.domain}`}>
117+
<Link
118+
external
119+
variant="quiet"
120+
href={`${$regionalProtocol}${proxyRule.domain}`}>
116121
<Layout.Stack direction="row" gap="xxs" alignItems="center">
117122
<Typography.Text truncate>
118-
{rule.domain}
123+
{proxyRule.domain}
119124
</Typography.Text>
120125
<Icon size="xs" icon={IconExternalLink} />
121126
</Layout.Stack>
122127
</Link>
123128

124-
{#if rule.status === 'verifying'}
125-
<Badge variant="secondary" content="Verifying" size="s" />
126-
{:else if rule.status !== 'verified'}
129+
{#if proxyRule.status !== 'verified'}
127130
<Badge
128-
size="s"
129-
type="warning"
130131
variant="secondary"
131-
content="Verification failed" />
132+
type={proxyRule.status === 'verifying' ? undefined : 'error'}
133+
content={proxyRule.status === 'created'
134+
? 'Verification failed'
135+
: proxyRule.status === 'verifying'
136+
? 'Generating certificate'
137+
: 'Certificate generation failed'}
138+
size="xs" />
139+
{/if}
140+
{#if isRetryable}
141+
<Link
142+
size="s"
143+
variant="muted"
144+
on:click={(e) => {
145+
e.preventDefault();
146+
selectedProxyRule = proxyRule;
147+
showRetry = true;
148+
}}>
149+
Retry
150+
</Link>
132151
{/if}
133152
</Layout.Stack>
134153
</Table.Cell>
@@ -145,7 +164,7 @@
145164
</Button>
146165

147166
<svelte:fragment slot="tooltip" let:toggle>
148-
{@render domainActions(rule, toggle)}
167+
{@render domainActions(proxyRule, toggle, isRetryable)}
149168
</svelte:fragment>
150169
</Popover>
151170
</Table.Cell>
@@ -169,12 +188,12 @@
169188
<RetryDomainModal bind:show={showRetry} {selectedProxyRule} />
170189
{/if}
171190

172-
{#snippet domainActions(rule, toggle)}
191+
{#snippet domainActions(rule, toggle, isRetryable)}
173192
<ActionMenu.Root>
174193
<ActionMenu.Item.Anchor href={`${$regionalProtocol}${rule.domain}`} external>
175194
Open domain
176195
</ActionMenu.Item.Anchor>
177-
{#if rule.status !== 'verified' && rule.status !== 'verifying'}
196+
{#if isRetryable}
178197
<ActionMenu.Item.Button
179198
leadingIcon={IconRefresh}
180199
on:click={() => {

0 commit comments

Comments
 (0)