update enable custom domain (new dialog, email verification and fixed issue where cant create new cert)

main
TZGyn 1 year ago
parent 63af563652
commit 9c13c29cfa
Signed by: TZGyn
GPG Key ID: 122EAF77AE81FD4A

@ -1,10 +1,8 @@
<script lang="ts">
import * as Tabs from '$lib/components/ui/tabs/index.js'
import * as Card from '$lib/components/ui/card/index.js'
import { Button } from '$lib/components/ui/button/index.js'
import { Input } from '$lib/components/ui/input/index.js'
import { Label } from '$lib/components/ui/label/index.js'
export let host: string
export let cname_record: string
export let a_record: string
export let aaaa_record: string
@ -24,12 +22,16 @@
{#if cname_record}
<Tabs.Content value="cname">
<Card.Root>
<Card.Header class="grid grid-cols-[80px_1fr] space-y-0 py-4">
<Card.Header
class="grid grid-cols-[80px_1fr_1fr] space-y-0 py-4">
<Card.Title>Type</Card.Title>
<Card.Title>Host</Card.Title>
<Card.Title>Value</Card.Title>
</Card.Header>
<Card.Footer class="bg-muted grid grid-cols-[80px_1fr] py-4">
<Card.Footer
class="bg-muted grid grid-cols-[80px_1fr_1fr] py-4">
<Card.Description>CNAME</Card.Description>
<Card.Description>{host}</Card.Description>
<Card.Description>{cname_record}</Card.Description>
</Card.Footer>
</Card.Root>
@ -41,13 +43,15 @@
{#if a_record}
<Card.Root>
<Card.Header
class="grid grid-cols-[80px_1fr] space-y-0 py-4">
class="grid grid-cols-[80px_1fr_1fr] space-y-0 py-4">
<Card.Title>Type</Card.Title>
<Card.Title>Host</Card.Title>
<Card.Title>Value</Card.Title>
</Card.Header>
<Card.Footer
class="bg-muted grid grid-cols-[80px_1fr] py-4">
class="bg-muted grid grid-cols-[80px_1fr_1fr] py-4">
<Card.Description>A</Card.Description>
<Card.Description>{host}</Card.Description>
<Card.Description>{a_record}</Card.Description>
</Card.Footer>
</Card.Root>
@ -55,13 +59,15 @@
{#if aaaa_record}
<Card.Root>
<Card.Header
class="grid grid-cols-[80px_1fr] space-y-0 py-4">
class="grid grid-cols-[80px_1fr_1fr] space-y-0 py-4">
<Card.Title>Type</Card.Title>
<Card.Title>Host</Card.Title>
<Card.Title>Value</Card.Title>
</Card.Header>
<Card.Footer
class="bg-muted grid grid-cols-[80px_1fr] py-4">
class="bg-muted grid grid-cols-[80px_1fr_1fr] py-4">
<Card.Description>AAAA</Card.Description>
<Card.Description>{host}</Card.Description>
<Card.Description>{aaaa_record}</Card.Description>
</Card.Footer>
</Card.Root>

@ -1,11 +1,17 @@
import { db } from '$lib/db'
import type { PageServerLoad, Actions } from './$types'
import { fail } from '@sveltejs/kit'
import { setError, superValidate } from 'sveltekit-superforms'
import {
message,
setError,
setMessage,
superValidate,
fail,
} from 'sveltekit-superforms'
import {
formSchema,
deleteSchema,
customDomainFormSchema,
enableCustomDomainFormSchema,
} from './schema'
import { zod } from 'sveltekit-superforms/adapters'
import {
@ -48,6 +54,10 @@ export const load = (async (event) => {
},
zod(formSchema),
),
enableCustomDomainForm: await superValidate(
{ enableDomain: project.custom_domain || '' },
zod(enableCustomDomainFormSchema),
),
customDomainForm: await superValidate(
{ domain: project.custom_domain || '' },
zod(customDomainFormSchema),
@ -95,8 +105,30 @@ export const actions: Actions = {
}
},
enable_custom_domain: async (event) => {
const form = await superValidate(
event,
zod(enableCustomDomainFormSchema),
)
if (!form.valid) {
return fail(400, {
form,
})
}
if (form.data.enableDomain === '') {
return setError(form, 'enableDomain', 'domain cannot be empty')
}
const userId = event.locals.user.id
if (!event.locals.user.email_verified) {
return setError(
form,
'enableDomain',
'Please verify your email account',
)
}
const existingProject = await db.query.project.findFirst({
where: (projectTable, { eq, and }) =>
and(
@ -109,9 +141,43 @@ export const actions: Actions = {
return fail(400, { message: 'Project not found' })
}
const sameDomainDifferentProject =
await db.query.project.findFirst({
where: (projectTable, { eq, and, ne }) =>
and(
ne(projectTable.uuid, event.params.id),
eq(projectTable.custom_domain, form.data.enableDomain),
),
})
if (sameDomainDifferentProject) {
return setError(form, 'enableDomain', 'Domain already taken')
}
const domainAvailable = await checkDomainAvailable(
form.data.enableDomain,
)
if (!domainAvailable) {
return setError(form, 'enableDomain', 'Domain is not available')
}
const customDomain = await createCustomDomain(
form.data.enableDomain,
)
if (!customDomain.success) {
return setError(
form,
'enableDomain',
'Cannot create custom domain',
)
}
await db
.update(projectTable)
.set({
custom_domain: form.data.enableDomain,
enable_custom_domain: true,
})
.where(
@ -121,7 +187,7 @@ export const actions: Actions = {
),
)
return { message: 'Custom domain enabled' }
return { form }
},
disable_custom_domain: async (event) => {
const userId = event.locals.user.id

@ -64,6 +64,24 @@
enhance: customDomainEnhance,
submitting: customDomainSubmitting,
} = customDomainForm
const enableCustomDomainForm = superForm(
data.enableCustomDomainForm,
{
onUpdated: ({ form }) => {
if (form.valid) {
toast.success(form.message)
}
},
},
)
const {
form: enableCustomDomainFormData,
enhance: enableCustomDomainEnchance,
submit: enableCustomDomainSubmit,
submitting: enableCustomDomainSubmitting,
} = enableCustomDomainForm
</script>
<ScrollArea>
@ -114,45 +132,94 @@
</div>
<div>
{#if !data.project.enable_custom_domain}
<AlertDialog.Root>
<AlertDialog.Trigger asChild let:builder>
<Dialog.Root>
<Dialog.Trigger asChild let:builder>
<Button builders={[builder]}>
Enable Custom Domain
</Button>
</AlertDialog.Trigger>
<AlertDialog.Content>
<AlertDialog.Header>
<AlertDialog.Title>
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>
Are you absolutely sure?
</AlertDialog.Title>
<AlertDialog.Description>
</Dialog.Title>
<Dialog.Description>
Enabling a custom domain will allow you to use
your project with a custom domain.
</AlertDialog.Description>
{#if data.cnameRecord || data.aRecord || data.aaaaRecord}
<DnsInfo
cname_record={data.cnameRecord}
a_record={data.aRecord}
aaaa_record={data.aaaaRecord} />
{/if}
</AlertDialog.Header>
<AlertDialog.Footer>
<AlertDialog.Cancel>Cancel</AlertDialog.Cancel>
<AlertDialog.Action
on:click={async () => {
await fetch('?/enable_custom_domain', {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
},
})
await invalidateAll()
}}>
Continue
</AlertDialog.Action>
</AlertDialog.Footer>
</AlertDialog.Content>
</AlertDialog.Root>
</Dialog.Description>
</Dialog.Header>
<form
method="POST"
action="?/enable_custom_domain"
class="flex flex-col gap-6"
use:enableCustomDomainEnchance>
<Form.Field
form={enableCustomDomainForm}
name="enableDomain"
class="flex flex-col gap-2">
<Form.Control let:attrs>
<Form.Label>Add Custom Domain</Form.Label>
<div class="flex items-center space-x-2">
<Input
{...attrs}
bind:value={$enableCustomDomainFormData.enableDomain}
placeholder="your-custom-domain.com" />
</div>
</Form.Control>
<Form.Description
class="flex items-center justify-between gap-2">
<Tooltip.Root>
<Tooltip.Trigger
class="flex items-center gap-2">
<InfoIcon class="h-4 w-4" />
Update Project Domain (leave blank to use default)
</Tooltip.Trigger>
<Tooltip.Content>
<p>
Only include the domain name, not the
protocol.
</p>
<p>
Make sure the domain is pointing to our
server.
</p>
<p>
Please contact us if you need a custom
domain.
</p>
</Tooltip.Content>
</Tooltip.Root>
</Form.Description>
<Form.FieldErrors />
</Form.Field>
</form>
{#if data.cnameRecord || data.aRecord || data.aaaaRecord}
<DnsInfo
host={$enableCustomDomainFormData.enableDomain}
cname_record={data.cnameRecord}
a_record={data.aRecord}
aaaa_record={data.aaaaRecord} />
{/if}
<Dialog.Footer>
<Dialog.Close asChild let:builder>
<Button
builders={[builder]}
variant={'outline'}>
Cancel
</Button>
</Dialog.Close>
<Button on:click={enableCustomDomainSubmit}>
{#if $enableCustomDomainSubmitting}
<LoaderCircle class="animate-spin" />
{/if}
Enable
</Button>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Root>
{:else}
<AlertDialog.Root>
<AlertDialog.Trigger asChild let:builder>

@ -12,6 +12,10 @@ export const formSchema = z.object({
.max(7),
})
export const enableCustomDomainFormSchema = z.object({
enableDomain: z.string(),
})
export const customDomainFormSchema = z.object({
domain: z.string(),
})

Loading…
Cancel
Save