mirror of
https://github.com/supabase/supabase.git
synced 2026-10-19 16:19:10 +03:00
* Add queries and mutations for third party auth. * Show the ThirdPartyAuth form in the auth settings. * Minor fixes to the mutations. * Add a comment for TODO. * Add all components for third party auth. * Minor fixes. * Update the firebase icons. * Update the api-types. * Fix the barrel file imports. * Make the sheets more intuitive. * Add a dialog for adding RLS policies for the firebase integration. * Hide the 3rd party auth section behind a form. * Fix a type error. * Update the wording on the Add RLS policy dialog. * Replace the sheets with dialogs. * Add fixes for the comments on github. * Minor fixes. * Fix a type error. * Make the delete integration awaitable.
165 lines
5.6 KiB
TypeScript
165 lines
5.6 KiB
TypeScript
import { PermissionAction } from '@supabase/shared-types/out/constants'
|
|
import { Loader2 } from 'lucide-react'
|
|
import { useState } from 'react'
|
|
import toast from 'react-hot-toast'
|
|
|
|
import { useParams } from 'common'
|
|
import AlertError from 'components/ui/AlertError'
|
|
import { FormHeader } from 'components/ui/Forms/FormHeader'
|
|
import { useDeleteThirdPartyAuthIntegrationMutation } from 'data/third-party-auth/integration-delete-mutation'
|
|
import {
|
|
ThirdPartyAuthIntegration,
|
|
useThirdPartyAuthIntegrationsQuery,
|
|
} from 'data/third-party-auth/integrations-query'
|
|
import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
|
|
import { useFlag } from 'hooks/ui/useFlag'
|
|
import { cn } from 'ui'
|
|
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
|
|
import { AddIntegrationDropdown } from './AddIntegrationDropdown'
|
|
import { CreateAuth0IntegrationDialog } from './CreateAuth0Dialog'
|
|
import { CreateAwsCognitoAuthIntegrationDialog } from './CreateAwsCognitoAuthDialog'
|
|
import { CreateFirebaseAuthIntegrationDialog } from './CreateFirebaseAuthDialog'
|
|
import { IntegrationCard } from './IntegrationCard'
|
|
import {
|
|
INTEGRATION_TYPES,
|
|
getIntegrationType,
|
|
getIntegrationTypeLabel,
|
|
} from './ThirdPartyAuthForm.utils'
|
|
|
|
export const ThirdPartyAuthForm = () => {
|
|
const thirdPartyAuthEnabled = useFlag('thirdPartyAuth')
|
|
const { ref: projectRef } = useParams()
|
|
const {
|
|
data: integrationsData,
|
|
isLoading,
|
|
isError,
|
|
isSuccess,
|
|
error,
|
|
} = useThirdPartyAuthIntegrationsQuery({ projectRef })
|
|
const integrations = integrationsData || []
|
|
|
|
const [selectedIntegration, setSelectedIntegration] = useState<INTEGRATION_TYPES>()
|
|
const [selectedIntegrationForDeletion, setSelectedIntegrationForDeletion] =
|
|
useState<ThirdPartyAuthIntegration>()
|
|
|
|
const { mutateAsync: deleteIntegration } = useDeleteThirdPartyAuthIntegrationMutation()
|
|
const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue')
|
|
|
|
if (!thirdPartyAuthEnabled) {
|
|
return null
|
|
}
|
|
|
|
if (isError) {
|
|
return (
|
|
<AlertError
|
|
error={error}
|
|
subject="Failed to retrieve auth configuration for Third Party Auth Integrations"
|
|
/>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="pb-4">
|
|
<FormHeader
|
|
title="Third Party Auth"
|
|
description="Use third-party authentication (TPA) systems based on JWTs to access your project."
|
|
actions={
|
|
integrations.length !== 0 ? (
|
|
<AddIntegrationDropdown onSelectIntegrationType={setSelectedIntegration} />
|
|
) : null
|
|
}
|
|
/>
|
|
|
|
{isLoading && (
|
|
<div
|
|
className={cn(
|
|
'border rounded border-default px-20 py-16 flex flex-col items-center justify-center space-y-4'
|
|
)}
|
|
>
|
|
<Loader2 size={24} className="animate-spin" />
|
|
</div>
|
|
)}
|
|
|
|
{isSuccess ? (
|
|
integrations.length === 0 ? (
|
|
<div
|
|
className={cn(
|
|
'border rounded border-default px-20 py-16 flex flex-col items-center justify-center space-y-4'
|
|
)}
|
|
>
|
|
<p className="text-sm text-foreground-light">No integrations configured yet</p>
|
|
<AddIntegrationDropdown
|
|
buttonText="Add a new integration"
|
|
onSelectIntegrationType={setSelectedIntegration}
|
|
/>
|
|
</div>
|
|
) : (
|
|
<div className="-space-y-px">
|
|
{integrations.map((integration) => {
|
|
return (
|
|
<IntegrationCard
|
|
key={integration.id}
|
|
integration={integration}
|
|
canUpdateConfig={canUpdateConfig}
|
|
onDelete={() => {
|
|
setSelectedIntegrationForDeletion(integration)
|
|
}}
|
|
/>
|
|
)
|
|
})}
|
|
</div>
|
|
)
|
|
) : null}
|
|
|
|
<CreateFirebaseAuthIntegrationDialog
|
|
visible={selectedIntegration === 'firebase'}
|
|
onDelete={() => {}}
|
|
onClose={() => setSelectedIntegration(undefined)}
|
|
/>
|
|
|
|
<CreateAwsCognitoAuthIntegrationDialog
|
|
visible={selectedIntegration === 'awsCognito'}
|
|
onDelete={() => {}}
|
|
onClose={() => setSelectedIntegration(undefined)}
|
|
/>
|
|
|
|
<CreateAuth0IntegrationDialog
|
|
visible={selectedIntegration === 'auth0'}
|
|
onDelete={() => {}}
|
|
onClose={() => setSelectedIntegration(undefined)}
|
|
/>
|
|
|
|
<ConfirmationModal
|
|
visible={!!selectedIntegrationForDeletion}
|
|
variant="destructive"
|
|
title="Confirm to delete"
|
|
confirmLabel="Delete"
|
|
confirmLabelLoading="Deleting"
|
|
onCancel={() => setSelectedIntegrationForDeletion(undefined)}
|
|
onConfirm={async () => {
|
|
if (!selectedIntegrationForDeletion) {
|
|
return
|
|
}
|
|
const type = getIntegrationType(selectedIntegrationForDeletion)
|
|
try {
|
|
await deleteIntegration({
|
|
projectRef: projectRef!,
|
|
tpaId: selectedIntegrationForDeletion.id,
|
|
})
|
|
toast.success(`Successfully deleted ${getIntegrationTypeLabel(type)}.`)
|
|
setSelectedIntegrationForDeletion(undefined)
|
|
setSelectedIntegration(undefined)
|
|
} catch (error) {
|
|
toast.error(`Failed to delete ${getIntegrationTypeLabel(type)}.`)
|
|
console.error(error)
|
|
}
|
|
}}
|
|
>
|
|
<p className="py-4 text-sm text-foreground-light">
|
|
{`Are you sure you want to delete the ${getIntegrationTypeLabel(getIntegrationType(selectedIntegrationForDeletion))} integration?`}
|
|
</p>
|
|
</ConfirmationModal>
|
|
</div>
|
|
)
|
|
}
|