mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-11-22 08:32:43 +03:00
fix: failed to load blobs in electron (#1927)
This commit is contained in:
parent
934e242116
commit
42756045bb
@ -1,16 +1,10 @@
|
|||||||
import type { RequestInit } from 'undici';
|
|
||||||
import { fetch, ProxyAgent } from 'undici';
|
|
||||||
|
|
||||||
const redirectUri = 'https://affine.pro/client/auth-callback';
|
const redirectUri = 'https://affine.pro/client/auth-callback';
|
||||||
|
|
||||||
export const oauthEndpoint = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${process.env.AFFINE_GOOGLE_CLIENT_ID}&redirect_uri=${redirectUri}&response_type=code&scope=openid https://www.googleapis.com/auth/userinfo.email profile&access_type=offline&customParameters={"prompt":"select_account"}`;
|
export const oauthEndpoint = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${process.env.AFFINE_GOOGLE_CLIENT_ID}&redirect_uri=${redirectUri}&response_type=code&scope=openid https://www.googleapis.com/auth/userinfo.email profile&access_type=offline&customParameters={"prompt":"select_account"}`;
|
||||||
|
|
||||||
const tokenEndpoint = 'https://oauth2.googleapis.com/token';
|
const tokenEndpoint = 'https://oauth2.googleapis.com/token';
|
||||||
|
|
||||||
export const exchangeToken = async (code: string) => {
|
export const getExchangeTokenParams = (code: string) => {
|
||||||
const httpProxy = process.env.HTTP_PROXY || process.env.http_proxy;
|
|
||||||
const proxyAgent = httpProxy ? new ProxyAgent(httpProxy) : undefined;
|
|
||||||
|
|
||||||
const postData = {
|
const postData = {
|
||||||
code,
|
code,
|
||||||
client_id: process.env.AFFINE_GOOGLE_CLIENT_ID || '',
|
client_id: process.env.AFFINE_GOOGLE_CLIENT_ID || '',
|
||||||
@ -18,15 +12,12 @@ export const exchangeToken = async (code: string) => {
|
|||||||
redirect_uri: redirectUri,
|
redirect_uri: redirectUri,
|
||||||
grant_type: 'authorization_code',
|
grant_type: 'authorization_code',
|
||||||
};
|
};
|
||||||
const requestOptions: RequestInit = {
|
const requestInit: RequestInit = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
},
|
},
|
||||||
body: new URLSearchParams(postData).toString(),
|
body: new URLSearchParams(postData).toString(),
|
||||||
dispatcher: proxyAgent,
|
|
||||||
};
|
};
|
||||||
return fetch(tokenEndpoint, requestOptions).then(response => {
|
return { requestInit, url: tokenEndpoint };
|
||||||
return response.json();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,7 @@ import { BrowserWindow, ipcMain, nativeTheme } from 'electron';
|
|||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import { parse } from 'url';
|
import { parse } from 'url';
|
||||||
|
|
||||||
import { exchangeToken, oauthEndpoint } from './google-auth';
|
import { getExchangeTokenParams, oauthEndpoint } from './google-auth';
|
||||||
|
|
||||||
const AFFINE_ROOT = path.join(os.homedir(), '.affine');
|
const AFFINE_ROOT = path.join(os.homedir(), '.affine');
|
||||||
|
|
||||||
@ -40,29 +40,24 @@ export const registerHandlers = () => {
|
|||||||
logger.info('sidebar visibility change', visible);
|
logger.info('sidebar visibility change', visible);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('ui:google-sign-in', async () => {
|
ipcMain.handle('ui:get-google-oauth-code', async () => {
|
||||||
logger.info('starting google sign in ...');
|
logger.info('starting google sign in ...');
|
||||||
shell.openExternal(oauthEndpoint);
|
shell.openExternal(oauthEndpoint);
|
||||||
|
|
||||||
return new Promise<string>((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const handleOpenUrl = async (_: any, url: string) => {
|
const handleOpenUrl = async (_: any, url: string) => {
|
||||||
const mainWindow = BrowserWindow.getAllWindows().find(
|
const mainWindow = BrowserWindow.getAllWindows().find(
|
||||||
w => !w.isDestroyed()
|
w => !w.isDestroyed()
|
||||||
);
|
);
|
||||||
const urlObj = parse(url.replace('??', '?'), true);
|
const urlObj = parse(url.replace('??', '?'), true);
|
||||||
if (!mainWindow || !url.startsWith('affine://')) return;
|
if (!mainWindow || !url.startsWith('affine://auth-callback')) return;
|
||||||
const code = urlObj.query['code'] as string;
|
const code = urlObj.query['code'] as string;
|
||||||
if (!code) return;
|
if (!code) return;
|
||||||
|
|
||||||
logger.info('google sign in code received from callback', code);
|
logger.info('google sign in code received from callback', code);
|
||||||
|
|
||||||
const token = (await exchangeToken(code)) as {
|
|
||||||
id_token: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
app.removeListener('open-url', handleOpenUrl);
|
app.removeListener('open-url', handleOpenUrl);
|
||||||
resolve(token.id_token);
|
resolve(getExchangeTokenParams(code));
|
||||||
logger.info('google sign in successful', token);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
app.on('open-url', handleOpenUrl);
|
app.on('open-url', handleOpenUrl);
|
||||||
@ -70,7 +65,7 @@ export const registerHandlers = () => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
reject(new Error('Timed out'));
|
reject(new Error('Timed out'));
|
||||||
app.removeListener('open-url', handleOpenUrl);
|
app.removeListener('open-url', handleOpenUrl);
|
||||||
}, 60000);
|
}, 30000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ export function registerProtocol() {
|
|||||||
const realpath = toAbsolutePath(url);
|
const realpath = toAbsolutePath(url);
|
||||||
// console.log('realpath', realpath, 'for', url);
|
// console.log('realpath', realpath, 'for', url);
|
||||||
callback(realpath);
|
callback(realpath);
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
protocol.registerFileProtocol('assets', (request, callback) => {
|
protocol.registerFileProtocol('assets', (request, callback) => {
|
||||||
@ -43,6 +44,7 @@ export function registerProtocol() {
|
|||||||
const realpath = toAbsolutePath(url);
|
const realpath = toAbsolutePath(url);
|
||||||
// console.log('realpath', realpath, 'for', url);
|
// console.log('realpath', realpath, 'for', url);
|
||||||
callback(realpath);
|
callback(realpath);
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +62,6 @@ export function registerProtocol() {
|
|||||||
'DELETE',
|
'DELETE',
|
||||||
'OPTIONS',
|
'OPTIONS',
|
||||||
];
|
];
|
||||||
// responseHeaders['Content-Security-Policy'] = ["default-src 'self'"];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
callback({ responseHeaders });
|
callback({ responseHeaders });
|
||||||
|
2
apps/electron/layers/preload/preload.d.ts
vendored
2
apps/electron/layers/preload/preload.d.ts
vendored
@ -7,6 +7,6 @@ interface Window {
|
|||||||
*
|
*
|
||||||
* @see https://github.com/cawa-93/dts-for-context-bridge
|
* @see https://github.com/cawa-93/dts-for-context-bridge
|
||||||
*/
|
*/
|
||||||
readonly apis: { workspaceSync: (id: string) => Promise<any>; onThemeChange: (theme: string) => Promise<any>; onSidebarVisibilityChange: (visible: boolean) => Promise<any>; googleSignIn: () => Promise<string>; updateEnv: (env: string, value: string) => void; };
|
readonly apis: { workspaceSync: (id: string) => Promise<any>; onThemeChange: (theme: string) => Promise<any>; onSidebarVisibilityChange: (visible: boolean) => Promise<any>; getGoogleOauthCode: () => Promise<{ requestInit: RequestInit; url: string; }>; updateEnv: (env: string, value: string) => void; };
|
||||||
readonly appInfo: { electron: boolean; isMacOS: boolean; };
|
readonly appInfo: { electron: boolean; isMacOS: boolean; };
|
||||||
}
|
}
|
||||||
|
@ -31,9 +31,11 @@ contextBridge.exposeInMainWorld('apis', {
|
|||||||
ipcRenderer.invoke('ui:sidebar-visibility-change', visible),
|
ipcRenderer.invoke('ui:sidebar-visibility-change', visible),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try sign in using Google and return a Google IDToken
|
* Try sign in using Google and return a request object to exchange the code for a token
|
||||||
|
* Not exchange in Node side because it is easier to do it in the renderer with VPN
|
||||||
*/
|
*/
|
||||||
googleSignIn: (): Promise<string> => ipcRenderer.invoke('ui:google-sign-in'),
|
getGoogleOauthCode: (): Promise<{ requestInit: RequestInit; url: string }> =>
|
||||||
|
ipcRenderer.invoke('ui:get-google-oauth-code'),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Secret backdoor to update environment variables in main process
|
* Secret backdoor to update environment variables in main process
|
||||||
|
@ -52,7 +52,10 @@ const getPersistenceAllWorkspace = () => {
|
|||||||
item.id,
|
item.id,
|
||||||
(k: string) =>
|
(k: string) =>
|
||||||
// fixme: token could be expired
|
// fixme: token could be expired
|
||||||
({ api: '/api/workspace', token: getLoginStorage()?.token }[k])
|
({
|
||||||
|
api: prefixUrl + 'api/workspace',
|
||||||
|
token: getLoginStorage()?.token,
|
||||||
|
}[k])
|
||||||
);
|
);
|
||||||
const affineWorkspace: AffineWorkspace = {
|
const affineWorkspace: AffineWorkspace = {
|
||||||
...item,
|
...item,
|
||||||
|
@ -67,10 +67,13 @@ export const setLoginStorage = (login: LoginResponse) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const signInWithElectron = async (firebaseAuth: FirebaseAuth) => {
|
const signInWithElectron = async (firebaseAuth: FirebaseAuth) => {
|
||||||
const code = await window.apis?.googleSignIn();
|
if (window.apis) {
|
||||||
const credential = GoogleAuthProvider.credential(code);
|
const { url, requestInit } = await window.apis.getGoogleOauthCode();
|
||||||
const user = await signInWithCredential(firebaseAuth, credential);
|
const { id_token } = await fetch(url, requestInit).then(res => res.json());
|
||||||
return await user.user.getIdToken();
|
const credential = GoogleAuthProvider.credential(id_token);
|
||||||
|
const user = await signInWithCredential(firebaseAuth, credential);
|
||||||
|
return await user.user.getIdToken();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const clearLoginStorage = () => {
|
export const clearLoginStorage = () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user