login-service.js 5.91 KB
'use strict';

const md5 = require('md5');
const uuid = require('uuid');
const _ = require('lodash');

const aes = require('./aes-pwd');
const cache = global.yoho.cache;
const sign = global.yoho.sign;
const cookie = global.yoho.cookie;
const config = global.yoho.config;
const crypto = global.yoho.crypto;
const authcode = require(`${global.utils}/authcode`);
const AUTH_TIME = 2592000000;

const Promise = require('bluebird');

const CartService = require('./cart-service');
const UserService = require('./user-service');
const LoginApi = require('./login-api');
const logger = global.yoho.logger;

module.exports = class extends global.yoho.BaseModel {
    constructor(ctx) {
        super(ctx);
        this.api = new LoginApi(ctx);
        this.cartService = new CartService(ctx);
        this.userService = new UserService(ctx);

        this.checkByQrCode = this.api.checkByQrCode.bind(this.api);
        this.sendPasswordBySMS = this.api.sendPasswordBySMS.bind(this.api);
        this.checkUserExitBySMS = this.api.checkUserExitBySMS.bind(this.api);
        this.verifyPasswordBySMS = this.api.verifyPasswordBySMS.bind(this.api);
        this.signinByOpenID = this.api.signinByOpenID.bind(this.api);
    }

    signin(type, area, profile, password, shoppingKey, close, id, captcha) {
        let loginBy = {
            password: this.api.signinByPasswordWithAes.bind(this.api),
            sms: this.api.signinBySMS.bind(this.api),
            qrcode: this.api.signinByQrCode.bind(this.api)
        };

        if (close) {
            delete loginBy.password;
        }

        return loginBy[type](area, profile, password, shoppingKey, id, captcha);
    }

    syncUserSession(user, req, res) {
        let uid = user.uid;
        let sessionKey = user.session_key;

        if (sessionKey) {
            cache.set(`java_session_key:${uid}`, sessionKey).catch(() => {
                logger.error('write session key fail');
            });
        }

        let uidObj = {
            toString() {
                return this.uid;
            },
            uid: uid,
            sessionKey: sessionKey,
            isValid() {
                return this.uid && this.sessionKey;
            }
        };

        return Promise.all([
            this.userService.profile(uidObj),
            this.cartService.goodsCount(uidObj),
            this.userService.checkNoCertEmailUser(uidObj)
                .catch(err => {
                    logger.error(`checkNoCertEmailUser${uid}err: ${err}`);
                })
        ]).spread((userInfo, count, isTipCert) => {
            let salt = uuid.v4().substr(0, 8);
            let saltedUid = uid + salt;

            let saltedToken = sign.makeToken(saltedUid);
            let publicToken = saltedToken + salt;

            let data = userInfo.data || {};

            if (!userInfo.data) { // 个新信息接口可能限流,即使限流也仍然可以登录
                logger.error(`app.passport.profile api error${uid}】`);
            }

            let encryptionUid = aes.encryptionUid(uid);


            let uidCookie =
                `${encodeURIComponent(data.profile_name || '')}::${encryptionUid}::${_.get(data, 'vip_info.title', '')}::${saltedToken}`; // eslint-disable-line
            let isStudent = _.get(data, 'vip_info.is_student') || 0;

            res.cookie('_UID', uidCookie, {
                domain: config.cookieDomain
            });

            // 个性化推荐id
            res.cookie('_PRID', encryptionUid, {
                expires: new Date(Date.now() + 86400 * 360),
                domain: config.cookieDomain
            });

            res.cookie('isStudent', isStudent, {
                domain: config.cookieDomain
            });

            res.cookie('_SESSION_KEY', authcode(sessionKey, '_SESSION_KEY', AUTH_TIME, 'encode'), {
                domain: config.cookieDomain,
                httpOnly: true
            });

            // 购物车中商品的数量
            res.cookie('_g', JSON.stringify({
                _k: cookie.getShoppingKey(req),
                _nac: count,
                _ac: 0,
                _c: 1
            }), {
                domain: config.cookieDomain
            });


            req.session.TOKEN_ = publicToken;
            req.session.LOGIN_UID_ = uid;
            req.session.USER_MOBILE = data.mobile;
            req.session.SESSION_TYPE = config.app;
            req.session.SESSION_KEY = sessionKey;

            res.cookie('_TOKEN', publicToken, {
                domain: config.cookieDomain,
                httpOnly: true
            });

            // 弱密码设置
            if (user.canSkip && user.token) {
                req.session.canSkip = user.canSkip;
                req.session.CSToken = user.token;
            } else {
                delete req.session.canSkip;
                delete req.session.CSToken;
            }

            if (isTipCert && isTipCert.code === 200 && isTipCert.data) {
                return isTipCert.data.isNeedPopupRelated === 'Y';
            }

        });
    }

    rememberAccount(accountInfo, req, res) {
        let aWeek = (new Date()).getTime() / 1000 + 504000; // 504000-一周
        let rememKey = md5(md5(accountInfo.account + accountInfo.password + accountInfo.area));

        res.cookie('isRemember', true, {
            maxAge: aWeek,
            domain: config.cookieDomain
        });
        res.cookie('remem', rememKey, {
            maxAge: aWeek,
            domain: config.cookieDomain
        });

        // if (!cache.get(rememKey)) {
        //     cache.set(rememKey, accountInfo, aWeek);
        // }
    }

    fetchByQrCode() {
        let code = {
            qrcode: uuid.v4(),
            time: new Date().getTime()
        };

        const encodeStr = _.flow(JSON.stringify, _.partial(crypto.encryption, null), encodeURIComponent);

        return Promise.resolve({
            data: {
                code: encodeStr(code)
            },
            code: 200
        });
    }
};