UNPKG

@batolye/bdk-core

Version:

Module to provide core utilities for BulusAtolyesi applications and services

140 lines (102 loc) 4.94 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.enforcePasswordPolicy = enforcePasswordPolicy; exports.storePreviousPassword = storePreviousPassword; exports.generatePassword = generatePassword; var _lodash = _interopRequireDefault(require("lodash")); var _passwordGenerator = _interopRequireDefault(require("password-generator")); var _debug = _interopRequireDefault(require("debug")); var _feathersHooksCommon = require("feathers-hooks-common"); var _errors = require("@feathersjs/errors"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const debug = (0, _debug.default)("batolye:bdk-core:users:hooks"); function enforcePasswordPolicy(options = {}) { return async function (hook) { if (hook.type !== "before") { throw new Error(`The 'enforePasswordPolicy' hook should only be used as a 'before' hook.`); } // By pass check ? if (hook.params.force) return hook; let app = hook.app; //https://feathers-plus.github.io/v1/feathers-hooks-common/#getitems let data = (0, _feathersHooksCommon.getItems)(hook); let user = options.userAsItem ? data : hook.params.user; // Get both password(s) since some rules target one and some the other one(s) let clearPassword = _lodash.default.get(data, options.passwordField || "clearPassword"); let hashedPasswords = _lodash.default.get(user, options.previousPasswordsField || "previousPasswords", []); if (clearPassword && hashedPasswords && app.core_getPasswordPolicy) { debug("Enforcing password policy on user", user); const validator = app.core_getPasswordPolicy(); // First check the clear password let result = validator.validate(clearPassword, { list: true }); // Then check for the last used passwords using password policy verifier for (let i = 0; i < hashedPasswords.length; i++) { try { await validator.comparePassword({ password: hashedPasswords[i] }, clearPassword); // If we have found a similar password stop result.push("previous"); break; } catch (error) {// Check next one } } if (!_lodash.default.isEmpty(result)) { throw new _errors.BadRequest("The provided password does not comply to the password policy", { translation: { key: "WEAK_PASSWORD", keys: result.map(rule => "WEAK_PASSWORD_" + rule.toUpperCase()), params: Object.assign({ failedRules: result }, _lodash.default.omit(validator.options, ["prohibited"])) } }); } } return hook; }; } function storePreviousPassword(options = {}) { return async function (hook) { if (hook.type !== "before") { throw new Error(`The 'storePreviousPassword' hook should only be used as a 'before' hook.`); } let app = hook.app; let data = (0, _feathersHooksCommon.getItems)(hook); if (app.core_getPasswordPolicy && hook.params.previousItem) { const validator = app.core_getPasswordPolicy(); // Based on previous password value let user = hook.params.previousItem; const passwordField = options.passwordField || "password"; let password = _lodash.default.get(user, passwordField); const previousPasswordsField = options.previousPasswordsField || "previousPasswords"; let previousPasswords = _lodash.default.get(user, previousPasswordsField, []); debug(`Moving previous password from field ${passwordField} in field ${previousPasswords} on user`, user); // Then check for the last used passwords using password // PULL REQUEST if (!(previousPasswords.length && previousPasswords[previousPasswords.length - 1] === hook.data.password)) { previousPasswords.push(password); // Pop oldest password when required const max = _lodash.default.get(validator, "options.history", 5); if (previousPasswords.length > max) previousPasswords.shift(); Object.assign(data, { [previousPasswordsField]: previousPasswords }); (0, _feathersHooksCommon.replaceItems)(hook, data); } } return hook; }; } function generatePassword(hook) { if (hook.type !== "before") { throw new Error(`The 'generatePassword' hook should only be used as a 'before' hook.`); } let app = hook.app; let data = hook.data; // Generate a password let passwordRule = new RegExp("[\\w\\d\\?\\-]"); // If we have a password policy ensure we match it if (app.core_getPasswordPolicy) { const validator = app.core_getPasswordPolicy(); do { data.password = (0, _passwordGenerator.default)(validator.options.minLength || 12, false, passwordRule); } while (!validator.validate(data.password)); } else { data.password = (0, _passwordGenerator.default)(12, false, passwordRule); } return hook; }