mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-05 19:40:30 +08:00
fix(core): desktop e2e (#15062)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Sign-in flows now reliably propagate richer authentication results (user data and session type), improving persistence and reducing intermittent sign-in issues. * Native token handling gains a fallback for environments without encrypted storage, improving session reliability. * **New Features** * User-visible warning when sign-in is session-only because encrypted storage is unavailable. * **Chores** * Tooling ignore patterns updated to exclude .codex. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -19,6 +19,16 @@ export interface SignInResponse {
|
||||
redirectUri?: string;
|
||||
}
|
||||
|
||||
export interface PasswordSignInResponse extends SignInResponse {
|
||||
id: string;
|
||||
email: string;
|
||||
name: string;
|
||||
hasPassword: boolean | null;
|
||||
avatarUrl: string | null;
|
||||
emailVerified: boolean;
|
||||
sessionOnly?: boolean;
|
||||
}
|
||||
|
||||
interface ExchangeResponse {
|
||||
token?: string;
|
||||
}
|
||||
@@ -86,8 +96,9 @@ async function exchangeSession(endpoint: string, response: SignInResponse) {
|
||||
throw new Error('Missing native auth token.');
|
||||
}
|
||||
|
||||
setNativeAuthToken(endpoint, body.token);
|
||||
const persistent = setNativeAuthToken(endpoint, body.token);
|
||||
await clearAuthCookies(endpoint);
|
||||
return { persistent };
|
||||
}
|
||||
|
||||
export const authHandlers = {
|
||||
@@ -104,7 +115,8 @@ export const authHandlers = {
|
||||
client_nonce: clientNonce,
|
||||
});
|
||||
const body = await readJson<SignInResponse>(response);
|
||||
await exchangeSession(endpoint, body);
|
||||
const { persistent } = await exchangeSession(endpoint, body);
|
||||
return { sessionOnly: !persistent };
|
||||
},
|
||||
|
||||
signInOauth: async (
|
||||
@@ -120,8 +132,8 @@ export const authHandlers = {
|
||||
client_nonce: clientNonce,
|
||||
});
|
||||
const body = await readJson<SignInResponse>(response);
|
||||
await exchangeSession(endpoint, body);
|
||||
return { redirectUri: body.redirectUri };
|
||||
const { persistent } = await exchangeSession(endpoint, body);
|
||||
return { redirectUri: body.redirectUri, sessionOnly: !persistent };
|
||||
},
|
||||
|
||||
signInPassword: async (
|
||||
@@ -152,16 +164,20 @@ export const authHandlers = {
|
||||
password: credential.password,
|
||||
}),
|
||||
});
|
||||
const body = await readJson<SignInResponse>(response);
|
||||
await exchangeSession(endpoint, body);
|
||||
return body;
|
||||
const body = await readJson<PasswordSignInResponse>(response);
|
||||
const { persistent } = await exchangeSession(endpoint, body);
|
||||
return { ...body, sessionOnly: !persistent };
|
||||
},
|
||||
|
||||
signInOpenAppSignInCode: async (_e, endpoint: string, code: string) => {
|
||||
const response = await fetchAuth(endpoint, '/api/auth/open-app/sign-in', {
|
||||
code,
|
||||
});
|
||||
await exchangeSession(endpoint, await readJson(response));
|
||||
const { persistent } = await exchangeSession(
|
||||
endpoint,
|
||||
await readJson(response)
|
||||
);
|
||||
return { sessionOnly: !persistent };
|
||||
},
|
||||
|
||||
signOut: async (_e, endpoint: string) => {
|
||||
|
||||
@@ -11,6 +11,9 @@ type TokenRecord = {
|
||||
token: string;
|
||||
};
|
||||
|
||||
// safeStorage may not be available in some environments (e.g. Linux without a keyring), so we fall back to an in-memory store in that case
|
||||
const memoryTokenStore: Record<string, string> = {};
|
||||
|
||||
function normalizeEndpoint(endpoint: string) {
|
||||
return new URL(endpoint).origin;
|
||||
}
|
||||
@@ -51,19 +54,33 @@ function decryptToken(value: string): TokenRecord | null {
|
||||
}
|
||||
|
||||
export function setNativeAuthToken(endpoint: string, token: string) {
|
||||
const normalizedEndpoint = normalizeEndpoint(endpoint);
|
||||
if (!safeStorage.isEncryptionAvailable()) {
|
||||
memoryTokenStore[normalizedEndpoint] = token;
|
||||
return false;
|
||||
}
|
||||
|
||||
const store = readStore();
|
||||
store[normalizeEndpoint(endpoint)] = encryptToken({ token });
|
||||
store[normalizedEndpoint] = encryptToken({ token });
|
||||
writeStore(store);
|
||||
return true;
|
||||
}
|
||||
|
||||
export function deleteNativeAuthToken(endpoint: string) {
|
||||
const normalizedEndpoint = normalizeEndpoint(endpoint);
|
||||
delete memoryTokenStore[normalizedEndpoint];
|
||||
|
||||
const store = readStore();
|
||||
delete store[normalizeEndpoint(endpoint)];
|
||||
delete store[normalizedEndpoint];
|
||||
writeStore(store);
|
||||
}
|
||||
|
||||
export function getNativeAuthToken(endpoint: string) {
|
||||
const encrypted = readStore()[normalizeEndpoint(endpoint)];
|
||||
const normalizedEndpoint = normalizeEndpoint(endpoint);
|
||||
const memoryToken = memoryTokenStore[normalizedEndpoint];
|
||||
if (memoryToken) return memoryToken;
|
||||
|
||||
const encrypted = readStore()[normalizedEndpoint];
|
||||
if (!encrypted) return null;
|
||||
return decryptToken(encrypted)?.token ?? null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user