Add eslint rule and fix as many issues as possible

This commit is contained in:
Khoa Le
2023-06-19 23:42:04 -04:00
parent e9eacc445d
commit 9d33e4756b
689 changed files with 9446 additions and 21821 deletions
+34 -34
View File
@@ -6,8 +6,8 @@
import { Key, Membership, MembershipOrg, Organization, User, Workspace } from "../models";
import { SecretService } from "../services";
import { Types } from 'mongoose';
import { getNodeEnv } from '../config';
import { Types } from "mongoose";
import { getNodeEnv } from "../config";
export const testUserEmail = "[email protected]"
export const testUserPassword = "testInfisical1"
@@ -25,71 +25,71 @@ export const createTestUserForDevelopment = async () => {
_id: testUserId,
email: testUserEmail,
refreshVersion: 0,
encryptedPrivateKey: 'ITMdDXtLoxib4+53U/qzvIV/T/UalRwimogFCXv/UsulzEoiKM+aK2aqOb0=',
firstName: 'Jake',
iv: '9fp0dZHI+UuHeKkWMDvD6w==',
lastName: 'Moni',
publicKey: 'cf44BhkybbBfsE0fZHe2jvqtCj6KLXvSq4hVjV0svzk=',
salt: 'd8099dc70958090346910fb9639262b83cf526fc9b4555a171b36a9e1bcd0240',
tag: 'bQ/UTghqcQHRoSMpLQD33g==',
verifier: '12271fcd50937ca4512e1e3166adaf9d9fc7a5cd0e4c4cb3eda89f35572ede4d9eef23f64aef9220367abff9437b0b6fa55792c442f177201d87051cf77dadade254ff667170440327355fb7d6ac4745d4db302f4843632c2ed5919ebdcff343287a4cd552255d9e3ce81177edefe089617b7616683901475d393405f554634b9bf9230c041ac85624f37a60401be20b78044932580ae0868323be3749fbf856df1518153ba375fec628275f0c445f237446ea4aa7f12c1aa1d6b5fd74b7f2e88d062845a19819ec63f2d2ed9e9f37c055149649461d997d2ae1482f53b04f9de7493efbb9686fb19b2d559b9aa2b502c22dec83f9fc43290dfea89a1dc6f03580b3642b3824513853e81a441be9a0b2fde2231bac60f3287872617a36884697805eeea673cf1a351697834484ada0f282e4745015c9c2928d61e6d092f1b9c3a27eda8413175d23bb2edae62f82ccaf52bf5a6a90344a766c7e4ebf65dae9ae90b2ad4ae65dbf16e3a6948e429771cc50307ae86d454f71a746939ed061f080dd3ae369c1a0739819aca17af46a085bac1f2a5d936d198e7951a8ac3bb38b893665fe7312835abd3f61811f81efa2a8761af5070085f9b6adcca80bf9b0d81899c3d41487fba90728bb24eceb98bd69770360a232624133700ceb4d153f2ad702e0a5b7dfaf97d20bc8aa71dc8c20024a58c06a8fecdad18cb5a2f89c51eaf7'
encryptedPrivateKey: "ITMdDXtLoxib4+53U/qzvIV/T/UalRwimogFCXv/UsulzEoiKM+aK2aqOb0=",
firstName: "Jake",
iv: "9fp0dZHI+UuHeKkWMDvD6w==",
lastName: "Moni",
publicKey: "cf44BhkybbBfsE0fZHe2jvqtCj6KLXvSq4hVjV0svzk=",
salt: "d8099dc70958090346910fb9639262b83cf526fc9b4555a171b36a9e1bcd0240",
tag: "bQ/UTghqcQHRoSMpLQD33g==",
verifier: "12271fcd50937ca4512e1e3166adaf9d9fc7a5cd0e4c4cb3eda89f35572ede4d9eef23f64aef9220367abff9437b0b6fa55792c442f177201d87051cf77dadade254ff667170440327355fb7d6ac4745d4db302f4843632c2ed5919ebdcff343287a4cd552255d9e3ce81177edefe089617b7616683901475d393405f554634b9bf9230c041ac85624f37a60401be20b78044932580ae0868323be3749fbf856df1518153ba375fec628275f0c445f237446ea4aa7f12c1aa1d6b5fd74b7f2e88d062845a19819ec63f2d2ed9e9f37c055149649461d997d2ae1482f53b04f9de7493efbb9686fb19b2d559b9aa2b502c22dec83f9fc43290dfea89a1dc6f03580b3642b3824513853e81a441be9a0b2fde2231bac60f3287872617a36884697805eeea673cf1a351697834484ada0f282e4745015c9c2928d61e6d092f1b9c3a27eda8413175d23bb2edae62f82ccaf52bf5a6a90344a766c7e4ebf65dae9ae90b2ad4ae65dbf16e3a6948e429771cc50307ae86d454f71a746939ed061f080dd3ae369c1a0739819aca17af46a085bac1f2a5d936d198e7951a8ac3bb38b893665fe7312835abd3f61811f81efa2a8761af5070085f9b6adcca80bf9b0d81899c3d41487fba90728bb24eceb98bd69770360a232624133700ceb4d153f2ad702e0a5b7dfaf97d20bc8aa71dc8c20024a58c06a8fecdad18cb5a2f89c51eaf7",
}
const testWorkspaceKey = {
_id: new Types.ObjectId(testWorkspaceKeyId),
workspace: testWorkspaceId,
encryptedKey: '96ZIRSU21CjVzIQ4Yp994FGWQvDdyK3gq+z+NCaJLK0ByTlvUePmf+AYGFJjkAdz',
nonce: '1jhCGqg9Wx3n0OtVxbDgiYYGq4S3EdgO',
sender: '63cefa6ec8d3175601cfa980',
receiver: '63cefa6ec8d3175601cfa980',
encryptedKey: "96ZIRSU21CjVzIQ4Yp994FGWQvDdyK3gq+z+NCaJLK0ByTlvUePmf+AYGFJjkAdz",
nonce: "1jhCGqg9Wx3n0OtVxbDgiYYGq4S3EdgO",
sender: "63cefa6ec8d3175601cfa980",
receiver: "63cefa6ec8d3175601cfa980",
}
const testWorkspace = {
_id: new Types.ObjectId(testWorkspaceId),
name: 'Example Project',
name: "Example Project",
organization: testOrgId,
environments: [
{
_id: '63cefb15c8d3175601cfa98a',
name: 'Development',
slug: 'dev'
_id: "63cefb15c8d3175601cfa98a",
name: "Development",
slug: "dev",
},
{
_id: '63cefb15c8d3175601cfa98b',
name: 'Test',
slug: 'test'
_id: "63cefb15c8d3175601cfa98b",
name: "Test",
slug: "test",
},
{
_id: '63cefb15c8d3175601cfa98c',
name: 'Staging',
slug: 'staging'
_id: "63cefb15c8d3175601cfa98c",
name: "Staging",
slug: "staging",
},
{
_id: '63cefb15c8d3175601cfa98d',
name: 'Production',
slug: 'prod'
}
_id: "63cefb15c8d3175601cfa98d",
name: "Production",
slug: "prod",
},
],
}
const testOrg = {
_id: testOrgId,
name: 'Jake\'s organization'
name: "Jake's organization",
}
const testMembershipOrg = {
_id: testMembershipOrgId,
organization: testOrgId,
role: 'owner',
status: 'accepted',
role: "owner",
status: "accepted",
user: testUserId,
}
const testMembership = {
_id: testMembershipId,
role: 'admin',
role: "admin",
user: testUserId,
workspace: testWorkspaceId
workspace: testWorkspaceId,
}
try {
@@ -124,7 +124,7 @@ export const createTestUserForDevelopment = async () => {
// initialize blind index salt for workspace
await SecretService.createSecretBlindIndexData({
workspaceId: workspace._id
workspaceId: workspace._id,
});
}
+10 -10
View File
@@ -1,6 +1,6 @@
import crypto = require('crypto');
import crypto = require("crypto");
const ALGORITHM = 'aes-256-gcm';
const ALGORITHM = "aes-256-gcm";
const BLOCK_SIZE_BYTES = 16;
export default class AesGCM {
@@ -13,12 +13,12 @@ export default class AesGCM {
const iv = crypto.randomBytes(BLOCK_SIZE_BYTES);
const cipher = crypto.createCipheriv(ALGORITHM, secret, iv);
let ciphertext = cipher.update(text, 'utf8', 'base64');
ciphertext += cipher.final('base64');
let ciphertext = cipher.update(text, "utf8", "base64");
ciphertext += cipher.final("base64");
return {
ciphertext,
iv: iv.toString('base64'),
tag: cipher.getAuthTag().toString('base64')
iv: iv.toString("base64"),
tag: cipher.getAuthTag().toString("base64"),
};
}
@@ -31,12 +31,12 @@ export default class AesGCM {
const decipher = crypto.createDecipheriv(
ALGORITHM,
secret,
Buffer.from(iv, 'base64')
Buffer.from(iv, "base64")
);
decipher.setAuthTag(Buffer.from(tag, 'base64'));
decipher.setAuthTag(Buffer.from(tag, "base64"));
let cleartext = decipher.update(ciphertext, 'base64', 'utf8');
cleartext += decipher.final('utf8');
let cleartext = decipher.update(ciphertext, "base64", "utf8");
cleartext += decipher.final("utf8");
return cleartext;
}
+13 -13
View File
@@ -1,22 +1,22 @@
import express from 'express';
import passport from 'passport';
import { AuthData } from '../interfaces/middleware';
import express from "express";
import passport from "passport";
import { AuthData } from "../interfaces/middleware";
import {
AuthProvider,
User,
ServiceAccount,
ServiceTokenData,
} from '../models';
import { createToken } from '../helpers/auth';
User,
} from "../models";
import { createToken } from "../helpers/auth";
import {
getClientIdGoogle,
getClientSecretGoogle,
getJwtProviderAuthLifetime,
getJwtProviderAuthSecret
} from '../config';
getJwtProviderAuthSecret,
} from "../config";
// eslint-disable-next-line @typescript-eslint/no-var-requires
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const GoogleStrategy = require("passport-google-oauth20").Strategy;
// TODO: find a more optimal folder structure to store these types of functions
@@ -68,8 +68,8 @@ const initializePassport = async () => {
passReqToCallback: true,
clientID: googleClientId,
clientSecret: googleClientSecret,
callbackURL: '/api/v1/auth/callback/google',
scope: ['profile', ' email'],
callbackURL: "/api/v1/auth/callback/google",
scope: ["profile", " email"],
}, async (
req: express.Request,
accessToken: string,
@@ -82,7 +82,7 @@ const initializePassport = async () => {
let user = await User.findOne({
authProvider: AuthProvider.GOOGLE,
authId: profile.id,
}).select('+publicKey')
}).select("+publicKey")
if (!user) {
user = await new User({
@@ -97,7 +97,7 @@ const initializePassport = async () => {
userId: user._id.toString(),
email: user.email,
authProvider: user.authProvider,
isUserCompleted: !!user.publicKey
isUserCompleted: !!user.publicKey,
},
expiresIn: await getJwtProviderAuthLifetime(),
secret: await getJwtProviderAuthSecret(),
+27 -28
View File
@@ -1,20 +1,19 @@
import crypto from 'crypto';
import nacl from 'tweetnacl';
import util from 'tweetnacl-util';
import crypto from "crypto";
import nacl from "tweetnacl";
import util from "tweetnacl-util";
import {
IGenerateKeyPairOutput,
IDecryptAsymmetricInput,
IDecryptSymmetricInput,
IEncryptAsymmetricInput,
IEncryptAsymmetricOutput,
IDecryptAsymmetricInput,
IEncryptSymmetricInput,
IDecryptSymmetricInput
} from '../../interfaces/utils';
import { BadRequestError } from '../errors';
IGenerateKeyPairOutput,
} from "../../interfaces/utils";
import { BadRequestError } from "../errors";
import {
ALGORITHM_AES_256_GCM,
NONCE_BYTES_SIZE,
BLOCK_SIZE_BYTES_16
} from '../../variables';
ALGORITHM_AES_256_GCM,
BLOCK_SIZE_BYTES_16,
} from "../../variables";
/**
* Return new base64, NaCl, public-private key pair.
@@ -27,7 +26,7 @@ const generateKeyPair = (): IGenerateKeyPairOutput => {
return ({
publicKey: util.encodeBase64(pair.publicKey),
privateKey: util.encodeBase64(pair.secretKey)
privateKey: util.encodeBase64(pair.secretKey),
});
}
@@ -45,7 +44,7 @@ const generateKeyPair = (): IGenerateKeyPairOutput => {
const encryptAsymmetric = ({
plaintext,
publicKey,
privateKey
privateKey,
}: IEncryptAsymmetricInput): IEncryptAsymmetricOutput => {
const nonce = nacl.randomBytes(24);
const ciphertext = nacl.box(
@@ -57,7 +56,7 @@ const encryptAsymmetric = ({
return {
ciphertext: util.encodeBase64(ciphertext),
nonce: util.encodeBase64(nonce)
nonce: util.encodeBase64(nonce),
};
};
@@ -75,7 +74,7 @@ const decryptAsymmetric = ({
ciphertext,
nonce,
publicKey,
privateKey
privateKey,
}: IDecryptAsymmetricInput): string => {
const plaintext: Uint8Array | null = nacl.box.open(
util.decodeBase64(ciphertext),
@@ -85,7 +84,7 @@ const decryptAsymmetric = ({
);
if (plaintext == null) throw BadRequestError({
message: 'Invalid ciphertext or keys'
message: "Invalid ciphertext or keys",
});
return util.encodeUTF8(plaintext);
@@ -108,18 +107,18 @@ const decryptAsymmetric = ({
*/
const encryptSymmetric128BitHexKeyUTF8 = ({
plaintext,
key
key,
}: IEncryptSymmetricInput) => {
const iv = crypto.randomBytes(BLOCK_SIZE_BYTES_16);
const cipher = crypto.createCipheriv(ALGORITHM_AES_256_GCM, key, iv);
let ciphertext = cipher.update(plaintext, 'utf8', 'base64');
ciphertext += cipher.final('base64');
let ciphertext = cipher.update(plaintext, "utf8", "base64");
ciphertext += cipher.final("base64");
return {
ciphertext,
iv: iv.toString('base64'),
tag: cipher.getAuthTag().toString('base64')
iv: iv.toString("base64"),
tag: cipher.getAuthTag().toString("base64"),
};
}
/**
@@ -141,18 +140,18 @@ const decryptSymmetric128BitHexKeyUTF8 = ({
ciphertext,
iv,
tag,
key
key,
}: IDecryptSymmetricInput) => {
const decipher = crypto.createDecipheriv(
ALGORITHM_AES_256_GCM,
key,
Buffer.from(iv, 'base64')
Buffer.from(iv, "base64")
);
decipher.setAuthTag(Buffer.from(tag, 'base64'));
decipher.setAuthTag(Buffer.from(tag, "base64"));
let cleartext = decipher.update(ciphertext, 'base64', 'utf8');
cleartext += decipher.final('utf8');
let cleartext = decipher.update(ciphertext, "base64", "utf8");
cleartext += decipher.final("utf8");
return cleartext;
}
@@ -162,5 +161,5 @@ export {
encryptAsymmetric,
decryptAsymmetric,
encryptSymmetric128BitHexKeyUTF8,
decryptSymmetric128BitHexKeyUTF8
decryptSymmetric128BitHexKeyUTF8,
};
+72 -72
View File
@@ -4,231 +4,231 @@ import RequestError, { LogLevel, RequestErrorContext } from "./requestError"
export const RouteNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.INFO,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'route_not_found',
message: error?.message ?? 'The requested source was not found',
type: error?.type ?? "route_not_found",
message: error?.message ?? "The requested source was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
export const MethodNotAllowedError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.INFO,
statusCode: error?.statusCode ?? 405,
type: error?.type ?? 'method_not_allowed',
message: error?.message ?? 'The requested method is not allowed for the resource',
type: error?.type ?? "method_not_allowed",
message: error?.message ?? "The requested method is not allowed for the resource",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
export const UnauthorizedRequestError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.INFO,
statusCode: error?.statusCode ?? 401,
type: error?.type ?? 'unauthorized',
message: error?.message ?? 'You are not authorized to access this resource',
type: error?.type ?? "unauthorized",
message: error?.message ?? "You are not authorized to access this resource",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
export const ForbiddenRequestError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.INFO,
statusCode: error?.statusCode ?? 403,
type: error?.type ?? 'forbidden',
message: error?.message ?? 'You are not allowed to access this resource',
type: error?.type ?? "forbidden",
message: error?.message ?? "You are not allowed to access this resource",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
export const BadRequestError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.INFO,
statusCode: error?.statusCode ?? 400,
type: error?.type ?? 'bad_request',
message: error?.message ?? 'The request is invalid or cannot be served',
type: error?.type ?? "bad_request",
message: error?.message ?? "The request is invalid or cannot be served",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
export const InternalServerError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 500,
type: error?.type ?? 'internal_server_error',
message: error?.message ?? 'The server encountered an error while processing the request',
type: error?.type ?? "internal_server_error",
message: error?.message ?? "The server encountered an error while processing the request",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
export const ServiceUnavailableError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 503,
type: error?.type ?? 'service_unavailable',
message: error?.message ?? 'The service is currently unavailable. Please try again later.',
type: error?.type ?? "service_unavailable",
message: error?.message ?? "The service is currently unavailable. Please try again later.",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
export const ValidationError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 400,
type: error?.type ?? 'validation_error',
message: error?.message ?? 'The request failed validation',
type: error?.type ?? "validation_error",
message: error?.message ?? "The request failed validation",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
//* ----->[INTEGRATION AUTH ERRORS]<-----
export const IntegrationAuthNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'integration_auth_not_found_error',
message: error?.message ?? 'The requested integration authorization was not found',
type: error?.type ?? "integration_auth_not_found_error",
message: error?.message ?? "The requested integration authorization was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
//* ----->[INTEGRATION ERRORS]<-----
export const IntegrationNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'integration_not_found_error',
message: error?.message ?? 'The requested integration was not found',
type: error?.type ?? "integration_not_found_error",
message: error?.message ?? "The requested integration was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
//* ----->[WORKSPACE ERRORS]<-----
export const WorkspaceNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'workspace_not_found_error',
message: error?.message ?? 'The requested workspace was not found',
type: error?.type ?? "workspace_not_found_error",
message: error?.message ?? "The requested workspace was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
//* ----->[WORKSPACE MEMBERSHIP ERRORS]<-----
export const MembershipNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'workspace_membership_not_found_error',
message: error?.message ?? 'The requested membership was not found',
type: error?.type ?? "workspace_membership_not_found_error",
message: error?.message ?? "The requested membership was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
//* ----->[ORGANIZATION ERRORS]<-----
export const OrganizationNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'organization_not_found_error',
message: error?.message ?? 'The requested organization was not found',
type: error?.type ?? "organization_not_found_error",
message: error?.message ?? "The requested organization was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
//* ----->[MEMBERSHIP ORGANIZATION ERRORS]<-----
export const MembershipOrgNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'organization_membership_not_found_error',
message: error?.message ?? 'The requested organization membership was not found',
type: error?.type ?? "organization_membership_not_found_error",
message: error?.message ?? "The requested organization membership was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
//* ----->[ACCOUNT ERRORS]<-----
export const AccountNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'account_not_found_error',
message: error?.message ?? 'The requested account was not found',
type: error?.type ?? "account_not_found_error",
message: error?.message ?? "The requested account was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
//* ----->[SECRET ERRORS]<-----
export const SecretNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'secret_not_found_error',
message: error?.message ?? 'The requested secret was not found',
type: error?.type ?? "secret_not_found_error",
message: error?.message ?? "The requested secret was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
//* ----->[SECRET BLIND INDEX DATA ERRORS]<-----
export const SecretBlindIndexDataNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'secret_blind_index_data_not_found_error',
message: error?.message ?? 'The requested secret was not found',
type: error?.type ?? "secret_blind_index_data_not_found_error",
message: error?.message ?? "The requested secret was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
//* ----->[SECRET SNAPSHOT ERRORS]<-----
export const SecretSnapshotNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'secret_snapshot_not_found_error',
message: error?.message ?? 'The requested secret snapshot was not found',
type: error?.type ?? "secret_snapshot_not_found_error",
message: error?.message ?? "The requested secret snapshot was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
//* ----->[ACTION ERRORS]<-----
export const ActionNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'action_not_found_error',
message: error?.message ?? 'The requested action was not found',
type: error?.type ?? "action_not_found_error",
message: error?.message ?? "The requested action was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
//* ----->[SERVICE TOKEN DATA ERRORS]<-----
export const ServiceTokenDataNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'service_token_data_not_found_error',
message: error?.message ?? 'The requested service token data was not found',
type: error?.type ?? "service_token_data_not_found_error",
message: error?.message ?? "The requested service token data was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
})
//* ----->[API KEY DATA ERRORS]<-----
export const APIKeyDataNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'api_key_data_not_found_error',
message: error?.message ?? 'The requested service token data was not found',
type: error?.type ?? "api_key_data_not_found_error",
message: error?.message ?? "The requested service token data was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
//* ----->[SERVICE_ACCOUNT ERRORS]<-----
export const ServiceAccountNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'service_account_not_found_error',
message: error?.message ?? 'The requested service account was not found',
type: error?.type ?? "service_account_not_found_error",
message: error?.message ?? "The requested service account was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
});
export const ServiceAccountKeyNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'service_account_key_not_found_error',
message: error?.message ?? 'The requested service account key was not found',
type: error?.type ?? "service_account_key_not_found_error",
message: error?.message ?? "The requested service account key was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
})
export const BotNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
logLevel: error?.logLevel ?? LogLevel.ERROR,
statusCode: error?.statusCode ?? 404,
type: error?.type ?? 'bot_not_found_error',
message: error?.message ?? 'The requested bot was not found',
type: error?.type ?? "bot_not_found_error",
message: error?.message ?? "The requested bot was not found",
context: error?.context,
stack: error?.stack
stack: error?.stack,
})
//* ----->[MISC ERRORS]<-----
+13 -13
View File
@@ -1,7 +1,7 @@
/* eslint-disable no-console */
import { createLogger, format, transports } from 'winston';
import LokiTransport from 'winston-loki';
import { getLokiHost, getNodeEnv } from '../config';
import { createLogger, format, transports } from "winston";
import LokiTransport from "winston-loki";
import { getLokiHost, getNodeEnv } from "../config";
const { combine, colorize, label, printf, splat, timestamp } = format;
@@ -13,7 +13,7 @@ const logFormat = (prefix: string) => combine(
);
const createLoggerWithLabel = async (level: string, label: string) => {
const _level = level.toLowerCase() || 'info'
const _level = level.toLowerCase() || "info"
//* Always add Console output to transports
const _transports: any[] = [
new transports.Console({
@@ -21,8 +21,8 @@ const createLoggerWithLabel = async (level: string, label: string) => {
colorize(),
logFormat(label),
// format.json()
)
})
),
}),
]
//* Add LokiTransport if it's enabled
if((await getLokiHost()) !== undefined){
@@ -40,9 +40,9 @@ const createLoggerWithLabel = async (level: string, label: string) => {
labels: {
app: process.env.npm_package_name,
version: process.env.npm_package_version,
environment: await getNodeEnv()
environment: await getNodeEnv(),
},
onConnectionError: (err: Error)=> console.error('Connection error while connecting to Loki Server.\n', err)
onConnectionError: (err: Error)=> console.error("Connection error while connecting to Loki Server.\n", err),
})
)
}
@@ -53,15 +53,15 @@ const createLoggerWithLabel = async (level: string, label: string) => {
transports: _transports,
format: format.combine(
logFormat(label),
format.metadata({ fillExcept: ['message', 'level', 'timestamp', 'label'] })
)
format.metadata({ fillExcept: ["message", "level", "timestamp", "label"] })
),
});
}
export const getLogger = async (loggerName: 'backend-main' | 'database') => {
export const getLogger = async (loggerName: "backend-main" | "database") => {
const logger = {
"backend-main": await createLoggerWithLabel('info', '[IFSC:backend-main]'),
"database": await createLoggerWithLabel('info', '[IFSC:database]'),
"backend-main": await createLoggerWithLabel("info", "[IFSC:backend-main]"),
"database": await createLoggerWithLabel("info", "[IFSC:database]"),
}
return logger[loggerName]
}
+1 -1
View File
@@ -7,7 +7,7 @@ export const getChannelFromUserAgent = function (userAgent: string | undefined)
return "cli"
} else if (userAgent == K8_OPERATOR_AGENT_NAME) {
return "k8-operator"
} else if (userAgent.toLowerCase().includes('mozilla')) {
} else if (userAgent.toLowerCase().includes("mozilla")) {
return "web"
} else {
return "other"
+13 -13
View File
@@ -1,5 +1,5 @@
import { Request } from 'express'
import { getVerboseErrorOutput } from '../config';
import { Request } from "express"
import { getVerboseErrorOutput } from "../config";
export enum LogLevel {
DEBUG = 100,
@@ -44,7 +44,7 @@ export default class RequestError extends Error{
if(stack) this.stack = stack
else Error.captureStackTrace(this, this.constructor)
this.stacktrace = this.stack?.split('\n')
this.stacktrace = this.stack?.split("\n")
}
static convertFrom(error: Error) {
@@ -52,13 +52,13 @@ export default class RequestError extends Error{
return new RequestError({
logLevel: LogLevel.ERROR,
statusCode: 500,
type: 'internal_server_error',
message: 'This error was not handled by error handler. Please report this incident to the staff',
type: "internal_server_error",
message: "This error was not handled by error handler. Please report this incident to the staff",
context: {
message: error.message,
name: error.name
name: error.name,
},
stack: error.stack
stack: error.stack,
})
}
@@ -66,7 +66,7 @@ export default class RequestError extends Error{
get levelName(){ return this._logName }
withTags(...tags: string[]|number[]){
this.context['tags'] = Object.assign(tags, this.context['tags'])
this.context["tags"] = Object.assign(tags, this.context["tags"])
return this
}
@@ -83,14 +83,14 @@ export default class RequestError extends Error{
public async format(req: Request){
let _context = Object.assign({
stacktrace: this.stacktrace
stacktrace: this.stacktrace,
}, this.context)
//* Omit sensitive information from context that can leak internal workings of this program if user is not developer
if(!(await getVerboseErrorOutput())){
_context = this._omit(_context, [
'stacktrace',
'exception',
"stacktrace",
"exception",
])
}
@@ -102,9 +102,9 @@ export default class RequestError extends Error{
level_name: this.levelName,
status_code: this.statusCode,
datetime_iso: new Date().toISOString(),
application: process.env.npm_package_name || 'unknown',
application: process.env.npm_package_name || "unknown",
request_id: req.headers["Request-Id"],
extra: this.extra
extra: this.extra,
}
return formatObject
+8 -8
View File
@@ -5,22 +5,22 @@ import { encryptSymmetric128BitHexKeyUTF8 } from "../crypto";
import { EESecretService } from "../../ee/services";
import { ISecretVersion, SecretSnapshot, SecretVersion } from "../../ee/models";
import {
Secret,
ISecret,
SecretBlindIndexData,
Workspace,
Bot,
BackupPrivateKey,
IntegrationAuth,
ServiceTokenData,
Bot,
ISecret,
Integration,
IntegrationAuth,
Secret,
SecretBlindIndexData,
ServiceTokenData,
Workspace,
} from "../../models";
import { generateKeyPair } from "../../utils/crypto";
import { client, getEncryptionKey, getRootEncryptionKey } from "../../config";
import {
ALGORITHM_AES_256_GCM,
ENCODING_SCHEME_UTF8,
ENCODING_SCHEME_BASE64,
ENCODING_SCHEME_UTF8,
} from "../../variables";
import { InternalServerError } from "../errors";
+8 -8
View File
@@ -7,24 +7,24 @@ import { createTestUserForDevelopment } from "../addDevelopmentUser";
// eslint-disable-next-line @typescript-eslint/no-var-requires
import { validateEncryptionKeysConfig } from "./validateConfig";
import {
backfillSecretVersions,
backfillBots,
backfillSecretBlindIndexData,
backfillEncryptionMetadata,
backfillSecretFolders,
backfillServiceToken,
backfillIntegration,
backfillSecretBlindIndexData,
backfillSecretFolders,
backfillSecretVersions,
backfillServiceToken,
} from "./backfillData";
import {
reencryptBotPrivateKeys,
reencryptSecretBlindIndexDataSalts,
} from "./reencryptData";
import {
getNodeEnv,
getMongoURL,
getSentryDSN,
getClientSecretGoogle,
getClientIdGoogle,
getClientSecretGoogle,
getMongoURL,
getNodeEnv,
getSentryDSN,
} from "../../config";
import { initializePassport } from "../auth";
+23 -23
View File
@@ -2,19 +2,19 @@ import {
Bot,
IBot,
ISecretBlindIndexData,
SecretBlindIndexData
} from '../../models';
import { decryptSymmetric128BitHexKeyUTF8 } from '../../utils/crypto';
SecretBlindIndexData,
} from "../../models";
import { decryptSymmetric128BitHexKeyUTF8 } from "../../utils/crypto";
import {
client,
getEncryptionKey,
getRootEncryptionKey
} from '../../config';
getRootEncryptionKey,
} from "../../config";
import {
ALGORITHM_AES_256_GCM,
ENCODING_SCHEME_BASE64,
ENCODING_SCHEME_UTF8,
ENCODING_SCHEME_BASE64
} from '../../variables';
} from "../../variables";
/**
* Re-encrypt bot private keys from hex 128-bit ENCRYPTION_KEY
@@ -28,8 +28,8 @@ export const reencryptBotPrivateKeys = async () => {
// 1: re-encrypt bot private keys under ROOT_ENCRYPTION_KEY
const bots = await Bot.find({
algorithm: ALGORITHM_AES_256_GCM,
keyEncoding: ENCODING_SCHEME_UTF8
}).select('+encryptedPrivateKey iv tag algorithm keyEncoding');
keyEncoding: ENCODING_SCHEME_UTF8,
}).select("+encryptedPrivateKey iv tag algorithm keyEncoding");
if (bots.length === 0) return;
@@ -40,28 +40,28 @@ export const reencryptBotPrivateKeys = async () => {
ciphertext: bot.encryptedPrivateKey,
iv: bot.iv,
tag: bot.tag,
key: encryptionKey
key: encryptionKey,
});
const {
ciphertext: encryptedPrivateKey,
iv,
tag
tag,
} = client.encryptSymmetric(privateKey, rootEncryptionKey);
return ({
updateOne: {
filter: {
_id: bot._id
_id: bot._id,
},
update: {
encryptedPrivateKey,
iv,
tag,
algorithm: ALGORITHM_AES_256_GCM,
keyEncoding: ENCODING_SCHEME_BASE64
}
}
keyEncoding: ENCODING_SCHEME_BASE64,
},
},
})
})
);
@@ -81,8 +81,8 @@ export const reencryptSecretBlindIndexDataSalts = async () => {
if (encryptionKey && rootEncryptionKey) {
const secretBlindIndexData = await SecretBlindIndexData.find({
algorithm: ALGORITHM_AES_256_GCM,
keyEncoding: ENCODING_SCHEME_UTF8
}).select('+encryptedSaltCiphertext +saltIV +saltTag +algorithm +keyEncoding');
keyEncoding: ENCODING_SCHEME_UTF8,
}).select("+encryptedSaltCiphertext +saltIV +saltTag +algorithm +keyEncoding");
if (secretBlindIndexData.length == 0) return;
@@ -93,28 +93,28 @@ export const reencryptSecretBlindIndexDataSalts = async () => {
ciphertext: secretBlindIndexDatum.encryptedSaltCiphertext,
iv: secretBlindIndexDatum.saltIV,
tag: secretBlindIndexDatum.saltTag,
key: encryptionKey
key: encryptionKey,
});
const {
ciphertext: encryptedSaltCiphertext,
iv: saltIV,
tag: saltTag
tag: saltTag,
} = client.encryptSymmetric(salt, rootEncryptionKey);
return ({
updateOne: {
filter: {
_id: secretBlindIndexDatum._id
_id: secretBlindIndexDatum._id,
},
update: {
encryptedSaltCiphertext,
saltIV,
saltTag,
algorithm: ALGORITHM_AES_256_GCM,
keyEncoding: ENCODING_SCHEME_BASE64
}
}
keyEncoding: ENCODING_SCHEME_BASE64,
},
},
})
})
);
+10 -10
View File
@@ -1,10 +1,10 @@
import {
getEncryptionKey,
getRootEncryptionKey
} from '../../config';
getRootEncryptionKey,
} from "../../config";
import {
InternalServerError
} from '../../utils/errors';
InternalServerError,
} from "../../utils/errors";
/**
* Validate ENCRYPTION_KEY and ROOT_ENCRYPTION_KEY. Specifically:
@@ -26,7 +26,7 @@ export const validateEncryptionKeysConfig = async () => {
(encryptionKey === undefined || encryptionKey === "") &&
(rootEncryptionKey === undefined || rootEncryptionKey === "")
) throw InternalServerError({
message: "Failed to find required root encryption key environment variable. Please make sure that you're passing in a ROOT_ENCRYPTION_KEY environment variable."
message: "Failed to find required root encryption key environment variable. Please make sure that you're passing in a ROOT_ENCRYPTION_KEY environment variable.",
});
// if (encryptionKey && encryptionKey !== '') {
@@ -44,18 +44,18 @@ export const validateEncryptionKeysConfig = async () => {
// });
// }
if (rootEncryptionKey && rootEncryptionKey !== '') {
if (rootEncryptionKey && rootEncryptionKey !== "") {
// validate [rootEncryptionKey]
const keyBuffer = Buffer.from(rootEncryptionKey, 'base64')
const decoded = keyBuffer.toString('base64');
const keyBuffer = Buffer.from(rootEncryptionKey, "base64")
const decoded = keyBuffer.toString("base64");
if (decoded !== rootEncryptionKey) throw InternalServerError({
message: 'Failed to validate that the root encryption key is correctly encoded in base64'
message: "Failed to validate that the root encryption key is correctly encoded in base64",
});
if (keyBuffer.length !== 32) throw InternalServerError({
message: 'Failed to validate that the encryption key is a 256-bit base64 string'
message: "Failed to validate that the encryption key is a 256-bit base64 string",
});
}
}