From 943d535e869abbecd73f1f98d69b3649234ba283 Mon Sep 17 00:00:00 2001 From: Michel Weststrate Date: Wed, 8 Dec 2021 04:25:28 -0800 Subject: [PATCH] Move sending intern requests from client to server Summary: This diff moves send intern request from the browser to the server. The reason to make this change is that making such requests from a browser environment causes CORS restrictions to kick in. Reviewed By: nikoant Differential Revision: D32835449 fbshipit-source-id: e8e92e51ca963aa50b3c859bb61c2381171e85ae --- desktop/flipper-common/src/index.tsx | 1 - desktop/flipper-common/src/server-types.tsx | 33 +++++++++++++ desktop/flipper-common/src/user-session.tsx | 41 ----------------- desktop/flipper-server-core/package.json | 5 +- .../src/FlipperServerImpl.tsx | 46 ++++++++++++++++--- .../src/comms/ServerController.tsx | 1 - .../src/fb-stubs/internRequests.tsx | 41 +++++++++++++++++ .../src/fb-stubs/sendScribeLogs.tsx | 12 +++++ .../src/utils/CertificateProvider.tsx | 34 ++++++++------ .../flipper-server-core/src/utils/keytar.tsx | 2 + desktop/flipper-server/src/index.tsx | 5 ++ .../flipper-server/src/startSocketServer.tsx | 1 - .../src/chrome/ShareSheetExportUrl.tsx | 2 +- .../src/fb-stubs/constants.tsx | 14 ------ desktop/flipper-ui-core/src/fb-stubs/user.tsx | 12 ++++- .../src/startFlipperDesktop.tsx | 11 +---- .../flipper-ui-core/src/utils/exportData.tsx | 2 +- desktop/types/flipperGlobals.d.ts | 13 ++++++ 18 files changed, 180 insertions(+), 96 deletions(-) delete mode 100644 desktop/flipper-common/src/user-session.tsx create mode 100644 desktop/flipper-server-core/src/fb-stubs/internRequests.tsx create mode 100644 desktop/flipper-server-core/src/fb-stubs/sendScribeLogs.tsx diff --git a/desktop/flipper-common/src/index.tsx b/desktop/flipper-common/src/index.tsx index b1da3dd81..482e38399 100644 --- a/desktop/flipper-common/src/index.tsx +++ b/desktop/flipper-common/src/index.tsx @@ -42,7 +42,6 @@ export { getStringFromErrorLike, getErrorFromErrorLike, } from './utils/errors'; -export * from './user-session'; export * from './GK'; export * from './clientUtils'; export * from './settings'; diff --git a/desktop/flipper-common/src/server-types.tsx b/desktop/flipper-common/src/server-types.tsx index 43b5b964c..19b9824d5 100644 --- a/desktop/flipper-common/src/server-types.tsx +++ b/desktop/flipper-common/src/server-types.tsx @@ -191,6 +191,39 @@ export type FlipperServerCommands = { name: string, ) => Promise; 'open-file': (path: string) => Promise; + 'intern-graph-post': ( + endpoint: string, + formFields: Record, + fileFields: Record, + options: { + timeout?: number; + internGraphUrl?: string; + }, + ) => Promise; + 'intern-graph-get': ( + endpoint: string, + params: Record, + options: { + timeout?: number; + internGraphUrl?: string; + }, + ) => Promise; + 'intern-upload-scribe-logs': ( + messages: {category: string; message: string}[], + ) => Promise; +}; + +export type GraphResponse = { + status: number; + data: any; + headers: Record; +}; + +export type GraphFileUpload = { + path?: string; + contents?: string; + filename?: string; + contentType?: string; }; /** diff --git a/desktop/flipper-common/src/user-session.tsx b/desktop/flipper-common/src/user-session.tsx deleted file mode 100644 index 31aab511f..000000000 --- a/desktop/flipper-common/src/user-session.tsx +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - */ - -/** - * APIs need to integration with Facebook services. - */ - -export type UserSessionManager = { - internGraphPOSTAPIRequest: typeof internGraphPOSTAPIRequest; -}; - -let instance: UserSessionManager | undefined = undefined; - -function getInstance(): UserSessionManager { - if (!instance) { - throw new Error('UserSessionManager not available or implemented'); - } - return instance; -} - -export function setUserSessionManagerInstance(i: UserSessionManager) { - instance = i; -} - -export async function internGraphPOSTAPIRequest( - _endpoint: string, - _formFields: { - [key: string]: any; - } = {}, - _internGraphUrl?: string, - _timeout?: number, -): Promise { - // eslint-disable-next-line - return getInstance().internGraphPOSTAPIRequest.apply(null, arguments as any); -} diff --git a/desktop/flipper-server-core/package.json b/desktop/flipper-server-core/package.json index e918bebed..cb5d1c78c 100644 --- a/desktop/flipper-server-core/package.json +++ b/desktop/flipper-server-core/package.json @@ -11,15 +11,16 @@ "bugs": "https://github.com/facebook/flipper/issues", "dependencies": { "@iarna/toml": "^2.2.5", - "axios": "^0.22.0", "JSONStream": "^1.3.1", "adbkit": "^2.11.1", "adbkit-logcat": "^2.0.1", "archiver": "^5.3.0", "async-mutex": "^0.3.2", - "flipper-plugin-lib": "0.0.0", + "axios": "^0.22.0", "flipper-common": "0.0.0", "flipper-doctor": "0.0.0", + "flipper-plugin-lib": "0.0.0", + "form-data": "^4.0.0", "fs-extra": "^10.0.0", "invariant": "^2.2.4", "js-base64": "^3.7.2", diff --git a/desktop/flipper-server-core/src/FlipperServerImpl.tsx b/desktop/flipper-server-core/src/FlipperServerImpl.tsx index f8bb11005..fe295dd0b 100644 --- a/desktop/flipper-server-core/src/FlipperServerImpl.tsx +++ b/desktop/flipper-server-core/src/FlipperServerImpl.tsx @@ -38,6 +38,13 @@ import {PluginManager} from './plugins/PluginManager'; import {runHealthcheck, getHealthChecks} from './utils/runHealthchecks'; import {openFile} from './utils/openFile'; import {getChangelog} from './utils/pathUtils'; +import {sendScribeLogs} from './fb-stubs/sendScribeLogs'; +import { + internGraphGETAPIRequest, + internGraphPOSTAPIRequest, +} from './fb-stubs/internRequests'; + +export const SERVICE_FLIPPER = 'flipper.oAuthToken'; /** * FlipperServer takes care of all incoming device & client connections. @@ -184,14 +191,24 @@ export class FlipperServerImpl implements FlipperServer { exec( event: Event, ...args: Parameters - ): ReturnType { - console.debug(`[FlipperServer] command ${event}: `, args); - const handler: (...args: any[]) => Promise = - this.commandHandler[event]; - if (!handler) { - throw new Error(`Unimplemented server command: ${event}`); + ): ReturnType; + async exec( + event: Event, + ...args: any[] + ): Promise { + try { + const handler: (...args: any[]) => Promise = + this.commandHandler[event]; + if (!handler) { + throw new Error(`Unimplemented server command: ${event}`); + } + const result = await handler(...args); + console.debug(`[FlipperServer] command '${event}' - OK`); + return result; + } catch (e) { + console.debug(`[FlipperServer] command '${event}' - ERROR: ${e} `); + throw e; } - return handler(...args) as any; } private commandHandler: FlipperServerCommands = { @@ -276,6 +293,21 @@ export class FlipperServerImpl implements FlipperServer { 'doctor-get-healthchecks': getHealthChecks, 'doctor-run-healthcheck': runHealthcheck, 'open-file': openFile, + 'intern-graph-post': async (endpoint, formfields, filefields, options) => { + const token = await this.keytarManager.retrieveToken(SERVICE_FLIPPER); + return internGraphPOSTAPIRequest( + endpoint, + formfields, + filefields, + options, + token, + ); + }, + 'intern-graph-get': async (endpoint, params, options) => { + const token = await this.keytarManager.retrieveToken(SERVICE_FLIPPER); + return internGraphGETAPIRequest(endpoint, params, options, token); + }, + 'intern-upload-scribe-logs': sendScribeLogs, }; registerDevice(device: ServerDevice) { diff --git a/desktop/flipper-server-core/src/comms/ServerController.tsx b/desktop/flipper-server-core/src/comms/ServerController.tsx index 8d3aa652b..cc9537bb6 100644 --- a/desktop/flipper-server-core/src/comms/ServerController.tsx +++ b/desktop/flipper-server-core/src/comms/ServerController.tsx @@ -95,7 +95,6 @@ class ServerController extends EventEmitter implements ServerEventsListener { this.timestamps = new Map(); this.certificateProvider = new CertificateProvider( this, - this.logger, getFlipperServerConfig().settings, ); this.connectionTracker = new ConnectionTracker(this.logger); diff --git a/desktop/flipper-server-core/src/fb-stubs/internRequests.tsx b/desktop/flipper-server-core/src/fb-stubs/internRequests.tsx new file mode 100644 index 000000000..3f27fb927 --- /dev/null +++ b/desktop/flipper-server-core/src/fb-stubs/internRequests.tsx @@ -0,0 +1,41 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import {GraphFileUpload, GraphResponse} from 'flipper-common'; + +/* eslint-disable @typescript-eslint/no-unused-vars */ + +export async function internGraphPOSTAPIRequest( + endpoint: string, + formFields: { + [key: string]: any; + }, + fileFields: Record, + options: { + timeout?: number; + internGraphUrl?: string; + }, + token: string, +): Promise { + throw new Error('Feature not implemented'); +} + +export async function internGraphGETAPIRequest( + endpoint: string, + params: { + [key: string]: any; + }, + _options: { + timeout?: number; + internGraphUrl?: string; + }, + token: string, +): Promise { + throw new Error('Feature not implemented'); +} diff --git a/desktop/flipper-server-core/src/fb-stubs/sendScribeLogs.tsx b/desktop/flipper-server-core/src/fb-stubs/sendScribeLogs.tsx new file mode 100644 index 000000000..1ed1f7e30 --- /dev/null +++ b/desktop/flipper-server-core/src/fb-stubs/sendScribeLogs.tsx @@ -0,0 +1,12 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +export async function sendScribeLogs( + _messages: {category: string; message: string}[], +): Promise {} diff --git a/desktop/flipper-server-core/src/utils/CertificateProvider.tsx b/desktop/flipper-server-core/src/utils/CertificateProvider.tsx index e0294ab8e..935c1cc86 100644 --- a/desktop/flipper-server-core/src/utils/CertificateProvider.tsx +++ b/desktop/flipper-server-core/src/utils/CertificateProvider.tsx @@ -7,8 +7,6 @@ * @format */ -import {Logger} from 'flipper-common'; -import {internGraphPOSTAPIRequest} from 'flipper-common'; import ServerController from '../comms/ServerController'; import {promisify} from 'util'; import fs from 'fs-extra'; @@ -28,6 +26,8 @@ import {Client as ADBClient} from 'adbkit'; import archiver from 'archiver'; import {timeout, isTest} from 'flipper-common'; import {v4 as uuid} from 'uuid'; +import {internGraphPOSTAPIRequest} from '../fb-stubs/internRequests'; +import {SERVICE_FLIPPER} from '../FlipperServerImpl'; export type CertificateExchangeMedium = 'FS_ACCESS' | 'WWW' | 'NONE'; @@ -89,7 +89,6 @@ type CertificateProviderConfig = { * Flipper CA. */ export default class CertificateProvider { - private logger: Logger; private _adb: Promise | undefined; private didCertificateSetup = false; private config: CertificateProviderConfig; @@ -105,12 +104,7 @@ export default class CertificateProvider { throw new Error('Android is not enabled in settings'); } - constructor( - server: ServerController, - logger: Logger, - config: CertificateProviderConfig, - ) { - this.logger = logger; + constructor(server: ServerController, config: CertificateProviderConfig) { // TODO: refactor this code to create promise lazily this._adb = config.enableAndroid ? (getAdbClient(config).catch((_e) => { @@ -133,15 +127,25 @@ export default class CertificateProvider { zipPath: string, deviceID: string, ): Promise => { - const buff = await fs.readFile(zipPath); - const file = new File([buff], 'certs.zip'); return reportPlatformFailures( timeout( 5 * 60 * 1000, - internGraphPOSTAPIRequest('flipper/certificates', { - certificate_zip: file, - device_id: deviceID, - }), + internGraphPOSTAPIRequest( + 'flipper/certificates', + { + device_id: deviceID, + }, + { + certificate_zip: { + path: zipPath, + filename: 'certs.zip', + }, + }, + {timeout: 5 * 60 * 1000}, + await this.server.flipperServer.keytarManager.retrieveToken( + SERVICE_FLIPPER, + ), + ).then(() => {}), 'Timed out uploading Flipper certificates to WWW.', ), 'uploadCertificates', diff --git a/desktop/flipper-server-core/src/utils/keytar.tsx b/desktop/flipper-server-core/src/utils/keytar.tsx index 4d262aa40..5cca22637 100644 --- a/desktop/flipper-server-core/src/utils/keytar.tsx +++ b/desktop/flipper-server-core/src/utils/keytar.tsx @@ -21,6 +21,7 @@ export class KeytarManager { if (this.keytar == null) { throw new Error('Keytar is not available.'); } + await this.keytar.deletePassword(service, os.userInfo().username); await this.keytar.setPassword(service, os.userInfo().username, password); } @@ -40,6 +41,7 @@ export class KeytarManager { if (!token) { throw new UserNotSignedInError(); } + return token; } } diff --git a/desktop/flipper-server/src/index.tsx b/desktop/flipper-server/src/index.tsx index e79e927a2..4da3e564d 100644 --- a/desktop/flipper-server/src/index.tsx +++ b/desktop/flipper-server/src/index.tsx @@ -22,6 +22,11 @@ const rootDir = path.resolve(__dirname, '..', '..'); const staticDir = path.join(rootDir, 'static'); async function start() { + // supress debug messages by default. TODO: make CLI flag + console.debug = function () { + // Noop + }; + const {app, server, socket} = await startBaseServer({ port: PORT, staticDir, diff --git a/desktop/flipper-server/src/startSocketServer.tsx b/desktop/flipper-server/src/startSocketServer.tsx index 79810f4b1..19a862b09 100644 --- a/desktop/flipper-server/src/startSocketServer.tsx +++ b/desktop/flipper-server/src/startSocketServer.tsx @@ -27,7 +27,6 @@ export function startSocketServer( flipperServer.onAny(onServerEvent); client.on('exec', (id, command, args) => { - console.log(id, command, args); flipperServer .exec(command, ...args) .then((result: any) => { diff --git a/desktop/flipper-ui-core/src/chrome/ShareSheetExportUrl.tsx b/desktop/flipper-ui-core/src/chrome/ShareSheetExportUrl.tsx index 6917ddf0f..73c9d945c 100644 --- a/desktop/flipper-ui-core/src/chrome/ShareSheetExportUrl.tsx +++ b/desktop/flipper-ui-core/src/chrome/ShareSheetExportUrl.tsx @@ -13,9 +13,9 @@ import {ReactReduxContext, ReactReduxContextValue} from 'react-redux'; import {Logger} from 'flipper-common'; import {IdlerImpl} from '../utils/Idler'; import { - shareFlipperData, DataExportResult, DataExportError, + shareFlipperData, } from '../fb-stubs/user'; import { exportStore, diff --git a/desktop/flipper-ui-core/src/fb-stubs/constants.tsx b/desktop/flipper-ui-core/src/fb-stubs/constants.tsx index deb6c5348..ae6d95bc4 100644 --- a/desktop/flipper-ui-core/src/fb-stubs/constants.tsx +++ b/desktop/flipper-ui-core/src/fb-stubs/constants.tsx @@ -10,19 +10,6 @@ import {DeviceOS} from 'flipper-plugin'; export default Object.freeze({ - GRAPH_APP_ID: '', - GRAPH_CLIENT_TOKEN: '', - GRAPH_ACCESS_TOKEN: '', - - // this provides elevated access to scribe. we really shouldn't be exposing this. - // need to investigate how to abstract the scribe logging so it's safe. - GRAPH_SECRET: '', - GRAPH_SECRET_ACCESS_TOKEN: '', - - // Provides access to Insights Validation endpoint on interngraph - INSIGHT_INTERN_APP_ID: '', - INSIGHT_INTERN_APP_TOKEN: '', - // Enables the flipper data to be exported through shareabale link ENABLE_SHAREABLE_LINK: false, @@ -44,5 +31,4 @@ export default Object.freeze({ SUPPORT_GROUPS: [], INTERN_URL: '', - INTERNGRAPH_API: '', }); diff --git a/desktop/flipper-ui-core/src/fb-stubs/user.tsx b/desktop/flipper-ui-core/src/fb-stubs/user.tsx index 23cb813e4..82d9c5a45 100644 --- a/desktop/flipper-ui-core/src/fb-stubs/user.tsx +++ b/desktop/flipper-ui-core/src/fb-stubs/user.tsx @@ -7,6 +7,7 @@ * @format */ +import {GraphFileUpload} from 'flipper-common'; import {Atom, createState} from 'flipper-plugin'; import {User} from '../reducers/user'; @@ -19,7 +20,11 @@ export async function internGraphPOSTAPIRequest( _formFields: { [key: string]: any; } = {}, - _internGraphUrl?: string, + _fileFields: Record = {}, + _options: { + timeout?: number; + internGraphUrl?: string; + } = {}, ): Promise { throw new Error('Feature not implemented'); } @@ -29,7 +34,10 @@ export async function internGraphGETAPIRequest( _params: { [key: string]: any; } = {}, - _internGraphUrl?: string, + _options: { + timeout?: number; + internGraphUrl?: string; + } = {}, ): Promise { throw new Error('Feature not implemented'); } diff --git a/desktop/flipper-ui-core/src/startFlipperDesktop.tsx b/desktop/flipper-ui-core/src/startFlipperDesktop.tsx index 5580f130d..64235fd88 100644 --- a/desktop/flipper-ui-core/src/startFlipperDesktop.tsx +++ b/desktop/flipper-ui-core/src/startFlipperDesktop.tsx @@ -39,13 +39,7 @@ import styled from '@emotion/styled'; import {CopyOutlined} from '@ant-design/icons'; import {getVersionString} from './utils/versionString'; import {PersistGate} from 'redux-persist/integration/react'; -import { - setLoggerInstance, - setUserSessionManagerInstance, - Settings, - FlipperServer, -} from 'flipper-common'; -import {internGraphPOSTAPIRequest} from './fb-stubs/user'; +import {setLoggerInstance, FlipperServer} from 'flipper-common'; import {getRenderHostInstance} from './RenderHost'; import {startGlobalErrorHandling} from './utils/globalErrorHandling'; import {loadTheme} from './utils/loadTheme'; @@ -168,9 +162,6 @@ function init(flipperServer: FlipperServer) { else console.warn(msg, r.error); } }); - setUserSessionManagerInstance({ - internGraphPOSTAPIRequest, - }); ReactDOM.render( , diff --git a/desktop/flipper-ui-core/src/utils/exportData.tsx b/desktop/flipper-ui-core/src/utils/exportData.tsx index 596cbe501..46c5af743 100644 --- a/desktop/flipper-ui-core/src/utils/exportData.tsx +++ b/desktop/flipper-ui-core/src/utils/exportData.tsx @@ -33,13 +33,13 @@ import {deconstructClientId} from 'flipper-common'; import {processMessageQueue} from './messageQueue'; import {getPluginTitle} from './pluginUtils'; import {capture} from './screenshot'; -import {uploadFlipperMedia} from '../fb-stubs/user'; import {Dialog, Idler} from 'flipper-plugin'; import {ClientQuery} from 'flipper-common'; import ShareSheetExportUrl from '../chrome/ShareSheetExportUrl'; import ShareSheetExportFile from '../chrome/ShareSheetExportFile'; import ExportDataPluginSheet from '../chrome/ExportDataPluginSheet'; import {getRenderHostInstance} from '../RenderHost'; +import {uploadFlipperMedia} from '../fb-stubs/user'; export const IMPORT_FLIPPER_TRACE_EVENT = 'import-flipper-trace'; export const EXPORT_FLIPPER_TRACE_EVENT = 'export-flipper-trace'; diff --git a/desktop/types/flipperGlobals.d.ts b/desktop/types/flipperGlobals.d.ts index 278d88cda..bf70c740a 100644 --- a/desktop/types/flipperGlobals.d.ts +++ b/desktop/types/flipperGlobals.d.ts @@ -14,3 +14,16 @@ declare const electronRequire: { resolve: (module: string) => string; cache: {[module: string]: any}; }; + +// For Electron +declare module NodeJS { + interface Global { + __REVISION__: string | undefined; + __VERSION__: string; + electronRequire: { + (name: string): any; + resolve: (module: string) => string; + cache: {[module: string]: any}; + }; + } +}