back.js 10.6 KB
/**
 * 找回密码
 * Created by Tao.Huang on 2016/6/12.
 */

'use strict';

const _ = require('lodash');

const helpers = global.yoho.helpers;

const service = require('../models/back-service');
const captchaService = require('../models/captcha-service');

const SIGN_IN = helpers.urlFormat('/passport/login');

/**
 * 通过邮箱找回密码页面
 */
const indexEmailPage = (req, res) => {
    res.render('back/email', Object.assign(
        {
            module: 'passport',
            page: 'back-email',
            title: '找回密码-通过邮箱'
        }, {
            // backUrl: SIGN_IN,
            headerText: '找回密码',
            isPassportPage: true,
            backEmail: true
        }
    ));
};

/**
 * 发送验证码到邮箱
 */
const sendCodeToEmailAPI = (req, res) => {
    let email = req.body.email || '';
    const ERR = {
        code: 400,
        message: '邮箱格式不正确,请重新输入',
        data: ''
    };

    if (!helpers.verifyEmail(email)) {
        res.json(ERR);
        return;
    }

    service.sendCodeToEmailAsync(email)
        .then(result => {
            if (result.code === 200) {
                result.data = helpers.urlFormat('/passport/back/success', { email: email });
            }

            res.json(result);
        })
        .catch(() => {
            res.json(ERR);
        });
};

/**
 * 重新发送验证码到邮箱
 */
const resendCodeToEmailAPI = (req, res) => {
    let email = req.query.email || '';

    service.sendCodeToEmailAsync(email)
        .then(result => {
            if (_.isEmpty(result)) {
                return Promise.rejected('重新发邮件失败');
            }

            res.json(result);
        })
        .catch(err => {
            res.json({
                code: 400,
                message: err
            });
        });
};

/**
 * 邮箱找回密码-返回成功页面
 */
const backSuccessByEmailPage = (req, res) => {
    let email = req.query.email || '';

    if (!helpers.verifyEmail(email)) {
        res.redirect(400);
    }

    let domain = email.split('@')[1];
    let emailUrl = `http://${domain === 'gmail.com' ? 'mail.google.com' : 'mail.'}${domain}`;

    res.render('back/email-success', Object.assign({
        module: 'passport',
        page: 'back-email-success',
        title: '找回密码-通过邮箱'
    }, {
        // backUrl: helpers.urlFormat('/passport/back/email'),
        headerText: '找回密码',
        isPassportPage: true,
        backEmailSuccess: true,
        goEmail: emailUrl,
        resendUrl: helpers.urlFormat('/passport/back/resendemail', { email: email })
    }));
};

/**
 * 根据邮箱修改密码
 */
const setNewPasswordByEmailAPI = (req, res) => {
    let pwd = req.body.password || '';
    let code = req.body.code || '';
    let data = {
        code: 200,
        data: SIGN_IN
    };

    service.modifyPasswordByEmailAsyncAes(pwd, code)
        .then(result => {
            if (result.includes('history.back')) {
                data.code = 400;
                data.message = '修改失败';
            }

            res.json(data);
        })
        .catch(() => {
            res.json(data);
        });
};

/**
 * 找回密码页面-通过手机号
 */
const indexMobilePage = (req, res, next) => {
    service.getAreaDataAsync()
        .then(result => {
            res.render('back/mobile', Object.assign({
                width750: true,
                module: 'passport',
                page: 'back-mobile',
                title: '找回密码-通过手机号'
            }, {
                // backUrl: SIGN_IN,
                headerText: '找回密码',
                isPassportPage: true,
                backMobile: true,
                countrys: result.data,
                areaCode: '+86',
                verifySrc: helpers.urlFormat('/passport/back/generatecodeimg.png', {t: Date.now()})
            }));
        })
        .catch(next);
};

/**
 * 生成验证码
 * @param req
 * @param res
 */
const generateCodeImg = (req, res) => {
    let verifyCodeImg = captchaService.generateCaptcha(109, 50, 4);

    if (verifyCodeImg) {

        if (req.session.backupCaptch) {
            req.session.backupCaptch.code = verifyCodeImg.text;
            req.session.backupCaptch.verifyResult = false;
        } else {
            req.session.backupCaptch = {
                code: verifyCodeImg.text,
                verifyResult: false
            };
        }

        res.set('Cache-Control', 'no-cache').send(verifyCodeImg.image);
    }
};

/**
 * 发送手机验证码
 */
const sendCodeToMobileAPI = (req, res, next) => {
    let verifyCode = req.body.verifyCode || '';
    let phoneNum = req.body.phoneNum || '';
    let areaCode = req.body.areaCode || '86';

    /* 如果设置了冻结时间,验证 */
    if (_.has(req.session, 'backupCaptch.timeout')) {
        let untilTime = (parseInt(req.session.backupCaptch.timeout, 10) -
            parseInt(Date.now(), 10)) / 1000 / 60;

        if (parseInt(Date.now(), 10) < parseInt(req.session.backupCaptch.timeout, 10)) {
            return res.json({
                code: 401,
                message: '请' + (parseInt(untilTime, 10) + 1) + '分钟后尝试!'
            });
        }
    }

    /* 如果设置了验证次数,验证是否合法,验证次数减 1;没有,设置验证次数 */
    if (_.has(req.session, 'backupCaptch.useTime')) {
        if (parseInt(req.session.backupCaptch.useTime, 10) <= 0) {

            /* 如果超过验证次数,冻结 5 分钟,更新验证次数 */
            req.session.backupCaptch.timeout = Date.now() + 5 * 60 * 1000;
            req.session.backupCaptch.useTime = 5;
            return res.json({
                code: 401,
                message: '请5分钟后尝试!'
            });
        }
        req.session.backupCaptch.useTime = req.session.backupCaptch.useTime - 1;
    } else {
        _.set(req.session, 'backupCaptch.useTime', 5);
    }

    if (verifyCode) {
        let captcha = _.get(req, 'session.captcha');

        if (captcha && verifyCode.toString() === captcha) {
            req.session.backupCaptch.verifyResult = true;
        } else {
            return res.json({
                code: 400,
                message: '验证码输入错误'
            });
        }
    } else if (!req.session.backupCaptch.verifyResult) {

        return res.json({
            code: 409,
            message: '非法请求!',
            refer: helpers.urlFormat('/')
        });
    }

    let ERR = {
        code: 400,
        message: '输入手机号码出错'
    };

    if (!helpers.verifyMobile(phoneNum)) {
        return res.json(ERR);
    }

    service.sendCodeToMobileAsync(phoneNum, areaCode)
        .then(result => {
            if (_.isEmpty(result) || result.code !== 200) {
                ERR.message = '发送验证码出错';
                res.json(ERR);
            }

            if (result.code === 200) {
                return res.json({
                    code: 200,
                    data: helpers.urlFormat('/passport/back/mobilecode', {
                        phoneNum: phoneNum,
                        areaCode: areaCode
                    })
                });
            }
        })
        .catch(next);
};

/**
 * 校验验证码页面
 */
const verifyCodeByMobilePage = (req, res) => {
    let phoneNum = req.query.phoneNum || '';
    let areaCode = req.query.areaCode || '86';

    /* 用户直接进入第二个页面的情况 */
    if (!_.get(req, 'session.backupCaptch.verifyResult')) {
        return res.redirect(helpers.urlFormat('/'));
    }

    res.render('back/mobile-code', Object.assign({
        module: 'passport',
        page: 'back-code',
        title: '找回密码-通过手机号'
    }, {
        // backUrl: helpers.urlFormat('/passport/back/mobile'),
        headerText: '找回密码',
        isPassportPage: true,
        backCode: true,
        areaCode: areaCode,
        phoneNum: phoneNum,
        verifySrc: helpers.urlFormat('/passport/back/generatecodeimg.png', {t: Date.now()})
    }));
};

/**
 * 校验手机验证码
 */
const verifyCodeByMobileAPI = (req, res, next) => {
    let phoneNum = req.body.phoneNum || '';
    let code = req.body.code || '';
    let areaCode = req.body.areaCode || '86';

    service.validateMobileCodeAsync(phoneNum, code, areaCode)
        .then(result => {
            if (result.code === 200) {
                res.json({
                    code: 200,
                    data: helpers.urlFormat('/passport/back/backcode', {
                        phoneNum: phoneNum,
                        token: result.data.token,
                        areaCode: areaCode
                    })
                });
            } else {
                res.json({
                    code: 400,
                    message: '验证码失败'
                });
            }
        })
        .catch(next);
};

/**
 * 找回密码页面,设置新密码页面-手机
 */
const setNewPasswordByMobilePage = (req, res) => {
    let phoneNum = req.query.phoneNum || '';
    let token = req.query.token || '';
    let areaCode = req.query.areaCode || '86';
    let code = req.query.code || '';

    if (!(code || (token && helpers.verifyMobile(phoneNum)))) {
        res.redirect(400);
        return;
    }

    res.render('back/new-password', Object.assign({
        module: 'passport',
        page: 'back-new-password',
        title: '找回密码-输入新密码'
    }, {
        // backUrl: SIGN_IN,
        headerText: '找回密码',
        isPassportPage: true,
        backNewPwd: true,
        phoneNum: phoneNum,
        token: token,
        areaCode: areaCode,
        code: code
    }));
};

/**
 * 根据手机验证码修改密码
 */
const setNewPasswordByMobileAPI = (req, res, next) => {
    let phoneNum = req.body.phoneNum || '';
    let token = req.body.token || '';
    let areaCode = req.body.areaCode || '86';
    let newPwd = req.body.password || '';

    service.modifyPasswordByMobileAsyncAes(phoneNum, token, newPwd, areaCode)
        .then(result => {
            if (result.code === 200) {
                res.json({
                    code: 200,
                    data: SIGN_IN
                });
            } else {
                res.json({
                    code: 400,
                    message: '修改密码失败'
                });
            }
        })
        .catch(next);
};

module.exports = {
    indexEmailPage,
    sendCodeToEmailAPI,
    resendCodeToEmailAPI,
    backSuccessByEmailPage,
    setNewPasswordByEmailAPI,
    indexMobilePage,
    sendCodeToMobileAPI,
    verifyCodeByMobilePage,
    verifyCodeByMobileAPI,
    setNewPasswordByMobilePage,
    setNewPasswordByMobileAPI,
    generateCodeImg
};