feat: add magic login link to email with login codes

This commit is contained in:
3252a8
2026-04-28 09:50:17 +03:00
parent 0251f939d7
commit dd0e6e75af
8 changed files with 350 additions and 13 deletions
@@ -511,6 +511,14 @@ const MOCK = (() => {
return;
}
const magicToken = readMagicLoginToken();
if (magicToken) {
const authenticated = await finalizeMagicLogin(magicToken);
if (authenticated) {
return;
}
}
// Explicit logout should survive refresh, even if the old cookie session is still valid.
if (isManuallyLoggedOut()) {
await startExternalAuth();
@@ -549,6 +557,54 @@ const MOCK = (() => {
await startExternalAuth();
}
function readMagicLoginToken() {
const query = new URLSearchParams(window.location.search);
const token = (query.get('login_token') || '').trim();
return token || null;
}
function clearMagicLoginQuery() {
const url = new URL(window.location.href);
['login_token', 'login_purpose'].forEach(key => url.searchParams.delete(key));
if (window.history && window.history.replaceState) {
window.history.replaceState({}, document.title, url.pathname + url.search + url.hash);
}
}
async function finalizeMagicLogin(token) {
if (state.authInProgress) return false;
state.authInProgress = true;
setAuthStatus(t('telegram_auth_verifying'));
try {
const payload = {token};
if (state.referralParam) payload.referral_code = state.referralParam;
const data = await publicApi('/auth/email/magic', payload);
if (data && data.ok && data.token) {
setToken(data.token, data.csrf_token);
clearManualLogoutFlag();
clearMagicLoginQuery();
try {
setAuthStatus('');
await loadData();
return true;
} catch (e) {
clearToken();
setAuthStatus(t('telegram_auth_failed'), true);
return false;
}
}
clearMagicLoginQuery();
setAuthStatus(emailErrorMessage(data, 'email_code_invalid'), true);
return false;
} catch (e) {
clearMagicLoginQuery();
setAuthStatus(t('telegram_auth_failed'), true);
return false;
} finally {
state.authInProgress = false;
}
}
function readTelegramLoginWidgetAuthData() {
const query = new URLSearchParams(window.location.search);
const keys = ['id', 'first_name', 'last_name', 'username', 'photo_url', 'auth_date', 'hash'];
@@ -2183,6 +2239,9 @@ const MOCK = (() => {
if (path === '/auth/email/verify') {
return {ok: true, token: 'local-preview', csrf_token: 'local-preview-csrf'};
}
if (path === '/auth/email/magic') {
return {ok: true, token: 'local-preview', csrf_token: 'local-preview-csrf'};
}
if (path === '/account/email/verify') {
MOCK.data.user.email = 'preview@example.com';
MOCK.data.user.email_verified = true;