CreateAuth0Dialog.tsx 5.6 KB

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