chore: fix login

This commit is contained in:
nathan
2025-10-01 19:05:58 +08:00
parent d846b792f5
commit 045ff0509c
5 changed files with 57 additions and 20 deletions

View File

@@ -124,7 +124,6 @@ export async function getUser<T extends User>(
strategy: StrategyType = StrategyType.CACHE_AND_NETWORK
) {
const exist = userId && (await hasUserCache(userId));
const data = await db.users.get(userId);
switch (strategy) {
case StrategyType.CACHE_ONLY: {
@@ -132,6 +131,7 @@ export async function getUser<T extends User>(
throw new Error('No cache found');
}
const data = await db.users.get(userId);
return data;
}
@@ -140,6 +140,7 @@ export async function getUser<T extends User>(
return revalidateUser(fetcher);
}
const data = await db.users.get(userId);
return data;
}
@@ -150,6 +151,7 @@ export async function getUser<T extends User>(
void revalidateUser(fetcher);
}
const data = await db.users.get(userId);
return data;
}

View File

@@ -184,24 +184,21 @@ export async function signInOTP({
});
const data = response?.data;
console.debug('signInOTP response data:', data);
console.log('[signInOTP] Response data:', data);
if (data) {
if (!data.code) {
// Save token to localStorage FIRST so axios interceptor can use it
console.debug('Saving token data:', data);
// Save token first so axios interceptor can use it
console.log('[signInOTP] Saving token to localStorage');
saveGoTrueAuth(JSON.stringify(data));
if (type === 'magiclink') {
emit(EventType.SESSION_VALID);
}
// Verify token with AppFlowy Cloud to create user if needed
let isNewUser = false;
try {
console.debug('[signInOTP] Calling verifyToken');
await verifyToken(data.access_token);
await new Promise(resolve => setTimeout(resolve, 500));
console.log('[signInOTP] Calling verifyToken');
const result = await verifyToken(data.access_token);
isNewUser = result.is_new;
console.log('[signInOTP] verifyToken completed, isNewUser:', isNewUser);
} catch (error) {
console.error('[signInOTP] Failed to verify token with AppFlowy Cloud:', error);
emit(EventType.SESSION_INVALID);
@@ -211,7 +208,21 @@ export async function signInOTP({
});
}
afterAuth();
// Emit session valid only after everything is complete
if (type === 'magiclink') {
emit(EventType.SESSION_VALID);
}
// For new users, always redirect to /app (don't use saved redirectTo)
if (isNewUser) {
console.log('[signInOTP] New user, clearing old data and redirecting to /app');
localStorage.removeItem('redirectTo');
// Use replace to avoid adding to history and ensure clean navigation
window.location.replace('/app');
} else {
console.log('[signInOTP] Existing user, calling afterAuth');
afterAuth();
}
} else {
emit(EventType.SESSION_INVALID);
return Promise.reject({

View File

@@ -1,8 +1,8 @@
import { getFileUploadUrl, getFileUrl } from '@/utils/file-storage-url';
import axios, { AxiosInstance, AxiosResponse } from 'axios';
import dayjs from 'dayjs';
import { omit } from 'lodash-es';
import { nanoid } from 'nanoid';
import { getFileUploadUrl, getFileUrl } from '@/utils/file-storage-url';
import { GlobalComment, Reaction } from '@/application/comment.type';
import { ERROR_CODE } from '@/application/constants';

View File

@@ -1,19 +1,19 @@
export function saveRedirectTo (redirectTo: string) {
export function saveRedirectTo(redirectTo: string) {
localStorage.setItem('redirectTo', redirectTo);
}
export function getRedirectTo () {
export function getRedirectTo() {
return localStorage.getItem('redirectTo');
}
export function clearRedirectTo () {
export function clearRedirectTo() {
localStorage.removeItem('redirectTo');
}
export const AUTH_CALLBACK_PATH = '/auth/callback';
export const AUTH_CALLBACK_URL = `${window.location.origin}${AUTH_CALLBACK_PATH}`;
export function withSignIn () {
export function withSignIn() {
return function (
// eslint-disable-next-line
_target: any,
@@ -40,7 +40,7 @@ export function withSignIn () {
};
}
export function afterAuth () {
export function afterAuth() {
const redirectTo = getRedirectTo();
clearRedirectTo();

View File

@@ -15,9 +15,33 @@ function LoginPage() {
const action = search.get('action') || '';
const email = search.get('email') || '';
const force = search.get('force') === 'true';
const redirectTo = search.get('redirectTo') || '';
const rawRedirectTo = search.get('redirectTo') || '';
const isAuthenticated = useContext(AFConfigContext)?.isAuthenticated || false;
// Sanitize redirectTo - remove workspace-specific URLs from previous sessions
const redirectTo = useMemo(() => {
if (!rawRedirectTo) return '';
try {
const url = new URL(decodeURIComponent(rawRedirectTo));
const pathname = url.pathname;
// Check if URL contains workspace/view UUIDs (user-specific paths)
// Pattern matches /app/{uuid}/{uuid} or /app/{uuid}
const hasUserSpecificIds = /\/app\/[a-f0-9-]{36}/.test(pathname);
if (hasUserSpecificIds) {
// Replace with clean /app path
return encodeURIComponent(`${url.origin}/app`);
}
return rawRedirectTo;
} catch (e) {
// If URL parsing fails, return original
return rawRedirectTo;
}
}, [rawRedirectTo]);
useEffect(() => {
if (action === LOGIN_ACTION.CHANGE_PASSWORD || force) {
return;