diff --git a/backend/src/app.ts b/backend/src/app.ts index 211a53dab..0fe39ae80 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -1,4 +1,6 @@ -import { patchRouterParam } from './utils/patchAsyncRoutes'; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { patchRouterParam } = require('./utils/patchAsyncRoutes'); + import express from 'express'; import helmet from 'helmet'; import cors from 'cors'; @@ -6,7 +8,7 @@ import cookieParser from 'cookie-parser'; import dotenv from 'dotenv'; dotenv.config(); -import { PORT, NODE_ENV, SITE_URL, LICENSE_KEY } from './config'; +import { PORT, NODE_ENV, SITE_URL } from './config'; import { apiLimiter } from './helpers/rateLimiter'; import { @@ -38,8 +40,8 @@ import { getLogger } from './utils/logger'; import { RouteNotFoundError } from './utils/errors'; import { requestErrorHandler } from './middleware/requestErrorHandler'; -//* Patch Async route params to handle Promise Rejections -patchRouterParam() +// patch async route params to handle Promise Rejections +patchRouterParam(); export const app = express(); diff --git a/backend/src/ee/services/EESecretService.ts b/backend/src/ee/services/EESecretService.ts index 9cc5fba2f..643f763f1 100644 --- a/backend/src/ee/services/EESecretService.ts +++ b/backend/src/ee/services/EESecretService.ts @@ -19,10 +19,8 @@ class EESecretService { * @param {String} obj.workspaceId */ static async takeSecretSnapshot({ - licenseKey, workspaceId }: { - licenseKey: string; workspaceId: string; }) { if (!EELicenseService.isLicenseValid) return; diff --git a/backend/src/helpers/secret.ts b/backend/src/helpers/secret.ts index c01503402..4b3585c40 100644 --- a/backend/src/helpers/secret.ts +++ b/backend/src/helpers/secret.ts @@ -56,6 +56,7 @@ const pushSecrets = async ({ environment: string; secrets: PushSecret[]; }): Promise => { + // TODO: clean up function and fix up types try { // construct useful data structures const oldSecrets = await pullSecrets({ @@ -63,10 +64,11 @@ const pushSecrets = async ({ workspaceId, environment }); + const oldSecretsObj: any = oldSecrets.reduce((accumulator, s: any) => ({ ...accumulator, [`${s.type}-${s.secretKeyHash}`]: s }) , {}); - const newSecretsObj = secrets.reduce((accumulator, s) => + const newSecretsObj: any = secrets.reduce((accumulator, s) => ({ ...accumulator, [`${s.type}-${s.hashKey}`]: s }) , {}); @@ -79,8 +81,6 @@ const pushSecrets = async ({ if (toDelete.length > 0) { await Secret.deleteMany({ _id: { $in: toDelete } - }, { - rawResult: true }); await SecretVersion.updateMany({ @@ -89,31 +89,48 @@ const pushSecrets = async ({ isDeleted: true }); } - - // handle modifying secrets where type or value changed - const toUpdate = secrets + + const toUpdate = oldSecrets .filter((s) => { - if (`${s.type}-${s.hashKey}` in oldSecretsObj) { - if (s.hashValue !== oldSecretsObj[`${s.type}-${s.hashKey}`].secretValueHash) { + if (`${s.type}-${s.secretKeyHash}` in newSecretsObj) { + if (s.secretValueHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].hashValue) { // case: filter secrets where value changed return true; } - } + if (!s.version) { + // case: filter (legacy) secrets that were not versioned + return true; + } + } + return false; }); - + const operations = toUpdate .map((s) => { + const { + ciphertextValue, + ivValue, + tagValue, + hashValue + } = newSecretsObj[`${s.type}-${s.secretKeyHash}`]; + const update: Update = { - secretValueCiphertext: s.ciphertextValue, - secretValueIV: s.ivValue, - secretValueTag: s.tagValue, - secretValueHash: s.hashValue, - $inc: { + secretValueCiphertext: ciphertextValue, + secretValueIV: ivValue, + secretValueTag: tagValue, + secretValueHash: hashValue + } + + if (!s.version) { + // case: (legacy) secret was not versioned + update.version = 1; + } else { + update['$inc'] = { version: 1 } - }; + } if (s.type === SECRET_PERSONAL) { // attach user associated with the personal secret @@ -123,7 +140,7 @@ const pushSecrets = async ({ return { updateOne: { filter: { - _id: oldSecretsObj[`${s.type}-${s.hashKey}`]._id + _id: oldSecretsObj[`${s.type}-${s.secretKeyHash}`]._id }, update } @@ -134,28 +151,26 @@ const pushSecrets = async ({ // (EE) add secret versions for updated secrets await EESecretService.addSecretVersions({ secretVersions: toUpdate.map(({ + _id, + version, type, - ciphertextKey, - ivKey, - tagKey, - hashKey, - ciphertextValue, - ivValue, - tagValue, - hashValue - }) => ({ - secret: oldSecretsObj[`${type}-${hashKey}`]._id, - version: oldSecretsObj[`${type}-${hashKey}`].version + 1, - isDeleted: false, - secretKeyCiphertext: ciphertextKey, - secretKeyIV: ivKey, - secretKeyTag: tagKey, - secretKeyHash: hashKey, - secretValueCiphertext: ciphertextValue, - secretValueIV: ivValue, - secretValueTag: tagValue, - secretValueHash: hashValue - })) + secretKeyHash, + }) => { + const newSecret = newSecretsObj[`${type}-${secretKeyHash}`]; + return ({ + secret: _id, + version: version ? version + 1 : 1, + isDeleted: false, + secretKeyCiphertext: newSecret.ciphertextKey, + secretKeyIV: newSecret.ivKey, + secretKeyTag: newSecret.tagKey, + secretKeyHash: newSecret.hashKey, + secretValueCiphertext: newSecret.ciphertextValue, + secretValueIV: newSecret.ivValue, + secretValueTag: newSecret.tagValue, + secretValueHash: newSecret.hashValue + }) + }) }); // handle adding new secrets @@ -166,6 +181,7 @@ const pushSecrets = async ({ const newSecrets = await Secret.insertMany( toAdd.map((s, idx) => { const obj: any = { + version: 1, workspace: workspaceId, type: toAdd[idx].type, environment, @@ -217,7 +233,6 @@ const pushSecrets = async ({ // (EE) take a secret snapshot await EESecretService.takeSecretSnapshot({ - licenseKey: LICENSE_KEY, workspaceId }) } catch (err) { diff --git a/backend/src/models/secret.ts b/backend/src/models/secret.ts index ee879de30..d34139ecb 100644 --- a/backend/src/models/secret.ts +++ b/backend/src/models/secret.ts @@ -29,8 +29,7 @@ const secretSchema = new Schema( { version: { type: Number, - default: 1, - required: true + required: true }, workspace: { type: Schema.Types.ObjectId, diff --git a/backend/src/utils/patchAsyncRoutes.js b/backend/src/utils/patchAsyncRoutes.js index 6f6d2367f..24fe007f9 100644 --- a/backend/src/utils/patchAsyncRoutes.js +++ b/backend/src/utils/patchAsyncRoutes.js @@ -45,7 +45,7 @@ function wrap(fn) { return copyFnProps(fn, newFn); } -export function patchRouterParam() { +function patchRouterParam() { const originalParam = Router.prototype.constructor.param; Router.prototype.constructor.param = function param(name, fn) { fn = wrap(fn); @@ -62,4 +62,8 @@ Object.defineProperty(Layer.prototype, 'handle', { fn = wrap(fn); this.__handle = fn; }, -}); \ No newline at end of file +}); + +module.exports = { + patchRouterParam +};