'use strict'; const assert = require('assert'); const _ = require('lodash'); const { ObjectId } = require('mongoose').Types; const { CrudService } = require('naf-framework-mongoose/lib/service'); const { BusinessError, ErrorCode } = require('naf-core').Error; const jwt = require('jsonwebtoken'); const uuid = require('uuid'); class LoginService extends CrudService { constructor(ctx) { super(ctx, 'login'); this.uModel = this.ctx.model.User; this.stuModel = this.ctx.model.Student; this.tModel = this.ctx.model.Teacher; this.schModel = this.ctx.model.School; this.hModel = this.ctx.model.Headteacher; } async login(data) { const { mobile, passwd } = data; assert(mobile, 'mobile不能为空'); // assert(/^\d{11}$/i.test(mobile), 'mobile无效'); assert(passwd, 'passwd不能为空'); const res = await this.uModel.findOne({ mobile }, '+passwd'); if (!res) { throw new BusinessError(ErrorCode.USER_NOT_EXIST); } // 验证密码 console.log('sjk-->' + res.passwd.secret); console.log('sr-->' + passwd); if (res.passwd.secret !== passwd) { throw new BusinessError(ErrorCode.BAD_PASSWORD); } return await this.createJwt(res); } // 创建登录Token async createJwt({ _id, name, mobile, openid, type, uid, status }) { const { secret, expiresIn = '1d', issuer = type } = this.config.jwt; const subject = mobile; let _userid = ''; let res = {}; // 身份,0、中心管理元1、班主任用户2、学校用户3、教师4、学生 if (type === '0') { _userid = _id.toString(); res = { userid: _userid, name, type, id: _id, status }; } else if (type === '1') { _userid = uid.toString(); const result = await this.hModel.findById(_userid); res = { userid: _userid, name, type, id: _id, status }; } else if (type === '2') { _userid = uid.toString(); const result = await this.schModel.findById(_userid); res = { userid: _userid, code: result.code, name, type, id: _id, status }; } else if (type === '3') { _userid = uid.toString(); const result = await this.tModel.findById(_userid); res = { userid: _userid, schid: result.schid, schname: result.schname, name, subid: result.subid, type, id: _id, status }; } else if (type === '4') { _userid = uid; console.log('进入查询--' + _userid); const result = await this.stuModel.findById(_userid); console.log(result); res = { userid: _userid, schid: result.schid, schname: result.school_name, termid: result.termid, batchid: result.batchid, classid: result.classid, bedroomid: result.bedroomid, bedroom: result.bedroom, job: result.job, name, type, id: _id, status, planid: result.planid }; } const token = await jwt.sign(res, secret, { expiresIn, issuer, subject }); return token; } // 微信校验mq接口 async wxcheck(data) { const { qrcode, openid } = data; assert(qrcode, 'qrcode不能为空'); assert(openid, 'openid不能为空'); // TODO: 发布扫码成功消息 console.log('qrcode-->' + qrcode); const { mq } = this.ctx; const ex = 'qrcode.login'; const parm = { durable: true, headers: { openid, } }; if (mq) { await mq.topic(ex, qrcode, 'scaned', parm); } } // 微信登录接口 async wxlogin(data) { const { qrcode, openid } = data; assert(qrcode, 'qrcode不能为空'); assert(openid, 'openid不能为空'); const res = await this.uModel.findOne({ openid }); if (!res) { throw new BusinessError(ErrorCode.USER_NOT_EXIST); } const result = await this.createJwt(res); return result; } async userbind(data) { const { qrcode, openid } = data; assert(qrcode, 'qrcode不能为空'); assert(openid, 'openid不能为空'); const key = `naf:qrcode:login:${qrcode}`; const status = await this.app.redis.get(key); if (!status) { throw new BusinessError(ErrorCode.SERVICE_FAULT, '二维码已过期'); } if (status !== 'pending') { throw new BusinessError(ErrorCode.SERVICE_FAULT, '二维码状态无效'); } const res = await this.uModel.findOne({ openid }); if (!res) { throw new BusinessError(ErrorCode.USER_NOT_EXIST); } const result = await this.createJwt(res); // TODO: 修改二维码状态,登录凭证保存到redis await this.app.redis.set(key, `scaned:${result}`, 'EX', 600); // TODO: 发布扫码成功消息 const { mq } = this.ctx; const ex = 'qrcode.login'; if (mq) { await mq.topic(ex, qrcode, 'scaned', { durable: true }); } } /** * 创建二维码 * 随机生成二维码,并保存在Redis中,状态初始为pending * 状态描述: * pending - 等待扫码 * consumed - 使用二维码登录完成 * ${jwt.token} - Jwt登录凭证 */ async createQrcode() { const qrcode = uuid(); const key = `naf:qrcode:login:${qrcode}`; await this.app.redis.set(key, 'pending', 'EX', 600); return qrcode; } // 使用二维码换取登录凭证 async qrcodeLogin(qrcode) { assert(qrcode, 'qrcode不能为空'); const key = `naf:qrcode:login:${qrcode}`; const val = await this.app.redis.get(key); if (!val) { throw new BusinessError(ErrorCode.SERVICE_FAULT, '二维码已过期'); } const [ status, token ] = val.split(':', 2); if (status !== 'scaned' || !token) { throw new BusinessError(ErrorCode.SERVICE_FAULT, '二维码状态无效'); } // TODO: 修改二维码状态 await this.app.redis.set(key, 'consumed', 'EX', 600); return { token }; } // 检查二维码状态 async checkQrcode(qrcode) { assert(qrcode, 'qrcode不能为空'); const key = `naf:qrcode:login:${qrcode}`; const val = await this.app.redis.get(key); if (!val) { throw new BusinessError(ErrorCode.SERVICE_FAULT, '二维码已过期'); } const [ status ] = val.split(':', 2); return { status }; } } module.exports = LoginService;