2
0

♻️ (auth) Make sure new users have an email

Also fix after-auth redirections

Closes #323
This commit is contained in:
Baptiste Arnaud
2023-02-18 09:00:04 +01:00
parent 0e1fa4e339
commit 0831dcf72a
7 changed files with 48 additions and 8 deletions

View File

@ -0,0 +1,24 @@
import { Alert } from '@chakra-ui/react'
type Props = {
error: string
}
const errors: Record<string, string> = {
Signin: 'Try signing with a different account.',
OAuthSignin: 'Try signing with a different account.',
OAuthCallback: 'Try signing with a different account.',
OAuthCreateAccount: 'Email not found. Try signing with a different provider.',
EmailCreateAccount: 'Try signing with a different account.',
Callback: 'Try signing with a different account.',
OAuthAccountNotLinked:
'To confirm your identity, sign in with the same account you used originally.',
CredentialsSignin:
'Sign in failed. Check the details you provided are correct.',
default: 'An error occurred. Please try again.',
}
export const SignInError = ({ error }: Props) => (
<Alert status="error" variant="solid" rounded="md">
{errors[error] ?? errors[error]}
</Alert>
)

View File

@ -23,6 +23,7 @@ import { useRouter } from 'next/router'
import { BuiltInProviderType } from 'next-auth/providers'
import { useToast } from '@/hooks/useToast'
import { TextLink } from '@/components/TextLink'
import { SignInError } from './SignInError'
type Props = {
defaultEmail?: string
@ -48,8 +49,10 @@ export const SignInForm = ({
!isLoadingProviders && Object.keys(providers ?? {}).length === 0
useEffect(() => {
if (status === 'authenticated')
router.replace({ pathname: '/typebots', query: router.query })
if (status === 'authenticated') {
router.replace(router.query.callbackUrl?.toString() ?? '/typebots')
return
}
;(async () => {
const providers = await getProviders()
setProviders(providers ?? undefined)
@ -131,6 +134,9 @@ export const SignInForm = ({
</HStack>
</>
)}
{router.query.error && (
<SignInError error={router.query.error.toString()} />
)}
</Stack>
)
}

View File

@ -12,6 +12,7 @@ import { stringify } from 'qs'
import { BuiltInProviderType } from 'next-auth/providers'
import { GoogleLogo } from '@/components/GoogleLogo'
import { AzureAdLogo, FacebookLogo, GitlabLogo } from './logos'
import { omit } from 'utils'
type Props = {
providers:
@ -28,7 +29,9 @@ export const SocialLoginButtons = ({ providers }: Props) => {
const handleSignIn = async (provider: string) => {
setAuthLoading(provider)
await signIn(provider, {
callbackUrl: `/typebots?${stringify(query)}`,
callbackUrl:
query.callbackUrl?.toString() ??
`/typebots?${stringify(omit(query, 'error', 'callbackUrl'))}`,
})
setTimeout(() => setAuthLoading(undefined), 3000)
}

View File

@ -46,6 +46,7 @@ import {
import { useAutoSave } from '@/hooks/useAutoSave'
import { createWebhookQuery } from '@/features/blocks/integrations/webhook/queries/createWebhookQuery'
import { duplicateWebhookQuery } from '@/features/blocks/integrations/webhook/queries/duplicateWebhookQuery'
import { useSession } from 'next-auth/react'
const autoSaveTimeout = 10000
@ -103,7 +104,8 @@ export const TypebotProvider = ({
children: ReactNode
typebotId: string
}) => {
const router = useRouter()
const { status } = useSession()
const { push } = useRouter()
const { showToast } = useToast()
const { typebot, publishedTypebot, webhooks, isReadOnly, isLoading, mutate } =
@ -246,15 +248,15 @@ export const TypebotProvider = ({
}, [localTypebot])
useEffect(() => {
if (isLoading) return
if (status !== 'authenticated' || isLoading) return
if (!typebot) {
showToast({ status: 'info', description: "Couldn't find typebot" })
router.replace('/typebots')
push('/typebots')
return
}
setLocalTypebot({ ...typebot })
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isLoading])
}, [status, isLoading])
const updateLocalTypebot = (updates: UpdateTypebotPayload) =>
localTypebot && setLocalTypebot({ ...localTypebot, ...updates })

View File

@ -25,7 +25,7 @@ const { ToastContainer, toast } = createStandaloneToast(customTheme)
const App = ({
Component,
pageProps: { session, ...pageProps },
}: AppProps<{ session: Session }>) => {
}: AppProps<{ session?: Session }>) => {
useRouterProgressBar()
const { query, pathname, isReady } = useRouter()

View File

@ -146,6 +146,9 @@ const handler = (req: NextApiRequest, res: NextApiResponse) => {
session: {
strategy: 'database',
},
pages: {
signIn: '/signin',
},
callbacks: {
session: async ({ session, user }) => {
const userFromDb = user as User

View File

@ -14,6 +14,8 @@ import {
export function CustomAdapter(p: PrismaClient): Adapter {
return {
createUser: async (data: Omit<AdapterUser, 'id'>) => {
if (!data.email)
throw Error('Provider did not forward email but it is required')
const user = { id: createId(), email: data.email as string }
const { invitations, workspaceInvitations } = await getNewUserInvitations(
p,