mirror of
https://github.com/supabase/supabase.git
synced 2026-05-09 02:09:50 -04:00
4a0bb36ca8
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
97 lines
3.4 KiB
TypeScript
97 lines
3.4 KiB
TypeScript
import { useParams } from 'common'
|
|
import { useRouter } from 'next/router'
|
|
import { toast } from 'sonner'
|
|
|
|
import { extractBucketNameFromDefinition } from './Storage.utils'
|
|
import { TextConfirmModal } from '@/components/ui/TextConfirmModalWrapper'
|
|
import { useDatabasePoliciesQuery } from '@/data/database-policies/database-policies-query'
|
|
import { useDatabasePolicyDeleteMutation } from '@/data/database-policies/database-policy-delete-mutation'
|
|
import { useBucketDeleteMutation } from '@/data/storage/bucket-delete-mutation'
|
|
import { Bucket } from '@/data/storage/buckets-query'
|
|
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
|
|
|
|
export interface DeleteBucketModalProps {
|
|
visible: boolean
|
|
bucket: Bucket
|
|
onClose: () => void
|
|
}
|
|
|
|
export const DeleteBucketModal = ({ visible, bucket, onClose }: DeleteBucketModalProps) => {
|
|
const router = useRouter()
|
|
const { ref: projectRef, bucketId } = useParams()
|
|
const { data: project } = useSelectedProjectQuery()
|
|
|
|
const { data: policies } = useDatabasePoliciesQuery({
|
|
projectRef: project?.ref,
|
|
connectionString: project?.connectionString,
|
|
schema: 'storage',
|
|
})
|
|
|
|
const { mutateAsync: deletePolicy, isPending: isDeletingPolicies } =
|
|
useDatabasePolicyDeleteMutation()
|
|
|
|
const { mutate: deleteBucket, isPending: isDeletingBucket } = useBucketDeleteMutation({
|
|
onSuccess: async () => {
|
|
if (!project) return console.error('Project is required')
|
|
|
|
// Clean up policies from the corresponding bucket that was deleted
|
|
const bucketPolicies = (policies ?? []).filter((policy) => {
|
|
if (policy.table !== 'objects') return false
|
|
|
|
const policyBucket = extractBucketNameFromDefinition(policy.definition ?? policy.check)
|
|
return policyBucket === bucket.name
|
|
})
|
|
|
|
try {
|
|
await Promise.all(
|
|
bucketPolicies.map((policy) =>
|
|
deletePolicy({
|
|
projectRef: project?.ref,
|
|
connectionString: project?.connectionString,
|
|
originalPolicy: policy,
|
|
})
|
|
)
|
|
)
|
|
|
|
toast.success(`Successfully deleted bucket ${bucket.id}`)
|
|
if (!!bucketId) router.push(`/project/${projectRef}/storage/files`)
|
|
onClose()
|
|
} catch (error) {
|
|
toast.success(
|
|
`Successfully deleted bucket ${bucket.id}. However, there was a problem deleting the policies tied to the bucket. Please review them in the storage policies section`
|
|
)
|
|
}
|
|
},
|
|
})
|
|
|
|
const onConfirmDelete = async () => {
|
|
if (!projectRef) return console.error('Project ref is required')
|
|
if (!bucket) return console.error('No bucket is selected')
|
|
deleteBucket({ projectRef, id: bucket.id })
|
|
}
|
|
|
|
return (
|
|
<TextConfirmModal
|
|
visible={visible}
|
|
size="medium"
|
|
variant="destructive"
|
|
title={`Delete bucket “${bucket.id}”`}
|
|
loading={isDeletingBucket || isDeletingPolicies}
|
|
confirmPlaceholder="Type bucket name"
|
|
confirmString={bucket.id}
|
|
confirmLabel="Delete bucket"
|
|
onCancel={onClose}
|
|
onConfirm={onConfirmDelete}
|
|
alert={{
|
|
title: 'You cannot recover this bucket once deleted',
|
|
description: 'This action cannot be undone',
|
|
}}
|
|
>
|
|
<p className="text-sm">
|
|
Your bucket <span className="font-bold text-foreground">{bucket.id}</span> and all of its
|
|
contents will be permanently deleted.
|
|
</p>
|
|
</TextConfirmModal>
|
|
)
|
|
}
|