text: var validator      = require('validator'); //nodejs的后端字符串验证器-validator
  var eventproxy     = require('eventproxy');
  var config         = require('../config');
  var User           = require('../proxy').User;
  var mail           = require('../common/mail');
  var tools          = require('../common/tools');
  var utility        = require('utility');
  var authMiddleWare = require('../middlewares/auth');
  var uuid           = require('node-uuid');
  
  //sign up
  exports.showSignup = function (req, res) {
    res.render('sign/signup');
  };
  
  exports.signup = function (req, res, next) {
    var loginname = validator.trim(req.body.loginname).toLowerCase();
    var email     = validator.trim(req.body.email).toLowerCase();
    var pass      = validator.trim(req.body.pass);
    var rePass    = validator.trim(req.body.re_pass);
  
    var ep = new eventproxy();
    ep.fail(next);
    ep.on('prop_err', function (msg) {
      res.status(422);
      res.render('sign/signup', {error: msg, loginname: loginname, email: email});
    });
  
    // 验证信息的正确性
    if ([loginname, pass, rePass, email].some(function (item) { return item === ''; })) {
      ep.emit('prop_err', '信息不完整。');
      return;
    }
    if (loginname.length < 5) {
      ep.emit('prop_err', '用户名至少需要5个字符。');
      return;
    }
    if (!tools.validateId(loginname)) {
      return ep.emit('prop_err', '用户名不合法。');
    }
    if (!validator.isEmail(email)) {
      return ep.emit('prop_err', '邮箱不合法。');
    }
    if (pass !== rePass) {
      return ep.emit('prop_err', '两次密码输入不一致。');
    }
    // END 验证信息的正确性
  
  
    User.getUsersByQuery({'$or': [
      {'loginname': loginname},
      {'email': email}
    ]}, {}, function (err, users) {
      if (err) {
        return next(err);
      }
      if (users.length > 0) {
        ep.emit('prop_err', '用户名或邮箱已被使用。');
        return;
      }
  
      tools.bhash(pass, ep.done(function (passhash) {
        // create gravatar
        var avatarUrl = User.makeGravatar(email);
        User.newAndSave(loginname, loginname, passhash, email, avatarUrl, false, function (err) {
          if (err) {
            return next(err);
          }
          // 发送激活邮件
          mail.sendActiveMail(email, utility.md5(email + passhash + config.session_secret), loginname);
          res.render('sign/signup', {
            success: '欢迎加入 ' + config.name + '！我们已给您的注册邮箱发送了一封邮件，请点击里面的链接来激活您的帐号。'
          });
        });
  
      }));
    });
  };
  
  /**
   * Show user login page.
   *
   * @param  {HttpRequest} req
   * @param  {HttpResponse} res
   */
  exports.showLogin = function (req, res) {
    req.session._loginReferer = req.headers.referer;
    res.render('sign/signin');
  };
  
  /**
   * define some page when login just jump to the home page
   * @type {Array}
   */
  var notJump = [
    '/active_account', //active page
    '/reset_pass',     //reset password page, avoid to reset twice
    '/signup',         //regist page
    '/search_pass'    //serch pass page
  ];
  
  /**
   * Handle user login.
   *
   * @param {HttpRequest} req
   * @param {HttpResponse} res
   * @param {Function} next
   */
  exports.login = function (req, res, next) {
    var loginname = validator.trim(req.body.name).toLowerCase();
    var pass      = validator.trim(req.body.pass);
    var ep        = new eventproxy();
  
    ep.fail(next);
  
    if (!loginname || !pass) {
      res.status(422);
      return res.render('sign/signin', { error: '信息不完整。' });
    }
  
    var getUser;
    if (loginname.indexOf('@') !== -1) {
      getUser = User.getUserByMail;
    } else {
      getUser = User.getUserByLoginName;
    }
  
    ep.on('login_error', function (login_error) {
      res.status(403);
      res.render('sign/signin', { error: '用户名或密码错误' });
    });
  
    getUser(loginname, function (err, user) {
      if (err) {
        return next(err);
      }
      if (!user) {
        return ep.emit('login_error');
      }
      var passhash = user.pass;
      tools.bcompare(pass, passhash, ep.done(function (bool) {
        if (!bool) {
          return ep.emit('login_error');
        }
        if (!user.active) {
          // 重新发送激活邮件
          mail.sendActiveMail(user.email, utility.md5(user.email + passhash + config.session_secret), user.loginname);
          res.status(403);
          return res.render('sign/signin', { error: '此帐号还没有被激活，激活链接已发送到 ' + user.email + ' 邮箱，请查收。' });
        }
        // store session cookie
        authMiddleWare.gen_session(user, res);
        //check at some page just jump to home page
        var refer = req.session._loginReferer || '/';
        for (var i = 0, len = notJump.length; i !== len; ++i) {
          if (refer.indexOf(notJump[i]) >= 0) {
            refer = '/';
            break;
          }
        }
        res.redirect(refer);
      }));
    });
  };
  
  // sign out
  exports.signout = function (req, res, next) {
    req.session.destroy();
    res.clearCookie(config.auth_cookie_name, { path: '/' });
    res.redirect('/');
  };
  
  exports.activeAccount = function (req, res, next) {
    var key  = validator.trim(req.query.key);
    var name = validator.trim(req.query.name);
  
    User.getUserByLoginName(name, function (err, user) {
      if (err) {
        return next(err);
      }
      if (!user) {
        return next(new Error('[ACTIVE_ACCOUNT] no such user: ' + name));
      }
      var passhash = user.pass;
      if (!user || utility.md5(user.email + passhash + config.session_secret) !== key) {
        return res.render('notify/notify', {error: '信息有误，帐号无法被激活。'});
      }
      if (user.active) {
        return res.render('notify/notify', {error: '帐号已经是激活状态。'});
      }
      user.active = true;
      user.save(function (err) {
        if (err) {
          return next(err);
        }
        res.render('notify/notify', {success: '帐号已被激活，请登录'});
      });
    });
  };
  
  exports.showSearchPass = function (req, res) {
    res.render('sign/search_pass');
  };
  
  exports.updateSearchPass = function (req, res, next) {
    var email = validator.trim(req.body.email).toLowerCase();
    if (!validator.isEmail(email)) {
      return res.render('sign/search_pass', {error: '邮箱不合法', email: email});
    }
  
    // 动态生成retrive_key和timestamp到users collection,之后重置密码进行验证
    var retrieveKey  = uuid.v4();
    var retrieveTime = new Date().getTime();
  
    User.getUserByMail(email, function (err, user) {
      if (!user) {
        res.render('sign/search_pass', {error: '没有这个电子邮箱。', email: email});
        return;
      }
      user.retrieve_key = retrieveKey;
      user.retrieve_time = retrieveTime;
      user.save(function (err) {
        if (err) {
          return next(err);
        }
        // 发送重置密码邮件
        mail.sendResetPassMail(email, retrieveKey, user.loginname);
        res.render('notify/notify', {success: '我们已给您填写的电子邮箱发送了一封邮件，请在24小时内点击里面的链接来重置密码。'});
      });
    });
  };
  
  /**
   * reset password
   * 'get' to show the page, 'post' to reset password
   * after reset password, retrieve_key&time will be destroy
   * @param  {http.req}   req
   * @param  {http.res}   res
   * @param  {Function} next
   */
  exports.resetPass = function (req, res, next) {
    var key  = validator.trim(req.query.key || '');
    var name = validator.trim(req.query.name || '');
  
    User.getUserByNameAndKey(name, key, function (err, user) {
      if (!user) {
        res.status(403);
        return res.render('notify/notify', {error: '信息有误，密码无法重置。'});
      }
      var now = new Date().getTime();
      var oneDay = 1000 * 60 * 60 * 24;
      if (!user.retrieve_time || now - user.retrieve_time > oneDay) {
        res.status(403);
        return res.render('notify/notify', {error: '该链接已过期，请重新申请。'});
      }
      return res.render('sign/reset', {name: name, key: key});
    });
  };
  
  exports.updatePass = function (req, res, next) {
    var psw   = validator.trim(req.body.psw) || '';
    var repsw = validator.trim(req.body.repsw) || '';
    var key   = validator.trim(req.body.key) || '';
    var name  = validator.trim(req.body.name) || '';
  
    var ep = new eventproxy();
    ep.fail(next);
  
    if (psw !== repsw) {
      return res.render('sign/reset', {name: name, key: key, error: '两次密码输入不一致。'});
    }
    User.getUserByNameAndKey(name, key, ep.done(function (user) {
      if (!user) {
        return res.render('notify/notify', {error: '错误的激活链接'});
      }
      tools.bhash(psw, ep.done(function (passhash) {
        user.pass          = passhash;
        user.retrieve_key  = null;
        user.retrieve_time = null;
        user.active        = true; // 用户激活
  
        user.save(function (err) {
          if (err) {
            return next(err);
          }
          return res.render('notify/notify', {success: '你的密码已重置。'});
        });
      }));
    }));
  };
  
  