PolicyDefinition.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import { usePrevious } from '@uidotdev/usehooks'
  2. import { noop } from 'lodash'
  3. import { HelpCircle } from 'lucide-react'
  4. import { useEffect } from 'react'
  5. import { Tooltip, TooltipContent, TooltipTrigger } from 'ui'
  6. import SqlEditor from '@/components/ui/SqlEditor'
  7. interface PolicyDefinitionProps {
  8. operation: string
  9. definition: string
  10. check: string
  11. onUpdatePolicyUsing: (using: string | undefined) => void
  12. onUpdatePolicyCheck: (check: string | undefined) => void
  13. }
  14. const PolicyDefinition = ({
  15. operation = '',
  16. definition = '',
  17. check = '',
  18. onUpdatePolicyUsing = noop,
  19. onUpdatePolicyCheck = noop,
  20. }: PolicyDefinitionProps) => {
  21. const showUsing = (operation: string) =>
  22. ['SELECT', 'UPDATE', 'DELETE', 'ALL'].includes(operation) || !operation
  23. const showCheck = (operation: string) => ['INSERT', 'UPDATE', 'ALL'].includes(operation)
  24. const previousOperation = usePrevious(operation) || ''
  25. useEffect(() => {
  26. if (showUsing(previousOperation) && !showUsing(operation)) onUpdatePolicyUsing(undefined)
  27. if (showCheck(previousOperation) && !showCheck(operation)) onUpdatePolicyCheck(undefined)
  28. }, [operation])
  29. return (
  30. <div className="space-y-4">
  31. {showUsing(operation) && (
  32. <div className="flex space-x-12">
  33. <div className="flex w-1/3 flex-col space-y-2">
  34. <div className="flex items-center space-x-2">
  35. <label className="text-base text-foreground-light" htmlFor="policy-name">
  36. USING expression
  37. </label>
  38. <Tooltip>
  39. <TooltipTrigger>
  40. <HelpCircle className="text-foreground-light" size={16} strokeWidth={1.5} />
  41. </TooltipTrigger>
  42. <TooltipContent side="bottom">
  43. <div className="w-[300px] space-y-2">
  44. <p className="text-xs text-foreground">
  45. This expression will be added to queries that refer to the table if row-level
  46. security is enabled.
  47. </p>
  48. <p className="text-xs text-foreground">
  49. Rows for which the expression returns true will be visible. Any rows for which
  50. the expression returns false or null will not be visible to the user (in a
  51. SELECT), and will not be available for modification (in an UPDATE or DELETE).
  52. </p>
  53. <p className="text-xs text-foreground">
  54. Such rows are silently suppressed - no error is reported.
  55. </p>
  56. </div>
  57. </TooltipContent>
  58. </Tooltip>
  59. </div>
  60. <p className="text-sm text-foreground-lighter">
  61. Provide a SQL conditional expression that returns a boolean.
  62. </p>
  63. </div>
  64. <div className={`w-2/3 ${showCheck(operation) ? 'h-32' : 'h-56'}`}>
  65. <SqlEditor defaultValue={definition} onInputChange={onUpdatePolicyUsing} />
  66. </div>
  67. </div>
  68. )}
  69. {showCheck(operation) && (
  70. <div className="flex space-x-12">
  71. <div className="flex w-1/3 flex-col space-y-2">
  72. <div className="flex items-center space-x-2">
  73. <label className="text-base text-foreground-light" htmlFor="policy-name">
  74. WITH CHECK expression
  75. </label>
  76. <Tooltip>
  77. <TooltipTrigger>
  78. <HelpCircle className="text-foreground-light" size={16} strokeWidth={1.5} />
  79. </TooltipTrigger>
  80. <TooltipContent side="bottom">
  81. <div className="w-[300px] space-y-2">
  82. <p className="text-xs text-foreground">
  83. This expression will be used in INSERT and UPDATE queries against the table if
  84. row-level security is enabled.
  85. </p>
  86. <p className="text-xs text-foreground">
  87. Only rows for which the expression evaluates to true will be allowed. An error
  88. will be thrown if the expression evaluates to false or null for any of the
  89. records inserted or any of the records that result from the update.
  90. </p>
  91. <p className="text-xs text-foreground">
  92. Note that this expression is evaluated against the proposed new contents of
  93. the row, not the original contents.
  94. </p>
  95. </div>
  96. </TooltipContent>
  97. </Tooltip>
  98. </div>
  99. <p className="text-sm text-foreground-lighter">
  100. Provide a SQL conditional expression that returns a boolean.
  101. </p>
  102. </div>
  103. <div className={`w-2/3 ${showUsing(operation) ? 'h-32' : 'h-56'}`}>
  104. <SqlEditor defaultValue={check} onInputChange={onUpdatePolicyCheck} />
  105. </div>
  106. </div>
  107. )}
  108. </div>
  109. )
  110. }
  111. export default PolicyDefinition