From 68949619fecbee12e128eeaf1f77bc12a23ac2d1 Mon Sep 17 00:00:00 2001
From: David Marby
Date: Wed, 27 Jan 2021 13:01:53 +0100
Subject: [PATCH] Remove legacy sync (#3028)
---
packages/insomnia-app/app/models/settings.js | 6 -
.../app/sync-legacy/__tests__/sync.test.js | 557 -----------
.../insomnia-app/app/sync-legacy/index.js | 870 ------------------
.../insomnia-app/app/sync-legacy/logger.js | 37 -
.../insomnia-app/app/sync-legacy/network.js | 77 --
.../insomnia-app/app/sync-legacy/storage.js | 240 -----
.../dropdowns/sync-legacy-dropdown.js | 234 -----
.../dropdowns/workspace-dropdown.js | 12 +-
.../app/ui/components/modals/login-modal.js | 5 -
.../modals/payment-notification-modal.js | 6 +-
.../ui/components/modals/setup-sync-modal.js | 181 ----
.../modals/workspace-share-settings-modal.js | 203 ----
.../app/ui/components/page-layout.js | 1 -
.../app/ui/components/settings/account.js | 3 +-
.../app/ui/components/settings/general.js | 8 -
.../app/ui/components/sidebar/sidebar.js | 13 +-
.../app/ui/components/wrapper-debug.js | 1 -
.../insomnia-app/app/ui/components/wrapper.js | 6 -
packages/insomnia-app/app/ui/index.js | 20 +-
19 files changed, 8 insertions(+), 2472 deletions(-)
delete mode 100644 packages/insomnia-app/app/sync-legacy/__tests__/sync.test.js
delete mode 100644 packages/insomnia-app/app/sync-legacy/index.js
delete mode 100644 packages/insomnia-app/app/sync-legacy/logger.js
delete mode 100644 packages/insomnia-app/app/sync-legacy/network.js
delete mode 100644 packages/insomnia-app/app/sync-legacy/storage.js
delete mode 100644 packages/insomnia-app/app/ui/components/dropdowns/sync-legacy-dropdown.js
delete mode 100644 packages/insomnia-app/app/ui/components/modals/setup-sync-modal.js
delete mode 100644 packages/insomnia-app/app/ui/components/modals/workspace-share-settings-modal.js
diff --git a/packages/insomnia-app/app/models/settings.js b/packages/insomnia-app/app/models/settings.js
index 971414ce87..c938f92cea 100644
--- a/packages/insomnia-app/app/models/settings.js
+++ b/packages/insomnia-app/app/models/settings.js
@@ -55,9 +55,6 @@ type BaseSettings = {
useBulkHeaderEditor: boolean,
useBulkParametersEditor: boolean,
validateSSL: boolean,
-
- // Feature flags
- enableSyncBeta: boolean,
};
export type Settings = BaseModel & BaseSettings;
@@ -111,9 +108,6 @@ export function init(): BaseSettings {
useBulkHeaderEditor: false,
useBulkParametersEditor: false,
validateSSL: true,
-
- // Feature flags
- enableSyncBeta: false,
};
}
diff --git a/packages/insomnia-app/app/sync-legacy/__tests__/sync.test.js b/packages/insomnia-app/app/sync-legacy/__tests__/sync.test.js
deleted file mode 100644
index da5e28e5fc..0000000000
--- a/packages/insomnia-app/app/sync-legacy/__tests__/sync.test.js
+++ /dev/null
@@ -1,557 +0,0 @@
-import * as sync from '../index';
-import * as models from '../../models';
-import * as db from '../../common/database';
-import * as syncStorage from '../storage';
-import * as network from '../network';
-import { globalBeforeEach } from '../../__jest__/before-each';
-import * as session from '../../account/session';
-import * as crypt from '../../account/crypt';
-
-describe('Test push/pull behaviour', () => {
- beforeEach(async () => {
- await globalBeforeEach();
-
- // Reset some things
- sync._testReset();
- await _setSessionData();
- await _setupSessionMocks();
-
- // Init sync and storage
- const config = { inMemoryOnly: true, autoload: false, filename: null };
- await syncStorage.initDB(config, true);
-
- // Add some data
- await models.workspace.create({ _id: 'wrk_1', name: 'Workspace 1' });
- await models.workspace.create({ _id: 'wrk_2', name: 'Workspace 2' });
- await models.request.create({
- _id: 'req_1',
- name: 'Request 1',
- parentId: 'wrk_1',
- });
- await models.request.create({
- _id: 'req_2',
- name: 'Request 2',
- parentId: 'wrk_2',
- });
-
- // Create resources, resource groups, and configs
- const workspaces = await models.workspace.all();
- const requests = await models.request.all();
- for (const d of [...workspaces, ...requests]) {
- await sync.getOrCreateResourceForDoc(d);
- }
- });
-
- it('Pushes sync mode with and without resource group id', async () => {
- const request = await models.request.getById('req_1');
- const request2 = await models.request.getById('req_2');
- const resourceRequest = await syncStorage.getResourceByDocId(request._id);
- const resourceRequest2 = await syncStorage.getResourceByDocId(request2._id);
-
- // Set up sync modes
- await sync.createOrUpdateConfig(resourceRequest.resourceGroupId, {
- syncMode: syncStorage.SYNC_MODE_ON,
- });
- await sync.createOrUpdateConfig(resourceRequest2.resourceGroupId, {
- syncMode: syncStorage.SYNC_MODE_UNSET,
- });
-
- await sync.push(); // Push only active configs
- await sync.push(resourceRequest.resourceGroupId); // Force push rg_1
- await sync.push(resourceRequest2.resourceGroupId); // Force push rg_2
-
- expect(network.syncPush.mock.calls.length).toBe(3);
- expect(network.syncPush.mock.calls[0][0].length).toBe(2);
- expect(network.syncPush.mock.calls[0][0][0].id).toBe('wrk_1');
- expect(network.syncPush.mock.calls[0][0][1].id).toBe('req_1');
- expect(network.syncPush.mock.calls[1][0].length).toBe(2);
- expect(network.syncPush.mock.calls[1][0][0].id).toBe('wrk_1');
- expect(network.syncPush.mock.calls[1][0][1].id).toBe('req_1');
- expect(network.syncPush.mock.calls[2][0].length).toBe(2);
- expect(network.syncPush.mock.calls[2][0][0].id).toBe('wrk_2');
- expect(network.syncPush.mock.calls[2][0][1].id).toBe('req_2');
- });
-
- it('Updates dirty flag for push response', async () => {
- const request = await models.request.getById('req_1');
- const resourceRequest = await syncStorage.getResourceByDocId(request._id);
- await sync.createOrUpdateConfig(resourceRequest.resourceGroupId, {
- syncMode: syncStorage.SYNC_MODE_ON,
- });
-
- network.syncPush.mockReturnValueOnce({
- updated: [],
- created: [{ id: request._id, version: 'new-version' }],
- removed: [],
- conflicts: [],
- });
-
- const resourceBefore = await syncStorage.getResourceByDocId(request._id);
- await sync.push(resourceRequest.resourceGroupId);
- const resourceAfter = await syncStorage.getResourceByDocId(request._id);
-
- expect(network.syncPush.mock.calls.length).toBe(1);
- expect(network.syncPush.mock.calls[0][0].length).toBe(2);
- expect(network.syncPush.mock.calls[0][0][0].id).toBe('wrk_1');
- expect(network.syncPush.mock.calls[0][0][1].id).toBe('req_1');
- expect(resourceBefore.dirty).toBe(true);
- expect(resourceAfter.dirty).toBe(false);
- });
-
- it('Updates resources for pull response', async () => {
- const request = await models.request.getById('req_1');
- const request2 = await models.request.getById('req_2');
- const requestNew = Object.assign({}, request, {
- _id: 'req_new',
- name: 'New Request',
- });
- const resourceBefore = await syncStorage.getResourceByDocId(request._id);
- const resource2Before = await syncStorage.getResourceByDocId(requestNew._id);
- await sync.createOrUpdateConfig(resourceBefore.resourceGroupId, {
- syncMode: syncStorage.SYNC_MODE_ON,
- });
- const updatedRequest = Object.assign({}, request, {
- name: 'Request Updated',
- });
- const updatedResource = Object.assign({}, resourceBefore, {
- version: 'ver1',
- encContent: await sync.encryptDoc(resourceBefore.resourceGroupId, updatedRequest),
- });
- const createdResourceNew = Object.assign({}, resourceBefore, {
- id: requestNew._id,
- resourceGroupId: 'rg_1',
- encContent: await sync.encryptDoc(resourceBefore.resourceGroupId, requestNew),
- });
-
- network.syncPull.mockReturnValueOnce({
- updatedResources: [updatedResource],
- createdResources: [createdResourceNew],
- idsToPush: [],
- idsToRemove: ['req_2'],
- });
-
- // Pull and get docs/resources
- await sync.pull(resourceBefore.resourceGroupId);
- const requestAfter = await models.request.getById(request._id);
- const request2After = await models.request.getById(request2._id);
- const requestNewAfter = await models.request.getById('req_new');
- const resourceAfter = await syncStorage.getResourceByDocId(
- request._id,
- resourceBefore.resourceGroupId,
- );
- const resource2After = await syncStorage.getResourceByDocId(request2._id);
- const resourceNewAfter = await syncStorage.getResourceByDocId(requestNewAfter._id);
-
- // Assert
- expect(resourceBefore.version).toBe('__NO_VERSION__');
- expect(resourceAfter.version).toBe(updatedResource.version);
- expect(resourceBefore.dirty).toBe(true);
- expect(resource2Before).toBe(null);
- expect(resourceAfter.dirty).toBe(false);
- expect(resource2After.removed).toBe(true);
- expect(requestAfter.name).toBe('Request Updated');
- expect(request2After).toBe(null);
- expect(resourceNewAfter).not.toBe(null);
- });
-
- it('Conflict: local version wins on modified before', async () => {
- const requestClient = await models.request.getById('req_1');
- const requestServer = Object.assign({}, requestClient, {
- name: 'Server Request',
- });
- const resourceRequest = await syncStorage.getResourceByDocId(requestClient._id);
- const resourceConflict = Object.assign({}, resourceRequest, {
- version: 'ver-2',
- encContent: await sync.encryptDoc(resourceRequest.resourceGroupId, requestServer),
- lastEdited: resourceRequest.lastEdited - 1000, // Same edited time
- });
-
- network.syncPush.mockReturnValueOnce({
- updated: [],
- created: [],
- removed: [],
- conflicts: [resourceConflict],
- });
-
- await sync.push(resourceRequest.resourceGroupId);
- const resourceAfter = await syncStorage.getResourceByDocId(
- requestClient._id,
- resourceRequest.resourceGroupId,
- );
- const requestAfter = await models.request.getById(requestClient._id);
-
- // Assert
- expect(network.syncPush.mock.calls.length).toBe(1);
- expect(network.syncPush.mock.calls[0][0].length).toBe(2);
- // Even when local wins, local resource gets the remove resource version
- expect(resourceAfter.version).toBe(resourceConflict.version);
- // Local resource gets marked as dirty so it's pushed right away
- expect(resourceAfter.dirty).toBe(true);
- // Local db should not be changed since the local won
- expect(requestAfter).toEqual(requestClient);
- });
-
- it('Conflict: local version wins on modified tie', async () => {
- const requestClient = await models.request.getById('req_1');
- const requestServer = Object.assign({}, requestClient, {
- name: 'Server Request',
- });
- const resourceRequest = await syncStorage.getResourceByDocId(requestClient._id);
- const resourceConflict = Object.assign({}, resourceRequest, {
- version: 'ver-2',
- encContent: await sync.encryptDoc(resourceRequest.resourceGroupId, requestServer),
- lastEdited: resourceRequest.lastEdited, // Same edited time
- });
-
- network.syncPush.mockReturnValueOnce({
- updated: [],
- created: [],
- removed: [],
- conflicts: [resourceConflict],
- });
-
- await sync.push(resourceRequest.resourceGroupId);
- const resourceAfter = await syncStorage.getResourceByDocId(
- requestClient._id,
- resourceRequest.resourceGroupId,
- );
- const requestAfter = await models.request.getById(requestClient._id);
-
- // Assert
- expect(network.syncPush.mock.calls.length).toBe(1);
- expect(network.syncPush.mock.calls[0][0].length).toBe(2);
- // Even when local wins, local resource gets the remove resource version
- expect(resourceAfter.version).toBe(resourceConflict.version);
- // Local resource gets marked as dirty so it's pushed right away
- expect(resourceAfter.dirty).toBe(true);
- // Local db should not be changed since the local won
- expect(requestAfter).toEqual(requestClient);
- });
-
- it('Conflict: server version wins if modified after', async () => {
- const requestClient = await models.request.getById('req_1');
- const requestServer = Object.assign({}, requestClient, {
- name: 'Server Request',
- });
- const resourceRequest = await syncStorage.getResourceByDocId(requestClient._id);
- const resourceConflict = Object.assign({}, resourceRequest, {
- version: 'ver-2',
- encContent: await sync.encryptDoc(resourceRequest.resourceGroupId, requestServer),
- lastEdited: resourceRequest.lastEdited + 1000,
- });
-
- network.syncPush.mockReturnValueOnce({
- updated: [],
- created: [],
- removed: [],
- conflicts: [resourceConflict],
- });
-
- await sync.push(resourceRequest.resourceGroupId);
- const resourceAfter = await syncStorage.getResourceByDocId(
- requestClient._id,
- resourceRequest.resourceGroupId,
- );
- const requestAfter = await models.request.getById(requestClient._id);
-
- // Assert
- expect(network.syncPush.mock.calls.length).toBe(1);
- expect(network.syncPush.mock.calls[0][0].length).toBe(2);
- expect(resourceAfter.lastEdited).toBeGreaterThan(resourceRequest.lastEdited);
- expect(resourceAfter.version).toBe(resourceConflict.version);
- // Local resource gets marked as dirty so it's pushed right away
- expect(resourceAfter.dirty).toBe(false);
- expect(requestAfter.name).toBe('Server Request');
- expect(requestAfter.modified).toBe(requestServer.modified);
- });
-});
-
-describe('Integration tests for creating Resources and pushing', () => {
- beforeEach(async () => {
- await globalBeforeEach();
-
- // Reset some things
- await _setSessionData();
- sync._testReset();
-
- // Mock some things
- await _setupSessionMocks();
- jest.useFakeTimers();
-
- // Init storage
- const config = { inMemoryOnly: true, autoload: false, filename: null };
- await syncStorage.initDB(config, true);
-
- // Add some data
- await models.workspace.create({
- _id: 'wrk_empty',
- name: 'Workspace Empty',
- });
- await models.workspace.create({ _id: 'wrk_1', name: 'Workspace 1' });
- await models.request.create({
- _id: 'req_1',
- name: 'Request 1',
- parentId: 'wrk_1',
- });
- await models.request.create({
- _id: 'req_2',
- name: 'Request 2',
- parentId: 'wrk_1',
- });
- await models.request.create({
- _id: 'req_3',
- name: 'Request 3',
- parentId: 'wrk_1',
- });
- await models.environment.create({
- _id: 'env_2',
- name: 'Env Prv',
- parentId: 'wrk_1',
- isPrivate: true,
- });
-
- // Flush changes just to be sure they won't affect our tests
- await db.flushChanges();
- await sync.writePendingChanges();
-
- // Assert that all our new models were created
- expect((await models.workspace.all()).length).toBe(2);
- expect((await models.request.all()).length).toBe(3);
- expect((await models.environment.all()).length).toBe(1);
- expect((await models.cookieJar.all()).length).toBe(0);
-
- // Assert that initializing sync will create the initial resources
- expect((await syncStorage.allConfigs()).length).toBe(0);
- expect((await syncStorage.allResources()).length).toBe(0);
- const promise = sync.init();
- jest.runOnlyPendingTimers();
- await promise;
- expect((await syncStorage.allConfigs()).length).toBe(2);
- expect((await syncStorage.allResources()).length).toBe(5);
-
- // Mark all configs as auto sync
- const configs = await syncStorage.allConfigs();
- for (const config of configs) {
- await syncStorage.updateConfig(config, {
- syncMode: syncStorage.SYNC_MODE_ON,
- });
- }
-
- // Do initial push
- await sync.push();
-
- // Reset mocks once again before tests
- await _setupSessionMocks();
- });
-
- it('Resources created on DB change', async () => {
- // Fetch the workspace and create a new request
- await db.bufferChanges();
- await models.request.create({
- _id: 'req_t',
- url: 'https://google.com',
- parentId: 'wrk_1',
- });
-
- await db.flushChanges();
- await sync.writePendingChanges();
- await sync.push();
-
- // Push changes and get resource
- const resource = await syncStorage.getResourceByDocId('req_t');
-
- // Assert
- expect((await syncStorage.allConfigs()).length).toBe(2);
- expect((await syncStorage.allResources()).length).toBe(6);
- expect(_decryptResource(resource).url).toBe('https://google.com');
- expect(resource.removed).toBe(false);
-
- expect(network.syncPush.mock.calls.length).toBe(1);
- expect(network.syncPush.mock.calls[0][0].length).toBe(6);
-
- expect(network.syncPull.mock.calls).toEqual([]);
- });
-
- it('Resources revived on DB change', async () => {
- // Fetch the workspace and create a new request
- await db.bufferChanges();
- const request = await models.request.create({
- _id: 'req_t',
- name: 'Original Request',
- parentId: 'wrk_1',
- });
- await db.flushChanges();
- await sync.writePendingChanges();
- await sync.push();
-
- // Mark resource as removed
- const originalResource = await syncStorage.getResourceByDocId('req_t');
- const updatedResource = await syncStorage.updateResource(originalResource, {
- removed: true,
- });
-
- // Update it and push it again
- await db.bufferChanges();
- await models.request.update(request, { name: 'New Name' });
- await db.flushChanges();
- await sync.writePendingChanges();
- await sync.push();
- const finalResource = await syncStorage.getResourceByDocId('req_t');
-
- // Assert
- expect(originalResource.removed).toBe(false);
- expect(updatedResource.removed).toBe(true);
- expect(finalResource.removed).toBe(false);
- });
-
- it('Resources update on DB change', async () => {
- // Create, update a request, and fetch it's resource
- const request = await models.request.getById('req_1');
- const resource = await syncStorage.getResourceByDocId(request._id);
- await db.bufferChanges();
- const updatedRequest = await models.request.update(request, {
- name: 'New Name',
- });
-
- // Drain and fetch new resource
- await db.flushChanges();
- await sync.writePendingChanges();
- await sync.push();
- const updatedResource = await syncStorage.getResourceByDocId(request._id);
-
- // Assert
- expect(request.name).toBe('Request 1');
- expect(_decryptResource(resource).name).toBe('Request 1');
- expect(updatedRequest.name).toBe('New Name');
- expect(_decryptResource(updatedResource).name).toBe('New Name');
- expect(resource.removed).toBe(false);
-
- expect(network.syncPush.mock.calls.length).toBe(1);
- expect(network.syncPush.mock.calls[0][0].length).toBe(5);
-
- expect(network.syncPull.mock.calls).toEqual([]);
- });
-
- it('Resources removed on DB change', async () => {
- // Create, update a request, and fetch it's resource
- const request = await models.request.getById('req_1');
- const resource = await syncStorage.getResourceByDocId(request._id);
- await db.bufferChanges();
- await models.request.remove(request);
-
- // Drain and fetch new resource
- await db.flushChanges();
- await sync.writePendingChanges();
- await sync.push();
- const updatedResource = await syncStorage.getResourceByDocId(request._id);
-
- // Assert
- expect(resource.removed).toBe(false);
- expect(updatedResource.removed).toBe(true);
-
- expect(network.syncPush.mock.calls.length).toBe(1);
- expect(network.syncPush.mock.calls[0][0].length).toBe(5);
-
- expect(network.syncPull.mock.calls).toEqual([]);
- });
-});
-
-// ~~~~~~~ //
-// Helpers //
-// ~~~~~~~ //
-
-function _decryptResource(resource) {
- const message = JSON.parse(resource.encContent);
- const fakeKey = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
- const docJSON = crypt.decryptAES(fakeKey, message);
- return JSON.parse(docJSON);
-}
-
-async function _setSessionData() {
- const symmetricKey = {
- alg: 'A256GCM',
- ext: true,
- k: '3-QU2OcQcpSyFIoL8idgclbImP3M8Y2d0oVAca3Vl4g',
- key_ops: ['encrypt', 'decrypt'],
- kty: 'oct',
- };
-
- const publicKey = {
- alg: 'RSA-OAEP-256',
- e: 'AQAB',
- ext: true,
- key_ops: ['encrypt'],
- kty: 'RSA',
- n: 'aaaa',
- };
-
- const { privateKey } = await crypt.generateKeyPairJWK();
- const encPrivateKey = {
- ad: '',
- d: Buffer.from(JSON.stringify(privateKey)).toString('hex'),
- iv: '968f1d810efdaec58f9e313e',
- t: '0e87a2e57a198ca79cb99585fe9c244a',
- };
-
- // Setup mocks and stuff
- session.setSessionData(
- 'ses_123',
- 'acct_123',
- 'Tammy',
- 'Tester',
- 'greg.schier@konghq.com',
- symmetricKey,
- publicKey,
- encPrivateKey,
- );
-}
-
-async function _setupSessionMocks() {
- const resourceGroups = {};
-
- network.syncCreateResourceGroup = jest.fn((parentId, name, _) => {
- const id = `rg_${Object.keys(resourceGroups).length + 1}`;
-
- // Generate a public key and use a symmetric equal to it's Id for
- // convenience
- const publicKey = session.getPublicKey();
- const symmetricKeyStr = JSON.stringify({ k: id });
- const encSymmetricKey = crypt.encryptRSAWithJWK(publicKey, symmetricKeyStr);
-
- // Store the resource group and return it
- resourceGroups[id] = Object.assign(
- {},
- { id, encSymmetricKey },
- {
- parentResourceId: parentId,
- name: name,
- encSymmetricKey: encSymmetricKey,
- },
- );
- return resourceGroups[id];
- });
-
- network.syncGetResourceGroup = jest.fn(id => {
- if (resourceGroups[id]) {
- return resourceGroups[id];
- }
-
- const err = new Error(`Not Found for ${id}`);
- err.statusCode = 404;
- throw err;
- });
-
- network.syncPull = jest.fn(body => ({
- updatedResources: [],
- createdResources: [],
- idsToPush: [],
- idsToRemove: [],
- }));
-
- network.syncPush = jest.fn(body => ({
- conflicts: [],
- updated: [],
- created: [],
- removed: [],
- }));
-}
diff --git a/packages/insomnia-app/app/sync-legacy/index.js b/packages/insomnia-app/app/sync-legacy/index.js
deleted file mode 100644
index 844be3ce29..0000000000
--- a/packages/insomnia-app/app/sync-legacy/index.js
+++ /dev/null
@@ -1,870 +0,0 @@
-import * as db from '../common/database';
-import * as models from '../models';
-import * as store from './storage';
-import * as misc from '../common/misc';
-import Logger from './logger';
-import * as zlib from 'zlib';
-import {
- syncCreateResourceGroup,
- syncFixDupes,
- syncGetResourceGroup,
- syncPull,
- syncPush,
- syncResetData,
-} from './network';
-import * as crypt from '../account/crypt';
-import * as session from '../account/session';
-
-export const START_DELAY = 1e3;
-export const PULL_PERIOD = 15e3;
-export const WRITE_PERIOD = 1e3;
-
-const WHITE_LIST = {
- [models.workspace.type]: true,
- [models.request.type]: true,
- [models.requestGroup.type]: true,
- [models.environment.type]: true,
- [models.unitTest.type]: true,
- [models.unitTestSuite.type]: true,
-
- // These can be overridden in sync config
- [models.cookieJar.type]: true,
- [models.clientCertificate.type]: true,
-};
-
-export const logger = new Logger();
-
-// TODO: Move this stuff somewhere else
-const NO_VERSION = '__NO_VERSION__';
-const resourceGroupSymmetricKeysCache = {};
-let _pullChangesInterval = null;
-let _writeChangesInterval = null;
-let _pendingDBChanges = {};
-let _isInitialized = false;
-
-// Used to mark whether or not the new sync system is enabled
-let _disabledForSession = false;
-
-export function disableForSession() {
- _disabledForSession = true;
-}
-
-export async function init() {
- if (_disabledForSession) {
- logger.debug('Legacy sync is disabled for current session');
- return;
- }
-
- if (_isInitialized) {
- logger.debug('Already enabled');
- return;
- }
-
- // NOTE: This is at the top to prevent race conditions
- _isInitialized = true;
- db.onChange(async changes => {
- // To help prevent bugs, put Workspaces first
- const sortedChanges = changes.sort(([event, doc, fromSync]) =>
- doc.type === models.workspace.type ? 1 : -1,
- );
-
- for (const [event, doc, fromSync] of sortedChanges) {
- const notOnWhitelist = !WHITE_LIST[doc.type];
- const notLoggedIn = !session.isLoggedIn();
-
- if (doc.isPrivate) {
- logger.debug(`Skip private doc change ${doc._id}`);
- continue;
- }
-
- if (notLoggedIn || notOnWhitelist || fromSync) {
- continue;
- }
-
- const key = `${event}:${doc._id}`;
- _pendingDBChanges[key] = [event, doc, Date.now()];
- }
- });
-
- await misc.delay(START_DELAY);
-
- await push();
- await pull();
-
- let nextSyncTime = 0;
- let isSyncing = false;
- _pullChangesInterval = setInterval(async () => {
- if (isSyncing) {
- return;
- }
-
- if (Date.now() < nextSyncTime) {
- return;
- }
-
- // Mark that we are currently executing a sync op
- isSyncing = true;
-
- const syncStartTime = Date.now();
-
- let extraDelay = 0;
- try {
- await push();
- await pull();
- } catch (err) {
- logger.error('Sync failed with', err);
- extraDelay += PULL_PERIOD;
- }
-
- const totalSyncTime = Date.now() - syncStartTime;
-
- // Add sync duration to give the server some room if it's being slow.
- // Also, multiply it by a random value so everyone doesn't sync up
- extraDelay += totalSyncTime * (Math.random() * 2);
-
- nextSyncTime = Date.now() + PULL_PERIOD + extraDelay;
- isSyncing = false;
- }, PULL_PERIOD / 5);
-
- _writeChangesInterval = setInterval(writePendingChanges, WRITE_PERIOD);
-
- logger.debug('Initialized');
-}
-
-// Used only during tests!
-export function _testReset() {
- _isInitialized = false;
- clearInterval(_pullChangesInterval);
- clearInterval(_writeChangesInterval);
-}
-
-/**
- * Non-blocking function to perform initial sync for an account. This will pull
- * all remote resources (if they exist) before initializing sync.
- */
-export function doInitialSync() {
- process.nextTick(async () => {
- // First, pull down all remote resources, without first creating new ones.
- // This makes sure that the first sync won't create resources locally, when
- // they already exist on the server.
- await pull(null, false);
-
- // Make sure sync is on (start the timers)
- await init();
- });
-}
-
-/**
- * This is a function to clean up Workspaces that might have had more than one
- * ResourceGroup created for them. This function should be called on init (or maybe
- * even periodically) and can be removed once the bug stops persisting.
- */
-export async function fixDuplicateResourceGroups() {
- if (!session.isLoggedIn()) {
- return;
- }
-
- let duplicateCount = 0;
- const workspaces = await models.workspace.all();
- for (const workspace of workspaces) {
- const resources = await store.findResourcesByDocId(workspace._id);
-
- // No duplicates found
- if (resources.length <= 1) {
- continue;
- }
-
- // Fix duplicates
- const ids = resources.map(r => r.resourceGroupId);
- const { deleteResourceGroupIds } = await syncFixDupes(ids);
-
- for (const idToDelete of deleteResourceGroupIds) {
- await store.removeResourceGroup(idToDelete);
- }
-
- duplicateCount++;
- }
-
- if (duplicateCount) {
- logger.debug(`Fixed ${duplicateCount}/${workspaces.length} duplicate synced Workspaces`);
- }
-}
-
-export async function writePendingChanges() {
- // First make a copy and clear pending changes
- const changes = Object.assign({}, _pendingDBChanges);
- _pendingDBChanges = {};
-
- const keys = Object.keys(changes);
-
- if (keys.length === 0) {
- // No changes, just return
- return;
- }
-
- for (const key of Object.keys(changes)) {
- const [event, doc, timestamp] = changes[key];
- await _handleChangeAndPush(event, doc, timestamp);
- }
-}
-
-export async function push(resourceGroupId = null) {
- if (_disabledForSession) {
- logger.debug('Legacy sync is disabled for current session');
- return;
- }
-
- if (!session.isLoggedIn()) {
- return;
- }
-
- let allDirtyResources = [];
- if (resourceGroupId) {
- allDirtyResources = await store.findActiveDirtyResourcesForResourceGroup(resourceGroupId);
- } else {
- allDirtyResources = await store.findActiveDirtyResources();
- }
-
- if (!allDirtyResources.length) {
- // No changes to push
- return;
- }
-
- const dirtyResources = [];
- for (const r of allDirtyResources) {
- // Check if resource type is blacklisted by user
- const config = await store.getConfig(r.resourceGroupId);
-
- if (r.type === models.clientCertificate.type && config.syncDisableClientCertificates) {
- logger.debug(`Skipping pushing blacklisted client certificate ${r.id}`);
- continue;
- }
-
- if (r.type === models.cookieJar.type && config.syncDisableCookieJars) {
- logger.debug(`Skipping pushing blacklisted cookie jar ${r.id}`);
- continue;
- }
-
- dirtyResources.push(r);
- }
-
- let responseBody;
- try {
- responseBody = await syncPush(dirtyResources);
- } catch (e) {
- logger.error('Failed to push changes', e);
- return;
- }
-
- const { updated, created, removed, conflicts } = responseBody;
-
- // Update all resource versions with the ones that were returned
- for (const { id, version } of updated) {
- const resource = await store.getResourceByDocId(id);
- await store.updateResource(resource, { version, dirty: false });
- }
- if (updated.length) {
- logger.debug(`Push updated ${updated.length} resources`);
- }
-
- // Update all resource versions with the ones that were returned
- for (const { id, version } of created) {
- const resource = await store.getResourceByDocId(id);
- await store.updateResource(resource, { version, dirty: false });
- }
- if (created.length) {
- logger.debug(`Push created ${created.length} resources`);
- }
-
- // Update all resource versions with the ones that were returned
- for (const { id, version } of removed) {
- const resource = await store.getResourceByDocId(id);
- await store.updateResource(resource, { version, dirty: false });
- }
- if (removed.length) {
- logger.debug(`Push removed ${removed.length} resources`);
- }
-
- // Resolve conflicts
- await db.bufferChanges();
- for (const serverResource of conflicts) {
- const localResource = await store.getResourceByDocId(
- serverResource.id,
- serverResource.resourceGroupId,
- );
-
- // On conflict, choose last edited one
- const serverIsNewer = serverResource.lastEdited > localResource.lastEdited;
- const winner = serverIsNewer ? serverResource : localResource;
-
- // Update local resource
- // NOTE: using localResource as the base to make sure we have _id
- await store.updateResource(localResource, winner, {
- version: serverResource.version, // Act as the server resource no matter what
- dirty: !serverIsNewer, // It's dirty if we chose the local doc
- });
-
- // Decrypt the docs from the resources. Don't fetch the local doc from the
- // app database, because it might have been deleted.
- const winnerName = serverIsNewer ? 'Server' : 'Local';
- logger.debug(`Resolved conflict for ${serverResource.id} (${winnerName})`);
-
- // If the server won, update ourselves. If we won, we already have the
- // latest version, so do nothing.
- if (serverIsNewer) {
- const doc = await decryptDoc(winner.resourceGroupId, winner.encContent);
- if (winner.removed) {
- await db.remove(doc, true);
- } else {
- await db.update(doc, true);
- }
- }
- }
-
- db.flushChangesAsync();
-}
-
-export async function pull(resourceGroupId = null, createMissingResources = true) {
- if (_disabledForSession) {
- logger.debug('Legacy sync is disabled for current session');
- return;
- }
-
- if (!session.isLoggedIn()) {
- return;
- }
-
- // Try to fix duplicates first. Don't worry if this is called a lot since if there
- // are no duplicates found it doesn't contact the network.
- await fixDuplicateResourceGroups();
-
- let allResources;
- if (createMissingResources) {
- allResources = await getOrCreateAllActiveResources(resourceGroupId);
- } else {
- allResources = await store.allActiveResources(resourceGroupId);
- }
-
- let blacklistedConfigs;
- if (resourceGroupId) {
- // When doing specific sync, blacklist all configs except the one we're trying to sync.
- const allConfigs = await store.allConfigs();
- blacklistedConfigs = allConfigs.filter(c => c.resourceGroupId !== resourceGroupId);
- } else {
- // When doing a full sync, blacklist the inactive configs
- blacklistedConfigs = await store.findInactiveConfigs(resourceGroupId);
- }
-
- const resources = allResources.map(r => ({
- id: r.id,
- resourceGroupId: r.resourceGroupId,
- version: r.version,
- removed: r.removed,
- }));
-
- const blacklistedResourceGroupIds = blacklistedConfigs.map(c => c.resourceGroupId);
-
- const body = {
- resources,
- blacklist: blacklistedResourceGroupIds,
- };
-
- if (resources.length) {
- logger.debug(`Pulling with ${resources.length} resources`);
- }
-
- let responseBody;
- try {
- responseBody = await syncPull(body);
- } catch (e) {
- logger.error('Failed to sync changes', e, body);
- return;
- }
-
- const { updatedResources, createdResources, idsToPush, idsToRemove } = responseBody;
-
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
- // Insert all the created docs to the DB //
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
-
- await db.bufferChanges();
- for (const serverResource of createdResources) {
- let doc;
-
- try {
- const { resourceGroupId, encContent } = serverResource;
- doc = await decryptDoc(resourceGroupId, encContent);
- } catch (e) {
- logger.warn('Failed to decode created resource', e, serverResource);
- return;
- }
-
- // Check if resource type is blacklisted by user
- const config = await store.getConfig(serverResource.resourceGroupId);
-
- if (
- serverResource.type === models.clientCertificate.type &&
- config.syncDisableClientCertificates
- ) {
- logger.debug(`[sync] Skipping pulling blacklisted client certificate ${serverResource.id}`);
- continue;
- }
-
- if (serverResource.type === models.cookieJar.type && config.syncDisableCookieJars) {
- logger.debug(`[sync] Skipping pulling blacklisted cookie jar ${serverResource.id}`);
- continue;
- }
-
- // Update local Resource
- try {
- await store.insertResource(serverResource, { dirty: false });
- } catch (e) {
- // This probably means we already have it. This should never happen, but
- // might due to a rare race condition.
- logger.error('Failed to insert resource', e, serverResource);
- return;
- }
-
- // NOTE: If the above Resource insert succeeded, that means we have safely
- // insert the document. However, we're using an upsert here instead because
- // it's very possible that the client already had that document locally.
- // This might happen, for example, if the user logs out and back in again.
- const existingDoc = await db.get(doc.type, doc._id);
- if (existingDoc) {
- await db.update(doc, true);
- } else {
- // Mark as not seen if we created a new workspace from sync
- if (doc.type === models.workspace.type) {
- const workspaceMeta = await models.workspaceMeta.getOrCreateByParentId(doc._id);
- await models.workspaceMeta.update(workspaceMeta, { hasSeen: false });
- }
- await db.insert(doc, true);
- }
- }
-
- if (createdResources.length) {
- logger.debug(`Pull created ${createdResources.length} resources`);
- }
-
- db.flushChangesAsync();
-
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
- // Save all the updated docs to the DB //
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
-
- await db.bufferChanges();
- for (const serverResource of updatedResources) {
- try {
- const { resourceGroupId, encContent } = serverResource;
- const doc = await decryptDoc(resourceGroupId, encContent);
-
- // Update app database
- // Needs to be upsert because we could be "undeleting" something
- await db.upsert(doc, true);
-
- // Update local resource
- const resource = await store.getResourceByDocId(
- serverResource.id,
- serverResource.resourceGroupId,
- );
- await store.updateResource(resource, serverResource, { dirty: false });
- } catch (e) {
- logger.warn('Failed to decode updated resource', e, serverResource);
- }
- }
- db.flushChangesAsync();
-
- if (updatedResources.length) {
- logger.debug(`Pull updated ${updatedResources.length} resources`);
- }
-
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
- // Remove all the docs that need removing //
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
-
- await db.bufferChanges();
- for (const id of idsToRemove) {
- const resource = await store.getResourceByDocId(id);
- if (!resource) {
- throw new Error(`Could not find Resource to remove for ${id}`);
- }
-
- const doc = await decryptDoc(resource.resourceGroupId, resource.encContent);
- if (!doc) {
- throw new Error(`Could not find doc to remove ${id}`);
- }
-
- // Mark resource as deleted
- await store.updateResource(resource, { dirty: false, removed: true });
-
- // Remove from DB
- await db.remove(doc, true);
- }
- db.flushChangesAsync();
-
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
- // Push all the docs that need pushing //
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
-
- for (const id of idsToPush) {
- const resource = await store.getResourceByDocId(id);
- if (!resource) {
- throw new Error(`Could not find Resource to push for id ${id}`);
- }
-
- // Mark all resources to push as dirty for the next push
- await store.updateResource(resource, { dirty: true });
- }
-
- return updatedResources.length + createdResources.length;
-}
-
-export async function getOrCreateConfig(resourceGroupId) {
- const config = await store.getConfig(resourceGroupId);
-
- if (!config) {
- return store.insertConfig({ resourceGroupId });
- } else {
- return config;
- }
-}
-
-export async function ensureConfigExists(resourceGroupId, syncMode) {
- const config = await store.getConfig(resourceGroupId);
- if (!config) {
- await store.insertConfig({ resourceGroupId, syncMode });
- }
-}
-
-export async function createOrUpdateConfig(resourceGroupId, patch) {
- const config = await store.getConfig(resourceGroupId);
- const finalPatch = { resourceGroupId, ...patch };
-
- if (config) {
- return store.updateConfig(config, finalPatch);
- } else {
- return store.insertConfig(finalPatch);
- }
-}
-
-export async function logout() {
- await session.logout();
- await resetLocalData();
-}
-
-export async function cancelTrial() {
- await session.endTrial();
- await session.logout();
- await resetLocalData();
-}
-
-export async function resetLocalData() {
- for (const c of await store.allConfigs()) {
- await store.removeConfig(c);
- }
-
- for (const r of await store.allResources()) {
- await store.removeResource(r);
- }
-}
-
-export async function resetRemoteData() {
- await syncResetData();
-}
-
-// ~~~~~~~ //
-// HELPERS //
-// ~~~~~~~ //
-
-async function _handleChangeAndPush(event, doc, timestamp) {
- // Update the resource content and set dirty
- // TODO: Remove one of these steps since it does encryption twice
- // in the case where the resource does not exist yet
- const resource = await getOrCreateResourceForDoc(doc);
-
- const updatedResource = await store.updateResource(resource, {
- name: doc.name || 'n/a',
- lastEdited: timestamp,
- lastEditedBy: session.getAccountId(),
- encContent: await encryptDoc(resource.resourceGroupId, doc),
- removed: event === db.CHANGE_REMOVE,
- dirty: true,
- });
-
- // Debounce pushing of dirty resources
- logger.debug(`Queue ${event} ${updatedResource.id}`);
-}
-
-/**
- * Fetch a ResourceGroup. If it has been fetched before, lookup from memory
- *
- * @param resourceGroupId
- * @returns {*}
- */
-const _fetchResourceGroupPromises = {};
-const _resourceGroupCache = {};
-
-export async function fetchResourceGroup(resourceGroupId, invalidateCache = false) {
- if (invalidateCache) {
- delete _resourceGroupCache[resourceGroupId];
- delete _fetchResourceGroupPromises[resourceGroupId];
- }
-
- // PERF: If we're currently fetching, return stored promise
- // TODO: Maybe move parallel fetch caching into the fetch helper
- if (_fetchResourceGroupPromises[resourceGroupId]) {
- return _fetchResourceGroupPromises[resourceGroupId];
- }
-
- const promise = new Promise(async (resolve, reject) => {
- let resourceGroup = _resourceGroupCache[resourceGroupId];
-
- if (!resourceGroup) {
- try {
- resourceGroup = await syncGetResourceGroup(resourceGroupId);
- } catch (e) {
- if (e.statusCode === 404) {
- await store.removeResourceGroup(resourceGroupId);
- logger.debug('ResourceGroup not found. Deleting...');
- reject(new Error('ResourceGroup was not found'));
- return;
- } else {
- logger.error(`Failed to get ResourceGroup ${resourceGroupId}: ${e}`);
- reject(e);
- return;
- }
- }
-
- if (resourceGroup.isDisabled) {
- await store.removeResourceGroup(resourceGroup.id);
- logger.debug('ResourceGroup was disabled. Deleting...');
- reject(new Error('ResourceGroup was disabled'));
- return;
- }
-
- // Also make sure a config exists when we first fetch it.
- // (This may not be needed but we'll do it just in case)
- await ensureConfigExists(resourceGroupId);
- }
-
- // Bust cached promise because we're done with it.
- _fetchResourceGroupPromises[resourceGroupId] = null;
-
- // Cache the ResourceGroup for next time (they never change)
- _resourceGroupCache[resourceGroupId] = resourceGroup;
-
- // Return the ResourceGroup
- resolve(resourceGroup);
- });
-
- // Cache the Promise in case we get asked for the same thing before done
- _fetchResourceGroupPromises[resourceGroupId] = promise;
- return promise;
-}
-
-/**
- * Get a ResourceGroup's symmetric encryption key
- *
- * @param resourceGroupId
- * @private
- */
-async function _getResourceGroupSymmetricKey(resourceGroupId) {
- let key = resourceGroupSymmetricKeysCache[resourceGroupId];
-
- if (!key) {
- const resourceGroup = await fetchResourceGroup(resourceGroupId);
- const accountPrivateKey = await session.getPrivateKey();
-
- const symmetricKeyStr = crypt.decryptRSAWithJWK(
- accountPrivateKey,
- resourceGroup.encSymmetricKey,
- );
-
- key = JSON.parse(symmetricKeyStr);
-
- // Update cache
- resourceGroupSymmetricKeysCache[resourceGroupId] = key;
- }
-
- return key;
-}
-
-export async function encryptDoc(resourceGroupId, doc) {
- try {
- const symmetricKey = await _getResourceGroupSymmetricKey(resourceGroupId);
-
- // TODO: Turn on compression once enough users are on version >= 5.7.0
- // const jsonStr = JSON.stringify(doc);
- // const docStr = zlib.gzipSync(jsonStr);
-
- // Don't use compression for now
- const docStr = JSON.stringify(doc);
-
- const message = crypt.encryptAES(symmetricKey, docStr);
- return JSON.stringify(message);
- } catch (e) {
- logger.error(`Failed to encrypt for ${resourceGroupId}: ${e}`);
- throw e;
- }
-}
-
-export async function decryptDoc(resourceGroupId, messageJSON) {
- let decrypted;
- try {
- const symmetricKey = await _getResourceGroupSymmetricKey(resourceGroupId);
- const message = JSON.parse(messageJSON);
- decrypted = crypt.decryptAES(symmetricKey, message);
- } catch (e) {
- logger.error(`Failed to decrypt from ${resourceGroupId}: ${e}`, messageJSON);
- throw e;
- }
-
- try {
- decrypted = zlib.gunzipSync(decrypted);
- } catch (err) {
- // It's not compressed (legacy), which is okay for now
- }
-
- try {
- return JSON.parse(decrypted);
- } catch (e) {
- logger.error(`Failed to parse after decrypt from ${resourceGroupId}: ${e}`, decrypted);
- throw e;
- }
-}
-
-async function _getWorkspaceForDoc(doc) {
- const ancestors = await db.withAncestors(doc);
- return ancestors.find(d => d.type === models.workspace.type);
-}
-
-export async function createResourceGroup(parentId, name) {
- // Generate symmetric key for ResourceGroup
- const rgSymmetricJWK = await crypt.generateAES256Key();
- const rgSymmetricJWKStr = JSON.stringify(rgSymmetricJWK);
-
- // Encrypt the symmetric key with Account public key
- const publicJWK = session.getPublicKey();
- const encRGSymmetricJWK = crypt.encryptRSAWithJWK(publicJWK, rgSymmetricJWKStr);
-
- // Create the new ResourceGroup
- let resourceGroup;
- try {
- resourceGroup = await syncCreateResourceGroup(parentId, name, encRGSymmetricJWK);
- } catch (e) {
- logger.error(`Failed to create ResourceGroup: ${e}`);
- throw e;
- }
-
- // Create a config for it
- await ensureConfigExists(resourceGroup.id, store.SYNC_MODE_UNSET);
-
- logger.debug(`Created ResourceGroup ${resourceGroup.id}`);
- return resourceGroup;
-}
-
-export async function createResource(doc, resourceGroupId) {
- return store.insertResource({
- id: doc._id,
- name: doc.name || 'n/a', // Set name to the doc name if it has one
- resourceGroupId: resourceGroupId,
- version: NO_VERSION,
- createdBy: session.getAccountId(),
- lastEdited: doc.modified,
- lastEditedBy: session.getAccountId(),
- removed: false,
- type: doc.type,
- encContent: await encryptDoc(resourceGroupId, doc),
- dirty: true,
- });
-}
-
-export async function createResourceForDoc(doc) {
- // No resource yet, so create one
- const workspace = await _getWorkspaceForDoc(doc);
-
- if (!workspace) {
- // Workspace was probably deleted before it's children could be synced.
- // TODO: Handle this case better
- throw new Error(`Could not find workspace for doc ${doc._id}`);
- }
-
- let workspaceResource = await store.getResourceByDocId(workspace._id);
-
- if (!workspaceResource) {
- const workspaceResourceGroup = await createResourceGroup(workspace._id, workspace.name);
- workspaceResource = await createResource(workspace, workspaceResourceGroup.id);
- }
-
- if (workspace === doc) {
- // If the current doc IS a Workspace, just return it
- return workspaceResource;
- } else {
- return createResource(doc, workspaceResource.resourceGroupId);
- }
-}
-
-export async function getOrCreateResourceForDoc(doc) {
- const [resource, ...extras] = await store.findResourcesByDocId(doc._id);
-
- // Sometimes there may be multiple resources created by accident for
- // the same doc. Let's delete the extras here if there are any.
- for (const resource of extras) {
- await store.removeResource(resource);
- }
-
- if (resource) {
- return resource;
- } else {
- return createResourceForDoc(doc);
- }
-}
-
-export async function getOrCreateAllActiveResources(resourceGroupId = null) {
- const startTime = Date.now();
- const activeResourceMap = {};
-
- let activeResources;
- if (resourceGroupId) {
- activeResources = await store.activeResourcesForResourceGroup(resourceGroupId);
- } else {
- activeResources = await store.allActiveResources();
- }
-
- for (const r of activeResources) {
- activeResourceMap[r.id] = r;
- }
-
- // Make sure Workspace is first, because the loop below depends on it
- const modelTypes = Object.keys(WHITE_LIST).sort((a, b) =>
- a.type === models.workspace.type ? 1 : -1,
- );
-
- let created = 0;
- for (const type of modelTypes) {
- for (const doc of await db.all(type)) {
- if (doc.isPrivate) {
- // logger.debug(`Skip private doc ${doc._id}`);
- continue;
- }
-
- const resource = await store.getResourceByDocId(doc._id);
- if (!resource) {
- try {
- activeResourceMap[doc._id] = await createResourceForDoc(doc);
- created++;
- } catch (e) {
- // logger.warn(`Failed to create resource for ${doc._id} ${e}`, {doc});
- }
- }
- }
- }
-
- const resources = Object.keys(activeResourceMap).map(k => activeResourceMap[k]);
-
- const time = (Date.now() - startTime) / 1000;
- if (created > 0) {
- logger.debug(`Created ${created}/${resources.length} Resources (${time.toFixed(2)}s)`);
- }
- return resources;
-}
diff --git a/packages/insomnia-app/app/sync-legacy/logger.js b/packages/insomnia-app/app/sync-legacy/logger.js
deleted file mode 100644
index 5c7bf391eb..0000000000
--- a/packages/insomnia-app/app/sync-legacy/logger.js
+++ /dev/null
@@ -1,37 +0,0 @@
-export default class Logger {
- constructor() {
- this._logs = [];
- }
-
- debug(message, ...args) {
- this._log('debug', message, ...args);
- }
-
- warn(message, ...args) {
- this._log('warn', message, ...args);
- }
-
- error(message, ...args) {
- this._log('error', message, ...args);
- }
-
- tail() {
- return this._logs;
- }
-
- /** @private */
- _log(type, message, ...args) {
- let fn;
- if (type === 'debug') {
- fn = 'log';
- } else if (type === 'warn') {
- fn = 'warn';
- } else {
- fn = 'error';
- }
-
- console[fn](`[sync] ${message}`, ...args);
- const date = new Date();
- this._logs.push({ type, date, message });
- }
-}
diff --git a/packages/insomnia-app/app/sync-legacy/network.js b/packages/insomnia-app/app/sync-legacy/network.js
deleted file mode 100644
index 57bf076b13..0000000000
--- a/packages/insomnia-app/app/sync-legacy/network.js
+++ /dev/null
@@ -1,77 +0,0 @@
-import * as fetch from '../account/fetch';
-import * as session from '../account/session';
-import * as crypt from '../account/crypt';
-
-export async function syncCreateResourceGroup(parentResourceId, name, encSymmetricKey) {
- return fetch.post(
- '/api/resource_groups',
- {
- parentResourceId,
- name,
- encSymmetricKey,
- },
- session.getCurrentSessionId(),
- );
-}
-
-export async function syncGetResourceGroup(id) {
- return fetch.get(`/api/resource_groups/${id}`, session.getCurrentSessionId());
-}
-
-export async function syncPull(body) {
- return fetch.post('/sync/pull', body, session.getCurrentSessionId(), true);
-}
-
-export async function syncPush(body) {
- return fetch.post('/sync/push', body, session.getCurrentSessionId(), true);
-}
-
-export async function syncResetData() {
- return fetch.post('/auth/reset', null, session.getCurrentSessionId());
-}
-
-export async function syncFixDupes(resourceGroupIds) {
- return fetch.post('/sync/fix-dupes', { ids: resourceGroupIds }, session.getCurrentSessionId());
-}
-
-export async function unshareWithAllTeams(resourceGroupId) {
- return fetch.put(
- `/api/resource_groups/${resourceGroupId}/unshare`,
- null,
- session.getCurrentSessionId(),
- );
-}
-
-export async function shareWithTeam(resourceGroupId, teamId) {
- // Ask the server what we need to do to invite the member
- const instructions = await fetch.post(
- `/api/resource_groups/${resourceGroupId}/share-a`,
- {
- teamId,
- },
- session.getCurrentSessionId(),
- );
-
- const privateKeyJWK = session.getPrivateKey();
- const resourceGroupSymmetricKey = crypt.decryptRSAWithJWK(
- privateKeyJWK,
- instructions.encSymmetricKey,
- );
-
- // Build the invite data request
- const newKeys = {};
- for (const accountId of Object.keys(instructions.keys)) {
- const accountPublicKeyJWK = JSON.parse(instructions.keys[accountId]);
- newKeys[accountId] = crypt.encryptRSAWithJWK(accountPublicKeyJWK, resourceGroupSymmetricKey);
- }
-
- // Actually share it with the team
- await fetch.post(
- `/api/resource_groups/${resourceGroupId}/share-b`,
- {
- teamId,
- keys: newKeys,
- },
- session.getCurrentSessionId(),
- );
-}
diff --git a/packages/insomnia-app/app/sync-legacy/storage.js b/packages/insomnia-app/app/sync-legacy/storage.js
deleted file mode 100644
index 85188e1ff1..0000000000
--- a/packages/insomnia-app/app/sync-legacy/storage.js
+++ /dev/null
@@ -1,240 +0,0 @@
-import NeDB from 'nedb';
-import fsPath from 'path';
-import crypto from 'crypto';
-import * as util from '../common/misc';
-import { DB_PERSIST_INTERVAL } from '../common/constants';
-
-const TYPE_RESOURCE = 'Resource';
-const TYPE_CONFIG = 'Config';
-
-export const SYNC_MODE_OFF = 'paused';
-export const SYNC_MODE_ON = 'active';
-export const SYNC_MODE_NEVER = 'never';
-export const SYNC_MODE_UNSET = 'unset';
-let changeListeners = [];
-
-export function onChange(callback) {
- changeListeners.push(callback);
-}
-
-export function offChange(callback) {
- changeListeners = changeListeners.filter(l => l !== callback);
-}
-
-let _changeTimeout = null;
-function _notifyChange() {
- clearTimeout(_changeTimeout);
- _changeTimeout = setTimeout(() => {
- for (const fn of changeListeners) {
- fn();
- }
- }, 200);
-}
-
-export function allActiveResources(resourceGroupId = null) {
- if (resourceGroupId) {
- return findActiveResources({ resourceGroupId });
- } else {
- return findActiveResources({});
- }
-}
-
-export function activeResourcesForResourceGroup(resourceGroupId) {
- return findActiveResources({ resourceGroupId });
-}
-
-export function allResources() {
- return findResources({});
-}
-
-export async function findResources(query = {}) {
- return _execDB(TYPE_RESOURCE, 'find', query);
-}
-
-export async function findActiveResources(query) {
- const configs = await findActiveConfigs();
- const resourceGroupIds = configs.map(c => c.resourceGroupId);
- return findResources(Object.assign({ resourceGroupId: { $in: resourceGroupIds } }, query));
-}
-
-export async function findActiveDirtyResources() {
- return findActiveResources({ dirty: true });
-}
-
-export async function findActiveDirtyResourcesForResourceGroup(resourceGroupId) {
- return findActiveResources({ dirty: true, resourceGroupId });
-}
-
-export async function findDirtyResourcesForResourceGroup(resourceGroupId) {
- return findResources({ dirty: true, resourceGroupId });
-}
-
-export async function findResourcesForResourceGroup(resourceGroupId) {
- return findResources({ resourceGroupId });
-}
-
-export async function getResourceByDocId(id, resourceGroupId = null) {
- let query;
- if (resourceGroupId) {
- query = { id, resourceGroupId };
- } else {
- query = { id };
- }
-
- const rawDocs = await _execDB(TYPE_RESOURCE, 'find', query);
- return rawDocs.length >= 1 ? rawDocs[0] : null;
-}
-
-/**
- * This function is temporary and should only be called when cleaning
- * up duplicate ResourceGroups
- * @param id
- * @returns {*}
- */
-export function findResourcesByDocId(id) {
- return _execDB(TYPE_RESOURCE, 'find', { id });
-}
-
-/**
- * This function is temporary and should only be called when cleaning
- * up duplicate ResourceGroups
- * @param resourceGroupId
- * @returns {*}
- */
-export async function removeResourceGroup(resourceGroupId) {
- await _execDB(TYPE_RESOURCE, 'remove', { resourceGroupId }, { multi: true });
- await _execDB(TYPE_CONFIG, 'remove', { resourceGroupId }, { multi: true });
- _notifyChange();
-}
-
-export async function insertResource(resource) {
- const h = crypto.createHash('md5');
- h.update(resource.resourceGroupId);
- h.update(resource.id);
- const newResource = Object.assign({}, resource, {
- _id: `rs_${h.digest('hex')}`,
- });
- await _execDB(TYPE_RESOURCE, 'insert', newResource);
- _notifyChange();
- return newResource;
-}
-
-export async function updateResource(resource, ...patches) {
- const newDoc = Object.assign({}, resource, ...patches);
- await _execDB(TYPE_RESOURCE, 'update', { _id: resource._id }, newDoc, {
- multi: true,
- });
- _notifyChange();
- return newDoc;
-}
-
-export async function removeResource(resource) {
- await _execDB(TYPE_RESOURCE, 'remove', { _id: resource._id }, { multi: true });
- _notifyChange();
-}
-
-// ~~~~~~ //
-// Config //
-// ~~~~~~ //
-
-export function findConfigs(query) {
- return _execDB(TYPE_CONFIG, 'find', query);
-}
-
-export function allConfigs() {
- return findConfigs({});
-}
-
-export function findInactiveConfigs(excludedResourceGroupId = null) {
- if (excludedResourceGroupId) {
- return findConfigs({
- $not: { syncMode: SYNC_MODE_ON, excludedResourceGroupId },
- });
- } else {
- return findConfigs({ $not: { syncMode: SYNC_MODE_ON } });
- }
-}
-
-export function findActiveConfigs(resourceGroupId = null) {
- if (resourceGroupId) {
- return findConfigs({ syncMode: SYNC_MODE_ON, resourceGroupId });
- } else {
- return findConfigs({ syncMode: SYNC_MODE_ON });
- }
-}
-
-export async function getConfig(resourceGroupId) {
- const rawDocs = await _execDB(TYPE_CONFIG, 'find', { resourceGroupId });
- return rawDocs.length >= 1 ? _initConfig(rawDocs[0]) : null;
-}
-
-export async function updateConfig(config, ...patches) {
- const doc = _initConfig(Object.assign(config, ...patches));
- await _execDB(TYPE_CONFIG, 'update', { _id: doc._id }, doc);
- return doc;
-}
-
-export function removeConfig(config) {
- return _execDB(TYPE_CONFIG, 'remove', { _id: config._id });
-}
-
-export async function insertConfig(config) {
- const doc = _initConfig(config);
- await _execDB(TYPE_CONFIG, 'insert', doc);
- return doc;
-}
-
-function _initConfig(data) {
- return Object.assign(
- {
- _id: util.generateId('scf'),
- syncMode: SYNC_MODE_UNSET,
- resourceGroupId: null,
- },
- data,
- );
-}
-
-export function initDB(config, forceReset) {
- if (!_database || forceReset) {
- const basePath = util.getDataDirectory();
- _database = {};
-
- // NOTE: Do not EVER change this. EVER!
- const resourcePath = fsPath.join(basePath, 'sync/Resource.db');
- const configPath = fsPath.join(basePath, 'sync/Config.db');
-
- // Fill in the defaults
- _database.Resource = new NeDB(
- Object.assign({ filename: resourcePath, autoload: true }, config),
- );
-
- _database.Config = new NeDB(Object.assign({ filename: configPath, autoload: true }, config));
-
- for (const key of Object.keys(_database)) {
- _database[key].persistence.setAutocompactionInterval(DB_PERSIST_INTERVAL);
- }
-
- // Done
- console.log(`[sync] Initialize Sync DB at ${basePath}`);
- }
-}
-
-// ~~~~~~~ //
-// Helpers //
-// ~~~~~~~ //
-
-let _database = null;
-
-function _getDB(type, config = {}) {
- initDB(config);
- return _database[type];
-}
-
-function _execDB(type, fnName, ...args) {
- return new Promise((resolve, reject) => {
- _getDB(type)[fnName](...args, (err, data) => {
- err ? reject(err) : resolve(data);
- });
- });
-}
diff --git a/packages/insomnia-app/app/ui/components/dropdowns/sync-legacy-dropdown.js b/packages/insomnia-app/app/ui/components/dropdowns/sync-legacy-dropdown.js
deleted file mode 100644
index 8ad51b31eb..0000000000
--- a/packages/insomnia-app/app/ui/components/dropdowns/sync-legacy-dropdown.js
+++ /dev/null
@@ -1,234 +0,0 @@
-// @flow
-import * as React from 'react';
-import autobind from 'autobind-decorator';
-import { Dropdown, DropdownButton, DropdownDivider, DropdownItem } from '../base/dropdown';
-import { showModal } from '../modals';
-import * as syncStorage from '../../../sync-legacy/storage';
-import * as sync from '../../../sync-legacy';
-import WorkspaceShareSettingsModal from '../modals/workspace-share-settings-modal';
-import SetupSyncModal from '../modals/setup-sync-modal';
-import type { Workspace } from '../../../models/workspace';
-import * as session from '../../../account/session';
-import { clickLink } from '../../../common/misc';
-
-type Props = {
- workspace: Workspace,
-
- // Optional
- className?: string,
-};
-
-type State = {
- loggedIn: boolean | null,
- loading: boolean,
- resourceGroupId: string | null,
- syncMode: string | null,
- syncPercent: number,
- workspaceName: string,
-};
-
-@autobind
-class SyncLegacyDropdown extends React.PureComponent {
- _hasPrompted: boolean;
- _isMounted: boolean;
-
- constructor(props: Props) {
- super(props);
-
- this._hasPrompted = false;
- this._isMounted = false;
-
- this.state = {
- loggedIn: null,
- loading: false,
- resourceGroupId: null,
- syncMode: null,
- syncPercent: 0,
- workspaceName: '',
- };
- }
-
- _handleShowShareSettings() {
- showModal(WorkspaceShareSettingsModal, { workspace: this.props.workspace });
- }
-
- async _handleSyncResourceGroupId() {
- const { resourceGroupId } = this.state;
-
- // Set loading state
- this.setState({ loading: true });
-
- await sync.getOrCreateConfig(resourceGroupId);
- await sync.pull(resourceGroupId);
- await sync.push(resourceGroupId);
-
- await this._reloadData();
-
- // Unset loading state
- this.setState({ loading: false });
- }
-
- async _reloadData() {
- const loggedIn = session.isLoggedIn();
-
- if (loggedIn !== this.state.loggedIn) {
- this.setState({ loggedIn });
- }
-
- if (!loggedIn) {
- return;
- }
-
- // Get or create any related sync data
- const { workspace } = this.props;
- const { resourceGroupId } = await sync.getOrCreateResourceForDoc(workspace);
- const config = await sync.getOrCreateConfig(resourceGroupId);
-
- // Analyze it
- const dirty = await syncStorage.findDirtyResourcesForResourceGroup(resourceGroupId);
- const all = await syncStorage.findResourcesForResourceGroup(resourceGroupId);
- const numClean = all.length - dirty.length;
- const syncPercent = all.length === 0 ? 100 : parseInt((numClean / all.length) * 1000) / 10;
-
- if (this._isMounted) {
- this.setState({
- resourceGroupId,
- syncPercent,
- syncMode: config.syncMode,
- workspaceName: workspace.name,
- });
- }
- }
-
- static _handleShowSyncBetaPrompt() {
- clickLink('https://support.insomnia.rest/article/67-version-control');
- }
-
- async _handleShowSyncModePrompt() {
- showModal(SetupSyncModal, {
- onSelectSyncMode: async syncMode => {
- await this._reloadData();
- },
- });
- }
-
- componentDidMount() {
- this._isMounted = true;
- syncStorage.onChange(this._reloadData);
- this._reloadData();
- }
-
- componentWillUnmount() {
- syncStorage.offChange(this._reloadData);
- this._isMounted = false;
- }
-
- componentDidUpdate() {
- const { resourceGroupId, syncMode } = this.state;
-
- if (!resourceGroupId) {
- return;
- }
-
- // Sync has not yet been configured for this workspace, so prompt the user to do so
- const isModeUnset = !syncMode || syncMode === syncStorage.SYNC_MODE_UNSET;
- if (isModeUnset && !this._hasPrompted) {
- this._hasPrompted = true;
- this._handleShowSyncModePrompt();
- }
- }
-
- _getSyncDescription(syncMode: string | null, syncPercentage: number) {
- let el = null;
- if (syncMode === syncStorage.SYNC_MODE_NEVER) {
- el = Sync Disabled;
- } else if (syncPercentage === 100) {
- el = Sync Up To Date;
- } else if (syncMode === syncStorage.SYNC_MODE_OFF) {
- el = (
-
- Sync Required
-
- );
- } else if (syncMode === syncStorage.SYNC_MODE_ON) {
- el = Sync Pending;
- } else if (!syncMode || syncMode === syncStorage.SYNC_MODE_UNSET) {
- el = (
-
- Configure Sync
-
- );
- }
-
- return el;
- }
-
- render() {
- const { className } = this.props;
- const { resourceGroupId, loading, loggedIn } = this.state;
-
- // Don't show the sync menu unless we're logged in
- if (!loggedIn) {
- return null;
- }
-
- if (!resourceGroupId) {
- return (
-
-
-
- );
- } else {
- const { syncMode, syncPercent } = this.state;
- return (
-
-
-
- {this._getSyncDescription(syncMode, syncPercent)}
-
- Workspace Synced {syncPercent}%
-
-
-
- Change Sync Mode
-
-
- {/* SYNCED */}
-
- {syncMode !== syncStorage.SYNC_MODE_NEVER ? (
-
- {loading ? (
-
- ) : (
-
- )}
- Sync Now
-
- ) : null}
-
- {syncMode !== syncStorage.SYNC_MODE_NEVER ? (
-
-
- Share Settings
-
- ) : null}
-
- {syncMode === syncStorage.SYNC_MODE_OFF && [
- // NOTE: We can't use here because the nesting breaks
- // the component's child detection
- ,
-
-
- Try New Sync Beta
- ,
- ]}
-
-
- );
- }
- }
-}
-
-export default SyncLegacyDropdown;
diff --git a/packages/insomnia-app/app/ui/components/dropdowns/workspace-dropdown.js b/packages/insomnia-app/app/ui/components/dropdowns/workspace-dropdown.js
index c42084c4b2..741d6b5544 100644
--- a/packages/insomnia-app/app/ui/components/dropdowns/workspace-dropdown.js
+++ b/packages/insomnia-app/app/ui/components/dropdowns/workspace-dropdown.js
@@ -13,7 +13,6 @@ import { getAppName, getAppVersion } from '../../../common/constants';
import { showAlert, showError, showModal, showPrompt } from '../modals';
import Link from '../base/link';
import WorkspaceSettingsModal from '../modals/workspace-settings-modal';
-import WorkspaceShareSettingsModal from '../modals/workspace-share-settings-modal';
import LoginModal from '../modals/login-modal';
import Tooltip from '../tooltip';
import KeydownBinder from '../keydown-binder';
@@ -26,7 +25,6 @@ import * as db from '../../../common/database';
import VCS from '../../../sync/vcs';
import HelpTooltip from '../help-tooltip';
import type { Project } from '../../../sync/types';
-import * as sync from '../../../sync-legacy/index';
import PromptButton from '../base/prompt-button';
import * as session from '../../../account/session';
import type { WorkspaceAction } from '../../../plugins';
@@ -38,7 +36,6 @@ import type { Environment } from '../../../models/environment';
type Props = {
activeEnvironment: Environment | null,
activeWorkspace: Workspace,
- enableSyncBeta: boolean,
handleSetActiveWorkspace: (id: string) => void,
hotKeyRegistry: HotKeyRegistry,
isLoading: boolean,
@@ -197,7 +194,7 @@ class WorkspaceDropdown extends React.PureComponent {
}
static async _handleLogout() {
- await sync.logout();
+ await session.logout();
}
static _handleShowExport() {
@@ -213,11 +210,7 @@ class WorkspaceDropdown extends React.PureComponent {
}
_handleShowShareSettings() {
- if (this.props.enableSyncBeta) {
- showModal(SyncShareModal);
- } else {
- showModal(WorkspaceShareSettingsModal);
- }
+ showModal(SyncShareModal);
}
_handleWorkspaceCreate() {
@@ -259,7 +252,6 @@ class WorkspaceDropdown extends React.PureComponent {
isLoading,
hotKeyRegistry,
handleSetActiveWorkspace,
- enableSyncBeta,
...other
} = this.props;
diff --git a/packages/insomnia-app/app/ui/components/modals/login-modal.js b/packages/insomnia-app/app/ui/components/modals/login-modal.js
index 042b11391c..e489482450 100644
--- a/packages/insomnia-app/app/ui/components/modals/login-modal.js
+++ b/packages/insomnia-app/app/ui/components/modals/login-modal.js
@@ -5,7 +5,6 @@ import Modal from '../base/modal';
import ModalBody from '../base/modal-body';
import ModalHeader from '../base/modal-header';
import ModalFooter from '../base/modal-footer';
-import * as sync from '../../../sync-legacy';
import * as session from '../../../account/session';
@autobind
@@ -42,10 +41,6 @@ class LoginModal extends PureComponent {
try {
await session.login(email, password);
-
- // Clear all existing sync data that might be there and enable sync
- await sync.resetLocalData();
- await sync.doInitialSync();
this.hide();
} catch (e) {
this.setState({ error: e.message, loading: false });
diff --git a/packages/insomnia-app/app/ui/components/modals/payment-notification-modal.js b/packages/insomnia-app/app/ui/components/modals/payment-notification-modal.js
index db40136a95..765bd802ea 100644
--- a/packages/insomnia-app/app/ui/components/modals/payment-notification-modal.js
+++ b/packages/insomnia-app/app/ui/components/modals/payment-notification-modal.js
@@ -5,8 +5,7 @@ import Link from '../base/link';
import Modal from '../base/modal';
import ModalBody from '../base/modal-body';
import ModalHeader from '../base/modal-header';
-import * as sync from '../../../sync-legacy/index';
-import { getFirstName } from '../../../account/session';
+import { getFirstName, endTrial, logout } from '../../../account/session';
let hidePaymentNotificationUntilNextLaunch = false;
@@ -14,7 +13,8 @@ let hidePaymentNotificationUntilNextLaunch = false;
class PaymentNotificationModal extends PureComponent {
async _handleCancel() {
try {
- await sync.cancelTrial();
+ await endTrial();
+ await logout();
} catch (err) {
// That's okay
}
diff --git a/packages/insomnia-app/app/ui/components/modals/setup-sync-modal.js b/packages/insomnia-app/app/ui/components/modals/setup-sync-modal.js
deleted file mode 100644
index bc79ef968b..0000000000
--- a/packages/insomnia-app/app/ui/components/modals/setup-sync-modal.js
+++ /dev/null
@@ -1,181 +0,0 @@
-// @flow
-import * as React from 'react';
-import autobind from 'autobind-decorator';
-import Modal from '../base/modal';
-import ModalBody from '../base/modal-body';
-import ModalHeader from '../base/modal-header';
-import ModalFooter from '../base/modal-footer';
-import * as sync from '../../../sync-legacy';
-import {
- SYNC_MODE_OFF,
- SYNC_MODE_ON,
- SYNC_MODE_NEVER,
- SYNC_MODE_UNSET,
-} from '../../../sync-legacy/storage';
-import type { Workspace } from '../../../models/workspace';
-import HelpTooltip from '../help-tooltip';
-
-type Props = {
- workspace: Workspace,
-};
-
-type State = {
- syncMode: string,
- selectedSyncMode: string,
- syncDisableCookieJars: boolean,
- syncDisableClientCertificates: boolean,
-};
-
-@autobind
-class SetupSyncModal extends React.PureComponent {
- modal: ?Modal;
- _onSelectSyncMode: ?(selectedSyncMode: string) => void;
-
- constructor(props: Props) {
- super(props);
- this.state = {
- syncMode: SYNC_MODE_UNSET,
- selectedSyncMode: SYNC_MODE_ON,
- syncDisableCookieJars: false,
- syncDisableClientCertificates: false,
- };
- }
-
- _setModalRef(n: ?Modal) {
- this.modal = n;
- }
-
- _handleToggleSyncCertificates(e: SyntheticEvent) {
- this.setState({ syncDisableClientCertificates: !e.currentTarget.checked });
- }
-
- _handleToggleSyncCookieJars(e: SyntheticEvent) {
- this.setState({ syncDisableCookieJars: !e.currentTarget.checked });
- }
-
- async _handleDone() {
- const { workspace } = this.props;
- const { selectedSyncMode, syncDisableClientCertificates, syncDisableCookieJars } = this.state;
-
- const resource = await sync.getOrCreateResourceForDoc(workspace);
- await sync.createOrUpdateConfig(resource.resourceGroupId, {
- syncMode: selectedSyncMode,
- syncDisableClientCertificates: !!syncDisableClientCertificates,
- syncDisableCookieJars: !!syncDisableCookieJars,
- });
-
- this.hide();
-
- this._onSelectSyncMode && this._onSelectSyncMode(selectedSyncMode);
- }
-
- _handleSyncModeChange(e: SyntheticEvent) {
- const selectedSyncMode = e.currentTarget.value;
-
- this.setState({
- selectedSyncMode,
- });
- }
-
- async show(options: { onSelectSyncMode: (syncMode: string) => void }) {
- const { workspace } = this.props;
-
- const resource = await sync.getOrCreateResourceForDoc(workspace);
- const config = await sync.getOrCreateConfig(resource.resourceGroupId);
- const { syncMode, syncDisableCookieJars, syncDisableClientCertificates } = config;
-
- // Set selected sync mode. If it's unset, default it to ON
- const selectedSyncMode = syncMode !== SYNC_MODE_UNSET ? syncMode : SYNC_MODE_ON;
-
- this.setState({
- syncMode,
- selectedSyncMode,
- syncDisableCookieJars,
- syncDisableClientCertificates,
- });
-
- this._onSelectSyncMode = options.onSelectSyncMode;
-
- this.modal && this.modal.show();
- }
-
- hide() {
- this.modal && this.modal.hide();
- }
-
- render() {
- const { workspace } = this.props;
- const {
- syncMode,
- selectedSyncMode,
- syncDisableClientCertificates,
- syncDisableCookieJars,
- } = this.state;
-
- return (
-
- Workspace Sync Setup
-
- {syncMode === SYNC_MODE_UNSET ? (
-
- You have not yet configured sync for your {workspace.name} workspace.
-
- ) : null}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- * This can be changed at any time
-
-
-
-
- );
- }
-}
-
-export default SetupSyncModal;
diff --git a/packages/insomnia-app/app/ui/components/modals/workspace-share-settings-modal.js b/packages/insomnia-app/app/ui/components/modals/workspace-share-settings-modal.js
deleted file mode 100644
index 0ea9b9a2d3..0000000000
--- a/packages/insomnia-app/app/ui/components/modals/workspace-share-settings-modal.js
+++ /dev/null
@@ -1,203 +0,0 @@
-import React, { PureComponent } from 'react';
-import PropTypes from 'prop-types';
-import autobind from 'autobind-decorator';
-import { Dropdown, DropdownButton, DropdownDivider, DropdownItem } from '../base/dropdown';
-import Link from '../base/link';
-import Modal from '../base/modal';
-import ModalBody from '../base/modal-body';
-import ModalHeader from '../base/modal-header';
-import ModalFooter from '../base/modal-footer';
-import * as sync from '../../../sync-legacy/index';
-import PromptButton from '../base/prompt-button';
-import { shareWithTeam, unshareWithAllTeams } from '../../../sync-legacy/network';
-import * as session from '../../../account/session';
-
-@autobind
-class WorkspaceShareSettingsModal extends PureComponent {
- constructor(props) {
- super(props);
- this.state = {};
- }
-
- static _handleSubmit(e) {
- e.preventDefault();
- }
-
- _handleClose() {
- this.hide();
- }
-
- _setModalRef(n) {
- this.modal = n;
- }
-
- async _handleUnshare() {
- if (!session.isLoggedIn()) {
- return;
- }
-
- const { resourceGroup } = this.state;
-
- this._resetState({ loading: true });
-
- try {
- await unshareWithAllTeams(resourceGroup.id);
- await this._load();
- } catch (err) {
- console.warn('Failed to unshare workspace', err);
- this._resetState({ error: err.message, loading: false });
- }
- }
-
- async _handleShareWithTeam(team) {
- const { resourceGroup } = this.state;
- this._resetState({ loading: true });
-
- try {
- await shareWithTeam(resourceGroup.id, team.id);
- await this._load();
- } catch (err) {
- this._resetState({ error: err.message, loading: false });
- }
- }
-
- async _load() {
- if (!session.isLoggedIn()) {
- this._resetState({});
- return;
- }
-
- const { workspace } = this.props;
- const resource = await sync.getOrCreateResourceForDoc(workspace);
-
- const teams = await session.listTeams();
-
- try {
- const resourceGroup = await sync.fetchResourceGroup(resource.resourceGroupId, true);
- this.setState({ teams, resourceGroup, loading: false, error: '' });
- } catch (err) {
- console.warn('Failed to fetch ResourceGroup', err);
- this.setState({
- error: 'No sync info found. Please try again.',
- loading: false,
- });
- }
- }
-
- _resetState(patch = {}) {
- this.setState(
- Object.assign(
- {
- teams: [],
- resourceGroup: null,
- error: '',
- loading: false,
- },
- patch,
- ),
- );
- }
-
- async show() {
- this._resetState();
- this.modal.show();
-
- // This takes a while, so do it after show()
- await this._load();
- }
-
- hide() {
- this.modal.hide();
- }
-
- // eslint-disable-next-line camelcase
- UNSAFE_componentWillMount() {
- this._resetState();
- }
-
- render() {
- const { teams, resourceGroup, error, loading } = this.state;
- const { workspace } = this.props;
- return (
-
- );
- }
-}
-
-WorkspaceShareSettingsModal.propTypes = {
- workspace: PropTypes.object.isRequired,
-};
-
-export default WorkspaceShareSettingsModal;
diff --git a/packages/insomnia-app/app/ui/components/page-layout.js b/packages/insomnia-app/app/ui/components/page-layout.js
index f41eb8548e..3dbffa2d32 100644
--- a/packages/insomnia-app/app/ui/components/page-layout.js
+++ b/packages/insomnia-app/app/ui/components/page-layout.js
@@ -123,7 +123,6 @@ class PageLayout extends React.PureComponent {
ref={handleSetSidebarRef}
activeEnvironment={activeEnvironment}
activeGitRepository={activeGitRepository}
- enableSyncBeta={settings.enableSyncBeta}
environmentHighlightColorStyle={settings.environmentHighlightColorStyle}
handleInitializeEntities={handleInitializeEntities}
handleSetActiveEnvironment={handleSetActiveEnvironment}
diff --git a/packages/insomnia-app/app/ui/components/settings/account.js b/packages/insomnia-app/app/ui/components/settings/account.js
index 5d9ea128bb..a68d37a724 100644
--- a/packages/insomnia-app/app/ui/components/settings/account.js
+++ b/packages/insomnia-app/app/ui/components/settings/account.js
@@ -1,7 +1,6 @@
// @flow
import * as React from 'react';
import autobind from 'autobind-decorator';
-import * as sync from '../../../sync-legacy/index';
import Link from '../base/link';
import LoginModal from '../modals/login-modal';
import { hideAllModals, showModal } from '../modals/index';
@@ -81,7 +80,7 @@ class Account extends React.PureComponent {
}
async _handleLogout() {
- await sync.logout();
+ await session.logout();
this.forceUpdate();
}
diff --git a/packages/insomnia-app/app/ui/components/settings/general.js b/packages/insomnia-app/app/ui/components/settings/general.js
index ec0e886570..de7aaf8a9f 100644
--- a/packages/insomnia-app/app/ui/components/settings/general.js
+++ b/packages/insomnia-app/app/ui/components/settings/general.js
@@ -19,7 +19,6 @@ import {
} from '../../../common/constants';
import type { Settings } from '../../../models/settings';
import { setFont } from '../../../plugins/misc';
-import * as session from '../../../account/session';
import Tooltip from '../tooltip';
import CheckForUpdatesButton from '../check-for-updates-button';
import { initNewOAuthSession } from '../../../network/o-auth-2/misc';
@@ -519,13 +518,6 @@ class General extends React.PureComponent {
as request data, names, etc.
-
- {session.isLoggedIn() && (
-
-
- {this.renderBooleanSetting('Enable version control beta', 'enableSyncBeta', '', true)}
-
- )}
);
}
diff --git a/packages/insomnia-app/app/ui/components/sidebar/sidebar.js b/packages/insomnia-app/app/ui/components/sidebar/sidebar.js
index 1495bb2d63..0178e8b3ba 100644
--- a/packages/insomnia-app/app/ui/components/sidebar/sidebar.js
+++ b/packages/insomnia-app/app/ui/components/sidebar/sidebar.js
@@ -7,14 +7,12 @@ import type { Environment } from '../../../models/environment';
import classnames from 'classnames';
import { COLLAPSE_SIDEBAR_REMS, SIDEBAR_SKINNY_REMS } from '../../../common/constants';
import SyncDropdown from '../dropdowns/sync-dropdown';
-import SyncLegacyDropdown from '../dropdowns/sync-legacy-dropdown';
import type { StatusCandidate } from '../../../sync/types';
import { isLoggedIn } from '../../../account/session';
type Props = {|
activeEnvironment: Environment | null,
children: React.Node,
- enableSyncBeta: boolean,
environmentHighlightColorStyle: string,
handleSetActiveEnvironment: Function,
handleSetActiveWorkspace: Function,
@@ -35,7 +33,6 @@ class Sidebar extends React.PureComponent {
const {
activeEnvironment,
children,
- enableSyncBeta,
environmentHighlightColorStyle,
hidden,
syncItems,
@@ -61,7 +58,7 @@ class Sidebar extends React.PureComponent {
}}>
{children}
- {enableSyncBeta && vcs && isLoggedIn() && (
+ {vcs && isLoggedIn() && (
{
syncItems={syncItems}
/>
)}
-
- {!enableSyncBeta && (
-
- )}
);
}
diff --git a/packages/insomnia-app/app/ui/components/wrapper-debug.js b/packages/insomnia-app/app/ui/components/wrapper-debug.js
index 87355bc169..ab500ed214 100644
--- a/packages/insomnia-app/app/ui/components/wrapper-debug.js
+++ b/packages/insomnia-app/app/ui/components/wrapper-debug.js
@@ -142,7 +142,6 @@ class WrapperDebug extends React.PureComponent {
unseenWorkspaces={unseenWorkspaces}
hotKeyRegistry={settings.hotKeyRegistry}
handleSetActiveWorkspace={handleSetActiveWorkspace}
- enableSyncBeta={settings.enableSyncBeta}
isLoading={isLoading}
vcs={vcs}
/>
diff --git a/packages/insomnia-app/app/ui/components/wrapper.js b/packages/insomnia-app/app/ui/components/wrapper.js
index 13742e6e00..26f428c82b 100644
--- a/packages/insomnia-app/app/ui/components/wrapper.js
+++ b/packages/insomnia-app/app/ui/components/wrapper.js
@@ -35,7 +35,6 @@ import RequestSwitcherModal from './modals/request-switcher-modal';
import SettingsModal from './modals/settings-modal';
import FilterHelpModal from './modals/filter-help-modal';
import RequestSettingsModal from './modals/request-settings-modal';
-import SetupSyncModal from './modals/setup-sync-modal';
import SyncStagingModal from './modals/sync-staging-modal';
import GitRepositorySettingsModal from './modals/git-repository-settings-modal';
import GitStagingModal from './modals/git-staging-modal';
@@ -49,7 +48,6 @@ import SyncDeleteModal from './modals/sync-delete-modal';
import RequestRenderErrorModal from './modals/request-render-error-modal';
import WorkspaceEnvironmentsEditModal from './modals/workspace-environments-edit-modal';
import WorkspaceSettingsModal from './modals/workspace-settings-modal';
-import WorkspaceShareSettingsModal from './modals/workspace-share-settings-modal';
import CodePromptModal from './modals/code-prompt-modal';
import * as db from '../../common/database';
import * as models from '../../models/index';
@@ -672,8 +670,6 @@ class Wrapper extends React.PureComponent {
isVariableUncovered={isVariableUncovered}
/>
-
-
{
isVariableUncovered={isVariableUncovered}
/>
-
-
{gitVCS && (
diff --git a/packages/insomnia-app/app/ui/index.js b/packages/insomnia-app/app/ui/index.js
index 9b604824ec..ddcd088d3e 100644
--- a/packages/insomnia-app/app/ui/index.js
+++ b/packages/insomnia-app/app/ui/index.js
@@ -5,16 +5,14 @@ import App from './containers/app';
import * as models from '../models';
import * as db from '../common/database';
import { init as initStore } from './redux/modules';
-import * as legacySync from '../sync-legacy';
import { init as initPlugins } from '../plugins';
import './css/index.less';
-import { getAppId, getAppLongName, isDevelopment } from '../common/constants';
+import { getAppLongName, isDevelopment } from '../common/constants';
import { setFont, setTheme } from '../plugins/misc';
import { AppContainer } from 'react-hot-loader';
import { DragDropContext } from 'react-dnd';
import DNDBackend from './dnd-backend';
import { trackEvent } from '../common/analytics';
-import { APP_ID_DESIGNER, APP_ID_INSOMNIA } from '../../config';
import * as styledComponents from 'styled-components';
import { initNewOAuthSession } from '../network/o-auth-2/misc';
import { initializeLogging } from '../common/log';
@@ -60,22 +58,6 @@ document.title = getAppLongName();
// render(App);
// });
}
-
- const appId = getAppId();
-
- // Legacy sync not part of Designer
- if (appId === APP_ID_DESIGNER) {
- legacySync.disableForSession();
- } else if (appId === APP_ID_INSOMNIA) {
- // Do things that can wait
- const { enableSyncBeta } = await models.settings.getOrCreate();
- if (enableSyncBeta) {
- console.log('[app] Enabling sync beta');
- legacySync.disableForSession();
- } else {
- process.nextTick(legacySync.init);
- }
- }
})();
// Export some useful things for dev