'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.checkSameEmail = checkSameEmail;
exports.getRole = getRole;
exports.commonPassword = commonPassword;
exports.encryptPassword = encryptPassword;
exports.getUserRoutes = getUserRoutes;
exports.findSync = findSync;
exports.find = find;
exports.findByUsername = findByUsername;
exports.findByEmail = findByEmail;
exports.findByResetPasswordToken = findByResetPasswordToken;
exports.isValid = isValid;
exports.decodeUser = decodeUser;
exports.getTokenFromCookies = getTokenFromCookies;
exports.isAbeRestrictedUrl = isAbeRestrictedUrl;
exports.isUserAllowedOnRoute = isUserAllowedOnRoute;
exports.getAll = getAll;
exports.getUserWorkflow = getUserWorkflow;
exports.loginLimitTry = loginLimitTry;

var _redis = require('redis');

var _redis2 = _interopRequireDefault(_redis);

var _ratelimiter = require('ratelimiter');

var _ratelimiter2 = _interopRequireDefault(_ratelimiter);

var _owaspPasswordStrengthTest = require('owasp-password-strength-test');

var _owaspPasswordStrengthTest2 = _interopRequireDefault(_owaspPasswordStrengthTest);

var _bcryptNodejs = require('bcrypt-nodejs');

var _bcryptNodejs2 = _interopRequireDefault(_bcryptNodejs);

var _cookies = require('cookies');

var _cookies2 = _interopRequireDefault(_cookies);

var _jwtSimple = require('jwt-simple');

var _jwtSimple2 = _interopRequireDefault(_jwtSimple);

var _cli = require('../../cli');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function checkSameEmail(data) {
  var emailAlreadyUsed = false;
  var bdd = _cli.User.manager.instance.get();
  for (var i = 0, len = bdd.length; i < len; i++) {
    var user = bdd[i];
    if (user.email === data.email && parseInt(user.id) !== parseInt(data.id)) {
      emailAlreadyUsed = true;
    }
  }

  if (emailAlreadyUsed === true) {
    return {
      success: 0,
      message: 'Email adress already exist'
    };
  } else {
    return {
      success: 1
    };
  }
}

function getRole(data) {
  var roles = _cli.config.users.roles;
  Array.prototype.forEach.call(roles, function (role) {
    if (role.name === data.role) {
      data.role = role;
    }
  });

  return data;
}

function commonPassword(data) {
  var owaspConfig = _cli.config.users.owasp;
  _owaspPasswordStrengthTest2.default.config(owaspConfig);
  var sameAsUser = typeof owaspConfig.sameAsUser !== 'undefined' && owaspConfig.sameAsUser !== null ? owaspConfig.sameAsUser : true;
  var mostCommon = typeof owaspConfig.mostCommon !== 'undefined' && owaspConfig.mostCommon !== null ? owaspConfig.mostCommon : true;
  var mostCommonPassword = _cli.config.users.mostCommonPassword;
  _owaspPasswordStrengthTest2.default.tests.required.push(function (password) {
    if (mostCommon && _cli.coreUtils.array.contains(mostCommonPassword, password.toLowerCase())) {
      return 'the password used is too common.';
    }
  });

  var currentUserName = data.username;
  _owaspPasswordStrengthTest2.default.tests.required.push(function (password) {
    var username = currentUserName;
    var shouldTest = sameAsUser;

    if (shouldTest) {
      if (password.toLowerCase() === username.toLowerCase()) {
        return 'username and password must be different.';
      }
      if (password.toLowerCase() === username.toLowerCase().split('').reverse().join('')) {
        return 'username and password must be different, not just inverted.';
      }
    }
  });

  var res = _owaspPasswordStrengthTest2.default.test(data.password);

  if (typeof res.errors !== 'undefined' && res.errors !== null && res.errors.length > 0) {
    var message = '';
    Array.prototype.forEach.call(res.errors, function (error) {
      message += error + '<br />';
    });
    return {
      success: 0,
      message: message
    };
  } else {
    return {
      success: 1
    };
  }
}

function encryptPassword(numb, password) {
  var salt = _bcryptNodejs2.default.genSaltSync(numb);
  return _bcryptNodejs2.default.hashSync(password, salt);
}

function getUserRoutes(workflow) {
  var routes = _cli.config.users.routes;
  var userRoles = [];
  Array.prototype.forEach.call(Object.keys(routes), function (role) {
    if (role === workflow) {
      userRoles = routes[role];
    }
  });

  return userRoles;
}

function findSync(id) {
  var bdd = _cli.User.manager.instance.get();
  for (var i = 0, len = bdd.length; i < len; i++) {
    var user = bdd[i];
    if (parseInt(user.id) === parseInt(id)) {
      return user;
    }
  }
  return null;
}

function find(id, done) {
  var bdd = _cli.User.manager.instance.get();
  for (var i = 0, len = bdd.length; i < len; i++) {
    var user = bdd[i];
    if (parseInt(user.id) === parseInt(id)) {
      return done(null, user);
    }
  }
  return done(null, null);
}

function findByUsername(username, done) {
  var bdd = _cli.User.manager.instance.get();
  for (var i = 0, len = bdd.length; i < len; i++) {
    var user = bdd[i];
    if (user.username === username) {
      return done(null, user);
    }
  }
  return done(null, null);
}

function findByEmail(email, done) {
  var bdd = _cli.User.manager.instance.get();
  for (var i = 0, len = bdd.length; i < len; i++) {
    var user = bdd[i];
    if (user.email === email) {
      return done(null, user);
    }
  }
  return done(null, null);
}

function findByResetPasswordToken(resetPasswordToken, done) {
  var bdd = _cli.User.manager.instance.get();
  for (var i = 0, len = bdd.length; i < len; i++) {
    var user = bdd[i];
    if (user.resetPasswordToken === resetPasswordToken) {
      return done(null, user);
    }
  }
  return done(null, null);
}

function isValid(user, password) {
  if (user.actif === 1) {
    if (_bcryptNodejs2.default.compareSync(password, user.password)) {
      return true;
    }
  }
  return false;
}

function decodeUser(req, res) {
  var decoded = {};
  var token = _cli.User.utils.getTokenFromCookies(req, res);
  if (typeof token !== 'undefined' && token !== null && token !== '') {
    try {
      var secret = _cli.config.users.secret;
      decoded = _jwtSimple2.default.decode(token, secret);
    } catch (err) {}
  }

  return decoded;
}

function getTokenFromCookies(req, res) {
  var cookies = new _cookies2.default(req, res, {
    secure: _cli.config.cookie.secure
  });
  return cookies.get('x-access-token');
}

function isAbeRestrictedUrl(currentRoute) {
  if (currentRoute.indexOf('/abe/users/forgot') > -1 || currentRoute.indexOf('/abe/users/login') > -1 || currentRoute.indexOf('/abe/users/reset') > -1 || !/^\/abe\//.test(currentRoute)) {
    return false;
  }

  return true;
}

function isUserAllowedOnRoute(workflow, currentRoute) {
  var isAllowed = false;

  if (_cli.config.users.enable) {
    if (currentRoute.indexOf('/abe/users/forgot') > -1 || currentRoute.indexOf('/abe/users/login') > -1 || !/^\/abe/.test(currentRoute)) {
      return true;
    }

    if (currentRoute.indexOf('abe/') === -1) {
      isAllowed = true;
    }

    if (workflow != null) {
      var routes = _cli.config.users.routes;
      if (typeof routes[workflow] !== 'undefined' && routes[workflow] !== null) {
        Array.prototype.forEach.call(routes[workflow], function (route) {
          var reg = new RegExp(route);
          if (reg.test(currentRoute)) {
            isAllowed = true;
          }
        });
      }
    }
  } else {
    isAllowed = true;
  }

  return isAllowed;
}

function getAll() {
  return _cli.User.manager.instance.get();
}

function getUserWorkflow(status) {
  var flows = [];

  function addFlow(flow, type, action) {
    type = type != null ? type : flow;
    return {
      status: flow,
      url: '/abe/operations/' + action + '/' + type
    };
  }

  if (_cli.config.users.enable) {
    var found = null;
    Array.prototype.forEach.call(_cli.config.users.workflow, function (flow) {

      if (found != null) {
        flows.push(addFlow(flow, flow, 'submit'));
        found = null;
      }

      if (status == flow) {
        found = flow;
        if (flow != 'draft' && flow != 'publish') {
          flows.push(addFlow('reject', flow, 'reject'));
        }
        if (flow == 'publish') {
          flows.push(addFlow('edit', 'draft', 'edit'));
        } else {
          flows.push(addFlow('save', flow, 'edit'));
        }
      }
    });
    if (found != null) {
      flows.push(addFlow('save', 'publish', 'submit'));
    }
  } else {
    flows = [addFlow('draft', 'draft', 'submit'), addFlow('publish', 'publish', 'submit')];
  }
  return flows;
}

function loginLimitTry(username) {
  var p = new Promise(function (resolve) {
    var isNexted = false;
    try {
      var limiterConfig = _cli.config.users.limiter;

      var client = _redis2.default.createClient();
      client.on('error', function () {
        if (!isNexted) {
          isNexted = true;
          resolve();
        }
      });

      var limit = new _ratelimiter2.default({
        id: username,
        db: client,
        duration: limiterConfig.duration,
        max: limiterConfig.max
      });

      limit.get(function (err, limit) {
        if (err) {
          resolve();
        } else {
          resolve(limit);
        }
      });
    } catch (e) {
      resolve();
    }
  });

  return p;
}