新增手机号绑定邮箱后邮箱模式重登流程
This commit is contained in:
@@ -270,6 +270,8 @@
|
||||
13: 'confirm-oauth',
|
||||
14: 'platform-verify',
|
||||
15: 'platform-verify',
|
||||
16: 'confirm-oauth',
|
||||
17: 'platform-verify',
|
||||
});
|
||||
|
||||
function getStepKeyForState(step, state = {}) {
|
||||
@@ -613,12 +615,18 @@
|
||||
const stateForStep = await getState();
|
||||
const stepKey = getStepKeyForState(step, stateForStep);
|
||||
|
||||
if (stepKey === 'oauth-login') {
|
||||
await syncStepAccountIdentityFromPayload(payload);
|
||||
if (stepKey === 'oauth-login' || stepKey === 'relogin-bound-email') {
|
||||
if (stepKey === 'oauth-login') {
|
||||
await syncStepAccountIdentityFromPayload(payload);
|
||||
}
|
||||
if (payload.skipLoginVerificationStep) {
|
||||
await setState({ loginVerificationRequestedAt: null });
|
||||
const latestState = await getState();
|
||||
const loginCodeStep = findStepByKeyAfter(step, 'fetch-login-code', latestState);
|
||||
const loginCodeStep = findStepByKeyAfter(
|
||||
step,
|
||||
stepKey === 'relogin-bound-email' ? 'fetch-bound-email-login-code' : 'fetch-login-code',
|
||||
latestState
|
||||
);
|
||||
if (loginCodeStep) {
|
||||
const currentStatus = getNodeStatusByStep(loginCodeStep, latestState);
|
||||
if (!isStepProtectedFromAutoSkip(currentStatus)) {
|
||||
@@ -635,7 +643,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (stepKey === 'fetch-login-code') {
|
||||
if (stepKey === 'fetch-login-code' || stepKey === 'fetch-bound-email-login-code') {
|
||||
await setState({
|
||||
...(payload.phoneVerification || payload.loginPhoneVerification ? {
|
||||
currentPhoneVerificationCode: '',
|
||||
@@ -649,7 +657,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (stepKey === 'post-login-phone-verification') {
|
||||
if (stepKey === 'post-login-phone-verification' || stepKey === 'post-bound-email-phone-verification') {
|
||||
await setState({
|
||||
currentPhoneVerificationCode: '',
|
||||
signupPhoneVerificationRequestedAt: null,
|
||||
@@ -1333,10 +1341,14 @@
|
||||
const plusPaymentChanged = Object.prototype.hasOwnProperty.call(updates, 'plusPaymentMethod')
|
||||
&& normalizePlusPaymentMethodForDisplay(currentState?.plusPaymentMethod || 'paypal')
|
||||
!== normalizePlusPaymentMethodForDisplay(updates.plusPaymentMethod || 'paypal');
|
||||
const phoneSignupReloginAfterBindEmailChanged = Object.prototype.hasOwnProperty.call(updates, 'phoneSignupReloginAfterBindEmailEnabled')
|
||||
&& Boolean(currentState?.phoneSignupReloginAfterBindEmailEnabled) !== Boolean(updates.phoneSignupReloginAfterBindEmailEnabled);
|
||||
const nextPlusModeEnabled = Object.prototype.hasOwnProperty.call(updates, 'plusModeEnabled')
|
||||
? Boolean(updates.plusModeEnabled)
|
||||
: Boolean(currentState?.plusModeEnabled);
|
||||
const stepModeChanged = modeChanged || (nextPlusModeEnabled && plusPaymentChanged);
|
||||
const stepModeChanged = modeChanged
|
||||
|| (nextPlusModeEnabled && plusPaymentChanged)
|
||||
|| phoneSignupReloginAfterBindEmailChanged;
|
||||
const oauthFlowTimeoutDisabled = Object.prototype.hasOwnProperty.call(updates, 'oauthFlowTimeoutEnabled')
|
||||
&& updates.oauthFlowTimeoutEnabled === false;
|
||||
await setPersistentSettings(updates);
|
||||
|
||||
@@ -124,6 +124,34 @@
|
||||
return String(value || '').trim().toLowerCase();
|
||||
}
|
||||
|
||||
function resolveBoundEmailLoginTarget(state = {}, visibleStep = 0) {
|
||||
const email = String(
|
||||
state?.step8VerificationTargetEmail
|
||||
|| state?.email
|
||||
|| state?.registrationEmailState?.current
|
||||
|| ''
|
||||
).trim();
|
||||
if (!email) {
|
||||
throw new Error(`步骤 ${visibleStep || 0}:缺少绑定邮箱,无法使用邮箱模式重新发起 OAuth 登录。`);
|
||||
}
|
||||
return email;
|
||||
}
|
||||
|
||||
function buildBoundEmailLoginState(state = {}, visibleStep = 0) {
|
||||
const email = resolveBoundEmailLoginTarget(state, visibleStep);
|
||||
return {
|
||||
...state,
|
||||
forceLoginIdentifierType: 'email',
|
||||
forceEmailLogin: true,
|
||||
signupMethod: 'email',
|
||||
resolvedSignupMethod: 'email',
|
||||
accountIdentifierType: 'email',
|
||||
accountIdentifier: email,
|
||||
email,
|
||||
step8VerificationTargetEmail: normalizeStep8VerificationTargetEmail(email),
|
||||
};
|
||||
}
|
||||
|
||||
async function getLoginAuthStateFromContent(visibleStep, options = {}) {
|
||||
if (typeof sendToContentScriptResilient !== 'function') {
|
||||
return {};
|
||||
@@ -142,7 +170,7 @@
|
||||
retryDelayMs: 600,
|
||||
logMessage: options.logMessage || `步骤 ${visibleStep}:认证页正在切换,等待页面重新就绪...`,
|
||||
logStep: visibleStep,
|
||||
logStepKey: 'fetch-login-code',
|
||||
logStepKey: options.logStepKey || activeFetchLoginCodeStepKey || 'fetch-login-code',
|
||||
}
|
||||
);
|
||||
if (result?.error) {
|
||||
@@ -240,9 +268,11 @@
|
||||
loginVerificationRequestedAt: null,
|
||||
});
|
||||
const fromRecovery = Boolean(options.fromRecovery);
|
||||
const stepKey = options.stepKey || activeFetchLoginCodeStepKey || 'fetch-login-code';
|
||||
await addLog(
|
||||
`步骤 ${visibleStep}:当前认证页已进入 OAuth 授权页${fromRecovery ? '(轮询失败后复核)' : ''},跳过登录验证码拉取并继续后续流程。`,
|
||||
'warn'
|
||||
'warn',
|
||||
{ step: visibleStep, stepKey }
|
||||
);
|
||||
if (typeof completeNodeFromBackground === 'function') {
|
||||
await completeNodeFromBackground(options.nodeId || 'fetch-login-code', {
|
||||
@@ -258,9 +288,11 @@
|
||||
step8VerificationTargetEmail: '',
|
||||
loginVerificationRequestedAt: null,
|
||||
});
|
||||
const stepKey = options.stepKey || activeFetchLoginCodeStepKey || 'fetch-login-code';
|
||||
await addLog(
|
||||
`步骤 ${visibleStep}:当前认证页已进入手机号验证流程,跳过登录邮箱验证码,交给后续“手机号验证”步骤处理。`,
|
||||
'warn'
|
||||
'warn',
|
||||
{ step: visibleStep, stepKey }
|
||||
);
|
||||
if (typeof completeNodeFromBackground === 'function') {
|
||||
await completeNodeFromBackground(options.nodeId || 'fetch-login-code', {
|
||||
@@ -416,9 +448,10 @@
|
||||
}
|
||||
|
||||
async function completePostLoginPhoneVerificationSkippedOnOauth(visibleStep, options = {}) {
|
||||
const stepKey = options.stepKey || 'post-login-phone-verification';
|
||||
await addLog(`步骤 ${visibleStep}:当前认证页已进入 OAuth 授权页,跳过手机号验证步骤。`, 'warn', {
|
||||
step: visibleStep,
|
||||
stepKey: 'post-login-phone-verification',
|
||||
stepKey,
|
||||
});
|
||||
if (typeof completeNodeFromBackground === 'function') {
|
||||
await completeNodeFromBackground(options.nodeId || 'post-login-phone-verification', {
|
||||
@@ -428,18 +461,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function executePostLoginPhoneVerification(state) {
|
||||
async function executePostLoginPhoneVerification(state, runtime = {}) {
|
||||
const visibleStep = getVisibleStep(state, 9);
|
||||
activeFetchLoginCodeStep = visibleStep;
|
||||
activeFetchLoginCodeStepKey = 'post-login-phone-verification';
|
||||
activeFetchLoginCodeStepKey = runtime.stepKey || 'post-login-phone-verification';
|
||||
const authTabId = await ensureAuthTabForPostLoginStep(state, visibleStep);
|
||||
const pageState = await getLoginAuthStateFromContent(visibleStep, {
|
||||
timeoutMs: await getStep8ReadyTimeoutMs('确认手机号验证页或 OAuth 授权页已就绪', state?.oauthUrl || '', visibleStep),
|
||||
logMessage: `步骤 ${visibleStep}:正在确认是否需要手机号验证...`,
|
||||
logStepKey: activeFetchLoginCodeStepKey,
|
||||
});
|
||||
|
||||
if (pageState?.state === 'oauth_consent_page') {
|
||||
await completePostLoginPhoneVerificationSkippedOnOauth(visibleStep, { nodeId: state?.nodeId });
|
||||
await completePostLoginPhoneVerificationSkippedOnOauth(visibleStep, {
|
||||
nodeId: state?.nodeId || runtime.fallbackNodeId,
|
||||
stepKey: activeFetchLoginCodeStepKey,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (pageState?.state !== 'add_phone_page' && pageState?.state !== 'phone_verification_page') {
|
||||
@@ -457,7 +494,7 @@
|
||||
visibleStep,
|
||||
});
|
||||
if (typeof completeNodeFromBackground === 'function') {
|
||||
await completeNodeFromBackground(state?.nodeId || 'post-login-phone-verification', {
|
||||
await completeNodeFromBackground(state?.nodeId || runtime.fallbackNodeId || 'post-login-phone-verification', {
|
||||
phoneVerification: true,
|
||||
postLoginPhoneVerification: true,
|
||||
code: result?.code || '',
|
||||
@@ -663,6 +700,64 @@
|
||||
});
|
||||
}
|
||||
|
||||
async function executeBoundEmailLoginCode(state) {
|
||||
const visibleStep = getVisibleStep(state, 11);
|
||||
activeFetchLoginCodeStep = visibleStep;
|
||||
activeFetchLoginCodeStepKey = 'fetch-bound-email-login-code';
|
||||
const preparedState = buildBoundEmailLoginState(state, visibleStep);
|
||||
const authTabId = await getTabId('signup-page');
|
||||
|
||||
if (authTabId) {
|
||||
await chrome.tabs.update(authTabId, { active: true });
|
||||
} else {
|
||||
if (!preparedState.oauthUrl) {
|
||||
throw new Error(`步骤 ${visibleStep}:缺少登录用 OAuth 链接,请先完成绑定邮箱后刷新 OAuth 并登录。`);
|
||||
}
|
||||
await reuseOrCreateTab('signup-page', preparedState.oauthUrl);
|
||||
}
|
||||
|
||||
throwIfStopped();
|
||||
const pageState = await ensureStep8VerificationPageReady({
|
||||
visibleStep,
|
||||
authLoginStep: Math.max(1, visibleStep - 1),
|
||||
allowPhoneVerificationPage: true,
|
||||
allowAddEmailPage: false,
|
||||
timeoutMs: await getStep8ReadyTimeoutMs('确认绑定邮箱登录验证码页已就绪', preparedState?.oauthUrl || '', visibleStep),
|
||||
});
|
||||
|
||||
if (pageState?.state === 'oauth_consent_page') {
|
||||
await completeStep8WhenAuthAlreadyOnOauthConsent(visibleStep, {
|
||||
nodeId: state?.nodeId || 'fetch-bound-email-login-code',
|
||||
stepKey: 'fetch-bound-email-login-code',
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (pageState?.state === 'add_phone_page' || pageState?.state === 'phone_verification_page') {
|
||||
await completeStep8WhenDeferredToPostLoginPhone(visibleStep, pageState, {
|
||||
nodeId: state?.nodeId || 'fetch-bound-email-login-code',
|
||||
stepKey: 'fetch-bound-email-login-code',
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (pageState?.state === 'add_email_page') {
|
||||
throw new Error(`步骤 ${visibleStep}:绑定邮箱后邮箱模式登录不应再进入添加邮箱页。URL: ${pageState?.url || ''}`.trim());
|
||||
}
|
||||
if (pageState?.state !== 'verification_page') {
|
||||
throw new Error(`步骤 ${visibleStep}:绑定邮箱后获取登录验证码只处理邮箱登录验证码页,当前状态:${pageState?.state || 'unknown'}。URL: ${pageState?.url || ''}`.trim());
|
||||
}
|
||||
|
||||
return pollEmailVerificationCode(preparedState, pageState, visibleStep, {
|
||||
stickyLastResendAt: Number(preparedState?.loginVerificationRequestedAt) || 0,
|
||||
});
|
||||
}
|
||||
|
||||
async function executeBoundEmailPostLoginPhoneVerification(state) {
|
||||
return executePostLoginPhoneVerification(state, {
|
||||
stepKey: 'post-bound-email-phone-verification',
|
||||
fallbackNodeId: 'post-bound-email-phone-verification',
|
||||
});
|
||||
}
|
||||
|
||||
async function runStep8Attempt(state, runtime = {}) {
|
||||
const visibleStep = getVisibleStep(state, 8);
|
||||
activeFetchLoginCodeStep = visibleStep;
|
||||
@@ -855,6 +950,8 @@
|
||||
executePostLoginPhoneVerification,
|
||||
executeBindEmail,
|
||||
executeFetchBindEmailCode,
|
||||
executeBoundEmailLoginCode,
|
||||
executeBoundEmailPostLoginPhoneVerification,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,11 @@
|
||||
return String(value || '').trim().toLowerCase() === 'phone' ? 'phone' : 'email';
|
||||
}
|
||||
|
||||
function shouldForceStep7EmailLogin(state = {}) {
|
||||
return normalizeStep7IdentifierType(state?.forceLoginIdentifierType) === 'email'
|
||||
|| Boolean(state?.forceEmailLogin);
|
||||
}
|
||||
|
||||
function canUseConfiguredPhoneSignup(state = {}) {
|
||||
return normalizeStep7SignupMethod(state?.signupMethod) === 'phone'
|
||||
&& Boolean(state?.phoneVerificationEnabled)
|
||||
@@ -75,6 +80,10 @@
|
||||
}
|
||||
|
||||
function resolveStep7LoginIdentifierType(state = {}, fallbackType = '') {
|
||||
if (shouldForceStep7EmailLogin(state)) {
|
||||
return 'email';
|
||||
}
|
||||
|
||||
if (shouldPreferStep7PhoneSignupIdentity(state)) {
|
||||
return 'phone';
|
||||
}
|
||||
@@ -234,7 +243,19 @@
|
||||
throwIfStopped();
|
||||
attempt += 1;
|
||||
try {
|
||||
const currentState = attempt === 1 ? state : await getState();
|
||||
const rawCurrentState = attempt === 1 ? state : await getState();
|
||||
const currentState = shouldForceStep7EmailLogin(state)
|
||||
? {
|
||||
...rawCurrentState,
|
||||
forceLoginIdentifierType: 'email',
|
||||
forceEmailLogin: true,
|
||||
signupMethod: 'email',
|
||||
resolvedSignupMethod: 'email',
|
||||
accountIdentifierType: 'email',
|
||||
accountIdentifier: email,
|
||||
email,
|
||||
}
|
||||
: rawCurrentState;
|
||||
const password = currentState.password || currentState.customPassword || '';
|
||||
const currentIdentifierType = resolveStep7LoginIdentifierType(currentState, resolvedIdentifierType);
|
||||
const currentPhoneNumber = currentIdentifierType === 'phone'
|
||||
|
||||
Reference in New Issue
Block a user