@qelos/auth
Version:
Express Passport authentication service
250 lines (249 loc) • 9.71 kB
JavaScript
;
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;