user.js

Generated by CoffeeScript 1.9.1

(function() {
  module.exports = (function() {
    var CPREFIX, UPREFIX, common, crypto, cuid, ld, storage, user;
    crypto = require('crypto');
    ld = require('lodash');
    cuid = require('cuid');
    storage = require('../storage.js');
    common = require('./common.js');
    UPREFIX = storage.DBPREFIX.USER;
    CPREFIX = storage.DBPREFIX.CONF;
    user = {
      ids: {}
    };
    user.fn = {};
    user.fn.getPasswordConf = function(callback) {
      var _keys;
      _keys = [CPREFIX + "passwordMin", CPREFIX + "passwordMax"];
      return storage.fn.getKeys(_keys, function(err, results) {
        if (err) {
          return callback(err);
        }
        return callback(null, results);
      });
    };
    user.fn.checkPasswordLength = function(password, params) {
      var max, min;
      min = params[CPREFIX + "passwordMin"];
      max = params[CPREFIX + "passwordMax"];
      if (password.length < min || password.length > max) {
        return new TypeError("password length must be between " + min + " and " + max + " characters");
      }
    };
    user.fn.genPassword = function(old, u, callback) {
      return user.fn.getPasswordConf(function(err, res) {
        var newPass, oldp;
        if (err) {
          return callback(err);
        }
        err = user.fn.checkPasswordLength(u.password, res);
        if (err) {
          return callback(err);
        }
        newPass = function() {
          return user.fn.hashPassword(null, u.password, function(err, pass) {
            if (err) {
              return callback(err);
            }
            u.password = pass;
            return callback(null, u);
          });
        };
        if (old) {
          oldp = old.password;
          return user.fn.hashPassword(oldp.salt, u.password, function(err, p) {
            if (err) {
              return callback(err);
            }
            if (p.hash === oldp.hash) {
              u.password = oldp;
              return callback(null, u);
            } else {
              return newPass();
            }
          });
        } else {
          return newPass();
        }
      });
    };
    user.fn.hashPassword = function(salt, password, callback) {
      return crypto.randomBytes(40, function(ex, buf) {
        var sha512;
        if (ex) {
          return callback(ex);
        }
        if (salt == null) {
          salt = buf.toString('hex');
        }
        sha512 = crypto.createHash('sha512');
        sha512.update(salt);
        return callback(null, {
          salt: salt,
          hash: sha512.update(password).digest('hex')
        });
      });
    };
    user.fn.assignProps = function(params) {
      var p, u;
      p = params;
      u = ld.reduce(['firstname', 'lastname', 'organization'], function(res, v) {
        res[v] = ld.isString(p[v]) ? p[v] : '';
        return res;
      }, {});
      u.email = ld.isEmail(p.email) ? p.email : '';
      u.groups = [];
      return ld.assign({
        _id: p._id,
        login: p.login,
        password: p.password
      }, u);
    };
    user.fn.checkLogin = function(_id, u, callback) {
      var e, exists, key;
      if (!_id) {
        exists = !ld.isUndefined(user.ids[u.login]) || ld.includes(ld.values(user.ids), u._id);
        if (exists) {
          e = 'user already exists, please choose another login';
          return callback(new Error(e));
        }
        return callback(null);
      } else {
        if (ld.isUndefined(user.ids[u.login])) {
          key = ld.findKey(user.ids, function(uid) {
            return uid === _id;
          });
          delete user.ids[key];
        }
        return callback(null);
      }
    };
    user.fn.getDel = function(del, login, callback) {
      var cb;
      if (!ld.isString(login) || ld.isEmpty(login)) {
        throw new TypeError('login must be a string');
      }
      if (ld.isUndefined(user.ids[login])) {
        return callback(new Error('user not found'));
      }
      cb = callback;
      if (del) {
        cb = function(err, u) {
          var GPREFIX;
          delete user.ids[u.login];
          if (u.groups.length) {
            GPREFIX = storage.DBPREFIX.GROUP;
            return storage.fn.getKeys(ld.map(u.groups, function(g) {
              return GPREFIX + g;
            }), function(err, groups) {
              if (err) {
                return callback(err);
              }
              groups = ld.reduce(groups, function(memo, g) {
                ld.pull(g.users, u._id);
                ld.pull(g.admins, u._id);
                memo[GPREFIX + g._id] = g;
                return memo;
              }, {});
              return storage.fn.setKeys(groups, function(err) {
                if (err) {
                  return callback(err);
                }
                return callback(null, u);
              });
            });
          } else {
            return callback(null, u);
          }
        };
      }
      return common.getDel(del, UPREFIX, user.ids[login], cb);
    };
    user.fn.set = function(u, callback) {
      return storage.db.set(UPREFIX + u._id, u, function(err) {
        if (err) {
          return callback(err);
        }
        user.ids[u.login] = u._id;
        return callback(null, u);
      });
    };
    user.init = function(callback) {
      return storage.db.findKeys(UPREFIX + "*", null, function(err, keys) {
        if (err) {
          return callback(err);
        }
        return storage.fn.getKeys(keys, function(err, results) {
          if (results) {
            user.ids = ld.transform(results, function(memo, val, key) {
              return memo[val.login] = key.replace(UPREFIX, '');
            });
          }
          return callback(null);
        });
      });
    };
    user.set = function(params, callback) {
      var u;
      common.addSetInit(params, callback, ['login', 'password']);
      u = user.fn.assignProps(params);
      if (u._id == null) {
        u._id = cuid();
      }
      return user.fn.checkLogin(params._id, u, function(err) {
        if (err) {
          return callback(err);
        }
        if (params._id) {
          return user.get(u.login, function(err, dbuser) {
            if (err) {
              return callback(err);
            }
            u.groups = dbuser.groups;
            return user.fn.genPassword(dbuser, u, function(err, u) {
              if (err) {
                return callback(err);
              }
              return user.fn.set(u, callback);
            });
          });
        } else {
          return user.fn.genPassword(null, u, function(err, u) {
            if (err) {
              return callback(err);
            }
            return user.fn.set(u, callback);
          });
        }
      });
    };
    user.get = ld.partial(user.fn.getDel, false);
    user.del = ld.partial(user.fn.getDel, true);
    ld.mixin({
      isEmail: function(val) {
        var rg;
        rg = new RegExp(['[a-z0-9!#$%&\'*+/=?^_`{|}~-]+', '(?:\\.[a-z0-9!#$%&\'*+/=?^_`{|}~-]+)*@(?:[a-z0-9]', '(?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9]', '(?:[a-z0-9-]*[a-z0-9])?'].join(''));
        return ld.isString(val) && rg.test(val);
      }
    });
    return user;
  })();

}).call(this);