feat: remove try-catch blocks for handling errors in middleware

This commit is contained in:
Spelchure
2023-06-05 21:15:35 +03:00
parent 08868681d8
commit bfee0a6d30
36 changed files with 3681 additions and 4753 deletions
@@ -1,5 +1,4 @@
import { Request, Response } from 'express';
import * as Sentry from '@sentry/node';
import { Action, SecretVersion } from '../../models';
import { ActionNotFoundError } from '../../../utils/errors';
@@ -28,4 +27,4 @@ export const getAction = async (req: Request, res: Response) => {
return res.status(200).send({
action
});
}
}
@@ -1,4 +1,3 @@
import * as Sentry from '@sentry/node';
import { Request, Response } from 'express';
import { EELicenseService } from '../../services';
import { getLicenseServerUrl } from '../../../config';
@@ -12,23 +11,18 @@ import { licenseServerKeyRequest } from '../../../config/request';
* @returns
*/
export const getCloudProducts = async (req: Request, res: Response) => {
try {
const billingCycle = req.query['billing-cycle'] as string;
const billingCycle = req.query['billing-cycle'] as string;
if (EELicenseService.instanceType === 'cloud') {
const { data } = await licenseServerKeyRequest.get(
`${await getLicenseServerUrl()}/api/license-server/v1/cloud-products?billing-cycle=${billingCycle}`
);
if (EELicenseService.instanceType === 'cloud') {
const { data } = await licenseServerKeyRequest.get(
`${await getLicenseServerUrl()}/api/license-server/v1/cloud-products?billing-cycle=${billingCycle}`
);
return res.status(200).send(data);
}
} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(200).send(data);
}
return res.status(200).send({
head: [],
rows: []
});
}
}
@@ -1,5 +1,4 @@
import { Request, Response } from "express";
import * as Sentry from "@sentry/node";
import { Secret } from "../../../models";
import { SecretVersion } from "../../models";
import { EESecretService } from "../../services";
@@ -55,29 +54,20 @@ export const getSecretVersions = async (req: Request, res: Response) => {
}
}
*/
let secretVersions;
try {
const { secretId, workspaceId, environment, folderId } = req.params;
const { secretId, workspaceId, environment, folderId } = req.params;
const offset: number = parseInt(req.query.offset as string);
const limit: number = parseInt(req.query.limit as string);
const offset: number = parseInt(req.query.offset as string);
const limit: number = parseInt(req.query.limit as string);
secretVersions = await SecretVersion.find({
secret: secretId,
workspace: workspaceId,
environment,
folder: folderId,
})
.sort({ createdAt: -1 })
.skip(offset)
.limit(limit);
} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(400).send({
message: "Failed to get secret versions",
});
}
const secretVersions = await SecretVersion.find({
secret: secretId,
workspace: workspaceId,
environment,
folder: folderId,
})
.sort({ createdAt: -1 })
.skip(offset)
.limit(limit);
return res.status(200).send({
secretVersions,
@@ -139,74 +129,45 @@ export const rollbackSecretVersion = async (req: Request, res: Response) => {
}
}
*/
let secret;
try {
const { secretId } = req.params;
const { version } = req.body;
const { secretId } = req.params;
const { version } = req.body;
// validate secret version
const oldSecretVersion = await SecretVersion.findOne({
secret: secretId,
version,
}).select("+secretBlindIndex");
// validate secret version
const oldSecretVersion = await SecretVersion.findOne({
secret: secretId,
version,
}).select("+secretBlindIndex");
if (!oldSecretVersion) throw new Error("Failed to find secret version");
if (!oldSecretVersion) throw new Error("Failed to find secret version");
const {
workspace,
type,
user,
environment,
secretBlindIndex,
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
folder,
algorithm,
keyEncoding,
} = oldSecretVersion;
const {
workspace,
type,
user,
environment,
secretBlindIndex,
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
algorithm,
folder,
keyEncoding,
} = oldSecretVersion;
// update secret
secret = await Secret.findByIdAndUpdate(
secretId,
{
$inc: {
version: 1,
},
workspace,
type,
user,
environment,
...(secretBlindIndex ? { secretBlindIndex } : {}),
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
folderId: folder,
algorithm,
keyEncoding,
// update secret
const secret = await Secret.findByIdAndUpdate(
secretId,
{
$inc: {
version: 1,
},
{
new: true,
}
);
if (!secret) throw new Error("Failed to find and update secret");
// add new secret version
await new SecretVersion({
secret: secretId,
version: secret.version,
workspace,
type,
user,
environment,
isDeleted: false,
...(secretBlindIndex ? { secretBlindIndex } : {}),
secretKeyCiphertext,
secretKeyIV,
@@ -214,24 +175,44 @@ export const rollbackSecretVersion = async (req: Request, res: Response) => {
secretValueCiphertext,
secretValueIV,
secretValueTag,
folder,
folderId: folder,
algorithm,
keyEncoding,
}).save();
},
{
new: true,
}
);
// take secret snapshot
await EESecretService.takeSecretSnapshot({
workspaceId: secret.workspace,
environment,
folderId: folder,
});
} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(400).send({
message: "Failed to roll back secret version",
});
}
if (!secret) throw new Error("Failed to find and update secret");
// add new secret version
await new SecretVersion({
secret: secretId,
version: secret.version,
workspace,
type,
user,
environment,
isDeleted: false,
...(secretBlindIndex ? { secretBlindIndex } : {}),
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
folder,
algorithm,
keyEncoding,
}).save();
// take secret snapshot
await EESecretService.takeSecretSnapshot({
workspaceId: secret.workspace,
environment,
folderId: folder,
});
return res.status(200).send({
secret,
@@ -1,5 +1,4 @@
import { Request, Response } from "express";
import * as Sentry from "@sentry/node";
import {
ISecretVersion,
SecretSnapshot,
@@ -13,23 +12,14 @@ import {
* @returns
*/
export const getSecretSnapshot = async (req: Request, res: Response) => {
let secretSnapshot;
try {
const { secretSnapshotId } = req.params;
const { secretSnapshotId } = req.params;
const secretSnapshot = await SecretSnapshot.findById(secretSnapshotId)
.lean()
.populate<{ secretVersions: ISecretVersion[] }>("secretVersions")
.populate<{ folderVersion: TFolderRootVersionSchema }>("folderVersion");
secretSnapshot = await SecretSnapshot.findById(secretSnapshotId)
.lean()
.populate<{ secretVersions: ISecretVersion[] }>("secretVersions")
.populate<{ folderVersion: TFolderRootVersionSchema }>("folderVersion");
if (!secretSnapshot) throw new Error("Failed to find secret snapshot");
if (!secretSnapshot) throw new Error("Failed to find secret snapshot");
} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(400).send({
message: "Failed to get secret snapshot",
});
}
const folderId = secretSnapshot.folderId;
// to show only the folder required secrets
secretSnapshot.secretVersions = secretSnapshot.secretVersions.filter(
@@ -1,4 +1,3 @@
import * as Sentry from '@sentry/node';
import { Request, Response } from 'express';
import Stripe from 'stripe';
import { getStripeSecretKey, getStripeWebhookSecret } from '../../../config';
@@ -10,26 +9,17 @@ import { getStripeSecretKey, getStripeWebhookSecret } from '../../../config';
* @returns
*/
export const handleWebhook = async (req: Request, res: Response) => {
let event;
try {
const stripe = new Stripe(await getStripeSecretKey(), {
apiVersion: '2022-08-01'
});
const stripe = new Stripe(await getStripeSecretKey(), {
apiVersion: '2022-08-01'
});
// check request for valid stripe signature
const sig = req.headers['stripe-signature'] as string;
event = stripe.webhooks.constructEvent(
req.body,
sig,
await getStripeWebhookSecret()
);
} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(400).send({
error: 'Failed to process webhook'
});
}
// check request for valid stripe signature
const sig = req.headers['stripe-signature'] as string;
const event = stripe.webhooks.constructEvent(
req.body,
sig,
await getStripeWebhookSecret()
);
switch (event.type) {
case '':
@@ -1,5 +1,4 @@
import { Request, Response } from "express";
import * as Sentry from "@sentry/node";
import { PipelineStage, Types } from "mongoose";
import { Secret } from "../../../models";
import {
@@ -69,29 +68,20 @@ export const getWorkspaceSecretSnapshots = async (
}
}
*/
let secretSnapshots;
try {
const { workspaceId } = req.params;
const { environment, folderId } = req.query;
const { workspaceId } = req.params;
const { environment, folderId } = req.query;
const offset: number = parseInt(req.query.offset as string);
const limit: number = parseInt(req.query.limit as string);
const offset: number = parseInt(req.query.offset as string);
const limit: number = parseInt(req.query.limit as string);
secretSnapshots = await SecretSnapshot.find({
workspace: workspaceId,
environment,
folderId: folderId || "root",
})
.sort({ createdAt: -1 })
.skip(offset)
.limit(limit);
} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(400).send({
message: "Failed to get secret snapshots",
});
}
const secretSnapshots = await SecretSnapshot.find({
workspace: workspaceId,
environment,
folderId: folderId || "root",
})
.sort({ createdAt: -1 })
.skip(offset)
.limit(limit);
return res.status(200).send({
secretSnapshots,
@@ -107,23 +97,14 @@ export const getWorkspaceSecretSnapshotsCount = async (
req: Request,
res: Response
) => {
let count;
try {
const { workspaceId } = req.params;
const { environment, folderId } = req.query;
const { workspaceId } = req.params;
const { environment, folderId } = req.query;
count = await SecretSnapshot.countDocuments({
workspace: workspaceId,
environment,
folderId: folderId || "root",
});
} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(400).send({
message: "Failed to count number of secret snapshots",
});
}
const count = await SecretSnapshot.countDocuments({
workspace: workspaceId,
environment,
folderId: folderId || "root",
});
return res.status(200).send({
count,
@@ -191,324 +172,315 @@ export const rollbackWorkspaceSecretSnapshot = async (
}
*/
let secrets;
try {
const { workspaceId } = req.params;
const { version, environment, folderId = "root" } = req.body;
const { workspaceId } = req.params;
const { version, environment, folderId = "root" } = req.body;
// validate secret snapshot
const secretSnapshot = await SecretSnapshot.findOne({
workspace: workspaceId,
version,
environment,
folderId: folderId,
// validate secret snapshot
const secretSnapshot = await SecretSnapshot.findOne({
workspace: workspaceId,
version,
environment,
folderId: folderId,
})
.populate<{ secretVersions: ISecretVersion[] }>({
path: "secretVersions",
select: "+secretBlindIndex",
})
.populate<{ secretVersions: ISecretVersion[] }>({
path: "secretVersions",
select: "+secretBlindIndex",
})
.populate<{ folderVersion: TFolderRootVersionSchema }>("folderVersion");
.populate<{ folderVersion: TFolderRootVersionSchema }>("folderVersion");
if (!secretSnapshot) throw new Error("Failed to find secret snapshot");
if (!secretSnapshot) throw new Error("Failed to find secret snapshot");
const snapshotFolderTree = secretSnapshot.folderVersion;
const latestFolderTree = await Folder.findOne({
workspace: workspaceId,
environment,
});
const snapshotFolderTree = secretSnapshot.folderVersion;
const latestFolderTree = await Folder.findOne({
workspace: workspaceId,
environment,
});
const latestFolderVersion = await FolderVersion.findOne({
environment,
workspace: workspaceId,
"nodes.id": folderId,
}).sort({ "nodes.version": -1 });
const latestFolderVersion = await FolderVersion.findOne({
environment,
workspace: workspaceId,
"nodes.id": folderId,
}).sort({ "nodes.version": -1 });
const oldSecretVersionsObj: Record<string, ISecretVersion> = {};
const secretIds: Types.ObjectId[] = [];
const folderIds: string[] = [folderId];
const oldSecretVersionsObj: Record<string, ISecretVersion> = {};
const secretIds: Types.ObjectId[] = [];
const folderIds: string[] = [folderId];
secretSnapshot.secretVersions.forEach((snapSecVer) => {
oldSecretVersionsObj[snapSecVer.secret.toString()] = snapSecVer;
secretIds.push(snapSecVer.secret);
});
secretSnapshot.secretVersions.forEach((snapSecVer) => {
oldSecretVersionsObj[snapSecVer.secret.toString()] = snapSecVer;
secretIds.push(snapSecVer.secret);
});
// the parent node from current latest one
// this will be modified according to the snapshot and latest snapshots
const newFolderTree =
latestFolderTree && searchByFolderId(latestFolderTree.nodes, folderId);
// the parent node from current latest one
// this will be modified according to the snapshot and latest snapshots
const newFolderTree =
latestFolderTree && searchByFolderId(latestFolderTree.nodes, folderId);
if (newFolderTree) {
newFolderTree.children = snapshotFolderTree?.nodes?.children || [];
const queue = [newFolderTree];
// a bfs algorithm in which we take the latest snapshots of all the folders in a level
if (newFolderTree) {
newFolderTree.children = snapshotFolderTree?.nodes?.children || [];
const queue = [newFolderTree];
// a bfs algorithm in which we take the latest snapshots of all the folders in a level
while (queue.length) {
const groupByFolderId: Record<string, TFolderSchema> = {};
// the original queue is popped out completely to get what ever in a level
// subqueue is filled with all the children thus next level folders
// subQueue will then be transfered to the oriinal queue
const subQueue: TFolderSchema[] = [];
// get everything inside a level
while (queue.length) {
const groupByFolderId: Record<string, TFolderSchema> = {};
// the original queue is popped out completely to get what ever in a level
// subqueue is filled with all the children thus next level folders
// subQueue will then be transfered to the oriinal queue
const subQueue: TFolderSchema[] = [];
// get everything inside a level
while (queue.length) {
const folder = queue.pop() as TFolderSchema;
folder.children.forEach((el) => {
folderIds.push(el.id); // push ids and data into queu
subQueue.push(el);
// to modify the original tree very fast we keep a reference object
// key with folder id and pointing to the various nodes
groupByFolderId[el.id] = el;
});
}
// get latest snapshots of all the folder
const matchWsFoldersPipeline = {
$match: {
workspace: new Types.ObjectId(workspaceId),
environment,
folderId: {
$in: Object.keys(groupByFolderId),
},
},
};
const sortByFolderIdAndVersion: PipelineStage = {
$sort: { folderId: 1, version: -1 },
};
const pickLatestVersionOfEachFolder = {
$group: {
_id: "$folderId",
latestVersion: { $first: "$version" },
doc: {
$first: "$$ROOT",
},
},
};
const populateSecVersion = {
$lookup: {
from: SecretVersion.collection.name,
localField: "doc.secretVersions",
foreignField: "_id",
as: "doc.secretVersions",
},
};
const populateFolderVersion = {
$lookup: {
from: FolderVersion.collection.name,
localField: "doc.folderVersion",
foreignField: "_id",
as: "doc.folderVersion",
},
};
const unwindFolderVerField = {
$unwind: {
path: "$doc.folderVersion",
preserveNullAndEmptyArrays: true,
},
};
const latestSnapshotsByFolders: Array<{ doc: typeof secretSnapshot }> =
await SecretSnapshot.aggregate([
matchWsFoldersPipeline,
sortByFolderIdAndVersion,
pickLatestVersionOfEachFolder,
populateSecVersion,
populateFolderVersion,
unwindFolderVerField,
]);
// recursive snapshotting each level
latestSnapshotsByFolders.forEach((snap) => {
// mutate the folder tree to update the nodes to the latest version tree
// we are reconstructing the folder tree by latest snapshots here
if (groupByFolderId[snap.doc.folderId]) {
groupByFolderId[snap.doc.folderId].children =
snap.doc?.folderVersion?.nodes?.children || [];
}
// push all children of next level snapshots
if (snap.doc.folderVersion?.nodes?.children) {
queue.push(...snap.doc.folderVersion.nodes.children);
}
snap.doc.secretVersions.forEach((snapSecVer) => {
// record all the secrets
oldSecretVersionsObj[snapSecVer.secret.toString()] = snapSecVer;
secretIds.push(snapSecVer.secret);
});
const folder = queue.pop() as TFolderSchema;
folder.children.forEach((el) => {
folderIds.push(el.id); // push ids and data into queu
subQueue.push(el);
// to modify the original tree very fast we keep a reference object
// key with folder id and pointing to the various nodes
groupByFolderId[el.id] = el;
});
queue.push(...subQueue);
}
}
// TODO: fix any
const latestSecretVersionIds = await getLatestSecretVersionIds({
secretIds,
});
// TODO: fix any
const latestSecretVersions: any = (
await SecretVersion.find(
{
_id: {
$in: latestSecretVersionIds.map((s) => s.versionId),
// get latest snapshots of all the folder
const matchWsFoldersPipeline = {
$match: {
workspace: new Types.ObjectId(workspaceId),
environment,
folderId: {
$in: Object.keys(groupByFolderId),
},
},
"secret version"
)
).reduce(
(accumulator, s) => ({
...accumulator,
[`${s.secret.toString()}`]: s,
}),
{}
);
};
const sortByFolderIdAndVersion: PipelineStage = {
$sort: { folderId: 1, version: -1 },
};
const pickLatestVersionOfEachFolder = {
$group: {
_id: "$folderId",
latestVersion: { $first: "$version" },
doc: {
$first: "$$ROOT",
},
},
};
const populateSecVersion = {
$lookup: {
from: SecretVersion.collection.name,
localField: "doc.secretVersions",
foreignField: "_id",
as: "doc.secretVersions",
},
};
const populateFolderVersion = {
$lookup: {
from: FolderVersion.collection.name,
localField: "doc.folderVersion",
foreignField: "_id",
as: "doc.folderVersion",
},
};
const unwindFolderVerField = {
$unwind: {
path: "$doc.folderVersion",
preserveNullAndEmptyArrays: true,
},
};
const latestSnapshotsByFolders: Array<{ doc: typeof secretSnapshot }> =
await SecretSnapshot.aggregate([
matchWsFoldersPipeline,
sortByFolderIdAndVersion,
pickLatestVersionOfEachFolder,
populateSecVersion,
populateFolderVersion,
unwindFolderVerField,
]);
const secDelQuery: Record<string, unknown> = {
workspace: workspaceId,
environment,
// undefined means root thus collect all secrets
};
if (folderId !== "root" && folderIds.length)
secDelQuery.folder = { $in: folderIds };
// recursive snapshotting each level
latestSnapshotsByFolders.forEach((snap) => {
// mutate the folder tree to update the nodes to the latest version tree
// we are reconstructing the folder tree by latest snapshots here
if (groupByFolderId[snap.doc.folderId]) {
groupByFolderId[snap.doc.folderId].children =
snap.doc?.folderVersion?.nodes?.children || [];
}
// delete existing secrets
await Secret.deleteMany(secDelQuery);
await Folder.deleteOne({
workspace: workspaceId,
environment,
});
// push all children of next level snapshots
if (snap.doc.folderVersion?.nodes?.children) {
queue.push(...snap.doc.folderVersion.nodes.children);
}
// add secrets
secrets = await Secret.insertMany(
Object.keys(oldSecretVersionsObj).map((sv) => {
const {
secret: secretId,
workspace,
type,
user,
environment,
secretBlindIndex,
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
createdAt,
algorithm,
keyEncoding,
folder: secFolderId,
} = oldSecretVersionsObj[sv];
return {
_id: secretId,
version: latestSecretVersions[secretId.toString()].version + 1,
workspace,
type,
user,
environment,
secretBlindIndex: secretBlindIndex ?? undefined,
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
secretCommentCiphertext: "",
secretCommentIV: "",
secretCommentTag: "",
createdAt,
algorithm,
keyEncoding,
folder: secFolderId,
};
})
);
// add secret versions
const secretV = await SecretVersion.insertMany(
secrets.map(
({
_id,
version,
workspace,
type,
user,
environment,
secretBlindIndex,
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
algorithm,
keyEncoding,
folder: secFolderId,
}) => ({
_id: new Types.ObjectId(),
secret: _id,
version,
workspace,
type,
user,
environment,
isDeleted: false,
secretBlindIndex: secretBlindIndex ?? undefined,
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
algorithm,
keyEncoding,
folder: secFolderId,
})
)
);
if (newFolderTree && latestFolderTree) {
// save the updated folder tree to the present one
newFolderTree.version = (latestFolderVersion?.nodes?.version || 0) + 1;
latestFolderTree._id = new Types.ObjectId();
latestFolderTree.isNew = true;
await latestFolderTree.save();
// create new folder version
const newFolderVersion = new FolderVersion({
workspace: workspaceId,
environment,
nodes: newFolderTree,
snap.doc.secretVersions.forEach((snapSecVer) => {
// record all the secrets
oldSecretVersionsObj[snapSecVer.secret.toString()] = snapSecVer;
secretIds.push(snapSecVer.secret);
});
});
await newFolderVersion.save();
}
// update secret versions of restored secrets as not deleted
await SecretVersion.updateMany(
queue.push(...subQueue);
}
}
// TODO: fix any
const latestSecretVersionIds = await getLatestSecretVersionIds({
secretIds,
});
// TODO: fix any
const latestSecretVersions: any = (
await SecretVersion.find(
{
secret: {
$in: Object.keys(oldSecretVersionsObj).map(
(sv) => oldSecretVersionsObj[sv].secret
),
_id: {
$in: latestSecretVersionIds.map((s) => s.versionId),
},
},
{
isDeleted: false,
}
);
"secret version"
)
).reduce(
(accumulator, s) => ({
...accumulator,
[`${s.secret.toString()}`]: s,
}),
{}
);
// take secret snapshot
await EESecretService.takeSecretSnapshot({
workspaceId: new Types.ObjectId(workspaceId),
const secDelQuery: Record<string, unknown> = {
workspace: workspaceId,
environment,
// undefined means root thus collect all secrets
};
if (folderId !== "root" && folderIds.length)
secDelQuery.folder = { $in: folderIds };
// delete existing secrets
await Secret.deleteMany(secDelQuery);
await Folder.deleteOne({
workspace: workspaceId,
environment,
});
// add secrets
const secrets = await Secret.insertMany(
Object.keys(oldSecretVersionsObj).map((sv) => {
const {
secret: secretId,
workspace,
type,
user,
environment,
secretBlindIndex,
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
createdAt,
algorithm,
keyEncoding,
folder: secFolderId,
} = oldSecretVersionsObj[sv];
return {
_id: secretId,
version: latestSecretVersions[secretId.toString()].version + 1,
workspace,
type,
user,
environment,
secretBlindIndex: secretBlindIndex ?? undefined,
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
secretCommentCiphertext: "",
secretCommentIV: "",
secretCommentTag: "",
createdAt,
algorithm,
keyEncoding,
folder: secFolderId,
};
})
);
// add secret versions
const secretV = await SecretVersion.insertMany(
secrets.map(
({
_id,
version,
workspace,
type,
user,
environment,
secretBlindIndex,
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
algorithm,
keyEncoding,
folder: secFolderId,
}) => ({
_id: new Types.ObjectId(),
secret: _id,
version,
workspace,
type,
user,
environment,
isDeleted: false,
secretBlindIndex: secretBlindIndex ?? undefined,
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag,
algorithm,
keyEncoding,
folder: secFolderId,
})
)
);
if (newFolderTree && latestFolderTree) {
// save the updated folder tree to the present one
newFolderTree.version = (latestFolderVersion?.nodes?.version || 0) + 1;
latestFolderTree._id = new Types.ObjectId();
latestFolderTree.isNew = true;
await latestFolderTree.save();
// create new folder version
const newFolderVersion = new FolderVersion({
workspace: workspaceId,
environment,
folderId,
});
} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(400).send({
message: "Failed to roll back secret snapshot",
nodes: newFolderTree,
});
await newFolderVersion.save();
}
// update secret versions of restored secrets as not deleted
await SecretVersion.updateMany(
{
secret: {
$in: Object.keys(oldSecretVersionsObj).map(
(sv) => oldSecretVersionsObj[sv].secret
),
},
},
{
isDeleted: false,
}
);
// take secret snapshot
await EESecretService.takeSecretSnapshot({
workspaceId: new Types.ObjectId(workspaceId),
environment,
folderId,
});
return res.status(200).send({
secrets,
});
@@ -587,39 +559,30 @@ export const getWorkspaceLogs = async (req: Request, res: Response) => {
}
}
*/
let logs;
try {
const { workspaceId } = req.params;
const { workspaceId } = req.params;
const offset: number = parseInt(req.query.offset as string);
const limit: number = parseInt(req.query.limit as string);
const sortBy: string = req.query.sortBy as string;
const userId: string = req.query.userId as string;
const actionNames: string = req.query.actionNames as string;
const offset: number = parseInt(req.query.offset as string);
const limit: number = parseInt(req.query.limit as string);
const sortBy: string = req.query.sortBy as string;
const userId: string = req.query.userId as string;
const actionNames: string = req.query.actionNames as string;
logs = await Log.find({
workspace: workspaceId,
...(userId ? { user: userId } : {}),
...(actionNames
? {
actionNames: {
$in: actionNames.split(","),
},
}
: {}),
})
.sort({ createdAt: sortBy === "recent" ? -1 : 1 })
.skip(offset)
.limit(limit)
.populate("actions")
.populate("user serviceAccount serviceTokenData");
} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(400).send({
message: "Failed to get workspace logs",
});
}
const logs = await Log.find({
workspace: workspaceId,
...(userId ? { user: userId } : {}),
...(actionNames
? {
actionNames: {
$in: actionNames.split(","),
},
}
: {}),
})
.sort({ createdAt: sortBy === "recent" ? -1 : 1 })
.skip(offset)
.limit(limit)
.populate("actions")
.populate("user serviceAccount serviceTokenData");
return res.status(200).send({
logs,
+20 -27
View File
@@ -1,5 +1,4 @@
import NodeCache from 'node-cache';
import * as Sentry from '@sentry/node';
import {
getLicenseKey,
getLicenseServerKey,
@@ -98,35 +97,29 @@ class EELicenseService {
const licenseServerKey = await getLicenseServerKey();
const licenseKey = await getLicenseKey();
try {
if (licenseServerKey) {
// license server key is present -> validate it
const token = await refreshLicenseServerKeyToken()
if (token) {
this.instanceType = 'cloud';
}
if (licenseServerKey) {
// license server key is present -> validate it
const token = await refreshLicenseServerKeyToken()
return;
if (token) {
this.instanceType = 'cloud';
}
if (licenseKey) {
// license key is present -> validate it
const token = await refreshLicenseKeyToken();
if (token) {
const { data: { currentPlan } } = await licenseKeyRequest.get(
`${await getLicenseServerUrl()}/api/license/v1/plan`
);
this.globalFeatureSet = currentPlan;
this.instanceType = 'enterprise-self-hosted';
}
return;
}
if (licenseKey) {
// license key is present -> validate it
const token = await refreshLicenseKeyToken();
if (token) {
const { data: { currentPlan } } = await licenseKeyRequest.get(
`${await getLicenseServerUrl()}/api/license/v1/plan`
);
this.globalFeatureSet = currentPlan;
this.instanceType = 'enterprise-self-hosted';
}
} catch (err) {
// case: self-hosted free
Sentry.setUser(null);
Sentry.captureException(err);
}
}
@@ -135,4 +128,4 @@ class EELicenseService {
}
}
export default new EELicenseService();
export default new EELicenseService();