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
+89 -89
View File
@@ -1,36 +1,36 @@
import { Types } from 'mongoose';
import jwt from 'jsonwebtoken';
import bcrypt from 'bcrypt';
import { Types } from "mongoose";
import jwt from "jsonwebtoken";
import bcrypt from "bcrypt";
import {
IUser,
User,
ServiceTokenData,
ServiceAccount,
APIKeyData,
ITokenVersion,
IUser,
ServiceAccount,
ServiceTokenData,
TokenVersion,
ITokenVersion
} from '../models';
User,
} from "../models";
import {
AccountNotFoundError,
ServiceTokenDataNotFoundError,
ServiceAccountNotFoundError,
APIKeyDataNotFoundError,
AccountNotFoundError,
BadRequestError,
ServiceAccountNotFoundError,
ServiceTokenDataNotFoundError,
UnauthorizedRequestError,
BadRequestError
} from '../utils/errors';
} from "../utils/errors";
import {
getJwtAuthLifetime,
getJwtAuthSecret,
getJwtProviderAuthSecret,
getJwtRefreshLifetime,
getJwtRefreshSecret
} from '../config';
getJwtRefreshSecret,
} from "../config";
import {
AUTH_MODE_API_KEY,
AUTH_MODE_JWT,
AUTH_MODE_SERVICE_ACCOUNT,
AUTH_MODE_SERVICE_TOKEN,
AUTH_MODE_API_KEY
} from '../variables';
} from "../variables";
/**
*
@@ -39,41 +39,41 @@ import {
*/
export const validateAuthMode = ({
headers,
acceptedAuthModes
acceptedAuthModes,
}: {
headers: { [key: string]: string | string[] | undefined },
acceptedAuthModes: string[]
}) => {
const apiKey = headers['x-api-key'];
const authHeader = headers['authorization'];
const apiKey = headers["x-api-key"];
const authHeader = headers["authorization"];
let authMode, authTokenValue;
if (apiKey === undefined && authHeader === undefined) {
// case: no auth or X-API-KEY header present
throw BadRequestError({ message: 'Missing Authorization or X-API-KEY in request header.' });
throw BadRequestError({ message: "Missing Authorization or X-API-KEY in request header." });
}
if (typeof apiKey === 'string') {
if (typeof apiKey === "string") {
// case: treat request authentication type as via X-API-KEY (i.e. API Key)
authMode = AUTH_MODE_API_KEY;
authTokenValue = apiKey;
}
if (typeof authHeader === 'string') {
if (typeof authHeader === "string") {
// case: treat request authentication type as via Authorization header (i.e. either JWT or service token)
const [tokenType, tokenValue] = <[string, string]>authHeader.split(' ', 2) ?? [null, null]
const [tokenType, tokenValue] = <[string, string]>authHeader.split(" ", 2) ?? [null, null]
if (tokenType === null)
throw BadRequestError({ message: `Missing Authorization Header in the request header.` });
if (tokenType.toLowerCase() !== 'bearer')
throw BadRequestError({ message: "Missing Authorization Header in the request header." });
if (tokenType.toLowerCase() !== "bearer")
throw BadRequestError({ message: `The provided authentication type '${tokenType}' is not supported.` });
if (tokenValue === null)
throw BadRequestError({ message: 'Missing Authorization Body in the request header.' });
throw BadRequestError({ message: "Missing Authorization Body in the request header." });
switch (tokenValue.split('.', 1)[0]) {
case 'st':
switch (tokenValue.split(".", 1)[0]) {
case "st":
authMode = AUTH_MODE_SERVICE_TOKEN;
break;
case 'sa':
case "sa":
authMode = AUTH_MODE_SERVICE_ACCOUNT;
break;
default:
@@ -83,13 +83,13 @@ export const validateAuthMode = ({
authTokenValue = tokenValue;
}
if (!authMode || !authTokenValue) throw BadRequestError({ message: 'Missing valid Authorization or X-API-KEY in request header.' });
if (!authMode || !authTokenValue) throw BadRequestError({ message: "Missing valid Authorization or X-API-KEY in request header." });
if (!acceptedAuthModes.includes(authMode)) throw BadRequestError({ message: 'The provided authentication type is not supported.' });
if (!acceptedAuthModes.includes(authMode)) throw BadRequestError({ message: "The provided authentication type is not supported." });
return ({
authMode,
authTokenValue
authTokenValue,
});
}
@@ -100,7 +100,7 @@ export const validateAuthMode = ({
* @returns {User} user - user corresponding to JWT token
*/
export const getAuthUserPayload = async ({
authTokenValue
authTokenValue,
}: {
authTokenValue: string;
}) => {
@@ -109,31 +109,31 @@ export const getAuthUserPayload = async ({
);
const user = await User.findOne({
_id: new Types.ObjectId(decodedToken.userId)
}).select('+publicKey +accessVersion');
_id: new Types.ObjectId(decodedToken.userId),
}).select("+publicKey +accessVersion");
if (!user) throw AccountNotFoundError({ message: 'Failed to find user' });
if (!user) throw AccountNotFoundError({ message: "Failed to find user" });
if (!user?.publicKey) throw UnauthorizedRequestError({ message: 'Failed to authenticate user with partially set up account' });
if (!user?.publicKey) throw UnauthorizedRequestError({ message: "Failed to authenticate user with partially set up account" });
const tokenVersion = await TokenVersion.findOneAndUpdate({
_id: new Types.ObjectId(decodedToken.tokenVersionId),
user: user._id
user: user._id,
}, {
lastUsed: new Date()
lastUsed: new Date(),
});
if (!tokenVersion) throw UnauthorizedRequestError({
message: 'Failed to validate access token'
message: "Failed to validate access token",
});
if (decodedToken.accessVersion !== tokenVersion.accessVersion) throw UnauthorizedRequestError({
message: 'Failed to validate access token'
message: "Failed to validate access token",
});
return ({
user,
tokenVersionId: tokenVersion._id
tokenVersionId: tokenVersion._id,
});
}
@@ -144,41 +144,41 @@ export const getAuthUserPayload = async ({
* @returns {ServiceTokenData} serviceTokenData - service token data
*/
export const getAuthSTDPayload = async ({
authTokenValue
authTokenValue,
}: {
authTokenValue: string;
}) => {
const [_, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>authTokenValue.split('.', 3);
const [_, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>authTokenValue.split(".", 3);
let serviceTokenData = await ServiceTokenData
.findById(TOKEN_IDENTIFIER, '+secretHash +expiresAt');
.findById(TOKEN_IDENTIFIER, "+secretHash +expiresAt");
if (!serviceTokenData) {
throw ServiceTokenDataNotFoundError({ message: 'Failed to find service token data' });
throw ServiceTokenDataNotFoundError({ message: "Failed to find service token data" });
} else if (serviceTokenData?.expiresAt && new Date(serviceTokenData.expiresAt) < new Date()) {
// case: service token expired
await ServiceTokenData.findByIdAndDelete(serviceTokenData._id);
throw UnauthorizedRequestError({
message: 'Failed to authenticate expired service token'
message: "Failed to authenticate expired service token",
});
}
const isMatch = await bcrypt.compare(TOKEN_SECRET, serviceTokenData.secretHash);
if (!isMatch) throw UnauthorizedRequestError({
message: 'Failed to authenticate service token'
message: "Failed to authenticate service token",
});
serviceTokenData = await ServiceTokenData
.findOneAndUpdate({
_id: new Types.ObjectId(TOKEN_IDENTIFIER)
_id: new Types.ObjectId(TOKEN_IDENTIFIER),
}, {
lastUsed: new Date()
lastUsed: new Date(),
}, {
new: true
new: true,
})
.select('+encryptedKey +iv +tag');
.select("+encryptedKey +iv +tag");
if (!serviceTokenData) throw ServiceTokenDataNotFoundError({ message: 'Failed to find service token data' });
if (!serviceTokenData) throw ServiceTokenDataNotFoundError({ message: "Failed to find service token data" });
return serviceTokenData;
}
@@ -190,23 +190,23 @@ export const getAuthSTDPayload = async ({
* @returns {ServiceAccount} serviceAccount
*/
export const getAuthSAAKPayload = async ({
authTokenValue
authTokenValue,
}: {
authTokenValue: string;
}) => {
const [_, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>authTokenValue.split('.', 3);
const [_, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>authTokenValue.split(".", 3);
const serviceAccount = await ServiceAccount.findById(
Buffer.from(TOKEN_IDENTIFIER, 'base64').toString('hex')
).select('+secretHash');
Buffer.from(TOKEN_IDENTIFIER, "base64").toString("hex")
).select("+secretHash");
if (!serviceAccount) {
throw ServiceAccountNotFoundError({ message: 'Failed to find service account' });
throw ServiceAccountNotFoundError({ message: "Failed to find service account" });
}
const result = await bcrypt.compare(TOKEN_SECRET, serviceAccount.secretHash);
if (!result) throw UnauthorizedRequestError({
message: 'Failed to authenticate service account access key'
message: "Failed to authenticate service account access key",
});
return serviceAccount;
@@ -219,48 +219,48 @@ export const getAuthSAAKPayload = async ({
* @returns {APIKeyData} apiKeyData - API key data
*/
export const getAuthAPIKeyPayload = async ({
authTokenValue
authTokenValue,
}: {
authTokenValue: string;
}) => {
const [_, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>authTokenValue.split('.', 3);
const [_, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>authTokenValue.split(".", 3);
let apiKeyData = await APIKeyData
.findById(TOKEN_IDENTIFIER, '+secretHash +expiresAt')
.populate<{ user: IUser }>('user', '+publicKey');
.findById(TOKEN_IDENTIFIER, "+secretHash +expiresAt")
.populate<{ user: IUser }>("user", "+publicKey");
if (!apiKeyData) {
throw APIKeyDataNotFoundError({ message: 'Failed to find API key data' });
throw APIKeyDataNotFoundError({ message: "Failed to find API key data" });
} else if (apiKeyData?.expiresAt && new Date(apiKeyData.expiresAt) < new Date()) {
// case: API key expired
await APIKeyData.findByIdAndDelete(apiKeyData._id);
throw UnauthorizedRequestError({
message: 'Failed to authenticate expired API key'
message: "Failed to authenticate expired API key",
});
}
const isMatch = await bcrypt.compare(TOKEN_SECRET, apiKeyData.secretHash);
if (!isMatch) throw UnauthorizedRequestError({
message: 'Failed to authenticate API key'
message: "Failed to authenticate API key",
});
apiKeyData = await APIKeyData.findOneAndUpdate({
_id: new Types.ObjectId(TOKEN_IDENTIFIER)
_id: new Types.ObjectId(TOKEN_IDENTIFIER),
}, {
lastUsed: new Date()
lastUsed: new Date(),
}, {
new: true
new: true,
});
if (!apiKeyData) {
throw APIKeyDataNotFoundError({ message: 'Failed to find API key data' });
throw APIKeyDataNotFoundError({ message: "Failed to find API key data" });
}
const user = await User.findById(apiKeyData.user).select('+publicKey');
const user = await User.findById(apiKeyData.user).select("+publicKey");
if (!user) {
throw AccountNotFoundError({
message: 'Failed to find user'
message: "Failed to find user",
});
}
@@ -278,7 +278,7 @@ export const getAuthAPIKeyPayload = async ({
export const issueAuthTokens = async ({
userId,
ip,
userAgent
userAgent,
}: {
userId: Types.ObjectId;
ip: string;
@@ -290,7 +290,7 @@ export const issueAuthTokens = async ({
tokenVersion = await TokenVersion.findOne({
user: userId,
ip,
userAgent
userAgent,
});
if (!tokenVersion) {
@@ -302,7 +302,7 @@ export const issueAuthTokens = async ({
accessVersion: 0,
ip,
userAgent,
lastUsed: new Date()
lastUsed: new Date(),
}).save();
}
@@ -311,25 +311,25 @@ export const issueAuthTokens = async ({
payload: {
userId,
tokenVersionId: tokenVersion._id.toString(),
accessVersion: tokenVersion.accessVersion
accessVersion: tokenVersion.accessVersion,
},
expiresIn: await getJwtAuthLifetime(),
secret: await getJwtAuthSecret()
secret: await getJwtAuthSecret(),
});
const refreshToken = createToken({
payload: {
userId,
tokenVersionId: tokenVersion._id.toString(),
refreshVersion: tokenVersion.refreshVersion
refreshVersion: tokenVersion.refreshVersion,
},
expiresIn: await getJwtRefreshLifetime(),
secret: await getJwtRefreshSecret()
secret: await getJwtRefreshSecret(),
});
return {
token,
refreshToken
refreshToken,
};
};
@@ -342,12 +342,12 @@ export const clearTokens = async (tokenVersionId: Types.ObjectId): Promise<void>
// increment refreshVersion on user by 1
await TokenVersion.findOneAndUpdate({
_id: tokenVersionId
_id: tokenVersionId,
}, {
$inc: {
refreshVersion: 1,
accessVersion: 1
}
accessVersion: 1,
},
});
};
@@ -362,14 +362,14 @@ export const clearTokens = async (tokenVersionId: Types.ObjectId): Promise<void>
export const createToken = ({
payload,
expiresIn,
secret
secret,
}: {
payload: any;
expiresIn: string | number;
secret: string;
}) => {
return jwt.sign(payload, secret, {
expiresIn
expiresIn,
});
};
@@ -383,7 +383,7 @@ export const validateProviderAuthToken = async ({
providerAuthToken?: string;
}) => {
if (!providerAuthToken) {
throw new Error('Invalid authentication request.');
throw new Error("Invalid authentication request.");
}
const decodedToken = <jwt.ProviderAuthJwtPayload>(
@@ -394,6 +394,6 @@ export const validateProviderAuthToken = async ({
decodedToken.authProvider !== user.authProvider ||
decodedToken.email !== email
) {
throw new Error('Invalid authentication credentials.')
throw new Error("Invalid authentication credentials.")
}
}
+7 -7
View File
@@ -1,18 +1,18 @@
import { Types } from "mongoose";
import { Bot, BotKey, Secret, ISecret, IUser } from "../models";
import { Bot, BotKey, ISecret, IUser, Secret } from "../models";
import {
generateKeyPair,
encryptSymmetric128BitHexKeyUTF8,
decryptSymmetric128BitHexKeyUTF8,
decryptAsymmetric,
decryptSymmetric128BitHexKeyUTF8,
encryptSymmetric128BitHexKeyUTF8,
generateKeyPair,
} from "../utils/crypto";
import {
SECRET_SHARED,
ALGORITHM_AES_256_GCM,
ENCODING_SCHEME_UTF8,
ENCODING_SCHEME_BASE64,
ENCODING_SCHEME_UTF8,
SECRET_SHARED,
} from "../variables";
import { getEncryptionKey, getRootEncryptionKey, client } from "../config";
import { client, getEncryptionKey, getRootEncryptionKey } from "../config";
import { InternalServerError } from "../utils/errors";
import Folder from "../models/folder";
import { getFolderByPath } from "../services/FolderService";
+7 -7
View File
@@ -1,5 +1,5 @@
import mongoose from 'mongoose';
import { getLogger } from '../utils/logger';
import mongoose from "mongoose";
import { getLogger } from "../utils/logger";
/**
* Initialize database connection
@@ -8,7 +8,7 @@ import { getLogger } from '../utils/logger';
* @returns
*/
export const initDatabaseHelper = async ({
mongoURL
mongoURL,
}: {
mongoURL: string;
}) => {
@@ -16,7 +16,7 @@ export const initDatabaseHelper = async ({
await mongoose.connect(mongoURL);
// allow empty strings to pass the required validator
mongoose.Schema.Types.String.checkRequired(v => typeof v === 'string');
mongoose.Schema.Types.String.checkRequired(v => typeof v === "string");
(await getLogger("database")).info("Database connection established");
@@ -35,10 +35,10 @@ export const closeDatabaseHelper = async () => {
new Promise((resolve) => {
if (mongoose.connection && mongoose.connection.readyState == 1) {
mongoose.connection.close()
.then(() => resolve('Database connection closed'));
.then(() => resolve("Database connection closed"));
} else {
resolve('Database connection already closed');
resolve("Database connection already closed");
}
})
}),
]);
}
+1 -1
View File
@@ -1,5 +1,5 @@
import { Types } from "mongoose";
import { Bot, IBot } from "../models";
import { Bot } from "../models";
import { EVENT_PUSH_SECRETS } from "../variables";
import { IntegrationService } from "../services";
+17 -17
View File
@@ -1,17 +1,17 @@
export * from './auth';
export * from './bot';
export * from './database';
export * from './event';
export * from './integration';
export * from './key';
export * from './membership';
export * from './membershipOrg';
export * from './nodemailer';
export * from './organization';
export * from './rateLimiter';
export * from './secret';
export * from './secrets';
export * from './signup';
export * from './token';
export * from './user';
export * from './workspace';
export * from "./auth";
export * from "./bot";
export * from "./database";
export * from "./event";
export * from "./integration";
export * from "./key";
export * from "./membership";
export * from "./membershipOrg";
export * from "./nodemailer";
export * from "./organization";
export * from "./rateLimiter";
export * from "./secret";
export * from "./secrets";
export * from "./signup";
export * from "./token";
export * from "./user";
export * from "./workspace";
+2 -2
View File
@@ -3,10 +3,10 @@ import { Bot, Integration, IntegrationAuth } from "../models";
import { exchangeCode, exchangeRefresh, syncSecrets } from "../integrations";
import { BotService } from "../services";
import {
INTEGRATION_VERCEL,
INTEGRATION_NETLIFY,
ALGORITHM_AES_256_GCM,
ENCODING_SCHEME_UTF8,
INTEGRATION_NETLIFY,
INTEGRATION_VERCEL,
} from "../variables";
import { UnauthorizedRequestError } from "../utils/errors";
+5 -5
View File
@@ -1,4 +1,4 @@
import { Key, IKey } from '../models';
import { IKey, Key } from "../models";
interface Key {
encryptedKey: string;
@@ -20,7 +20,7 @@ interface Key {
export const pushKeys = async ({
userId,
workspaceId,
keys
keys,
}: {
userId: string;
workspaceId: string;
@@ -31,9 +31,9 @@ export const pushKeys = async ({
(
await Key.find(
{
workspace: workspaceId
workspace: workspaceId,
},
'receiver'
"receiver"
)
).map((k: IKey) => k.receiver.toString())
);
@@ -47,7 +47,7 @@ export const pushKeys = async ({
nonce: k.nonce,
sender: userId,
receiver: k.userId,
workspace: workspaceId
workspace: workspaceId,
}))
);
};
+4 -4
View File
@@ -1,6 +1,6 @@
import { Types } from "mongoose";
import { Membership, Key } from "../models";
import { MembershipNotFoundError, BadRequestError } from "../utils/errors";
import { Key, Membership } from "../models";
import { BadRequestError, MembershipNotFoundError } from "../utils/errors";
/**
* Validate that user with id [userId] is a member of workspace with id [workspaceId]
@@ -62,7 +62,7 @@ export const findMembership = async (queryObj: any) => {
export const addMemberships = async ({
userIds,
workspaceId,
roles
roles,
}: {
userIds: string[];
workspaceId: string;
@@ -95,7 +95,7 @@ export const addMemberships = async ({
*/
export const deleteMembership = async ({ membershipId }: { membershipId: string }) => {
const deletedMembership = await Membership.findOneAndDelete({
_id: membershipId
_id: membershipId,
});
// delete keys associated with the membership
+27 -27
View File
@@ -1,14 +1,14 @@
import { Types } from 'mongoose';
import { Types } from "mongoose";
import {
MembershipOrg,
Workspace,
Key,
Membership,
Key
} from '../models';
MembershipOrg,
Workspace,
} from "../models";
import {
MembershipOrgNotFoundError,
UnauthorizedRequestError
} from '../utils/errors';
UnauthorizedRequestError,
} from "../utils/errors";
/**
* Validate that user with id [userId] is a member of organization with id [organizationId]
@@ -22,31 +22,31 @@ export const validateMembershipOrg = async ({
userId,
organizationId,
acceptedRoles,
acceptedStatuses
acceptedStatuses,
}: {
userId: Types.ObjectId;
organizationId: Types.ObjectId;
acceptedRoles?: Array<'owner' | 'admin' | 'member'>;
acceptedStatuses?: Array<'invited' | 'accepted'>;
acceptedRoles?: Array<"owner" | "admin" | "member">;
acceptedStatuses?: Array<"invited" | "accepted">;
}) => {
const membershipOrg = await MembershipOrg.findOne({
user: userId,
organization: organizationId
organization: organizationId,
});
if (!membershipOrg) {
throw MembershipOrgNotFoundError({ message: 'Failed to find organization membership' });
throw MembershipOrgNotFoundError({ message: "Failed to find organization membership" });
}
if (acceptedRoles) {
if (!acceptedRoles.includes(membershipOrg.role)) {
throw UnauthorizedRequestError({ message: 'Failed to validate organization membership role' });
throw UnauthorizedRequestError({ message: "Failed to validate organization membership role" });
}
}
if (acceptedStatuses) {
if (!acceptedStatuses.includes(membershipOrg.status)) {
throw UnauthorizedRequestError({ message: 'Failed to validate organization membership status' });
throw UnauthorizedRequestError({ message: "Failed to validate organization membership status" });
}
}
@@ -76,7 +76,7 @@ export const addMembershipsOrg = async ({
userIds,
organizationId,
roles,
statuses
statuses,
}: {
userIds: string[];
organizationId: string;
@@ -90,16 +90,16 @@ export const addMembershipsOrg = async ({
user: userId,
organization: organizationId,
role: roles[idx],
status: statuses[idx]
status: statuses[idx],
},
update: {
user: userId,
organization: organizationId,
role: roles[idx],
status: statuses[idx]
status: statuses[idx],
},
upsert: true
}
upsert: true,
},
};
});
@@ -112,15 +112,15 @@ export const addMembershipsOrg = async ({
* @param {String} obj.membershipOrgId - id of organization membership to delete
*/
export const deleteMembershipOrg = async ({
membershipOrgId
membershipOrgId,
}: {
membershipOrgId: string;
}) => {
const deletedMembershipOrg = await MembershipOrg.findOneAndDelete({
_id: membershipOrgId
_id: membershipOrgId,
});
if (!deletedMembershipOrg) throw new Error('Failed to delete organization membership');
if (!deletedMembershipOrg) throw new Error("Failed to delete organization membership");
// delete keys associated with organization membership
if (deletedMembershipOrg?.user) {
@@ -128,22 +128,22 @@ export const deleteMembershipOrg = async ({
const workspaces = (
await Workspace.find({
organization: deletedMembershipOrg.organization
organization: deletedMembershipOrg.organization,
})
).map((w) => w._id.toString());
await Membership.deleteMany({
user: deletedMembershipOrg.user,
workspace: {
$in: workspaces
}
$in: workspaces,
},
});
await Key.deleteMany({
receiver: deletedMembershipOrg.user,
workspace: {
$in: workspaces
}
$in: workspaces,
},
});
}
+10 -10
View File
@@ -1,8 +1,8 @@
import fs from 'fs';
import path from 'path';
import handlebars from 'handlebars';
import nodemailer from 'nodemailer';
import { getSmtpFromName, getSmtpFromAddress, getSmtpConfigured } from '../config';
import fs from "fs";
import path from "path";
import handlebars from "handlebars";
import nodemailer from "nodemailer";
import { getSmtpConfigured, getSmtpFromAddress, getSmtpFromName } from "../config";
let smtpTransporter: nodemailer.Transporter;
@@ -17,7 +17,7 @@ export const sendMail = async ({
template,
subjectLine,
recipients,
substitutions
substitutions,
}: {
template: string;
subjectLine: string;
@@ -26,17 +26,17 @@ export const sendMail = async ({
}) => {
if (await getSmtpConfigured()) {
const html = fs.readFileSync(
path.resolve(__dirname, '../templates/' + template),
'utf8'
path.resolve(__dirname, "../templates/" + template),
"utf8"
);
const temp = handlebars.compile(html);
const htmlToSend = temp(substitutions);
await smtpTransporter.sendMail({
from: `"${await getSmtpFromName()}" <${await getSmtpFromAddress()}>`,
to: recipients.join(', '),
to: recipients.join(", "),
subject: subjectLine,
html: htmlToSend
html: htmlToSend,
});
}
};
+15 -15
View File
@@ -1,25 +1,25 @@
import Stripe from "stripe";
import { Types } from "mongoose";
import { Organization, MembershipOrg } from "../models";
import { MembershipOrg, Organization } from "../models";
import {
ACCEPTED
ACCEPTED,
} from "../variables";
import {
getStripeSecretKey,
getStripeProductPro,
getStripeProductTeam,
getStripeProductStarter,
getStripeProductTeam,
getStripeSecretKey,
} from "../config";
import {
EELicenseService
} from '../ee/services';
EELicenseService,
} from "../ee/services";
import {
getLicenseServerUrl
} from '../config';
getLicenseServerUrl,
} from "../config";
import {
licenseKeyRequest,
licenseServerKeyRequest,
licenseKeyRequest
} from '../config/request';
} from "../config/request";
/**
* Create an organization with name [name]
@@ -137,7 +137,7 @@ export const updateSubscriptionOrgQuantity = async ({
});
if (organization && organization.customerId) {
if (EELicenseService.instanceType === 'cloud') {
if (EELicenseService.instanceType === "cloud") {
// instance of Infisical is a cloud instance
const quantity = await MembershipOrg.countDocuments({
organization: new Types.ObjectId(organizationId),
@@ -147,7 +147,7 @@ export const updateSubscriptionOrgQuantity = async ({
await licenseServerKeyRequest.patch(
`${await getLicenseServerUrl()}/api/license-server/v1/customers/${organization.customerId}/cloud-plan`,
{
quantity
quantity,
}
);
@@ -155,17 +155,17 @@ export const updateSubscriptionOrgQuantity = async ({
}
}
if (EELicenseService.instanceType === 'enterprise-self-hosted') {
if (EELicenseService.instanceType === "enterprise-self-hosted") {
// instance of Infisical is an enterprise self-hosted instance
const usedSeats = await MembershipOrg.countDocuments({
status: ACCEPTED
status: ACCEPTED,
});
await licenseKeyRequest.patch(
`${await getLicenseServerUrl()}/api/license/v1/license`,
{
usedSeats
usedSeats,
}
);
}
+6 -6
View File
@@ -1,4 +1,4 @@
import rateLimit from 'express-rate-limit';
import rateLimit from "express-rate-limit";
// const MongoStore = require('rate-limit-mongo');
// 200 per minute
@@ -14,11 +14,11 @@ export const apiLimiter = rateLimit({
standardHeaders: true,
legacyHeaders: false,
skip: (request) => {
return request.path === '/healthcheck' || request.path === '/api/status'
return request.path === "/healthcheck" || request.path === "/api/status"
},
keyGenerator: (req, res) => {
return req.realIP
}
},
});
// 50 requests per 1 hours
@@ -35,7 +35,7 @@ const authLimit = rateLimit({
legacyHeaders: false,
keyGenerator: (req, res) => {
return req.realIP
}
},
});
// 5 requests per 1 hour
@@ -52,11 +52,11 @@ export const passwordLimiter = rateLimit({
legacyHeaders: false,
keyGenerator: (req, res) => {
return req.realIP
}
},
});
export const authLimiter = (req: any, res: any, next: any) => {
if (process.env.NODE_ENV === 'production') {
if (process.env.NODE_ENV === "production") {
authLimit(req, res, next);
} else {
next();
+5 -5
View File
@@ -1,16 +1,16 @@
import { Types } from "mongoose";
import { Secret, ISecret } from "../models";
import { EESecretService, EELogService } from "../ee/services";
import { ISecret, Secret } from "../models";
import { EELogService, EESecretService } from "../ee/services";
import { IAction, SecretVersion } from "../ee/models";
import {
SECRET_SHARED,
SECRET_PERSONAL,
ACTION_ADD_SECRETS,
ACTION_UPDATE_SECRETS,
ACTION_DELETE_SECRETS,
ACTION_READ_SECRETS,
ACTION_UPDATE_SECRETS,
ALGORITHM_AES_256_GCM,
ENCODING_SCHEME_UTF8,
SECRET_PERSONAL,
SECRET_SHARED,
} from "../variables";
interface V1PushSecret {
+23 -23
View File
@@ -1,45 +1,45 @@
import { Types } from "mongoose";
import {
CreateSecretParams,
GetSecretsParams,
GetSecretParams,
UpdateSecretParams,
DeleteSecretParams,
} from '../interfaces/services/SecretService';
GetSecretParams,
GetSecretsParams,
UpdateSecretParams,
} from "../interfaces/services/SecretService";
import {
Secret,
ISecret,
Secret,
SecretBlindIndexData,
ServiceTokenData,
} from "../models";
import { SecretVersion } from "../ee/models";
import {
BadRequestError,
SecretNotFoundError,
SecretBlindIndexDataNotFoundError,
InternalServerError,
SecretBlindIndexDataNotFoundError,
SecretNotFoundError,
UnauthorizedRequestError,
} from "../utils/errors";
import {
SECRET_PERSONAL,
SECRET_SHARED,
ACTION_ADD_SECRETS,
ACTION_DELETE_SECRETS,
ACTION_READ_SECRETS,
ACTION_UPDATE_SECRETS,
ACTION_DELETE_SECRETS,
ALGORITHM_AES_256_GCM,
ENCODING_SCHEME_UTF8,
ENCODING_SCHEME_BASE64,
ENCODING_SCHEME_UTF8,
SECRET_PERSONAL,
SECRET_SHARED,
} from "../variables";
import crypto from "crypto";
import * as argon2 from "argon2";
import {
encryptSymmetric128BitHexKeyUTF8,
decryptSymmetric128BitHexKeyUTF8,
} from '../utils/crypto';
import { TelemetryService } from '../services';
import { getEncryptionKey, client, getRootEncryptionKey } from "../config";
import { EESecretService, EELogService } from "../ee/services";
encryptSymmetric128BitHexKeyUTF8,
} from "../utils/crypto";
import { TelemetryService } from "../services";
import { client, getEncryptionKey, getRootEncryptionKey } from "../config";
import { EELogService, EESecretService } from "../ee/services";
import {
getAuthDataPayloadIdObj,
getAuthDataPayloadUserObj,
@@ -56,7 +56,7 @@ import { getFolderIdFromServiceToken } from "../services/FolderService";
*/
export const repackageSecretToRaw = ({
secret,
key
key,
}: {
secret: ISecret;
key: string;
@@ -66,24 +66,24 @@ export const repackageSecretToRaw = ({
ciphertext: secret.secretKeyCiphertext,
iv: secret.secretKeyIV,
tag: secret.secretKeyTag,
key
key,
});
const secretValue = decryptSymmetric128BitHexKeyUTF8({
ciphertext: secret.secretValueCiphertext,
iv: secret.secretValueIV,
tag: secret.secretValueTag,
key
key,
});
let secretComment: string = '';
let secretComment = "";
if (secret.secretCommentCiphertext && secret.secretCommentIV && secret.secretCommentTag) {
secretComment = decryptSymmetric128BitHexKeyUTF8({
ciphertext: secret.secretCommentCiphertext,
iv: secret.secretCommentIV,
tag: secret.secretCommentTag,
key
key,
});
}
@@ -96,7 +96,7 @@ export const repackageSecretToRaw = ({
user: secret.user,
secretKey,
secretValue,
secretComment
secretComment,
});
}
@@ -944,6 +944,6 @@ export const deleteSecretHelper = async ({
return ({
secrets,
secret
secret,
});
};
+17 -17
View File
@@ -1,10 +1,10 @@
import { IUser } from '../models';
import { createOrganization } from './organization';
import { addMembershipsOrg } from './membershipOrg';
import { OWNER, ACCEPTED } from '../variables';
import { sendMail } from '../helpers/nodemailer';
import { TokenService } from '../services';
import { TOKEN_EMAIL_CONFIRMATION } from '../variables';
import { IUser } from "../models";
import { createOrganization } from "./organization";
import { addMembershipsOrg } from "./membershipOrg";
import { ACCEPTED, OWNER } from "../variables";
import { sendMail } from "../helpers/nodemailer";
import { TokenService } from "../services";
import { TOKEN_EMAIL_CONFIRMATION } from "../variables";
/**
* Send magic link to verify email to [email]
@@ -16,17 +16,17 @@ import { TOKEN_EMAIL_CONFIRMATION } from '../variables';
export const sendEmailVerification = async ({ email }: { email: string }) => {
const token = await TokenService.createToken({
type: TOKEN_EMAIL_CONFIRMATION,
email
email,
});
// send mail
await sendMail({
template: 'emailVerification.handlebars',
subjectLine: 'Infisical confirmation code',
template: "emailVerification.handlebars",
subjectLine: "Infisical confirmation code",
recipients: [email],
substitutions: {
code: token
}
code: token,
},
});
};
@@ -38,7 +38,7 @@ export const sendEmailVerification = async ({ email }: { email: string }) => {
*/
export const checkEmailVerification = async ({
email,
code
code,
}: {
email: string;
code: string;
@@ -46,7 +46,7 @@ export const checkEmailVerification = async ({
await TokenService.validateToken({
type: TOKEN_EMAIL_CONFIRMATION,
email,
token: code
token: code,
});
};
@@ -59,7 +59,7 @@ export const checkEmailVerification = async ({
*/
export const initializeDefaultOrg = async ({
organizationName,
user
user,
}: {
organizationName: string;
user: IUser;
@@ -69,14 +69,14 @@ export const initializeDefaultOrg = async ({
// subscription
const organization = await createOrganization({
email: user.email,
name: organizationName
name: organizationName,
});
await addMembershipsOrg({
userIds: [user._id.toString()],
organizationId: organization._id.toString(),
roles: [OWNER],
statuses: [ACCEPTED]
statuses: [ACCEPTED],
});
} catch (err) {
throw new Error(`Failed to initialize default organization and workspace [err=${err}]`);
+12 -12
View File
@@ -1,8 +1,8 @@
import {
IUser,
User,
} from '../models';
import { sendMail } from './nodemailer';
} from "../models";
import { sendMail } from "./nodemailer";
/**
* Initialize a user under email [email]
@@ -12,7 +12,7 @@ import { sendMail } from './nodemailer';
*/
export const setupAccount = async ({ email }: { email: string }) => {
const user = await new User({
email
email,
}).save();
return user;
@@ -49,7 +49,7 @@ export const completeAccount = async ({
encryptedPrivateKeyIV,
encryptedPrivateKeyTag,
salt,
verifier
verifier,
}: {
userId: string;
firstName: string;
@@ -66,7 +66,7 @@ export const completeAccount = async ({
verifier: string;
}) => {
const options = {
new: true
new: true,
};
const user = await User.findByIdAndUpdate(
userId,
@@ -82,7 +82,7 @@ export const completeAccount = async ({
iv: encryptedPrivateKeyIV,
tag: encryptedPrivateKeyTag,
salt,
verifier
verifier,
},
options
);
@@ -100,7 +100,7 @@ export const completeAccount = async ({
export const checkUserDevice = async ({
user,
ip,
userAgent
userAgent,
}: {
user: IUser;
ip: string;
@@ -114,22 +114,22 @@ export const checkUserDevice = async ({
user.devices = user.devices.concat([{
ip: String(ip),
userAgent
userAgent,
}]);
await user.save();
// send MFA code [code] to [email]
await sendMail({
template: 'newDevice.handlebars',
subjectLine: `Successful login from new device`,
template: "newDevice.handlebars",
subjectLine: "Successful login from new device",
recipients: [user.email],
substitutions: {
email: user.email,
timestamp: new Date().toString(),
ip,
userAgent
}
userAgent,
},
});
}
}
+16 -16
View File
@@ -1,13 +1,13 @@
import {
Workspace,
Bot,
Membership,
Key,
Secret
} from '../models';
import { createBot } from '../helpers/bot';
import { EELicenseService } from '../ee/services';
import { SecretService } from '../services';
Membership,
Secret,
Workspace,
} from "../models";
import { createBot } from "../helpers/bot";
import { EELicenseService } from "../ee/services";
import { SecretService } from "../services";
/**
* Create a workspace with name [name] in organization with id [organizationId]
@@ -18,7 +18,7 @@ import { SecretService } from '../services';
*/
export const createWorkspace = async ({
name,
organizationId
organizationId,
}: {
name: string;
organizationId: string;
@@ -27,18 +27,18 @@ export const createWorkspace = async ({
const workspace = await new Workspace({
name,
organization: organizationId,
autoCapitalization: true
autoCapitalization: true,
}).save();
// initialize bot for workspace
await createBot({
name: 'Infisical Bot',
workspaceId: workspace._id
name: "Infisical Bot",
workspaceId: workspace._id,
});
// initialize blind index salt for workspace
await SecretService.createSecretBlindIndexData({
workspaceId: workspace._id
workspaceId: workspace._id,
});
await EELicenseService.refreshPlan(organizationId);
@@ -55,15 +55,15 @@ export const createWorkspace = async ({
export const deleteWorkspace = async ({ id }: { id: string }) => {
await Workspace.deleteOne({ _id: id });
await Bot.deleteOne({
workspace: id
workspace: id,
});
await Membership.deleteMany({
workspace: id
workspace: id,
});
await Secret.deleteMany({
workspace: id
workspace: id,
});
await Key.deleteMany({
workspace: id
workspace: id,
});
};