♻️ (auth) Make sure new users have an email
Also fix after-auth redirections Closes #323
This commit is contained in:
24
apps/builder/src/features/auth/components/SignInError.tsx
Normal file
24
apps/builder/src/features/auth/components/SignInError.tsx
Normal 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>
|
||||
)
|
@ -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>
|
||||
)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 })
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
Reference in New Issue
Block a user