ProjectComplianceMode.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import { PermissionAction } from '@supabase/shared-types/out/constants'
  2. import { useParams } from 'common'
  3. import { Loader2 } from 'lucide-react'
  4. import { useEffect, useState } from 'react'
  5. import { toast } from 'sonner'
  6. import { Card, CardContent, Switch, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
  7. import {
  8. PageSection,
  9. PageSectionContent,
  10. PageSectionDescription,
  11. PageSectionMeta,
  12. PageSectionSummary,
  13. PageSectionTitle,
  14. } from 'ui-patterns/PageSection'
  15. import AlertError from '@/components/ui/AlertError'
  16. import { DocsButton } from '@/components/ui/DocsButton'
  17. import { InlineLink } from '@/components/ui/InlineLink'
  18. import { useComplianceConfigUpdateMutation } from '@/data/config/project-compliance-config-mutation'
  19. import { useProjectSettingsV2Query } from '@/data/config/project-settings-v2-query'
  20. import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
  21. import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
  22. import { DOCS_URL } from '@/lib/constants'
  23. export const ComplianceConfig = () => {
  24. const { ref } = useParams()
  25. const { data: project } = useSelectedProjectQuery()
  26. const [isSensitive, setIsSensitive] = useState(false)
  27. const { can: canUpdateComplianceConfig } = useAsyncCheckPermissions(
  28. PermissionAction.UPDATE,
  29. 'projects',
  30. {
  31. resource: { project_id: project?.id },
  32. }
  33. )
  34. const {
  35. data: settings,
  36. error,
  37. isError,
  38. isPending: isLoading,
  39. isSuccess,
  40. } = useProjectSettingsV2Query({ projectRef: ref })
  41. const initialIsSensitive = settings?.is_sensitive || false
  42. const { mutate: updateComplianceConfig, isPending: isSubmitting } =
  43. useComplianceConfigUpdateMutation({
  44. onSuccess: () => {
  45. toast.success('Successfully updated project compliance configuration')
  46. },
  47. onError: (error) => {
  48. setIsSensitive(initialIsSensitive)
  49. toast.error(`Failed to update project compliance configuration: ${error.message}`)
  50. },
  51. })
  52. const toggleIsSensitive = async () => {
  53. if (!ref) return console.error('Project ref is required')
  54. setIsSensitive(!isSensitive)
  55. updateComplianceConfig({ projectRef: ref, isSensitive: !isSensitive })
  56. }
  57. useEffect(() => {
  58. if (!isLoading) setIsSensitive(initialIsSensitive)
  59. }, [isLoading])
  60. return (
  61. <PageSection id="compliance-configuration">
  62. <PageSectionMeta>
  63. <div className="flex flex-col gap-3 @lg:flex-row @lg:items-center @lg:justify-between">
  64. <PageSectionSummary>
  65. <PageSectionTitle>High Compliance Configuration</PageSectionTitle>
  66. <PageSectionDescription>
  67. For projects storing and processing sensitive data (HIPAA).
  68. </PageSectionDescription>
  69. </PageSectionSummary>
  70. <DocsButton href={`${DOCS_URL}/guides/platform/hipaa-projects`} />
  71. </div>
  72. </PageSectionMeta>
  73. <PageSectionContent>
  74. <Card>
  75. <CardContent className="flex flex-col gap-4 @lg:flex-row @lg:items-center @lg:justify-between">
  76. <div className="space-y-2 max-w-2xl">
  77. <p className="text-sm">Apply additional compliance controls to project</p>
  78. <p className="text-sm text-foreground-light">
  79. Enable security warnings in the{' '}
  80. <InlineLink href={`/project/${ref}/advisors/security`}>Security Advisor</InlineLink>{' '}
  81. to enforce requirements for managing sensitive data.
  82. </p>
  83. </div>
  84. <div className="flex items-center justify-end space-x-2">
  85. {(isLoading || isSubmitting) && (
  86. <Loader2 className="animate-spin" strokeWidth={1.5} size={16} />
  87. )}
  88. {isError && (
  89. <AlertError error={error} subject="Failed to retrieve project settings" />
  90. )}
  91. {isSuccess && (
  92. <Tooltip>
  93. <TooltipTrigger asChild>
  94. {/* [Joshen] Added div as tooltip is messing with data state property of toggle */}
  95. <div>
  96. <Switch
  97. size="large"
  98. checked={isSensitive}
  99. disabled={isLoading || isSubmitting || !canUpdateComplianceConfig}
  100. onCheckedChange={toggleIsSensitive}
  101. />
  102. </div>
  103. </TooltipTrigger>
  104. {!canUpdateComplianceConfig && (
  105. <TooltipContent side="bottom" className="w-64 text-center">
  106. You need additional permissions to update the compliance configuration for
  107. your project
  108. </TooltipContent>
  109. )}
  110. </Tooltip>
  111. )}
  112. </div>
  113. </CardContent>
  114. </Card>
  115. </PageSectionContent>
  116. </PageSection>
  117. )
  118. }