-
Notifications
You must be signed in to change notification settings - Fork 452
Expand file tree
/
Copy pathSignInFactorOneEmailLinkCard.tsx
More file actions
122 lines (110 loc) · 4.46 KB
/
SignInFactorOneEmailLinkCard.tsx
File metadata and controls
122 lines (110 loc) · 4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import { isUserLockedError } from '@clerk/shared/error';
import { useClerk } from '@clerk/shared/react';
import type { EmailLinkFactor, SignInResource } from '@clerk/shared/types';
import React from 'react';
import type { VerificationCodeCardProps } from '@/ui/elements/VerificationCodeCard';
import { VerificationLinkCard } from '@/ui/elements/VerificationLinkCard';
import { handleError } from '@/ui/utils/errorHandler';
import { EmailLinkStatusCard } from '../../common';
import { buildVerificationRedirectUrl } from '../../common/redirects';
import { useCoreSignIn, useEnvironment, useSignInContext } from '../../contexts';
import { Flow, localizationKeys, useLocalizations } from '../../customizables';
import { useCardState } from '../../elements/contexts';
import { useEmailLink } from '../../hooks/useEmailLink';
import { useRouter } from '../../router/RouteContext';
import { handleSignUpIfMissingTransfer } from './handleSignUpIfMissingTransfer';
type SignInFactorOneEmailLinkCardProps = Pick<VerificationCodeCardProps, 'onShowAlternativeMethodsClicked'> & {
factor: EmailLinkFactor;
factorAlreadyPrepared: boolean;
onFactorPrepare: () => void;
};
export const SignInFactorOneEmailLinkCard = (props: SignInFactorOneEmailLinkCardProps) => {
const { t } = useLocalizations();
const card = useCardState();
const signIn = useCoreSignIn();
const signInContext = useSignInContext();
const { signInUrl, afterSignInUrl, afterSignUpUrl, isCombinedFlow, navigateOnSetActive } = signInContext;
const { navigate } = useRouter();
const { setActive } = useClerk();
const { userSettings } = useEnvironment();
const { startEmailLinkFlow, cancelEmailLinkFlow } = useEmailLink(signIn);
const [showVerifyModal, setShowVerifyModal] = React.useState(false);
const clerk = useClerk();
React.useEffect(() => {
void startEmailLinkVerification();
}, []);
const restartVerification = () => {
cancelEmailLinkFlow();
void startEmailLinkVerification();
};
const startEmailLinkVerification = () => {
startEmailLinkFlow({
emailAddressId: props.factor.emailAddressId,
redirectUrl: buildVerificationRedirectUrl({ ctx: signInContext, baseUrl: signInUrl, intent: 'sign-in' }),
})
.then(res => handleVerificationResult(res))
.catch(err => {
if (isUserLockedError(err)) {
// @ts-expect-error -- private method for the time being
return clerk.__internal_navigateWithError('..', err.errors[0]);
}
handleError(err, [], card.setError);
});
};
const handleVerificationResult = async (si: SignInResource) => {
const ver = si.firstFactorVerification;
if (ver.status === 'expired') {
card.setError(t(localizationKeys('formFieldError__verificationLinkExpired')));
} else if (
isCombinedFlow &&
userSettings.attackProtection.enumeration_protection.enabled &&
ver.status === 'transferable'
) {
return handleSignUpIfMissingTransfer({
clerk,
navigate,
afterSignUpUrl,
navigateOnSetActive,
unsafeMetadata: signInContext.unsafeMetadata,
});
} else if (ver.verifiedFromTheSameClient()) {
setShowVerifyModal(true);
} else {
await completeSignInFlow(si);
}
};
const completeSignInFlow = async (si: SignInResource) => {
if (si.status === 'complete') {
return setActive({
session: si.createdSessionId,
redirectUrl: afterSignInUrl,
});
} else if (si.status === 'needs_second_factor') {
return navigate('../factor-two');
}
};
if (showVerifyModal) {
return (
<EmailLinkStatusCard
title={localizationKeys('signIn.emailLink.verifiedSwitchTab.titleNewTab')}
subtitle={localizationKeys('signIn.emailLink.verifiedSwitchTab.subtitleNewTab')}
status='verified_switch_tab'
/>
);
}
return (
<Flow.Part part='emailLink'>
<VerificationLinkCard
cardTitle={localizationKeys('signIn.emailLink.title')}
cardSubtitle={localizationKeys('signIn.emailLink.subtitle')}
formTitle={localizationKeys('signIn.emailLink.formTitle')}
formSubtitle={localizationKeys('signIn.emailLink.formSubtitle')}
resendButton={localizationKeys('signIn.emailLink.resendButton')}
onResendCodeClicked={restartVerification}
safeIdentifier={props.factor.safeIdentifier}
profileImageUrl={signIn.userData.imageUrl}
onShowAlternativeMethodsClicked={props.onShowAlternativeMethodsClicked}
/>
</Flow.Part>
);
};