Files
infisical/backend/src/helpers/user.ts
T

135 lines
3.3 KiB
TypeScript

import {
IUser,
User,
} from '../models';
import { sendMail } from './nodemailer';
/**
* Initialize a user under email [email]
* @param {Object} obj
* @param {String} obj.email - email of user to initialize
* @returns {Object} user - the initialized user
*/
export const setupAccount = async ({ email }: { email: string }) => {
const user = await new User({
email
}).save();
return user;
};
/**
* Finish setting up user
* @param {Object} obj
* @param {String} obj.userId - id of user to finish setting up
* @param {String} obj.firstName - first name of user
* @param {String} obj.lastName - last name of user
* @param {Number} obj.encryptionVersion - version of auth encryption scheme used
* @param {String} obj.protectedKey - protected key in encryption version 2
* @param {String} obj.protectedKeyIV - IV of protected key in encryption version 2
* @param {String} obj.protectedKeyTag - tag of protected key in encryption version 2
* @param {String} obj.publicKey - publickey of user
* @param {String} obj.encryptedPrivateKey - (encrypted) private key of user
* @param {String} obj.encryptedPrivateKeyIV - iv for (encrypted) private key of user
* @param {String} obj.encryptedPrivateKeyTag - tag for (encrypted) private key of user
* @param {String} obj.salt - salt for auth SRP
* @param {String} obj.verifier - verifier for auth SRP
* @returns {Object} user - the completed user
*/
export const completeAccount = async ({
userId,
firstName,
lastName,
encryptionVersion,
protectedKey,
protectedKeyIV,
protectedKeyTag,
publicKey,
encryptedPrivateKey,
encryptedPrivateKeyIV,
encryptedPrivateKeyTag,
salt,
verifier
}: {
userId: string;
firstName: string;
lastName: string;
encryptionVersion: number;
protectedKey: string;
protectedKeyIV: string;
protectedKeyTag: string;
publicKey: string;
encryptedPrivateKey: string;
encryptedPrivateKeyIV: string;
encryptedPrivateKeyTag: string;
salt: string;
verifier: string;
}) => {
const options = {
new: true
};
const user = await User.findByIdAndUpdate(
userId,
{
firstName,
lastName,
encryptionVersion,
protectedKey,
protectedKeyIV,
protectedKeyTag,
publicKey,
encryptedPrivateKey,
iv: encryptedPrivateKeyIV,
tag: encryptedPrivateKeyTag,
salt,
verifier
},
options
);
return user;
};
/**
* Check if device with ip [ip] and user-agent [userAgent] has been seen for user [user].
* If the device is unseen, then notify the user of the new device
* @param {Object} obj
* @param {String} obj.ip - login ip address
* @param {String} obj.userAgent - login user-agent
*/
export const checkUserDevice = async ({
user,
ip,
userAgent
}: {
user: IUser;
ip: string;
userAgent: string;
}) => {
const isDeviceSeen = user.devices.some((device) => device.ip === ip && device.userAgent === userAgent);
if (!isDeviceSeen) {
// case: unseen login ip detected for user
// -> notify user about the sign-in from new ip
user.devices = user.devices.concat([{
ip: String(ip),
userAgent
}]);
await user.save();
// send MFA code [code] to [email]
await sendMail({
template: 'newDevice.handlebars',
subjectLine: `Successful login from new device`,
recipients: [user.email],
substitutions: {
email: user.email,
timestamp: new Date().toString(),
ip,
userAgent
}
});
}
}