Implement preliminary pentest remediations

This commit is contained in:
Tuan Dang
2023-06-05 00:44:10 +01:00
parent 4865b69e6d
commit 0c18bd71c4
14 changed files with 3592 additions and 22 deletions
+1 -1
View File
@@ -89,7 +89,7 @@ export const login2 = async (req: Request, res: Response) => {
const { email, clientProof } = req.body;
const user = await User.findOne({
email
}).select('+salt +verifier +publicKey +encryptedPrivateKey +iv +tag');
}).select('+salt +verifier +publicKey +encryptedPrivateKey +iv +tag +devices');
if (!user) throw new Error('Failed to find user');
@@ -7,8 +7,10 @@ import { createToken } from '../../helpers/auth';
import { updateSubscriptionOrgQuantity } from '../../helpers/organization';
import { sendMail } from '../../helpers/nodemailer';
import { TokenService } from '../../services';
import { EELicenseService } from '../../ee/services';
import { OWNER, ADMIN, MEMBER, ACCEPTED, INVITED, TOKEN_EMAIL_ORG_INVITATION } from '../../variables';
import { getSiteURL, getJwtSignupLifetime, getJwtSignupSecret, getSmtpConfigured } from '../../config';
import { validateUserEmail } from '../../validation';
/**
* Delete organization membership with id [membershipOrgId] from organization
@@ -115,6 +117,19 @@ export const inviteUserToOrganization = async (req: Request, res: Response) => {
if (!membershipOrg) {
throw new Error('Failed to validate organization membership');
}
const plan = await EELicenseService.getOrganizationPlan(organizationId);
if (plan.memberLimit !== null) {
// case: limit imposed on number of members allowed
if (plan.membersUsed >= plan.memberLimit) {
// case: number of members used exceeds the number of members allowed
return res.status(400).send({
message: 'Failed to invite member due to member limit reached. Upgrade plan to invite more members.'
});
}
}
invitee = await User.findOne({
email: inviteeEmail
@@ -153,6 +168,9 @@ export const inviteUserToOrganization = async (req: Request, res: Response) => {
if (!inviteeMembershipOrg) {
// case: invitee has never been invited before
// validate that email is not disposable
validateUserEmail(inviteeEmail);
await new MembershipOrg({
inviteEmail: inviteeEmail,
@@ -28,7 +28,7 @@ export const emailPasswordReset = async (req: Request, res: Response) => {
// case: user has already completed account
return res.status(403).send({
error: 'Failed to send email verification for password reset'
message: "If an account exists with this email, a password reset link has been sent"
});
}
@@ -56,7 +56,7 @@ export const emailPasswordReset = async (req: Request, res: Response) => {
}
return res.status(200).send({
message: `Sent an email for account recovery to ${email}`
message:"If an account exists with this email, a password reset link has been sent"
});
}
@@ -8,6 +8,7 @@ import {
import { createToken } from '../../helpers/auth';
import { BadRequestError } from '../../utils/errors';
import { getInviteOnlySignup, getJwtSignupLifetime, getJwtSignupSecret, getSmtpConfigured } from '../../config';
import { validateUserEmail } from '../../validation';
/**
* Signup step 1: Initialize account for user under email [email] and send a verification code
@@ -20,6 +21,9 @@ export const beginEmailSignup = async (req: Request, res: Response) => {
let email: string;
try {
email = req.body.email;
// validate that email is not disposable
validateUserEmail(email);
const user = await User.findOne({ email }).select('+publicKey');
if (user && user?.publicKey) {
@@ -14,6 +14,7 @@ import {
createWorkspace as create,
deleteWorkspace as deleteWork,
} from "../../helpers/workspace";
import { EELicenseService } from '../../ee/services';
import { addMemberships } from "../../helpers/membership";
import { ADMIN } from "../../variables";
@@ -141,6 +142,7 @@ export const getWorkspace = async (req: Request, res: Response) => {
*/
export const createWorkspace = async (req: Request, res: Response) => {
let workspace;
try {
const { workspaceName, organizationId } = req.body;
@@ -154,6 +156,18 @@ export const createWorkspace = async (req: Request, res: Response) => {
throw new Error("Failed to validate organization membership");
}
const plan = await EELicenseService.getOrganizationPlan(organizationId);
if (plan.workspaceLimit !== null) {
// case: limit imposed on number of workspaces allowed
if (plan.workspacesUsed >= plan.workspaceLimit) {
// case: number of workspaces used exceeds the number of workspaces allowed
return res.status(400).send({
message: 'Failed to create workspace due to plan limit reached. Upgrade plan to add more workspaces.'
});
}
}
if (workspaceName.length < 1) {
throw new Error("Workspace names must be at least 1-character long");
}
+7 -1
View File
@@ -22,6 +22,10 @@ import {
getHttpsEnabled
} from '../../config';
// note: move this out
import path from 'path';
import fs from 'fs';
declare module 'jsonwebtoken' {
export interface UserIDJwtPayload extends jwt.JwtPayload {
userId: string;
@@ -93,7 +97,7 @@ export const login2 = async (req: Request, res: Response) => {
const { email, clientProof } = req.body;
const user = await User.findOne({
email
}).select('+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag');
}).select('+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag +devices');
if (!user) throw new Error('Failed to find user');
@@ -231,6 +235,8 @@ export const login2 = async (req: Request, res: Response) => {
}
};
import { validateUserEmail } from '../../validation';
/**
* Send MFA token to email [email]
* @param req