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 } }); } }