From 0831dcf72a3f0761e583555185dc41c114ae6f43 Mon Sep 17 00:00:00 2001 From: Baptiste Arnaud Date: Sat, 18 Feb 2023 09:00:04 +0100 Subject: [PATCH] :recycle: (auth) Make sure new users have an email Also fix after-auth redirections Closes #323 --- .../features/auth/components/SignInError.tsx | 24 +++++++++++++++++++ .../features/auth/components/SignInForm.tsx | 10 ++++++-- .../auth/components/SocialLoginButtons.tsx | 5 +++- .../TypebotProvider/TypebotProvider.tsx | 10 ++++---- apps/builder/src/pages/_app.tsx | 2 +- .../src/pages/api/auth/[...nextauth].ts | 3 +++ apps/builder/src/pages/api/auth/adapter.ts | 2 ++ 7 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 apps/builder/src/features/auth/components/SignInError.tsx diff --git a/apps/builder/src/features/auth/components/SignInError.tsx b/apps/builder/src/features/auth/components/SignInError.tsx new file mode 100644 index 000000000..0371b7175 --- /dev/null +++ b/apps/builder/src/features/auth/components/SignInError.tsx @@ -0,0 +1,24 @@ +import { Alert } from '@chakra-ui/react' + +type Props = { + error: string +} +const errors: Record = { + 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) => ( + + {errors[error] ?? errors[error]} + +) diff --git a/apps/builder/src/features/auth/components/SignInForm.tsx b/apps/builder/src/features/auth/components/SignInForm.tsx index 64d435854..a922a730d 100644 --- a/apps/builder/src/features/auth/components/SignInForm.tsx +++ b/apps/builder/src/features/auth/components/SignInForm.tsx @@ -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 = ({ )} + {router.query.error && ( + + )} ) } diff --git a/apps/builder/src/features/auth/components/SocialLoginButtons.tsx b/apps/builder/src/features/auth/components/SocialLoginButtons.tsx index 80b69dd48..88ae51d12 100644 --- a/apps/builder/src/features/auth/components/SocialLoginButtons.tsx +++ b/apps/builder/src/features/auth/components/SocialLoginButtons.tsx @@ -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) } diff --git a/apps/builder/src/features/editor/providers/TypebotProvider/TypebotProvider.tsx b/apps/builder/src/features/editor/providers/TypebotProvider/TypebotProvider.tsx index 53c733cb7..34d8d9a17 100644 --- a/apps/builder/src/features/editor/providers/TypebotProvider/TypebotProvider.tsx +++ b/apps/builder/src/features/editor/providers/TypebotProvider/TypebotProvider.tsx @@ -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 }) diff --git a/apps/builder/src/pages/_app.tsx b/apps/builder/src/pages/_app.tsx index ce57eba4d..77a039113 100644 --- a/apps/builder/src/pages/_app.tsx +++ b/apps/builder/src/pages/_app.tsx @@ -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() diff --git a/apps/builder/src/pages/api/auth/[...nextauth].ts b/apps/builder/src/pages/api/auth/[...nextauth].ts index 93e5e6a78..3fbad4675 100644 --- a/apps/builder/src/pages/api/auth/[...nextauth].ts +++ b/apps/builder/src/pages/api/auth/[...nextauth].ts @@ -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 diff --git a/apps/builder/src/pages/api/auth/adapter.ts b/apps/builder/src/pages/api/auth/adapter.ts index 59724e905..87019b5c9 100644 --- a/apps/builder/src/pages/api/auth/adapter.ts +++ b/apps/builder/src/pages/api/auth/adapter.ts @@ -14,6 +14,8 @@ import { export function CustomAdapter(p: PrismaClient): Adapter { return { createUser: async (data: Omit) => { + 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,