Skip to content

Commit

Permalink
Support FormData interception + RN plugin update
Browse files Browse the repository at this point in the history
  • Loading branch information
RNEvok committed Dec 6, 2023
1 parent 02c4477 commit 04ea8ac
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 15 deletions.
19 changes: 12 additions & 7 deletions Connector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { EventHandleError, ScenarioHandleError } from './Errors';
import { SOCKET_EVENTS_LISTEN, SOCKET_EVENTS_EMIT } from './api/api';
import { SPECIAL_INSTRUCTIONS_TABLE, SPECIAL_INSTRUCTIONS } from './constants/events';
import { io, Socket } from "socket.io-client";
import { codebudConsoleLog, codebudConsoleWarn, jsonStringifyKeepMethods, stringifyIfNotString } from './helpers/helperFunctions';
import { codebudConsoleLog, codebudConsoleWarn, jsonStringifyKeepMeta, stringifyIfNotString } from './helpers/helperFunctions';
import { getProcessEnv } from './helpers/environment';
import { getOS } from './helpers/os';
import { remoteSettingsService } from './services/remoteSettingsService';
Expand Down Expand Up @@ -63,6 +63,7 @@ export class Connector {
private _storageActionsBatchingTimeMs: number = 500;
private _sendStorageActionsBatchingTimer: NodeJS.Timeout | null = null;
private _currentStorageActionsBatch: InterceptedStorageActionPreparedData[] = [];
private _unsubscribeFromAppStateChanges: (() => void) | undefined;

public static lastEvent: RemoteEvent | null = null;
public readonly instanceId: number;
Expand All @@ -75,14 +76,16 @@ export class Connector {
delete Connector._eventListenersTable[key];
};

private _prepareEnvironmentInfo(): ObjectT<any> {
private _prepareEnvironmentInfo(config?: PackageConfig): ObjectT<any> {
try {
const envInfo = getProcessEnv();
const osInfo = getOS();
const osInfo = config?.ReactNativePlugin ? config.ReactNativePlugin.getOS() : getOS();
const additionalInfo = config?.ReactNativePlugin ? config.ReactNativePlugin.getPlatformInfo() : {};

return {
...envInfo,
...osInfo
...osInfo,
...additionalInfo
};
} catch (e) {
return {};
Expand All @@ -91,7 +94,7 @@ export class Connector {

private _encryptData(json: any) {
if (!this._encryption)
return jsonStringifyKeepMethods(json);
return jsonStringifyKeepMeta(json);

return this._encryption.encryptData(json);
};
Expand Down Expand Up @@ -252,7 +255,7 @@ export class Connector {
};

private async _setupRN(config: PackageConfig) {
config.ReactNativePlugin.subscribeForAppStateChanges(
this._unsubscribeFromAppStateChanges = config.ReactNativePlugin.subscribeForAppStateChanges(
() => this._socket?.emit(SOCKET_EVENTS_EMIT.SAVE_MOBILE_APP_STATE, {foreground: true}),
() => this._socket?.emit(SOCKET_EVENTS_EMIT.SAVE_MOBILE_APP_STATE, {foreground: false}),
);
Expand All @@ -275,7 +278,7 @@ export class Connector {
this._connectionInfoPacket = {
apiKey,
projectId: this._projectInfo?.projectId,
environmentInfo: this._prepareEnvironmentInfo(),
environmentInfo: this._prepareEnvironmentInfo(config),
clientType: "CLIENT",
publicKey: this._encryption?.publicKey,
availableInstructions: this._getInstructionsPublicFields(instructions),
Expand Down Expand Up @@ -453,6 +456,8 @@ export class Connector {
this._untrackLocalStorage && this._untrackLocalStorage();
this._localStorageHandler = null;
}

this._unsubscribeFromAppStateChanges && this._unsubscribeFromAppStateChanges();

// Think about it later
Connector.lastEvent = null;
Expand Down
4 changes: 2 additions & 2 deletions encryption/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { box, randomBytes } from 'tweetnacl';
import { decodeUTF8, encodeBase64 } from 'tweetnacl-util';
import { codebudConsoleLog, codebudConsoleWarn, jsonStringifyKeepMethods } from '../helpers/helperFunctions';
import { codebudConsoleLog, codebudConsoleWarn, jsonStringifyKeepMeta } from '../helpers/helperFunctions';

export class EncryptionPlugin {
private _keyPair: nacl.BoxKeyPair | null = null;
Expand All @@ -17,7 +17,7 @@ export class EncryptionPlugin {
throw new Error("Shared key not generated");

const nonce = this.newNonce();
const messageUint8 = decodeUTF8(jsonStringifyKeepMethods(json));
const messageUint8 = decodeUTF8(jsonStringifyKeepMeta(json));

const encrypted = box.after(messageUint8, nonce, this._sharedKey);

Expand Down
42 changes: 37 additions & 5 deletions helpers/helperFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,46 @@ export const emptyMiddleware = () => next => action => {
return next(action);
}

export const jsonStringifyKeepMethods = (data: ObjectT<any>) => {
export const getFormDataMeta = (fData: FormData) => {
try {
const fDataMeta: {[key: string]: any} = {};

fData.forEach((value, key) => {
if (value instanceof File) {
fDataMeta[key] = {
"lastModified": value.lastModified,
// @ts-ignore
"lastModifiedDate": value.lastModifiedDate,
"name": value.name,
"size": value.size,
"type": value.type,
"webkitRelativePath": value.webkitRelativePath
};
} else {
fDataMeta[key] = value;
}
});

return fDataMeta;
} catch (e) {
return {};
}
}

// Custom JSON.stringify wrapper that keeps as much metadata as possible
export const jsonStringifyKeepMeta = (data: ObjectT<any>) => {
return JSON.stringify(
data,
function(key, value) {
if (typeof value === 'function') {
return "Function (...)";
} else {
return value;
const type = typeof value;

switch (type) {
case "object":
return (value instanceof FormData) ? getFormDataMeta(value) : value;
case "function":
return "Function (...)";
default:
return value;
}
}
);
Expand Down
16 changes: 15 additions & 1 deletion rn/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AppState } from 'react-native';
import { AppState, Platform } from 'react-native';
import { StartNetworkLoggingOptions } from './types';
import logger from './loggerSingleton';

Expand Down Expand Up @@ -32,5 +32,19 @@ export const ReactNativePlugin = {
appState = nextAppState;
},
);

// Returns unsubscribe method
return subscription.remove;
},
getOS: () => {
return { OS: Platform.OS };
},
getPlatformInfo: () => {
return {
...Platform.constants,
PlatformVersion: Platform.Version,
isTV: Platform.isTV,
isTesting: Platform.isTesting
};
}
}

0 comments on commit 04ea8ac

Please sign in to comment.