123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- 'use strict';
- const { CrudService } = require('naf-framework-mongoose-free/lib/service');
- const { BusinessError, ErrorCode } = require('naf-core').Error;
- const _ = require('lodash');
- const assert = require('assert');
- //
- class UserService extends CrudService {
- constructor(ctx) {
- super(ctx, 'user');
- this.redis = this.app.redis;
- this.model = this.ctx.model.User.User;
- this.bindEmailKey = 'bindEmail:';
- this.httpUtil = this.ctx.service.util.httpUtil;
- this.emailServiceUrl = _.get(this.app, 'config.httpPrefix.email');
- this.emailServiceConfig = _.get(this.app, 'config.emailConfig.config');
- this.bindPhoneKey = 'bindPhone:';
- this.smsServiceUrl = _.get(this.app, 'config.httpPrefix.sms');
- this.smsServiceConfig = _.get(this.app, 'config.smsConfig.config');
- this.phoneLoginKey = 'phoneLogin:';
- this.conenctCode = '&&';
- }
- async beforeCreate(data) {
- const openid = _.get(data, 'openid');
- const phone = _.get(data, 'phone');
- if (!openid && phone) {
- const num = await this.model.count({ phone });
- if (num > 0) throw new BusinessError(ErrorCode.DATA_EXISTED, '该手机号已注册');
- } else if (openid) {
- const num = await this.model.count({ openid });
- if (num > 0) throw new BusinessError(ErrorCode.DATA_EXISTED, '该微信号已注册');
- }
- return data;
- }
- async resetPwd({ id }, { password }) {
- const data = await this.model.findById(id);
- if (!data) throw new BusinessError(ErrorCode.USER_NOT_EXIST);
- data.password = { secret: password };
- await data.save();
- }
- /**
- * 登陆
- * @param {Object} body 登陆参数
- * @param body.phone 账户
- * @param body.password 密码
- */
- async login({ phone, password }) {
- const { populate } = this.getRefMods();
- let user = await this.model.findOne({ phone }, '+password').populate(populate);
- if (!user) throw new BusinessError(ErrorCode.USER_NOT_EXIST);
- const { password: upwd, status } = user;
- if (status !== '0') throw new BusinessError(ErrorCode.USER_NOT_BIND, '该账号处于禁止使用状态');
- if (password !== upwd.secret) throw new BusinessError(ErrorCode.BAD_PASSWORD);
- // // 使用redis存储,后续的任何操作进行token的校验
- // await this.setUserInRedis(user);
- user = JSON.parse(JSON.stringify(user));
- delete user.password;
- delete user.meta;
- delete user.__v;
- const token = this.ctx.service.util.jwt.encrypt(user);
- return token;
- }
- /**
- * 微信登录
- * @param {Object} body 登陆参数
- * @param body.openid 微信小程序的openid
- */
- async wxLogin({ openid }) {
- const { populate } = this.getRefMods();
- const user = await this.model.findOne({ openid }).populate(populate);
- if (!user) throw new BusinessError(ErrorCode.USER_NOT_EXIST);
- const { status } = user;
- if (status !== '0') throw new BusinessError(ErrorCode.USER_NOT_BIND, '该账号处于禁止使用状态');
- delete user.meta;
- delete user.__v;
- const token = this.ctx.service.util.jwt.encrypt(user);
- return token;
- }
- /**
- * 绑定邮箱验证码
- * @param {Object} body 请求体
- * @param body.id 用户id
- * @param body.email 用户要绑定的邮箱
- */
- async toBindEmail({ id, email }) {
- const code = _.random(100000, 999999);
- const value = `${email}${this.conenctCode}${code}`;
- await this.redis.set(`${this.bindEmailKey}${id}`, value, 'EX', 300);
- // 发邮件
- const data = { config: this.emailServiceConfig, template: 'bindEmail', receiver: email, params: { code } };
- const url = `${this.emailServiceUrl}/sendEmail`;
- await this.httpUtil.cpost(url, data);
- }
- async checkBindEmail({ code, id, email }) {
- const redisData = await this.redis.get(`${this.bindEmailKey}${id}`);
- if (!redisData) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '验证码已超时');
- const arr = redisData.split(this.conenctCode);
- const rEmail = _.head(arr);
- const rCode = _.last(arr);
- if (code !== rCode) throw new BusinessError(ErrorCode.DATA_INVALID, '验证码错误');
- if (email !== rEmail) throw new BusinessError(ErrorCode.DATA_INVALID, '要绑定的邮箱与接收验证码的邮箱不是同一个邮箱');
- await this.model.updateOne({ _id: id }, { email });
- await this.redis.del(`${this.bindEmailKey}${id}`);
- }
- /**
- * 绑定手机验证码
- * @param {Object} body 请求体
- * @param body.id 用户id
- * @param body.phone 用户要绑定的手机
- */
- async toBindPhone({ id, phone }) {
- const num = await this.model.count({ phone });
- if (num > 0) throw new BusinessError(ErrorCode.DATA_EXISTED, '手机号已被绑定');
- const code = _.random(100000, 999999);
- const value = `${phone}${this.conenctCode}${code}`;
- await this.redis.set(`${this.bindPhoneKey}${id}`, value, 'EX', 300);
- // 发短信
- const data = { config: this.smsServiceConfig, template: 'bind', phone, params: { code } };
- const url = `${this.smsServiceUrl}/sendMessage`;
- await this.httpUtil.cpost(url, data);
- }
- async checkBindPhone({ code, id, phone }) {
- const redisData = await this.redis.get(`${this.bindPhoneKey}${id}`);
- if (!redisData) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '验证码已超时');
- const arr = redisData.split(this.conenctCode);
- const rphone = _.head(arr);
- const rCode = _.last(arr);
- if (code !== rCode) throw new BusinessError(ErrorCode.DATA_INVALID, '验证码错误');
- if (phone !== rphone) throw new BusinessError(ErrorCode.DATA_INVALID, '要绑定的手机号与接收验证码的手机号不是同一个手机号');
- await this.model.updateOne({ _id: id }, { phone });
- await this.redis.del(`${this.bindPhoneKey}${id}`);
- }
- // 发送登陆验证码
- async toLoginByCode({ phone }) {
- const code = _.random(100000, 999999);
- const value = `${phone}${this.conenctCode}${code}`;
- await this.redis.set(`${this.phoneLoginKey}${phone}`, value, 'EX', 300);
- // 发短信
- const data = { config: this.smsServiceConfig, template: 'login', phone, params: { code } };
- const url = `${this.smsServiceUrl}/sendMessage`;
- await this.httpUtil.cpost(url, data);
- }
- // 检查登陆验证码,然后登陆
- async checkLoginCode({ phone, code }) {
- const redisData = await this.redis.get(`${this.phoneLoginKey}${phone}`);
- if (!redisData) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '验证码已超时');
- const arr = redisData.split(this.conenctCode);
- const rphone = _.head(arr);
- const rCode = _.last(arr);
- if (code !== rCode) throw new BusinessError(ErrorCode.DATA_INVALID, '验证码错误');
- if (phone !== rphone) throw new BusinessError(ErrorCode.DATA_INVALID, '要登陆的手机号与接收验证码的手机号不是同一个手机号');
- const { populate } = this.getRefMods();
- const user = await this.model.findOne({ phone }).populate(populate);
- if (!user) throw new BusinessError(ErrorCode.USER_NOT_EXIST);
- const { status } = user;
- if (status !== '0') throw new BusinessError(ErrorCode.USER_NOT_BIND, '该账号处于禁止使用状态');
- delete user.meta;
- delete user.__v;
- const token = this.ctx.service.util.jwt.encrypt(user);
- return token;
- }
- /**
- * 删除用户
- * @param {Object} param 地址参数
- * @param {String} param.key 就是key
- * @param {String} param.target 操作对象
- */
- async delete({ key, target }) {
- const { opera_id, target: rt } = await this.ctx.service.util.user.getKeyData(key);
- const admin = _.get(this.ctx, 'admin');
- const _id = _.get(admin, '_id');
- if (opera_id !== _id) throw new BusinessError(ErrorCode.DATA_INVALID, '不是同一个操作人,操作无效');
- if (target !== rt) throw new BusinessError(ErrorCode.DATA_INVALID, '操作对象不是同一个数据,操作无效');
- await this.model.deleteOne({ _id: target });
- }
- async getUserIsLeader(id) {
- const user = await this.model.findById(id, { is_leader: 1 }).lean();
- if (!user) return false;
- const is_leader = _.get(user, 'is_leader', '1');
- return is_leader === '0';
- }
- async changeCacheToken() {
- const user_id = _.get(this.ctx, 'user._id');
- if (!user_id) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到用户信息');
- const user = await this.model.findById(user_id).lean();
- if (user) {
- delete user.meta;
- delete user.__v;
- if (!user.id) user.id = user_id;
- const token = this.ctx.service.util.jwt.encrypt(user);
- return token;
- }
- }
- }
- module.exports = UserService;
|