CreateAuth0Dialog.tsx179 lines · main
1import { zodResolver } from '@hookform/resolvers/zod'
2import { useParams } from 'common'
3import { Trash } from 'lucide-react'
4import { useEffect } from 'react'
5import { SubmitHandler, useForm } from 'react-hook-form'
6import { toast } from 'sonner'
7import {
8 Button,
9 Dialog,
10 DialogContent,
11 DialogFooter,
12 DialogHeader,
13 DialogSection,
14 DialogTitle,
15 Form,
16 FormControl,
17 FormField,
18 Input,
19 Separator,
20} from 'ui'
21import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
22import * as z from 'zod'
23
24import { useCreateThirdPartyAuthIntegrationMutation } from '@/data/third-party-auth/integration-create-mutation'
25
26interface CreateAuth0IntegrationProps {
27 visible: boolean
28 onClose: () => void
29 // TODO: Remove this if this Dialog is only used for creating.
30 onDelete: () => void
31}
32
33const FORM_ID = 'create-auth0-auth-integration-form'
34
35const FormSchema = z.object({
36 enabled: z.boolean(),
37 auth0DomainName: z
38 .string()
39 .trim()
40 .min(1)
41 .regex(/^[A-Za-z0-9-.]+$/, 'Project IDs should only have alphanumeric characters and hyphens.'), // Only allow alphanumeric characters and hyphens.
42})
43
44export const CreateAuth0IntegrationDialog = ({
45 visible,
46 onClose,
47 onDelete,
48}: CreateAuth0IntegrationProps) => {
49 // TODO: Remove this if this Dialog is only used for creating.
50 const isCreating = true
51
52 const { ref: projectRef } = useParams()
53 const { mutate: createAuthIntegration, isPending } = useCreateThirdPartyAuthIntegrationMutation({
54 onSuccess: () => {
55 toast.success(`Successfully created a new Auth0 Auth integration.`)
56 onClose()
57 },
58 })
59
60 const form = useForm<z.infer<typeof FormSchema>>({
61 resolver: zodResolver(FormSchema as any),
62 defaultValues: {
63 enabled: true,
64 auth0DomainName: '',
65 },
66 })
67
68 useEffect(() => {
69 if (visible) {
70 form.reset({
71 enabled: true,
72 auth0DomainName: '',
73 })
74
75 // the form input doesn't exist when the form is reset
76 setTimeout(() => {
77 form.setFocus('auth0DomainName')
78 }, 25)
79 }
80 }, [visible])
81
82 const onSubmit: SubmitHandler<z.infer<typeof FormSchema>> = async (values) => {
83 createAuthIntegration({
84 projectRef: projectRef!,
85 oidcIssuerUrl: `https://${values.auth0DomainName}.auth0.com`,
86 })
87 }
88
89 return (
90 <Dialog open={visible} onOpenChange={() => onClose()}>
91 <DialogContent>
92 <DialogHeader>
93 <DialogTitle className="truncate">
94 {isCreating ? `Add new Auth0 connection` : `Update existing Auth0 connection`}
95 </DialogTitle>
96 </DialogHeader>
97 <Separator />
98 <DialogSection>
99 <Form {...form}>
100 <form id={FORM_ID} onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
101 {/* Enabled flag can't be changed for now because there's no update API call for integrations */}
102 {/* <FormField
103 key="enabled"
104 control={form.control}
105 name="enabled"
106 render={({ field }) => (
107 <FormItemLayout
108 className="px-8"
109 label={`Enable Auth0 Auth Connection`}
110 layout="flex"
111 >
112 <FormControl>
113 <Switch
114 checked={field.value}
115 onCheckedChange={field.onChange}
116 disabled={field.disabled}
117 />
118 </FormControl>
119 </FormItemLayout>
120 )}
121 />
122 <Separator /> */}
123 <p className="text-sm text-foreground-light">
124 This will enable a JWT token from your Auth0 project to access data from this
125 Briven project.
126 </p>
127 <FormField
128 key="auth0DomainName"
129 control={form.control}
130 name="auth0DomainName"
131 render={({ field }) => (
132 <FormItemLayout label="Auth0 domain name">
133 <div className="flex flex-row">
134 <Button
135 type="default"
136 size="small"
137 className="px-2 text-foreground-light rounded-r-none"
138 onClick={() => form.setFocus('auth0DomainName')}
139 >
140 https://
141 </Button>
142 <FormControl>
143 <Input className="border-l-0 rounded-none border-r-0 z-50" {...field} />
144 </FormControl>
145 <Button
146 type="default"
147 size="small"
148 className="px-2 text-foreground-light rounded-l-none"
149 onClick={() => form.setFocus('auth0DomainName')}
150 >
151 .auth0.com
152 </Button>
153 </div>
154 </FormItemLayout>
155 )}
156 />
157 </form>
158 </Form>
159 </DialogSection>
160 <DialogFooter>
161 {!isCreating && (
162 <div className="flex-1">
163 <Button type="danger" onClick={() => onDelete()} icon={<Trash />}>
164 Remove connection
165 </Button>
166 </div>
167 )}
168
169 <Button disabled={isPending} type="default" onClick={() => onClose()}>
170 Cancel
171 </Button>
172 <Button form={FORM_ID} htmlType="submit" disabled={isPending} loading={isPending}>
173 {isCreating ? 'Create connection' : 'Update connection'}
174 </Button>
175 </DialogFooter>
176 </DialogContent>
177 </Dialog>
178 )
179}