UNPKG

@qelos/auth

Version:

Express Passport authentication service

250 lines (249 loc) 9.71 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getUserMetadata = exports.getCookieTokenValue = exports.getCookieTokenName = exports.clearOldTokens = exports.getUserIfTokenExists = exports.deleteToken = exports.updateToken = exports.setToken = exports.comparePassword = exports.deleteUser = exports.updateUser = exports.getUser = exports.getValidMetadata = void 0; const user_1 = __importDefault(require("../models/user")); const config_1 = require("../../config"); const dates_1 = require("./dates"); const logger_1 = __importDefault(require("./logger")); const tokens_1 = require("./tokens"); function getValidMetadata(metadata = {}, additionalFields = []) { const result = {}; for (const field of additionalFields) { if (metadata[field.key] !== undefined && typeof metadata[field.key] === field.valueType) { result[field.key] = metadata[field.key]; } else if (field.defaultValue) { result[field.key] = field.defaultValue; } else if (field.required) { throw { code: 'INVALID_METADATA' }; } } return result; } exports.getValidMetadata = getValidMetadata; function getUser(query) { return __awaiter(this, void 0, void 0, function* () { try { const user = yield user_1.default.findOne(query).exec(); if (user) { return user; } else { query.email = query.username; delete query.username; const raceUser = yield user_1.default.findOne(query).exec(); if (raceUser) { raceUser.username = raceUser.email; yield raceUser.save(); return raceUser; } } } catch (err) { throw { code: 'FORM_SUBMISSION_FAILED', info: err }; } throw { code: 'INCORRECT_CREDENTIALS' }; }); } exports.getUser = getUser; function updateUser(user, { username = null, password = null, fullName = null, roles = null, firstName = null, lastName = null, birthDate = null, profileImage = null, metadata = null }, authConfig) { return __awaiter(this, void 0, void 0, function* () { let directUpdate; if (!(user instanceof user_1.default)) { if (username || roles || password) { user = yield user_1.default.findOne({ _id: user._id, tenant: user.tenant }).exec(); } else { directUpdate = { _id: user._id, tenant: user.tenant }; user = {}; } } if (fullName) { user.fullName = fullName; } if (username) { user.username = username; switch (authConfig === null || authConfig === void 0 ? void 0 : authConfig.treatUsernameAs) { case 'email': user.email = user.username; break; case 'phone': user.phone = user.username; break; default: break; } } if (password) { user.password = password; } if (firstName) { user.firstName = firstName; } if (lastName) { user.lastName = lastName; } if (birthDate) { user.birthDate = (0, dates_1.getAbsoluteDate)(birthDate); } if (profileImage) { user.profileImage = profileImage; } if (roles) { user.roles = roles; } if (metadata && authConfig) { user.metadata = getValidMetadata(metadata, authConfig.additionalUserFields); } return (directUpdate ? user_1.default.updateOne(directUpdate, { $set: user }) : user.save()).catch((err) => { logger_1.default.error('failed to update user', err); return Promise.reject({ code: 'UPDATE_USER_FAILED', info: err }); }); }); } exports.updateUser = updateUser; function deleteUser(userId, tenant) { return __awaiter(this, void 0, void 0, function* () { if (!tenant) { throw new Error('tenant is missing'); } try { yield user_1.default.deleteOne({ _id: userId, tenant }).exec(); return { code: 'USER_DELETED_SUCCESSFULLY', info: userId }; } catch (error) { throw { code: 'USER_DELETE_FAILED', info: error }; } }); } exports.deleteUser = deleteUser; function comparePassword(user, password) { return new Promise((resolve, reject) => { return user.comparePassword(password.trim(), (passwordErr, isMatch) => { if (passwordErr) { return reject({ code: 'FORM_SUBMISSION_FAILED', info: passwordErr }); } if (!isMatch) { return reject({ code: 'INCORRECT_CREDENTIALS' }); } resolve(user); }); }); } exports.comparePassword = comparePassword; function setToken({ user, workspace }, authType) { if (authType === 'oauth') { return setOAuthAuthentication(user, workspace); } if (authType === 'cookie') { return setCookieAuthentication(user, workspace); } throw { code: 'INVALID_AUTH_TYPE' }; } exports.setToken = setToken; function updateToken(user, authType, currentPayload, newToken) { return user .updateToken(authType, currentPayload, newToken) .catch((err) => Promise.reject({ code: 'UPDATE_TOKEN_FAILED', info: err })); } exports.updateToken = updateToken; function deleteToken(tenant, userId, authType, token, isRelatedToken) { var _a; return __awaiter(this, void 0, void 0, function* () { try { const user = yield user_1.default.findOne({ _id: userId, tenant }).exec(); if (isRelatedToken) { token = yield (user === null || user === void 0 ? void 0 : user.getTokenByRelatedTokens(authType, token)); } else { token = ((_a = ((yield (0, tokens_1.verifyToken)(token, tenant)))) === null || _a === void 0 ? void 0 : _a.tokenIdentifier) || ''; } user === null || user === void 0 ? void 0 : user.deleteToken(authType, token); } catch (e) { return false; } return true; }); } exports.deleteToken = deleteToken; function setOAuthAuthentication(user, workspace) { const token = user.getToken({ authType: 'oauth', workspace }); const refreshToken = user.getRefreshToken(token, workspace); return user.save().then(() => { return { token, refreshToken, user, workspace, }; }); } function setCookieAuthentication(user, workspace) { const cookieToken = user.getToken({ authType: 'cookie', expiresIn: config_1.cookieTokenExpiration / 1000, workspace }); return user.save().then(() => { return { user, workspace, cookieToken }; }); } function getUserIfTokenExists(tenant, userId, tokenId) { return user_1.default.findOne({ _id: userId, tenant, 'tokens.tokenIdentifier': tokenId, }) .then((user) => user || Promise.reject()) .catch(() => Promise.reject({ code: 'USER_WITH_TOKEN_NOT_EXISTS' })); } exports.getUserIfTokenExists = getUserIfTokenExists; function clearOldTokens(userId) { return __awaiter(this, void 0, void 0, function* () { if (!userId) { return; } const user = yield user_1.default.findOne({ _id: userId }).select('tokens').exec(); if (!user) { return; } const now = Date.now(); const validTokens = user.tokens.filter(t => new Date(t.expiresAt).getTime() > now); if (validTokens.length === user.tokens) { return; } yield user_1.default.updateOne({ _id: userId }, { $set: { tokens: validTokens } }).exec(); }); } exports.clearOldTokens = clearOldTokens; function getCookieTokenName(tenant) { return `qlt_${tenant.substring(0, 8)}`.trim(); } exports.getCookieTokenName = getCookieTokenName; function getCookieTokenValue(req) { const tokenKey = getCookieTokenName(req.headers.tenant); return req.signedCookies[tokenKey] || req.cookies[tokenKey] || req.signedCookies.token || req.cookies.token; } exports.getCookieTokenValue = getCookieTokenValue; function getUserMetadata(userId, tenant) { return __awaiter(this, void 0, void 0, function* () { const user = yield user_1.default.findOne({ _id: userId, tenant }).select('metadata').lean().exec(); return (user === null || user === void 0 ? void 0 : user.metadata) || {}; }); } exports.getUserMetadata = getUserMetadata;