Blame view

apps/passport/controllers/sms.js 9.01 KB
陈轩 authored
1 2
/* eslint no-unused-vars: ["error", { "args": "none" }] */
'use strict';
陈轩 authored
3
const _ = require('lodash');
4
const co = Promise.coroutine;
5
const moment = require('moment');
陈轩 authored
6
const cookie = global.yoho.cookie;
郭成尧 authored
7
const config = global.yoho.config;
8
const utils = require(global.utils);
郭成尧 authored
9
const RegServiceModel = require('../models/reg-service');
郭成尧 authored
10
const PhoneServiceModel = require('../models/phone-service');
郭成尧 authored
11
const AuthHelperModel = require('../models/auth-helper');
12
const LoginNewModel = require('../models/login-new');
陈轩 authored
13 14 15

// constrant
const CODE_REQUIRED = '请输入校验码';
陈轩 authored
16
const PASSWORD_REQUIRED = '请输入密码';
陈轩 authored
17
const PASSWORD_LENGTH_ERROR = '密码6-20位,请重新输入';
陈轩 authored
18
const BAD_PASSWORD = '密码格式不正确';
陈轩 authored
19
const LOGIN_SUCCSS = '登录成功';
陈轩 authored
20
const VERIFY_ERROR = '校验失败';
陈轩 authored
21
22
class SmsLogin {
陈轩 authored
23
24 25
    smsLoginPage(req, res, next) {
        _.set(req.session, 'smsLogin.step', 1);
陈轩 authored
26
27 28 29
        if (req.session.captchaValidCount == null) { // eslint-disable-line
            req.session.captchaValidCount = 5;
        }
陈轩 authored
30
31 32 33 34 35 36 37 38 39 40 41 42 43
        co(function* () {
            let bannerData = yield req.ctx(LoginNewModel).getTopBanner();
            let banner = _.get(bannerData, 'data[0].data[0].src', '');

            // 是否打开账号登录
            let openPassword = !_.get(req.app.locals.wap, 'close.passwordLogin', false);

            res.render('sms/sms-login-new', {
                module: 'passport',
                page: 'sms-login-new',
                width750: true,
                localCss: true,
                banner: banner,
郭成尧 authored
44
                countrys: req.ctx(RegServiceModel).getAreaData(), // 地区信息列表
郭成尧 authored
45
                captchaShow: req.yoho.captchaShow,
46 47 48 49 50 51 52 53 54 55 56 57 58 59
                backUrl: 'javascript:history.go(-1)', // eslint-disable-line
                loginUrl: '/passport/login',
                registerUrl: '/passport/reg/index', // 注册的URL链接
                aliLoginUrl: '/passport/login/alipay', // 支付宝快捷登录的URL链接
                weiboLoginUrl: '/passport/login/sina', // 微博登录的URL链接
                qqLoginUrl: '/passport/login/qq', // 腾讯QQ登录的URL链接
                wechatLoginUrl: '/passport/login/wechat', // 微信登录的URL链接
                internationalUrl: '/passport/international', // 国际号登录的URL链接
                phoneRetriveUrl: '/passport/back/mobile', // 通过手机号找回密码的URL链接
                emailRetriveUrl: '/passport/back/email', // 通过邮箱找回密码的URL链接
                isWechat: req.yoho.isWechat,
                openPassword
            });
        })().catch(next);
陈轩 authored
60 61
    }
62 63 64 65 66 67
    /**
     *  step1 的表单提交验证
     */
    indexCheck(req, res, next) {
        let area = req.body.area = (req.body.area || '').trim();
        let mobile = req.body.mobile = (req.body.mobile || '').trim();
毕凯 authored
68
        let udid = req.cookies.udid;
郭成尧 authored
69
        let captcha = req.body.captcha;
70 71 72 73
        let errorData = {
            code: 400,
            message: ''
        };
陈轩 authored
74
郭成尧 authored
75
        // 简单数据校验
76
        if ([area, mobile].some(val => val === '')) {
郭成尧 authored
77
            return res.json(Object.assign(errorData, { message: '请填写手机号' }));
78
        }
79
郭成尧 authored
80 81 82 83 84
        let params = {
            mobile, area, type: 1, udid, captcha
        };

        if (req.body.geetest_challenge) {
郭成尧 authored
85 86
            params.captcha = '';
            params.superCapture = config.superCapture;
郭成尧 authored
87 88
        }
郭成尧 authored
89
        co(function* () {
郭成尧 authored
90
            let sendSmsResult = yield req.ctx(PhoneServiceModel).sendSMS(params);
郭成尧 authored
91 92 93

            res.json(sendSmsResult);
        })().catch(next);
陈轩 authored
94 95
    }
96
    tokenBefore(req, res, next) {
97
98 99 100
        let step = _.get(req.session, 'smsLogin.step');
        let count = _.get(req.session, 'smsLogin.count');
        let interval = _.get(req.session, 'smsLogin.interval');
101
陈轩 authored
102
103
        if (!req.xhr || step !== 2) {
毕凯 authored
104
            return next();
105
        }
106
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
        let now = Date.now();

        // 重发次数用完了, 回冻结5min
        //      1. 过了冻结期, count 重设为 5次
        //      2. 没过冻结期, end
        // 没有用完, 判断是否请求太频繁
        let during = moment.duration(interval - now, 'ms').minutes();
        let message = `请${during}分钟后再试`;

        if (!count) {
            if (interval > now) {
                return res.json({
                    code: 400,
                    message: message,
                    during: Math.ceil((interval - now) / 1000)
                });
            } else {
                _.set(req.session, 'smsLogin.count', 5);
            }
        } else if (interval > now) {
陈轩 authored
127
            return res.json({
128 129
                code: 429,
                message: message
陈轩 authored
130 131
            });
        }
132 133

        next();
陈轩 authored
134 135
    }
136 137 138
    checkBefore(req, res, next) {
        let code = req.query.code = (req.query.code || '').trim();
        let step = _.get(req.session, 'smsLogin.step');
陈轩 authored
139
140
        if (!req.xhr && step !== 2) {
毕凯 authored
141
            return next();
142
        }
陈轩 authored
143
144 145 146 147 148 149
        if (!code) {
            return res.json({
                code: 404,
                message: CODE_REQUIRED
            });
        }
陈轩 authored
150
151 152
        next();
    }
陈轩 authored
153
154 155
    // AJAX 校验验证码 in step2
    check(req, res, next) {
郭成尧 authored
156 157 158 159
        let code = req.query.code;
        let mobile = req.query.mobile;
        let area = req.query.area;
        let shopping_key = cookie.getShoppingKey(req); // eslint-disable-line
郭成尧 authored
160
        let from = req.cookies.from || 'yohobuy';
161 162 163 164 165 166 167 168

        if (!mobile || !area) {
            res.json({
                code: 401,
                message: VERIFY_ERROR
            });
            return;
        }
陈轩 authored
169
170
        req.ctx(PhoneServiceModel).verifySMS(mobile, area, code, 1).then(r2 => {
郭成尧 authored
171 172 173 174 175 176

            // 验证码 校验异常
            if (r2.code !== 200) {
                res.json(r2);
                return;
            }
177
郭成尧 authored
178 179 180 181
            // 校验失败
            if (r2.data.is_pass !== 'Y') {
                res.json({
                    code: 401,
郭成尧 authored
182
                    message: '短信验证码错误'
郭成尧 authored
183
                });
陈轩 authored
184
郭成尧 authored
185 186
                return;
            }
陈轩 authored
187
郭成尧 authored
188 189 190 191 192 193 194 195 196 197
            // 手机号码已注册 --> 直接登录
            req.ctx(PhoneServiceModel).autoSignin({
                profile: mobile,
                code: r2.data.code,
                area,
                shopping_key,
                from
            }).then(info => {
                if (info.code !== 200) {
                    return Promise.reject(info);
198 199
                }
郭成尧 authored
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
                res.cookie('_LOGIN_TYPE', 5, {
                    domain: 'm.yohobuy.com'
                });
                return req.ctx(AuthHelperModel).syncUserSession(info.data.uid, req, res, info.data.session_key);
            }).then((authData) => {
                res.json({
                    code: 200,
                    message: LOGIN_SUCCSS,
                    redirect: _.get(authData, 'refer') || utils.refererLimit(req.cookies.refer)
                });

                delete req.session.smsLogin;
            }).catch(error => {
                res.json(error);
            });
        }).catch(next);
216
    }
陈轩 authored
217
218 219 220
    // AJAX 短信登录 设置密码 in step3
    password(req, res, next) {
        let step = _.get(req.session, 'smsLogin.step');
陈轩 authored
221
222 223 224
        if (step !== 3) {
            return next();
        }
陈轩 authored
225 226

227 228 229 230
        let data = {
            code: '400',
            message: BAD_PASSWORD
        };
陈轩 authored
231
232 233 234 235 236
        let mobile = _.get(req.session, 'smsLogin.mobile');
        let area = _.get(req.session, 'smsLogin.area');
        let password = (req.body.password || '').trim();
        let registerCode = req.body.registerCode || '';
        let clientIp = req.yoho.clientIp || '';
郭成尧 authored
237
        let from = req.cookies.from || 'yohobuy';
陈轩 authored
238
239 240 241 242
        if (!password) {
            data.message = PASSWORD_REQUIRED;
            return res.json(data);
        }
陈轩 authored
243
244 245 246 247
        if (password.length < 6 || password.length > 20) {
            data.message = PASSWORD_LENGTH_ERROR;
            return res.json(data);
        }
陈轩 authored
248
249 250 251
        if (!/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/.test(password)) {
            return res.json(data);
        }
陈轩 authored
252
253 254
        // 购物车key
        let shoppingKey = cookie.getShoppingKey(req);
陈轩 authored
255 256

257 258
        // 验证注册的标识码是否有效
        let resultCopy = null;
陈峰 authored
259
郭成尧 authored
260
        req.ctx(RegServiceModel).regMobileAes(area, mobile, password,
郭成尧 authored
261
            shoppingKey, registerCode, '0', clientIp, from).then(result => {
262 263 264 265 266 267 268
            if (!result.code || result.code !== 200) {
                return res.send(result);
            }
            if (!result.data || !result.data.uid) {
                return res.send(result);
            }
            resultCopy = result;
陈轩 authored
269
郭成尧 authored
270
            return req.ctx(AuthHelperModel).syncUserSession(result.data.uid, req, res, result.data.session_key);
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
        }).then((authData) => {
            if (!resultCopy) {
                return;
            }
            res.json({
                code: 200,
                message: LOGIN_SUCCSS,
                redirect: _.get(authData, 'refer') || utils.refererLimit(req.cookies.refer)
            });
            delete req.session.smsLogin;
        }).catch(next);
    }
}

module.exports = new SmsLogin();