SecurityOptions.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import { UseFormReturn } from 'react-hook-form'
  2. import {
  3. Checkbox,
  4. cn,
  5. FormControl,
  6. FormDescription,
  7. FormField,
  8. FormItem,
  9. FormLabel,
  10. Tooltip,
  11. TooltipContent,
  12. TooltipTrigger,
  13. useWatch,
  14. } from 'ui'
  15. import { Admonition } from 'ui-patterns'
  16. import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
  17. import { CreateProjectForm } from './ProjectCreation.schema'
  18. import { InlineLink } from '@/components/ui/InlineLink'
  19. import Panel from '@/components/ui/Panel'
  20. import { useTrackDefaultPrivilegesExposure } from '@/hooks/misc/useDataApiRevokeOnCreateDefault'
  21. import { DOCS_URL } from '@/lib/constants'
  22. interface SecurityOptionsProps {
  23. form: UseFormReturn<CreateProjectForm>
  24. layout?: 'vertical' | 'horizontal'
  25. }
  26. export const SecurityOptions = ({ form, layout = 'horizontal' }: SecurityOptionsProps) => {
  27. const dataApi = useWatch({ control: form.control, name: 'dataApi' })
  28. const dataApiDefaultPrivileges = useWatch({
  29. control: form.control,
  30. name: 'dataApiDefaultPrivileges',
  31. })
  32. const hasUserModified = form.getFieldState('dataApiDefaultPrivileges', form.formState).isDirty
  33. useTrackDefaultPrivilegesExposure({
  34. surface: 'main',
  35. dataApiDefaultPrivileges: dataApiDefaultPrivileges ?? true,
  36. hasUserModified,
  37. })
  38. return (
  39. <Panel.Content className="pb-8">
  40. <FormItemLayout layout={layout} label="Security" isReactForm={false}>
  41. <div className="flex flex-col gap-4">
  42. <FormField
  43. name="dataApi"
  44. control={form.control}
  45. render={({ field }) => (
  46. <FormItem className="flex items-start gap-3">
  47. <FormControl>
  48. <Checkbox
  49. checked={field.value}
  50. disabled={field.disabled}
  51. onCheckedChange={(value) => field.onChange(value === true)}
  52. />
  53. </FormControl>
  54. <div className="space-y-1">
  55. <FormLabel className="text-sm text-foreground">Enable Data API</FormLabel>
  56. <FormDescription className="text-foreground-lighter">
  57. Autogenerate a RESTful API for your public schema. Recommended if using a client
  58. library like{' '}
  59. <InlineLink href={`${DOCS_URL}/reference/javascript/introduction`}>
  60. briven-js
  61. </InlineLink>
  62. .
  63. </FormDescription>
  64. </div>
  65. </FormItem>
  66. )}
  67. />
  68. <FormField
  69. name="dataApiDefaultPrivileges"
  70. control={form.control}
  71. render={({ field }) => (
  72. <FormItem
  73. className={cn(
  74. 'flex items-start gap-3',
  75. !dataApi && 'opacity-50 cursor-not-allowed'
  76. )}
  77. >
  78. <FormControl>
  79. {dataApi ? (
  80. <Checkbox
  81. checked={field.value}
  82. disabled={field.disabled}
  83. onCheckedChange={(value) => field.onChange(value === true)}
  84. />
  85. ) : (
  86. <Tooltip>
  87. <TooltipTrigger asChild>
  88. <span className="cursor-not-allowed">
  89. <Checkbox checked={field.value} disabled />
  90. </span>
  91. </TooltipTrigger>
  92. <TooltipContent side="top">
  93. Enable the Data API to configure default privileges.
  94. </TooltipContent>
  95. </Tooltip>
  96. )}
  97. </FormControl>
  98. <div className="space-y-1">
  99. <FormLabel
  100. className={cn('text-sm text-foreground', !dataApi && 'text-foreground-muted')}
  101. >
  102. Automatically expose new tables
  103. </FormLabel>
  104. <FormDescription className="text-foreground-lighter">
  105. Grants privileges to Data API roles by default, exposing new tables.
  106. <br />
  107. <strong className="font-medium text-foreground-light">
  108. We recommend disabling this to control access manually.
  109. </strong>
  110. </FormDescription>
  111. </div>
  112. </FormItem>
  113. )}
  114. />
  115. <FormField
  116. name="enableRlsEventTrigger"
  117. control={form.control}
  118. render={({ field }) => (
  119. <FormItem className="flex items-start gap-3">
  120. <FormControl>
  121. <Checkbox
  122. checked={field.value}
  123. disabled={field.disabled}
  124. onCheckedChange={(value) => field.onChange(value === true)}
  125. />
  126. </FormControl>
  127. <div className="space-y-1">
  128. <FormLabel className="text-sm text-foreground">Enable automatic RLS</FormLabel>
  129. <FormDescription className="text-foreground-lighter">
  130. Create an event trigger that automatically enables Row Level Security on all new
  131. tables in the public schema.
  132. </FormDescription>
  133. </div>
  134. </FormItem>
  135. )}
  136. />
  137. {!dataApi && (
  138. <Admonition
  139. type="warning"
  140. title="Client libraries need Data API to query your database"
  141. >
  142. Disabling it means briven-js and similar libraries can't query or mutate data.
  143. </Admonition>
  144. )}
  145. </div>
  146. </FormItemLayout>
  147. </Panel.Content>
  148. )
  149. }