Skip to content

Commit

Permalink
merge backend
Browse files Browse the repository at this point in the history
  • Loading branch information
maidul98 committed Mar 16, 2023
2 parents 3d818f9 + 8e55d17 commit fdae510
Show file tree
Hide file tree
Showing 18 changed files with 310 additions and 154 deletions.
7 changes: 4 additions & 3 deletions backend/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,18 @@ export const getPostHogProjectApiKey = () => infisical.get('POSTHOG_PROJECT_API_
export const getSentryDSN = () => infisical.get('SENTRY_DSN')!;
export const getSiteURL = () => infisical.get('SITE_URL')!;
export const getSmtpHost = () => infisical.get('SMTP_HOST')!;
export const getSmtpSecure = () => infisical.get('SMTP_SECURE')! === 'true' || false;
export const getSmtpSecure = () => infisical.get('SMTP_SECURE')! === 'true' || false;
export const getSmtpPort = () => parseInt(infisical.get('SMTP_PORT')!) || 587;
export const getSmtpUsername = () => infisical.get('SMTP_USERNAME')!;
export const getSmtpPassword = () => infisical.get('SMTP_PASSWORD')!;
export const getSmtpFromAddress = () => infisical.get('SMTP_FROM_ADDRESS')!;
export const getSmtpFromName = () => infisical.get('SMTP_FROM_NAME')! || 'Infisical';
export const getSmtpFromName = () => infisical.get('SMTP_FROM_NAME')! || 'Infisical';
export const getStripeProductStarter = () => infisical.get('STRIPE_PRODUCT_STARTER')!;
export const getStripeProductPro = () => infisical.get('STRIPE_PRODUCT_PRO')!;
export const getStripeProductTeam = () => infisical.get('STRIPE_PRODUCT_TEAM')!;
export const getStripePublishableKey = () => infisical.get('STRIPE_PUBLISHABLE_KEY')!;
export const getStripeSecretKey = () => infisical.get('STRIPE_SECRET_KEY')!;
export const getStripeWebhookSecret = () => infisical.get('STRIPE_WEBHOOK_SECRET')!;
export const getTelemetryEnabled = () => infisical.get('TELEMETRY_ENABLED')! !== 'false' && true;
export const getLoopsApiKey = () => infisical.get('LOOPS_API_KEY')!;
export const getLoopsApiKey = () => infisical.get('LOOPS_API_KEY')!;
export const getSmtpConfigured = () => infisical.get('SMTP_HOST') == '' || infisical.get('SMTP_HOST') == undefined ? false : true
14 changes: 8 additions & 6 deletions backend/src/controllers/v1/signupController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from '../../helpers/signup';
import { createToken } from '../../helpers/auth';
import { BadRequestError } from '../../utils/errors';
import { getInviteOnlySignup, getJwtSignupLifetime, getJwtSignupSecret } from '../../config';
import { getInviteOnlySignup, getJwtSignupLifetime, getJwtSignupSecret, getSmtpConfigured } from '../../config';

/**
* Signup step 1: Initialize account for user under email [email] and send a verification code
Expand All @@ -21,7 +21,7 @@ export const beginEmailSignup = async (req: Request, res: Response) => {
try {
email = req.body.email;

if (getInviteOnlySignup() || false) {
if (getInviteOnlySignup()) {
// Only one user can create an account without being invited. The rest need to be invited in order to make an account
const userCount = await User.countDocuments({})
if (userCount != 0) {
Expand Down Expand Up @@ -75,10 +75,12 @@ export const verifyEmailSignup = async (req: Request, res: Response) => {
}

// verify email
await checkEmailVerification({
email,
code
});
if (getSmtpConfigured()) {
await checkEmailVerification({
email,
code
});
}

if (!user) {
user = await new User({
Expand Down
162 changes: 87 additions & 75 deletions backend/src/controllers/v2/authController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export const login1 = async (req: Request, res: Response) => {
*/
export const login2 = async (req: Request, res: Response) => {
try {

if (!req.headers['user-agent']) throw InternalServerError({ message: 'User-Agent header is required' });

const { email, clientProof } = req.body;
Expand Down Expand Up @@ -127,12 +127,12 @@ export const login2 = async (req: Request, res: Response) => {
expiresIn: getJwtMfaLifetime(),
secret: getJwtMfaSecret()
});

const code = await TokenService.createToken({
type: TOKEN_EMAIL_MFA,
email
});

// send MFA code [code] to [email]
await sendMail({
template: 'emailMfa.handlebars',
Expand All @@ -142,13 +142,13 @@ export const login2 = async (req: Request, res: Response) => {
code
}
});

return res.status(200).send({
mfaEnabled: true,
token
});
}

await checkUserDevice({
user,
ip: req.ip,
Expand Down Expand Up @@ -181,7 +181,7 @@ export const login2 = async (req: Request, res: Response) => {
iv?: string;
tag?: string;
}

const response: ResponseData = {
mfaEnabled: false,
encryptionVersion: user.encryptionVersion,
Expand All @@ -191,7 +191,7 @@ export const login2 = async (req: Request, res: Response) => {
iv: user.iv,
tag: user.tag
}

if (
user?.protectedKey &&
user?.protectedKeyIV &&
Expand All @@ -206,14 +206,14 @@ export const login2 = async (req: Request, res: Response) => {
name: ACTION_LOGIN,
userId: user._id
});

loginAction && await EELogService.createLog({
userId: user._id,
actions: [loginAction],
channel: getChannelFromUserAgent(req.headers['user-agent']),
ipAddress: req.ip
});

return res.status(200).send(response);
}

Expand Down Expand Up @@ -244,7 +244,7 @@ export const sendMfaToken = async (req: Request, res: Response) => {
type: TOKEN_EMAIL_MFA,
email
});

// send MFA code [code] to [email]
await sendMail({
template: 'emailMfa.handlebars',
Expand All @@ -259,9 +259,9 @@ export const sendMfaToken = async (req: Request, res: Response) => {
Sentry.captureException(err);
return res.status(400).send({
message: 'Failed to send MFA code'
});
});
}

return res.status(200).send({
message: 'Successfully sent new MFA code'
});
Expand All @@ -274,75 +274,87 @@ export const sendMfaToken = async (req: Request, res: Response) => {
* @param res
*/
export const verifyMfaToken = async (req: Request, res: Response) => {
const { email, mfaToken } = req.body;
const { email, mfaToken } = req.body;

await TokenService.validateToken({
type: TOKEN_EMAIL_MFA,
email,
token: mfaToken
});
await TokenService.validateToken({
type: TOKEN_EMAIL_MFA,
email,
token: mfaToken
});

const user = await User.findOne({
email
}).select('+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag');
const user = await User.findOne({
email
}).select('+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag');

if (!user) throw new Error('Failed to find user');
if (!user) throw new Error('Failed to find user');

await checkUserDevice({
user,
ip: req.ip,
userAgent: req.headers['user-agent'] ?? ''
});
await checkUserDevice({
user,
ip: req.ip,
userAgent: req.headers['user-agent'] ?? ''
});

// issue tokens
const tokens = await issueAuthTokens({ userId: user._id.toString() });
// issue tokens
const tokens = await issueAuthTokens({ userId: user._id.toString() });

// store (refresh) token in httpOnly cookie
res.cookie('jid', tokens.refreshToken, {
httpOnly: true,
path: '/',
sameSite: 'strict',
secure: getNodeEnv() === 'production' ? true : false
});

interface VerifyMfaTokenRes {
encryptionVersion: number;
protectedKey?: string;
protectedKeyIV?: string;
protectedKeyTag?: string;
token: string;
publicKey: string;
encryptedPrivateKey: string;
iv: string;
tag: string;
}
// store (refresh) token in httpOnly cookie
res.cookie('jid', tokens.refreshToken, {
httpOnly: true,
path: '/',
sameSite: 'strict',
secure: getNodeEnv() === 'production' ? true : false
});

const resObj: VerifyMfaTokenRes = {
encryptionVersion: user.encryptionVersion,
token: tokens.token,
publicKey: user.publicKey as string,
encryptedPrivateKey: user.encryptedPrivateKey as string,
iv: user.iv as string,
tag: user.tag as string
}

if (user?.protectedKey && user?.protectedKeyIV && user?.protectedKeyTag) {
resObj.protectedKey = user.protectedKey;
resObj.protectedKeyIV = user.protectedKeyIV;
resObj.protectedKeyTag = user.protectedKeyTag;
}
interface VerifyMfaTokenRes {
encryptionVersion: number;
protectedKey?: string;
protectedKeyIV?: string;
protectedKeyTag?: string;
token: string;
publicKey: string;
encryptedPrivateKey: string;
iv: string;
tag: string;
}

const loginAction = await EELogService.createAction({
name: ACTION_LOGIN,
userId: user._id
});

loginAction && await EELogService.createLog({
userId: user._id,
actions: [loginAction],
channel: getChannelFromUserAgent(req.headers['user-agent']),
ipAddress: req.ip
});
interface VerifyMfaTokenRes {
encryptionVersion: number;
protectedKey?: string;
protectedKeyIV?: string;
protectedKeyTag?: string;
token: string;
publicKey: string;
encryptedPrivateKey: string;
iv: string;
tag: string;
}

return res.status(200).send(resObj);
}
const resObj: VerifyMfaTokenRes = {
encryptionVersion: user.encryptionVersion,
token: tokens.token,
publicKey: user.publicKey as string,
encryptedPrivateKey: user.encryptedPrivateKey as string,
iv: user.iv as string,
tag: user.tag as string
}

if (user?.protectedKey && user?.protectedKeyIV && user?.protectedKeyTag) {
resObj.protectedKey = user.protectedKey;
resObj.protectedKeyIV = user.protectedKeyIV;
resObj.protectedKeyTag = user.protectedKeyTag;
}

const loginAction = await EELogService.createAction({
name: ACTION_LOGIN,
userId: user._id
});

loginAction && await EELogService.createLog({
userId: user._id,
actions: [loginAction],
channel: getChannelFromUserAgent(req.headers['user-agent']),
ipAddress: req.ip
});

return res.status(200).send(resObj);
}
36 changes: 19 additions & 17 deletions backend/src/helpers/nodemailer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import fs from 'fs';
import path from 'path';
import handlebars from 'handlebars';
import nodemailer from 'nodemailer';
import { getSmtpFromName, getSmtpFromAddress } from '../config';
import { getSmtpFromName, getSmtpFromAddress, getSmtpConfigured } from '../config';

let smtpTransporter: nodemailer.Transporter;

Expand All @@ -25,23 +25,25 @@ const sendMail = async ({
recipients: string[];
substitutions: any;
}) => {
try {
const html = fs.readFileSync(
path.resolve(__dirname, '../templates/' + template),
'utf8'
);
const temp = handlebars.compile(html);
const htmlToSend = temp(substitutions);
if (getSmtpConfigured()) {
try {
const html = fs.readFileSync(
path.resolve(__dirname, '../templates/' + template),
'utf8'
);
const temp = handlebars.compile(html);
const htmlToSend = temp(substitutions);

await smtpTransporter.sendMail({
from: `"${getSmtpFromName()}" <${getSmtpFromAddress()}>`,
to: recipients.join(', '),
subject: subjectLine,
html: htmlToSend
});
} catch (err) {
Sentry.setUser(null);
Sentry.captureException(err);
await smtpTransporter.sendMail({
from: `"${getSmtpFromName()}" <${getSmtpFromAddress()}>`,
to: recipients.join(', '),
subject: subjectLine,
html: htmlToSend
});
} catch (err) {
Sentry.setUser(null);
Sentry.captureException(err);
}
}
};

Expand Down
Loading

0 comments on commit fdae510

Please sign in to comment.