login.service.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import { Config, Inject, Provide } from '@midwayjs/core';
  2. import { get } from 'lodash';
  3. import { RoleService } from '../service/system/role.service';
  4. import { RedisService } from '@midwayjs/redis';
  5. import * as Crypto from 'crypto-js';
  6. import { Context } from '@midwayjs/koa';
  7. import { ServiceError, ErrorCode } from '../error/service.error';
  8. import { InjectEntityModel } from '@midwayjs/typeorm';
  9. import { Equal, Repository } from 'typeorm';
  10. import { LoginDTO, LoginType, UPwdDTO } from '../interface/login.interface';
  11. import { Opera } from '../frame/dbOpera';
  12. import { Admin } from '../entity/system/admin.entity';
  13. import * as bcrypt from 'bcryptjs';
  14. import { User } from '../entity/system/user.entity';
  15. @Provide()
  16. export class LoginService {
  17. @Inject()
  18. roleService: RoleService;
  19. @Inject()
  20. ctx: Context;
  21. @Config('loginSign')
  22. loginSign;
  23. @Config('jwt.secret')
  24. jwtSecret;
  25. @Config('jwt.expiresIn')
  26. jwtExpiresIn;
  27. @Inject()
  28. redisService: RedisService;
  29. @InjectEntityModel(Admin)
  30. adminModel: Repository<Admin>;
  31. @InjectEntityModel(User)
  32. userModel: Repository<User>;
  33. async onePointLogin(loginVo) {
  34. const { id, role } = loginVo;
  35. const rediskey = `${this.loginSign}:${role}:${id}`;
  36. // 随机字符串 验证用户登录用
  37. const str = this.randomStr();
  38. // 拼接成token内的登录code 加密前数据
  39. const val = `${rediskey}:${str}`;
  40. // 加密后存入token内
  41. const code = Crypto.AES.encrypt(val, this.jwtSecret).toString();
  42. // 设置redis登录记录 将 随机字符串存在redis中. 验证时需要将加密的字符串解密,解密后和redis中的对比验证
  43. await this.redisService.set(rediskey, str, 'EX', this.jwtExpiresIn);
  44. return code;
  45. }
  46. /**
  47. * 账密登录
  48. * @param data 用户名和密码
  49. * @param type 用户类型
  50. * @returns 用户信息/空值
  51. */
  52. async loginByAccount(data: LoginDTO, type: LoginType) {
  53. let model;
  54. if (type === LoginType.Admin) model = this.adminModel;
  55. else model = this.userModel;
  56. const user = await model.createQueryBuilder('t').where('t.account = :account', { account: data.account }).addSelect('t.password').getOne();
  57. if (!user) throw new ServiceError(ErrorCode.USER_NOT_FOUND);
  58. await this.checkAccountCanLogin(user, type);
  59. const result = bcrypt.compareSync(data.password, user.password);
  60. if (!result) throw new ServiceError(ErrorCode.BAD_PASSWORD);
  61. return user;
  62. }
  63. /**
  64. * 检查用户是否可以登录(从用户本身和角色检查)
  65. * @param user 用户信息
  66. * @param type 用户类型
  67. */
  68. async checkAccountCanLogin(user, type: LoginType) {
  69. // 判断是否可以使用:
  70. // 管理员: 超级管理员无视,直接往下; 普通管理员需要查看is_use是不是'0'
  71. // 其他用户需要看status是不是'1';
  72. if (type === 'Admin') {
  73. if (get(user, 'is_super') === '1') {
  74. if (get(user, 'is_use') === '1') throw new ServiceError(ErrorCode.USER_IS_DISABLED);
  75. }
  76. } else {
  77. if (get(user, 'status') !== '1') throw new ServiceError(ErrorCode.USER_IS_DISABLED);
  78. const qb = [
  79. { column: 'code', opera: [Opera.Equal], value: type },
  80. { column: 'is_use', opera: [Opera.Equal], value: '0' },
  81. ];
  82. const role = await this.roleService.fetch(qb);
  83. if (!role) throw new ServiceError(ErrorCode.ROLE_IS_DISABLED);
  84. }
  85. }
  86. // 修改密码
  87. async updatePwd(data: UPwdDTO, type: LoginType) {
  88. let model;
  89. if (type === LoginType.Admin) model = this.adminModel;
  90. else model = this.userModel;
  91. const user = await model.findOne({ where: { id: Equal(data.id) } });
  92. if (!user) new ServiceError(ErrorCode.USER_NOT_FOUND);
  93. await model.update({ id: data.id }, { password: data.password });
  94. }
  95. // 需要改的时候再用
  96. async wxAppLogin(openid: string, type: LoginType) {
  97. let model;
  98. if (type === LoginType.Admin) model = this.adminModel;
  99. else model = this.userModel;
  100. const user = await model.findOne({ where: { openid: Equal(openid) } });
  101. if (!user) throw new ServiceError(ErrorCode.USER_NOT_FOUND);
  102. return user;
  103. }
  104. randomStr(len = 32) {
  105. return Math.random().toString(36).slice(-len);
  106. }
  107. }