feat(auth): add invite token handling to OTP sign-in and update metho… (#280)
* feat(auth): add invite token handling to OTP sign-in and update method descriptions
This commit is contained in:
committed by
GitHub
parent
f95da27b8f
commit
1143a01727
@@ -76,6 +76,7 @@
|
||||
"methodMagicLink": "email link",
|
||||
"methodOauth": "social sign-in",
|
||||
"methodOauthWithProvider": "<provider>{{provider}}</provider>",
|
||||
"methodDefault": "another method",
|
||||
"existingAccountHint": "You previously signed in with <method>{{method}}</method>. <signInLink>Already have an account?</signInLink>",
|
||||
"errors": {
|
||||
"Invalid login credentials": "The credentials entered are invalid",
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useMemo } from 'react';
|
||||
|
||||
import dynamic from 'next/dynamic';
|
||||
import Link from 'next/link';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
|
||||
import { UserCheck } from 'lucide-react';
|
||||
|
||||
@@ -33,6 +34,14 @@ export function ExistingAccountHintImpl({
|
||||
const { hasLastMethod, methodType, providerName, isOAuth } =
|
||||
useLastAuthMethod();
|
||||
|
||||
const params = useSearchParams();
|
||||
|
||||
const isInvite = params.get('invite_token');
|
||||
|
||||
if (isInvite) {
|
||||
signInPath = signInPath + '?invite_token=' + isInvite;
|
||||
}
|
||||
|
||||
// Get the appropriate method description for the hint
|
||||
// This must be called before any conditional returns to follow Rules of Hooks
|
||||
const methodDescription = useMemo(() => {
|
||||
@@ -42,13 +51,13 @@ export function ExistingAccountHintImpl({
|
||||
|
||||
switch (methodType) {
|
||||
case 'password':
|
||||
return 'email and password';
|
||||
return 'auth:methodPassword';
|
||||
case 'otp':
|
||||
return 'email verification';
|
||||
return 'auth:methodOtp';
|
||||
case 'magic_link':
|
||||
return 'email link';
|
||||
return 'auth:methodMagicLink';
|
||||
default:
|
||||
return 'another method';
|
||||
return 'auth:methodDefault';
|
||||
}
|
||||
}, [methodType, isOAuth, providerName]);
|
||||
|
||||
|
||||
@@ -34,17 +34,16 @@ import { AuthErrorAlert } from './auth-error-alert';
|
||||
const EmailSchema = z.object({ email: z.string().email() });
|
||||
const OtpSchema = z.object({ token: z.string().min(6).max(6) });
|
||||
|
||||
export function OtpSignInContainer({
|
||||
onSignIn,
|
||||
shouldCreateUser,
|
||||
}: {
|
||||
onSignIn?: (userId?: string) => void;
|
||||
type OtpSignInContainerProps = {
|
||||
shouldCreateUser: boolean;
|
||||
}) {
|
||||
inviteToken?: string;
|
||||
};
|
||||
|
||||
export function OtpSignInContainer(props: OtpSignInContainerProps) {
|
||||
const verifyMutation = useVerifyOtp();
|
||||
const router = useRouter();
|
||||
const params = useSearchParams();
|
||||
const { recordAuthMethod } = useLastAuthMethod();
|
||||
const params = useSearchParams();
|
||||
|
||||
const otpForm = useForm({
|
||||
resolver: zodResolver(OtpSchema.merge(EmailSchema)),
|
||||
@@ -61,6 +60,9 @@ export function OtpSignInContainer({
|
||||
|
||||
const isEmailStep = !email;
|
||||
|
||||
const shouldCreateUser =
|
||||
'shouldCreateUser' in props && props.shouldCreateUser;
|
||||
|
||||
const handleVerifyOtp = async ({
|
||||
token,
|
||||
email,
|
||||
@@ -68,7 +70,7 @@ export function OtpSignInContainer({
|
||||
token: string;
|
||||
email: string;
|
||||
}) => {
|
||||
const result = await verifyMutation.mutateAsync({
|
||||
await verifyMutation.mutateAsync({
|
||||
type: 'email',
|
||||
email,
|
||||
token,
|
||||
@@ -77,14 +79,18 @@ export function OtpSignInContainer({
|
||||
// Record successful OTP sign-in
|
||||
recordAuthMethod('otp', { email });
|
||||
|
||||
if (onSignIn) {
|
||||
return onSignIn(result?.user?.id);
|
||||
}
|
||||
// on sign ups we redirect to the app home
|
||||
const inviteToken = props.inviteToken;
|
||||
const next = params.get('next') ?? '/home';
|
||||
|
||||
// on sign ups we redirect to the app home
|
||||
if (shouldCreateUser) {
|
||||
const next = params.get('next') ?? '/home';
|
||||
if (inviteToken) {
|
||||
const params = new URLSearchParams({
|
||||
invite_token: inviteToken,
|
||||
next,
|
||||
});
|
||||
|
||||
router.replace(`/join?${params.toString()}`);
|
||||
} else {
|
||||
router.replace(next);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -74,7 +74,10 @@ export function SignInMethodsContainer(props: {
|
||||
</If>
|
||||
|
||||
<If condition={props.providers.otp}>
|
||||
<OtpSignInContainer shouldCreateUser={false} onSignIn={onSignIn} />
|
||||
<OtpSignInContainer
|
||||
inviteToken={props.inviteToken}
|
||||
shouldCreateUser={false}
|
||||
/>
|
||||
</If>
|
||||
|
||||
<If condition={props.providers.oAuth.length}>
|
||||
|
||||
@@ -51,7 +51,10 @@ export function SignUpMethodsContainer(props: {
|
||||
</If>
|
||||
|
||||
<If condition={props.providers.otp}>
|
||||
<OtpSignInContainer shouldCreateUser={true} />
|
||||
<OtpSignInContainer
|
||||
inviteToken={props.inviteToken}
|
||||
shouldCreateUser={true}
|
||||
/>
|
||||
</If>
|
||||
|
||||
<If condition={props.providers.magicLink}>
|
||||
|
||||
@@ -87,6 +87,7 @@ export function usePasswordSignUpFlow({
|
||||
router,
|
||||
onSignUp,
|
||||
resetCaptchaToken,
|
||||
recordAuthMethod,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user