Upload/Download certs zip from Flipper
Summary: This diff adds upload and download logic for certs. It makes changes on both Flipper Client and Desktop side. With this we enable cert exchange through WWW. Next Diffs: 1) Add Flipper state in cert provider for more debug data 2) Tests Reviewed By: jknoxville Differential Revision: D23092706 fbshipit-source-id: e576253606b64b62848b70203db7e09a3bd77fd9
This commit is contained in:
committed by
Facebook GitHub Bot
parent
6e0b407063
commit
f626925443
@@ -14,10 +14,13 @@
|
|||||||
"@emotion/core": "^10.0.22",
|
"@emotion/core": "^10.0.22",
|
||||||
"@emotion/styled": "^10.0.23",
|
"@emotion/styled": "^10.0.23",
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
|
"@types/archiver": "^3.1.0",
|
||||||
|
"@types/uuid": "^8.0.1",
|
||||||
"JSONStream": "^1.3.1",
|
"JSONStream": "^1.3.1",
|
||||||
"adbkit": "^2.11.1",
|
"adbkit": "^2.11.1",
|
||||||
"adbkit-logcat": "^2.0.1",
|
"adbkit-logcat": "^2.0.1",
|
||||||
"algoliasearch": "^4.0.0",
|
"algoliasearch": "^4.0.0",
|
||||||
|
"archiver": "^5.0.0",
|
||||||
"async-mutex": "^0.1.3",
|
"async-mutex": "^0.1.3",
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
"deep-equal": "^2.0.1",
|
"deep-equal": "^2.0.1",
|
||||||
@@ -61,7 +64,7 @@
|
|||||||
"semver": "^7.3.2",
|
"semver": "^7.3.2",
|
||||||
"string-natural-compare": "^3.0.0",
|
"string-natural-compare": "^3.0.0",
|
||||||
"tmp": "^0.2.1",
|
"tmp": "^0.2.1",
|
||||||
"uuid": "^8.1.0",
|
"uuid": "^8.3.0",
|
||||||
"which": "^2.0.1",
|
"which": "^2.0.1",
|
||||||
"ws": "^7.3.0",
|
"ws": "^7.3.0",
|
||||||
"xdg-basedir": "^4.0.0"
|
"xdg-basedir": "^4.0.0"
|
||||||
|
|||||||
@@ -72,7 +72,12 @@ function getStore(selectedPlugins: Array<string>) {
|
|||||||
|
|
||||||
const client = new Client(
|
const client = new Client(
|
||||||
clientId,
|
clientId,
|
||||||
{app: 'app', os: 'iOS', device: 'TestiPhone', device_id: 'serial'},
|
{
|
||||||
|
app: 'app',
|
||||||
|
os: 'iOS',
|
||||||
|
device: 'TestiPhone',
|
||||||
|
device_id: 'serial',
|
||||||
|
},
|
||||||
null,
|
null,
|
||||||
logger,
|
logger,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|||||||
17
desktop/app/src/devices/ClientDevice.tsx
Normal file
17
desktop/app/src/devices/ClientDevice.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* 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 BaseDevice, {OS} from './BaseDevice';
|
||||||
|
|
||||||
|
export default class ClientDevice extends BaseDevice {
|
||||||
|
constructor(serial: string, title: string, os: OS) {
|
||||||
|
super(serial, 'emulator', title, os);
|
||||||
|
this.devicePlugins = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,6 +37,7 @@ import querystring from 'querystring';
|
|||||||
import {IncomingMessage} from 'http';
|
import {IncomingMessage} from 'http';
|
||||||
import ws from 'ws';
|
import ws from 'ws';
|
||||||
import {initSelfInpector} from './utils/self-inspection/selfInspectionUtils';
|
import {initSelfInpector} from './utils/self-inspection/selfInspectionUtils';
|
||||||
|
import ClientDevice from './devices/ClientDevice';
|
||||||
|
|
||||||
type ClientInfo = {
|
type ClientInfo = {
|
||||||
connection: FlipperClientConnection<any, any> | null | undefined;
|
connection: FlipperClientConnection<any, any> | null | undefined;
|
||||||
@@ -51,9 +52,9 @@ type ClientCsrQuery = {
|
|||||||
function transformCertificateExchangeMediumToType(
|
function transformCertificateExchangeMediumToType(
|
||||||
medium: number | undefined,
|
medium: number | undefined,
|
||||||
): CertificateExchangeMedium {
|
): CertificateExchangeMedium {
|
||||||
if (medium === 1) {
|
if (medium == 1) {
|
||||||
return 'FS_ACCESS';
|
return 'FS_ACCESS';
|
||||||
} else if (medium === 2) {
|
} else if (medium == 2) {
|
||||||
return 'WWW';
|
return 'WWW';
|
||||||
} else {
|
} else {
|
||||||
return 'FS_ACCESS';
|
return 'FS_ACCESS';
|
||||||
@@ -226,6 +227,7 @@ class Server extends EventEmitter {
|
|||||||
device: 'device',
|
device: 'device',
|
||||||
device_id: deviceId,
|
device_id: deviceId,
|
||||||
sdk_version: 1,
|
sdk_version: 1,
|
||||||
|
medium: 'FS_ACCESS',
|
||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
).then((c) => (resolvedClient = c));
|
).then((c) => (resolvedClient = c));
|
||||||
@@ -277,14 +279,43 @@ class Server extends EventEmitter {
|
|||||||
if (!payload.data) {
|
if (!payload.data) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const clientData: ClientQuery & ClientCsrQuery = JSON.parse(payload.data);
|
const clientData: ClientQuery &
|
||||||
|
ClientCsrQuery & {medium: number | undefined} = JSON.parse(payload.data);
|
||||||
this.connectionTracker.logConnectionAttempt(clientData);
|
this.connectionTracker.logConnectionAttempt(clientData);
|
||||||
|
|
||||||
const {app, os, device, device_id, sdk_version, csr, csr_path} = clientData;
|
const {
|
||||||
|
app,
|
||||||
|
os,
|
||||||
|
device,
|
||||||
|
device_id,
|
||||||
|
sdk_version,
|
||||||
|
csr,
|
||||||
|
csr_path,
|
||||||
|
medium,
|
||||||
|
} = clientData;
|
||||||
|
const transformedMedium = transformCertificateExchangeMediumToType(medium);
|
||||||
|
const duplicateDevices = this.store
|
||||||
|
.getState()
|
||||||
|
.connections.devices.filter((device) => device.serial === device_id);
|
||||||
|
// When user switches from WWW to FS_ACCESS, we reset the certs folder, but we don't do it other way around. Thus when user switches to WWW from FS_ACCESS and if certs arepresent then the device id sent by Flipper SDK is the original one and in that case we need not create a device.
|
||||||
|
if (transformedMedium === 'WWW' && duplicateDevices.length == 0) {
|
||||||
|
// TODO unregister previous ClientDevice's for a particular device
|
||||||
|
this.store.dispatch({
|
||||||
|
type: 'REGISTER_DEVICE',
|
||||||
|
payload: new ClientDevice(device_id, app, os),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const client: Promise<Client> = this.addConnection(
|
const client: Promise<Client> = this.addConnection(
|
||||||
socket,
|
socket,
|
||||||
{app, os, device, device_id, sdk_version},
|
{
|
||||||
|
app,
|
||||||
|
os,
|
||||||
|
device,
|
||||||
|
device_id,
|
||||||
|
sdk_version,
|
||||||
|
medium: transformedMedium,
|
||||||
|
},
|
||||||
{csr, csr_path},
|
{csr, csr_path},
|
||||||
).then((client) => {
|
).then((client) => {
|
||||||
return (resolvedClient = client);
|
return (resolvedClient = client);
|
||||||
@@ -364,6 +395,7 @@ class Server extends EventEmitter {
|
|||||||
destination: string;
|
destination: string;
|
||||||
medium: number | undefined; // OSS's older Client SDK might not send medium information. This is not an issue for internal FB users, as Flipper release is insync with client SDK through launcher.
|
medium: number | undefined; // OSS's older Client SDK might not send medium information. This is not an issue for internal FB users, as Flipper release is insync with client SDK through launcher.
|
||||||
} = rawData;
|
} = rawData;
|
||||||
|
|
||||||
if (json.method === 'signCertificate') {
|
if (json.method === 'signCertificate') {
|
||||||
console.debug('CSR received from device', 'server');
|
console.debug('CSR received from device', 'server');
|
||||||
|
|
||||||
@@ -461,7 +493,7 @@ class Server extends EventEmitter {
|
|||||||
|
|
||||||
async addConnection(
|
async addConnection(
|
||||||
conn: FlipperClientConnection<any, any>,
|
conn: FlipperClientConnection<any, any>,
|
||||||
query: ClientQuery,
|
query: ClientQuery & {medium: CertificateExchangeMedium},
|
||||||
csrQuery: ClientCsrQuery,
|
csrQuery: ClientCsrQuery,
|
||||||
): Promise<Client> {
|
): Promise<Client> {
|
||||||
invariant(query, 'expected query');
|
invariant(query, 'expected query');
|
||||||
@@ -469,7 +501,7 @@ class Server extends EventEmitter {
|
|||||||
// try to get id by comparing giving `csr` to file from `csr_path`
|
// try to get id by comparing giving `csr` to file from `csr_path`
|
||||||
// otherwise, use given device_id
|
// otherwise, use given device_id
|
||||||
const {csr_path, csr} = csrQuery;
|
const {csr_path, csr} = csrQuery;
|
||||||
return (csr_path && csr
|
return (csr_path && csr && query.medium === 'FS_ACCESS'
|
||||||
? this.certificateProvider.extractAppNameFromCSR(csr).then((appName) => {
|
? this.certificateProvider.extractAppNameFromCSR(csr).then((appName) => {
|
||||||
return this.certificateProvider.getTargetDeviceId(
|
return this.certificateProvider.getTargetDeviceId(
|
||||||
query.os,
|
query.os,
|
||||||
|
|||||||
@@ -8,9 +8,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Logger} from '../fb-interfaces/Logger';
|
import {Logger} from '../fb-interfaces/Logger';
|
||||||
|
import {internGraphPOSTAPIRequest} from '../fb-stubs/user';
|
||||||
import Server from '../server';
|
import Server from '../server';
|
||||||
import {promisify} from 'util';
|
import {promisify} from 'util';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import fsExtra from 'fs-extra';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
openssl,
|
openssl,
|
||||||
isInstalled as opensslInstalled,
|
isInstalled as opensslInstalled,
|
||||||
@@ -24,6 +27,9 @@ import * as androidUtil from './androidContainerUtility';
|
|||||||
import os from 'os';
|
import os from 'os';
|
||||||
import {Client as ADBClient} from 'adbkit';
|
import {Client as ADBClient} from 'adbkit';
|
||||||
import {Store} from '../reducers/index';
|
import {Store} from '../reducers/index';
|
||||||
|
import archiver from 'archiver';
|
||||||
|
import promiseTimeout from '../utils/promiseTimeout';
|
||||||
|
import {v4 as uuid} from 'uuid';
|
||||||
|
|
||||||
export type CertificateExchangeMedium = 'FS_ACCESS' | 'WWW';
|
export type CertificateExchangeMedium = 'FS_ACCESS' | 'WWW';
|
||||||
|
|
||||||
@@ -94,47 +100,90 @@ export default class CertificateProvider {
|
|||||||
this.server = server;
|
this.server = server;
|
||||||
}
|
}
|
||||||
|
|
||||||
processCertificateSigningRequest(
|
uploadFiles = async (zipPath: string, deviceID: string): Promise<void> => {
|
||||||
|
const buff = await fsExtra.readFile(zipPath);
|
||||||
|
const file = new File([buff], 'certs.zip');
|
||||||
|
return reportPlatformFailures(
|
||||||
|
promiseTimeout(
|
||||||
|
5 * 60 * 1000,
|
||||||
|
internGraphPOSTAPIRequest('flipper/certificates', {
|
||||||
|
certificate_zip: file,
|
||||||
|
device_id: deviceID,
|
||||||
|
}),
|
||||||
|
'Timed out uploading Flipper export.',
|
||||||
|
),
|
||||||
|
'uploadCertificates',
|
||||||
|
).catch((e) => console.error(`Failed to upload certificates due to ${e}`));
|
||||||
|
};
|
||||||
|
|
||||||
|
async processCertificateSigningRequest(
|
||||||
unsanitizedCsr: string,
|
unsanitizedCsr: string,
|
||||||
os: string,
|
os: string,
|
||||||
appDirectory: string,
|
appDirectory: string,
|
||||||
medium: CertificateExchangeMedium,
|
medium: CertificateExchangeMedium,
|
||||||
): Promise<{deviceId: string}> {
|
): Promise<{deviceId: string}> {
|
||||||
// TODO: Add implementations for each of these conditions
|
|
||||||
if (medium === 'FS_ACCESS') {
|
|
||||||
// Use IDB for cert exchange
|
|
||||||
} else if (medium === 'WWW') {
|
|
||||||
// Use WWWW
|
|
||||||
}
|
|
||||||
const csr = this.santitizeString(unsanitizedCsr);
|
const csr = this.santitizeString(unsanitizedCsr);
|
||||||
if (csr === '') {
|
if (csr === '') {
|
||||||
return Promise.reject(new Error(`Received empty CSR from ${os} device`));
|
return Promise.reject(new Error(`Received empty CSR from ${os} device`));
|
||||||
}
|
}
|
||||||
this.ensureOpenSSLIsAvailable();
|
this.ensureOpenSSLIsAvailable();
|
||||||
|
const rootFolder = await promisify(tmp.dir)();
|
||||||
|
const certFolder = rootFolder + '/FlipperCerts/';
|
||||||
|
const certsZipPath = rootFolder + '/certs.zip';
|
||||||
return this.certificateSetup
|
return this.certificateSetup
|
||||||
.then((_) => this.getCACertificate())
|
.then((_) => this.getCACertificate())
|
||||||
.then((caCert) =>
|
.then((caCert) =>
|
||||||
this.deployFileToMobileApp(
|
this.deployOrStageFileForMobileApp(
|
||||||
appDirectory,
|
appDirectory,
|
||||||
deviceCAcertFile,
|
deviceCAcertFile,
|
||||||
caCert,
|
caCert,
|
||||||
csr,
|
csr,
|
||||||
os,
|
os,
|
||||||
|
medium,
|
||||||
|
certFolder,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.then((_) => this.generateClientCertificate(csr))
|
.then((_) => this.generateClientCertificate(csr))
|
||||||
.then((clientCert) =>
|
.then((clientCert) =>
|
||||||
this.deployFileToMobileApp(
|
this.deployOrStageFileForMobileApp(
|
||||||
appDirectory,
|
appDirectory,
|
||||||
deviceClientCertFile,
|
deviceClientCertFile,
|
||||||
clientCert,
|
clientCert,
|
||||||
csr,
|
csr,
|
||||||
os,
|
os,
|
||||||
|
medium,
|
||||||
|
certFolder,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.then((_) => this.extractAppNameFromCSR(csr))
|
.then((_) => {
|
||||||
.then((appName) => this.getTargetDeviceId(os, appName, appDirectory, csr))
|
return this.extractAppNameFromCSR(csr);
|
||||||
.then((deviceId) => {
|
})
|
||||||
|
.then((appName) => {
|
||||||
|
if (medium === 'FS_ACCESS') {
|
||||||
|
return this.getTargetDeviceId(os, appName, appDirectory, csr);
|
||||||
|
} else {
|
||||||
|
return uuid();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(async (deviceId) => {
|
||||||
|
if (medium === 'WWW') {
|
||||||
|
const zipPromise = new Promise((resolve, reject) => {
|
||||||
|
const output = fs.createWriteStream(certsZipPath);
|
||||||
|
const archive = archiver('zip', {
|
||||||
|
zlib: {level: 9}, // Sets the compression level.
|
||||||
|
});
|
||||||
|
archive.directory(certFolder, false);
|
||||||
|
output.on('close', function () {
|
||||||
|
resolve(certsZipPath);
|
||||||
|
});
|
||||||
|
archive.on('warning', reject);
|
||||||
|
archive.on('error', reject);
|
||||||
|
archive.pipe(output);
|
||||||
|
archive.finalize();
|
||||||
|
});
|
||||||
|
await zipPromise;
|
||||||
|
await this.uploadFiles(certsZipPath, deviceId);
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
deviceId,
|
deviceId,
|
||||||
};
|
};
|
||||||
@@ -201,15 +250,31 @@ export default class CertificateProvider {
|
|||||||
throw new Error("Path didn't match expected pattern: " + absolutePath);
|
throw new Error("Path didn't match expected pattern: " + absolutePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
deployFileToMobileApp(
|
async deployOrStageFileForMobileApp(
|
||||||
destination: string,
|
destination: string,
|
||||||
filename: string,
|
filename: string,
|
||||||
contents: string,
|
contents: string,
|
||||||
csr: string,
|
csr: string,
|
||||||
os: string,
|
os: string,
|
||||||
|
medium: CertificateExchangeMedium,
|
||||||
|
certFolder: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const appNamePromise = this.extractAppNameFromCSR(csr);
|
const appNamePromise = this.extractAppNameFromCSR(csr);
|
||||||
|
|
||||||
|
if (medium === 'WWW') {
|
||||||
|
const certPathExists = await fsExtra.pathExists(certFolder);
|
||||||
|
if (!certPathExists) {
|
||||||
|
await fsExtra.mkdir(certFolder);
|
||||||
|
}
|
||||||
|
return promisify(fs.writeFile)(certFolder + filename, contents).catch(
|
||||||
|
(e) => {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to write ${filename} to temporary folder. Error: ${e}`,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (os === 'Android') {
|
if (os === 'Android') {
|
||||||
const deviceIdPromise = appNamePromise.then((app) =>
|
const deviceIdPromise = appNamePromise.then((app) =>
|
||||||
this.getTargetAndroidDeviceId(app, destination, csr),
|
this.getTargetAndroidDeviceId(app, destination, csr),
|
||||||
@@ -237,9 +302,9 @@ export default class CertificateProvider {
|
|||||||
destination,
|
destination,
|
||||||
);
|
);
|
||||||
return appNamePromise
|
return appNamePromise
|
||||||
.then((appName) =>
|
.then((appName) => {
|
||||||
this.getTargetiOSDeviceId(appName, destination, csr),
|
return this.getTargetiOSDeviceId(appName, destination, csr);
|
||||||
)
|
})
|
||||||
.then((udid) => {
|
.then((udid) => {
|
||||||
return appNamePromise.then((appName) =>
|
return appNamePromise.then((appName) =>
|
||||||
this.pushFileToiOSDevice(
|
this.pushFileToiOSDevice(
|
||||||
|
|||||||
@@ -716,7 +716,12 @@ test('test determinePluginsToProcess for mutilple clients having plugins present
|
|||||||
const device1 = new BaseDevice('serial1', 'emulator', 'TestiPhone', 'iOS');
|
const device1 = new BaseDevice('serial1', 'emulator', 'TestiPhone', 'iOS');
|
||||||
const client1 = new Client(
|
const client1 = new Client(
|
||||||
generateClientIdentifier(device1, 'app'),
|
generateClientIdentifier(device1, 'app'),
|
||||||
{app: 'app', os: 'iOS', device: 'TestiPhone', device_id: 'serial1'},
|
{
|
||||||
|
app: 'app',
|
||||||
|
os: 'iOS',
|
||||||
|
device: 'TestiPhone',
|
||||||
|
device_id: 'serial1',
|
||||||
|
},
|
||||||
null,
|
null,
|
||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
@@ -724,7 +729,12 @@ test('test determinePluginsToProcess for mutilple clients having plugins present
|
|||||||
);
|
);
|
||||||
const client2 = new Client(
|
const client2 = new Client(
|
||||||
generateClientIdentifier(device1, 'app2'),
|
generateClientIdentifier(device1, 'app2'),
|
||||||
{app: 'app2', os: 'iOS', device: 'TestiPhone', device_id: 'serial1'},
|
{
|
||||||
|
app: 'app2',
|
||||||
|
os: 'iOS',
|
||||||
|
device: 'TestiPhone',
|
||||||
|
device_id: 'serial1',
|
||||||
|
},
|
||||||
null,
|
null,
|
||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
@@ -732,7 +742,12 @@ test('test determinePluginsToProcess for mutilple clients having plugins present
|
|||||||
);
|
);
|
||||||
const client3 = new Client(
|
const client3 = new Client(
|
||||||
generateClientIdentifier(device1, 'app3'),
|
generateClientIdentifier(device1, 'app3'),
|
||||||
{app: 'app3', os: 'iOS', device: 'TestiPhone', device_id: 'serial1'},
|
{
|
||||||
|
app: 'app3',
|
||||||
|
os: 'iOS',
|
||||||
|
device: 'TestiPhone',
|
||||||
|
device_id: 'serial1',
|
||||||
|
},
|
||||||
null,
|
null,
|
||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
@@ -777,7 +792,12 @@ test('test determinePluginsToProcess for no selected plugin present in any clien
|
|||||||
const device1 = new BaseDevice('serial1', 'emulator', 'TestiPhone', 'iOS');
|
const device1 = new BaseDevice('serial1', 'emulator', 'TestiPhone', 'iOS');
|
||||||
const client1 = new Client(
|
const client1 = new Client(
|
||||||
generateClientIdentifier(device1, 'app'),
|
generateClientIdentifier(device1, 'app'),
|
||||||
{app: 'app', os: 'iOS', device: 'TestiPhone', device_id: 'serial1'},
|
{
|
||||||
|
app: 'app',
|
||||||
|
os: 'iOS',
|
||||||
|
device: 'TestiPhone',
|
||||||
|
device_id: 'serial1',
|
||||||
|
},
|
||||||
null,
|
null,
|
||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
@@ -785,7 +805,12 @@ test('test determinePluginsToProcess for no selected plugin present in any clien
|
|||||||
);
|
);
|
||||||
const client2 = new Client(
|
const client2 = new Client(
|
||||||
generateClientIdentifier(device1, 'app2'),
|
generateClientIdentifier(device1, 'app2'),
|
||||||
{app: 'app2', os: 'iOS', device: 'TestiPhone', device_id: 'serial1'},
|
{
|
||||||
|
app: 'app2',
|
||||||
|
os: 'iOS',
|
||||||
|
device: 'TestiPhone',
|
||||||
|
device_id: 'serial1',
|
||||||
|
},
|
||||||
null,
|
null,
|
||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
@@ -811,7 +836,12 @@ test('test determinePluginsToProcess for multiple clients on same device', async
|
|||||||
const device1 = new BaseDevice('serial1', 'emulator', 'TestiPhone', 'iOS');
|
const device1 = new BaseDevice('serial1', 'emulator', 'TestiPhone', 'iOS');
|
||||||
const client1 = new Client(
|
const client1 = new Client(
|
||||||
generateClientIdentifier(device1, 'app'),
|
generateClientIdentifier(device1, 'app'),
|
||||||
{app: 'app', os: 'iOS', device: 'TestiPhone', device_id: 'serial1'},
|
{
|
||||||
|
app: 'app',
|
||||||
|
os: 'iOS',
|
||||||
|
device: 'TestiPhone',
|
||||||
|
device_id: 'serial1',
|
||||||
|
},
|
||||||
null,
|
null,
|
||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
@@ -819,7 +849,12 @@ test('test determinePluginsToProcess for multiple clients on same device', async
|
|||||||
);
|
);
|
||||||
const client2 = new Client(
|
const client2 = new Client(
|
||||||
generateClientIdentifier(device1, 'app2'),
|
generateClientIdentifier(device1, 'app2'),
|
||||||
{app: 'app2', os: 'iOS', device: 'TestiPhone', device_id: 'serial1'},
|
{
|
||||||
|
app: 'app2',
|
||||||
|
os: 'iOS',
|
||||||
|
device: 'TestiPhone',
|
||||||
|
device_id: 'serial1',
|
||||||
|
},
|
||||||
null,
|
null,
|
||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
@@ -852,7 +887,12 @@ test('test determinePluginsToProcess for multiple clients on different device',
|
|||||||
const device2 = new BaseDevice('serial2', 'emulator', 'TestiPhone', 'iOS');
|
const device2 = new BaseDevice('serial2', 'emulator', 'TestiPhone', 'iOS');
|
||||||
const client1Device1 = new Client(
|
const client1Device1 = new Client(
|
||||||
generateClientIdentifier(device1, 'app'),
|
generateClientIdentifier(device1, 'app'),
|
||||||
{app: 'app', os: 'iOS', device: 'TestiPhone', device_id: 'serial1'},
|
{
|
||||||
|
app: 'app',
|
||||||
|
os: 'iOS',
|
||||||
|
device: 'TestiPhone',
|
||||||
|
device_id: 'serial1',
|
||||||
|
},
|
||||||
null,
|
null,
|
||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
@@ -860,7 +900,12 @@ test('test determinePluginsToProcess for multiple clients on different device',
|
|||||||
);
|
);
|
||||||
const client2Device1 = new Client(
|
const client2Device1 = new Client(
|
||||||
generateClientIdentifier(device1, 'app2'),
|
generateClientIdentifier(device1, 'app2'),
|
||||||
{app: 'app1', os: 'iOS', device: 'TestiPhone', device_id: 'serial1'},
|
{
|
||||||
|
app: 'app1',
|
||||||
|
os: 'iOS',
|
||||||
|
device: 'TestiPhone',
|
||||||
|
device_id: 'serial1',
|
||||||
|
},
|
||||||
null,
|
null,
|
||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
@@ -868,7 +913,12 @@ test('test determinePluginsToProcess for multiple clients on different device',
|
|||||||
);
|
);
|
||||||
const client1Device2 = new Client(
|
const client1Device2 = new Client(
|
||||||
generateClientIdentifier(device2, 'app'),
|
generateClientIdentifier(device2, 'app'),
|
||||||
{app: 'app', os: 'iOS', device: 'TestiPhone', device_id: 'serial2'},
|
{
|
||||||
|
app: 'app',
|
||||||
|
os: 'iOS',
|
||||||
|
device: 'TestiPhone',
|
||||||
|
device_id: 'serial2',
|
||||||
|
},
|
||||||
null,
|
null,
|
||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
@@ -876,7 +926,12 @@ test('test determinePluginsToProcess for multiple clients on different device',
|
|||||||
);
|
);
|
||||||
const client2Device2 = new Client(
|
const client2Device2 = new Client(
|
||||||
generateClientIdentifier(device2, 'app2'),
|
generateClientIdentifier(device2, 'app2'),
|
||||||
{app: 'app1', os: 'iOS', device: 'TestiPhone', device_id: 'serial2'},
|
{
|
||||||
|
app: 'app1',
|
||||||
|
os: 'iOS',
|
||||||
|
device: 'TestiPhone',
|
||||||
|
device_id: 'serial2',
|
||||||
|
},
|
||||||
null,
|
null,
|
||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
@@ -934,7 +989,12 @@ test('test determinePluginsToProcess to ignore archived clients', async () => {
|
|||||||
const mockStore = configureStore<State, {}>([])();
|
const mockStore = configureStore<State, {}>([])();
|
||||||
const client = new Client(
|
const client = new Client(
|
||||||
generateClientIdentifier(selectedDevice, 'app'),
|
generateClientIdentifier(selectedDevice, 'app'),
|
||||||
{app: 'app', os: 'iOS', device: 'TestiPhone', device_id: 'serial'},
|
{
|
||||||
|
app: 'app',
|
||||||
|
os: 'iOS',
|
||||||
|
device: 'TestiPhone',
|
||||||
|
device_id: 'serial',
|
||||||
|
},
|
||||||
null,
|
null,
|
||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
@@ -942,7 +1002,12 @@ test('test determinePluginsToProcess to ignore archived clients', async () => {
|
|||||||
);
|
);
|
||||||
const archivedClient = new Client(
|
const archivedClient = new Client(
|
||||||
generateClientIdentifier(archivedDevice, 'app'),
|
generateClientIdentifier(archivedDevice, 'app'),
|
||||||
{app: 'app', os: 'iOS', device: 'TestiPhone', device_id: 'serial-archived'},
|
{
|
||||||
|
app: 'app',
|
||||||
|
os: 'iOS',
|
||||||
|
device: 'TestiPhone',
|
||||||
|
device_id: 'serial-archived',
|
||||||
|
},
|
||||||
null,
|
null,
|
||||||
logger,
|
logger,
|
||||||
mockStore,
|
mockStore,
|
||||||
|
|||||||
@@ -1882,6 +1882,13 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/algoliasearch/-/algoliasearch-3.34.5.tgz#c40e346a6c5526f9b27af7863117d1200456e7d2"
|
resolved "https://registry.yarnpkg.com/@types/algoliasearch/-/algoliasearch-3.34.5.tgz#c40e346a6c5526f9b27af7863117d1200456e7d2"
|
||||||
integrity sha512-JS+5KT9SfwzGIkoCsj7EyYHzhrsagj321BEPH3oroHYnuKUfPVoei58qLsBPo9RRa27Vb79WJssSSPBicnaAng==
|
integrity sha512-JS+5KT9SfwzGIkoCsj7EyYHzhrsagj321BEPH3oroHYnuKUfPVoei58qLsBPo9RRa27Vb79WJssSSPBicnaAng==
|
||||||
|
|
||||||
|
"@types/archiver@^3.1.0":
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/archiver/-/archiver-3.1.0.tgz#0d5bd922ba5cf06e137cd6793db7942439b1805e"
|
||||||
|
integrity sha512-nTvHwgWONL+iXG+9CX+gnQ/tTOV+qucAjwpXqeUn4OCRMxP42T29FFP/7XaOo0EqqO3TlENhObeZEe7RUJAriw==
|
||||||
|
dependencies:
|
||||||
|
"@types/glob" "*"
|
||||||
|
|
||||||
"@types/aria-query@^4.2.0":
|
"@types/aria-query@^4.2.0":
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0"
|
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0"
|
||||||
@@ -2049,6 +2056,14 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/glob@*":
|
||||||
|
version "7.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183"
|
||||||
|
integrity sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==
|
||||||
|
dependencies:
|
||||||
|
"@types/minimatch" "*"
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/glob@^7.1.1":
|
"@types/glob@^7.1.1":
|
||||||
version "7.1.1"
|
version "7.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575"
|
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575"
|
||||||
@@ -2467,6 +2482,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.0.0.tgz#165aae4819ad2174a17476dbe66feebd549556c0"
|
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.0.0.tgz#165aae4819ad2174a17476dbe66feebd549556c0"
|
||||||
integrity sha512-xSQfNcvOiE5f9dyd4Kzxbof1aTrLobL278pGLKOZI6esGfZ7ts9Ka16CzIN6Y8hFHE1C7jIBZokULhK1bOgjRw==
|
integrity sha512-xSQfNcvOiE5f9dyd4Kzxbof1aTrLobL278pGLKOZI6esGfZ7ts9Ka16CzIN6Y8hFHE1C7jIBZokULhK1bOgjRw==
|
||||||
|
|
||||||
|
"@types/uuid@^8.0.1":
|
||||||
|
version "8.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.0.1.tgz#42958a1a880640b139eea97a1640e1a3f61016d2"
|
||||||
|
integrity sha512-2kE8rEFgJpbBAPw5JghccEevQb0XVU0tewF/8h7wPQTeCtoJ6h8qmBIwuzUVm2MutmzC/cpCkwxudixoNYDp1A==
|
||||||
|
|
||||||
"@types/webdriverio@^4.8.0":
|
"@types/webdriverio@^4.8.0":
|
||||||
version "4.13.3"
|
version "4.13.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/webdriverio/-/webdriverio-4.13.3.tgz#c1571c4e62724135c0b11e7d7e36b07af5168856"
|
resolved "https://registry.yarnpkg.com/@types/webdriverio/-/webdriverio-4.13.3.tgz#c1571c4e62724135c0b11e7d7e36b07af5168856"
|
||||||
@@ -2919,6 +2939,35 @@ archiver-utils@^1.3.0:
|
|||||||
normalize-path "^2.0.0"
|
normalize-path "^2.0.0"
|
||||||
readable-stream "^2.0.0"
|
readable-stream "^2.0.0"
|
||||||
|
|
||||||
|
archiver-utils@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2"
|
||||||
|
integrity sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==
|
||||||
|
dependencies:
|
||||||
|
glob "^7.1.4"
|
||||||
|
graceful-fs "^4.2.0"
|
||||||
|
lazystream "^1.0.0"
|
||||||
|
lodash.defaults "^4.2.0"
|
||||||
|
lodash.difference "^4.5.0"
|
||||||
|
lodash.flatten "^4.4.0"
|
||||||
|
lodash.isplainobject "^4.0.6"
|
||||||
|
lodash.union "^4.6.0"
|
||||||
|
normalize-path "^3.0.0"
|
||||||
|
readable-stream "^2.0.0"
|
||||||
|
|
||||||
|
archiver@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.0.0.tgz#b1e7dc075a4e18e0aa59afdd7c3e5f3d3321cbeb"
|
||||||
|
integrity sha512-AEWhJz6Yi6hWtN1Sqy/H4sZo/lLMJ/NftXxGaDy/TnOMmmjsRaZc/Ts+U4BsPoBQkuunTN6t8hk7iU9A+HBxLw==
|
||||||
|
dependencies:
|
||||||
|
archiver-utils "^2.1.0"
|
||||||
|
async "^3.2.0"
|
||||||
|
buffer-crc32 "^0.2.1"
|
||||||
|
readable-stream "^3.6.0"
|
||||||
|
readdir-glob "^1.0.0"
|
||||||
|
tar-stream "^2.1.2"
|
||||||
|
zip-stream "^4.0.0"
|
||||||
|
|
||||||
archiver@~2.1.0:
|
archiver@~2.1.0:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/archiver/-/archiver-2.1.1.tgz#ff662b4a78201494a3ee544d3a33fe7496509ebc"
|
resolved "https://registry.yarnpkg.com/archiver/-/archiver-2.1.1.tgz#ff662b4a78201494a3ee544d3a33fe7496509ebc"
|
||||||
@@ -3074,6 +3123,11 @@ async@^2.0.0, async@^2.4.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
lodash "^4.17.14"
|
lodash "^4.17.14"
|
||||||
|
|
||||||
|
async@^3.2.0:
|
||||||
|
version "3.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720"
|
||||||
|
integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==
|
||||||
|
|
||||||
async@~0.2.9:
|
async@~0.2.9:
|
||||||
version "0.2.10"
|
version "0.2.10"
|
||||||
resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
|
resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
|
||||||
@@ -3540,7 +3594,7 @@ buffer-alloc@^1.2.0:
|
|||||||
buffer-alloc-unsafe "^1.1.0"
|
buffer-alloc-unsafe "^1.1.0"
|
||||||
buffer-fill "^1.0.0"
|
buffer-fill "^1.0.0"
|
||||||
|
|
||||||
buffer-crc32@^0.2.1, buffer-crc32@~0.2.3:
|
buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3:
|
||||||
version "0.2.13"
|
version "0.2.13"
|
||||||
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
|
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
|
||||||
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
|
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
|
||||||
@@ -4025,6 +4079,16 @@ compress-commons@^1.2.0:
|
|||||||
normalize-path "^2.0.0"
|
normalize-path "^2.0.0"
|
||||||
readable-stream "^2.0.0"
|
readable-stream "^2.0.0"
|
||||||
|
|
||||||
|
compress-commons@^4.0.0:
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-4.0.1.tgz#c5fa908a791a0c71329fba211d73cd2a32005ea8"
|
||||||
|
integrity sha512-xZm9o6iikekkI0GnXCmAl3LQGZj5TBDj0zLowsqi7tJtEa3FMGSEcHcqrSJIrOAk1UG/NBbDn/F1q+MG/p/EsA==
|
||||||
|
dependencies:
|
||||||
|
buffer-crc32 "^0.2.13"
|
||||||
|
crc32-stream "^4.0.0"
|
||||||
|
normalize-path "^3.0.0"
|
||||||
|
readable-stream "^3.6.0"
|
||||||
|
|
||||||
concat-map@0.0.1:
|
concat-map@0.0.1:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||||
@@ -4171,6 +4235,14 @@ crc32-stream@^2.0.0:
|
|||||||
crc "^3.4.4"
|
crc "^3.4.4"
|
||||||
readable-stream "^2.0.0"
|
readable-stream "^2.0.0"
|
||||||
|
|
||||||
|
crc32-stream@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-4.0.0.tgz#05b7ca047d831e98c215538666f372b756d91893"
|
||||||
|
integrity sha512-tyMw2IeUX6t9jhgXI6um0eKfWq4EIDpfv5m7GX4Jzp7eVelQ360xd8EPXJhp2mHwLQIkqlnMLjzqSZI3a+0wRw==
|
||||||
|
dependencies:
|
||||||
|
crc "^3.4.4"
|
||||||
|
readable-stream "^3.4.0"
|
||||||
|
|
||||||
crc@^3.4.4:
|
crc@^3.4.4:
|
||||||
version "3.8.0"
|
version "3.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6"
|
resolved "https://registry.yarnpkg.com/crc/-/crc-3.8.0.tgz#ad60269c2c856f8c299e2c4cc0de4556914056c6"
|
||||||
@@ -8212,6 +8284,21 @@ lodash.debounce@4.0.8, lodash.debounce@^4.0.8:
|
|||||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||||
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
|
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
|
||||||
|
|
||||||
|
lodash.defaults@^4.2.0:
|
||||||
|
version "4.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
|
||||||
|
integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=
|
||||||
|
|
||||||
|
lodash.difference@^4.5.0:
|
||||||
|
version "4.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c"
|
||||||
|
integrity sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=
|
||||||
|
|
||||||
|
lodash.flatten@^4.4.0:
|
||||||
|
version "4.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
|
||||||
|
integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=
|
||||||
|
|
||||||
lodash.isplainobject@^4.0.6:
|
lodash.isplainobject@^4.0.6:
|
||||||
version "4.0.6"
|
version "4.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
|
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
|
||||||
@@ -8247,6 +8334,11 @@ lodash.throttle@^4.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
|
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
|
||||||
integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
|
integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
|
||||||
|
|
||||||
|
lodash.union@^4.6.0:
|
||||||
|
version "4.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
|
||||||
|
integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=
|
||||||
|
|
||||||
lodash@^4.0.1, lodash@^4.16.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.8.0, lodash@~4.17.12, lodash@~4.17.4:
|
lodash@^4.0.1, lodash@^4.16.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.8.0, lodash@~4.17.12, lodash@~4.17.4:
|
||||||
version "4.17.19"
|
version "4.17.19"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
|
||||||
@@ -10107,7 +10199,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.1.4, readable
|
|||||||
string_decoder "~1.1.1"
|
string_decoder "~1.1.1"
|
||||||
util-deprecate "~1.0.1"
|
util-deprecate "~1.0.1"
|
||||||
|
|
||||||
readable-stream@^3.1.1, readable-stream@^3.4.0:
|
readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0:
|
||||||
version "3.6.0"
|
version "3.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||||
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
||||||
@@ -10116,6 +10208,13 @@ readable-stream@^3.1.1, readable-stream@^3.4.0:
|
|||||||
string_decoder "^1.1.1"
|
string_decoder "^1.1.1"
|
||||||
util-deprecate "^1.0.1"
|
util-deprecate "^1.0.1"
|
||||||
|
|
||||||
|
readdir-glob@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.0.0.tgz#a495436934bbe57be6a68039d16e8946621eb8c5"
|
||||||
|
integrity sha512-km0DIcwQVZ1ZUhXhMWpF74/Wm5aFEd5/jDiVWF1Hkw2myPQovG8vCQ8+FQO2KXE9npQQvCnAMZhhWuUee4WcCQ==
|
||||||
|
dependencies:
|
||||||
|
minimatch "^3.0.4"
|
||||||
|
|
||||||
realpath-native@^2.0.0:
|
realpath-native@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-2.0.0.tgz#7377ac429b6e1fd599dc38d08ed942d0d7beb866"
|
resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-2.0.0.tgz#7377ac429b6e1fd599dc38d08ed942d0d7beb866"
|
||||||
@@ -11485,6 +11584,17 @@ tar-stream@^2.0.0:
|
|||||||
inherits "^2.0.3"
|
inherits "^2.0.3"
|
||||||
readable-stream "^3.1.1"
|
readable-stream "^3.1.1"
|
||||||
|
|
||||||
|
tar-stream@^2.1.2:
|
||||||
|
version "2.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.3.tgz#1e2022559221b7866161660f118255e20fa79e41"
|
||||||
|
integrity sha512-Z9yri56Dih8IaK8gncVPx4Wqt86NDmQTSh49XLZgjWpGZL9GK9HKParS2scqHCC4w6X9Gh2jwaU45V47XTKwVA==
|
||||||
|
dependencies:
|
||||||
|
bl "^4.0.1"
|
||||||
|
end-of-stream "^1.4.1"
|
||||||
|
fs-constants "^1.0.0"
|
||||||
|
inherits "^2.0.3"
|
||||||
|
readable-stream "^3.1.1"
|
||||||
|
|
||||||
tar@^6.0.1:
|
tar@^6.0.1:
|
||||||
version "6.0.2"
|
version "6.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.2.tgz#5df17813468a6264ff14f766886c622b84ae2f39"
|
resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.2.tgz#5df17813468a6264ff14f766886c622b84ae2f39"
|
||||||
@@ -12141,6 +12251,11 @@ uuid@^8.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d"
|
||||||
integrity sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg==
|
integrity sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg==
|
||||||
|
|
||||||
|
uuid@^8.3.0:
|
||||||
|
version "8.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.0.tgz#ab738085ca22dc9a8c92725e459b1d507df5d6ea"
|
||||||
|
integrity sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==
|
||||||
|
|
||||||
v8-compile-cache@^2.0.3:
|
v8-compile-cache@^2.0.3:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e"
|
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e"
|
||||||
@@ -12613,3 +12728,12 @@ zip-stream@^1.2.0:
|
|||||||
compress-commons "^1.2.0"
|
compress-commons "^1.2.0"
|
||||||
lodash "^4.8.0"
|
lodash "^4.8.0"
|
||||||
readable-stream "^2.0.0"
|
readable-stream "^2.0.0"
|
||||||
|
|
||||||
|
zip-stream@^4.0.0:
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-4.0.2.tgz#3a20f1bd7729c2b59fd4efa04df5eb7a5a217d2e"
|
||||||
|
integrity sha512-TGxB2g+1ur6MHkvM644DuZr8Uzyz0k0OYWtS3YlpfWBEmK4woaC2t3+pozEL3dBfIPmpgmClR5B2QRcMgGt22g==
|
||||||
|
dependencies:
|
||||||
|
archiver-utils "^2.1.0"
|
||||||
|
compress-commons "^4.0.0"
|
||||||
|
readable-stream "^3.6.0"
|
||||||
|
|||||||
@@ -28,10 +28,22 @@ class FlipperCertificateProvider {
|
|||||||
const std::string& path,
|
const std::string& path,
|
||||||
const std::string& deviceID) = 0;
|
const std::string& deviceID) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets certificate exchange medium
|
||||||
|
*/
|
||||||
virtual void setCertificateExchangeMedium(
|
virtual void setCertificateExchangeMedium(
|
||||||
const FlipperCertificateExchangeMedium medium) = 0;
|
const FlipperCertificateExchangeMedium medium) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets certificate exchange medium
|
||||||
|
*/
|
||||||
virtual FlipperCertificateExchangeMedium getCertificateExchangeMedium() = 0;
|
virtual FlipperCertificateExchangeMedium getCertificateExchangeMedium() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This lets the Client know if it should reset the connection folder when
|
||||||
|
* `stop` is called.
|
||||||
|
*/
|
||||||
|
virtual bool shouldResetCertificateFolder() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace flipper
|
} // namespace flipper
|
||||||
|
|||||||
@@ -235,12 +235,15 @@ bool FlipperConnectionManagerImpl::connectSecurely() {
|
|||||||
if (deviceId.compare("unknown")) {
|
if (deviceId.compare("unknown")) {
|
||||||
loadingDeviceId->complete();
|
loadingDeviceId->complete();
|
||||||
}
|
}
|
||||||
|
int medium = certProvider_ != nullptr
|
||||||
|
? certProvider_->getCertificateExchangeMedium()
|
||||||
|
: FlipperCertificateExchangeMedium::FS_ACCESS;
|
||||||
|
|
||||||
parameters.payload = rsocket::Payload(folly::toJson(folly::dynamic::object(
|
parameters.payload = rsocket::Payload(folly::toJson(folly::dynamic::object(
|
||||||
"csr", contextStore_->getCertificateSigningRequest().c_str())(
|
"csr", contextStore_->getCertificateSigningRequest().c_str())(
|
||||||
"csr_path", contextStore_->getCertificateDirectoryPath().c_str())(
|
"csr_path", contextStore_->getCertificateDirectoryPath().c_str())(
|
||||||
"os", deviceData_.os)("device", deviceData_.device)(
|
"os", deviceData_.os)("device", deviceData_.device)(
|
||||||
"device_id", deviceId)("app", deviceData_.app)(
|
"device_id", deviceId)("app", deviceData_.app)("medium", medium)(
|
||||||
"sdk_version", sdkVersion)));
|
"sdk_version", sdkVersion)));
|
||||||
address.setFromHostPort(deviceData_.host, securePort);
|
address.setFromHostPort(deviceData_.host, securePort);
|
||||||
|
|
||||||
@@ -293,6 +296,9 @@ void FlipperConnectionManagerImpl::reconnect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FlipperConnectionManagerImpl::stop() {
|
void FlipperConnectionManagerImpl::stop() {
|
||||||
|
if (certProvider_ && certProvider_->shouldResetCertificateFolder()) {
|
||||||
|
contextStore_->resetState();
|
||||||
|
}
|
||||||
if (!isStarted_) {
|
if (!isStarted_) {
|
||||||
log("Not started");
|
log("Not started");
|
||||||
return;
|
return;
|
||||||
@@ -353,10 +359,13 @@ void FlipperConnectionManagerImpl::requestSignedCertFromFlipper() {
|
|||||||
auto generatingCSR = flipperState_->start("Generate CSR");
|
auto generatingCSR = flipperState_->start("Generate CSR");
|
||||||
std::string csr = contextStore_->getCertificateSigningRequest();
|
std::string csr = contextStore_->getCertificateSigningRequest();
|
||||||
generatingCSR->complete();
|
generatingCSR->complete();
|
||||||
|
int medium = certProvider_ != nullptr
|
||||||
|
? certProvider_->getCertificateExchangeMedium()
|
||||||
|
: FlipperCertificateExchangeMedium::FS_ACCESS;
|
||||||
folly::dynamic message =
|
folly::dynamic message =
|
||||||
folly::dynamic::object("method", "signCertificate")("csr", csr.c_str())(
|
folly::dynamic::object("method", "signCertificate")("csr", csr.c_str())(
|
||||||
"destination", contextStore_->getCertificateDirectoryPath().c_str());
|
"destination", contextStore_->getCertificateDirectoryPath().c_str())(
|
||||||
|
"medium", medium);
|
||||||
auto gettingCert = flipperState_->start("Getting cert from desktop");
|
auto gettingCert = flipperState_->start("Getting cert from desktop");
|
||||||
|
|
||||||
flipperEventBase_->add([this, message, gettingCert]() {
|
flipperEventBase_->add([this, message, gettingCert]() {
|
||||||
@@ -369,10 +378,32 @@ void FlipperConnectionManagerImpl::requestSignedCertFromFlipper() {
|
|||||||
folly::dynamic config = folly::parseJson(response);
|
folly::dynamic config = folly::parseJson(response);
|
||||||
contextStore_->storeConnectionConfig(config);
|
contextStore_->storeConnectionConfig(config);
|
||||||
}
|
}
|
||||||
gettingCert->complete();
|
if (certProvider_) {
|
||||||
|
auto gettingCertFromProvider =
|
||||||
|
flipperState_->start("Getting cert from Cert Provider");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Certificates should be present in app's sandbox after it is
|
||||||
|
// returned. The reason we can't have a completion block here
|
||||||
|
// is because if the certs are not present after it returns
|
||||||
|
// then the flipper tries to reconnect on insecured channel
|
||||||
|
// and recreates the app.csr. By the time completion block is
|
||||||
|
// called the DeviceCA cert doesn't match app's csr and it
|
||||||
|
// throws an SSL error.
|
||||||
|
certProvider_->getCertificates(
|
||||||
|
contextStore_->getCertificateDirectoryPath(),
|
||||||
|
contextStore_->getDeviceId());
|
||||||
|
gettingCertFromProvider->complete();
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
gettingCertFromProvider->fail(e.what());
|
||||||
|
gettingCert->fail(e.what());
|
||||||
|
} catch (...) {
|
||||||
|
gettingCertFromProvider->fail("Exception from certProvider");
|
||||||
|
gettingCert->fail("Exception from certProvider");
|
||||||
|
}
|
||||||
|
}
|
||||||
log("Certificate exchange complete.");
|
log("Certificate exchange complete.");
|
||||||
// TODO: Use Certificate provider get Certificates
|
gettingCert->complete();
|
||||||
// `certProvider_->getCertificates("path", "device");`
|
|
||||||
|
|
||||||
// Disconnect after message sending is complete.
|
// Disconnect after message sending is complete.
|
||||||
// This will trigger a reconnect which should use the secure
|
// This will trigger a reconnect which should use the secure
|
||||||
|
|||||||
Reference in New Issue
Block a user