yunjiuye.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. 'use strict';
  2. const Service = require('egg').Service;
  3. const assert = require('assert');
  4. const _ = require('lodash');
  5. const { BusinessError, ErrorCode } = require('naf-core').Error;
  6. const { ObjectId } = require('mongoose').Types;
  7. const crypto = require('crypto');
  8. // 云就业生成的公钥,用来加密退出登录的参数
  9. const publicKey = `-----BEGIN PUBLIC KEY-----
  10. MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDafDeoNSNhqaj0dEK3bK/nXnGe7QdQHTegc49/jFHtbky3gZle0XKvbqPHv8d9eih89RJe3UOORUhBV6eRkvCLaf8lj+BgI0TyWDgjHg1jGi6MN+LZx9GKZ/Tq+TVPH3Fv/YPGcQADb4lELwSK3F6kRcm1duwcij0bnFhfTA999QIDAQAB
  11. -----END PUBLIC KEY-----`;
  12. // 双困生生成的私钥,用来解密登录的参数
  13. const privateKey = `-----BEGIN ENCRYPTED PRIVATE KEY-----
  14. MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIDrmClOodJAACAggA
  15. MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBDFUSMr1yfAK9Lt9r4Idi5EBIIE
  16. 0JmkwwNWz+ya4IffVvzQS2fEbIRoAcxoBEKaZjLd2cCBQbE/0BODdlEWcJ7Z4Z3k
  17. 1NfDaqQToh+k9sE2C108q2jCETLiLPWodTMAMO0pVHBiiJeh2ZOoDxwyDWsyHYcA
  18. 6S7EhuQPOY7Fd8WKWeYcH1m8TLyL40fmWq0cseCoyvP1M0LRQ5OFKD7+uOYJBQhq
  19. 7pPwuJouorKMUHbxpribrOmr8fspfkglhP6+TZ7p7XzAs6e92mNz1SfiflmChoPH
  20. sqcJb0SJaHCdzblMT/yCF1Gm+h91gpU9L3sJUbivBtjFkX4LsE8DMs15dkPIbWHq
  21. YTJx+2QSOpGp6cK1D7LS8LInptHxI/UGRVYH3FLP1oUJuuFj+Wl7PKvOpZcc5uk1
  22. u5tbHmUkhpJeklqsCWi6brQpPxiQAiCeiqMiTOQLlwiRNTT51waOqrvb60onDHAw
  23. bEWfb0FQ0o3kb1yEQd/qPTJXWPZ96WhM3/7VNGoEDKwCzv5m8G1JbO4ct79iPF5x
  24. Y7rx0uKJFPbekNACRmb9U0f3DpXm8hdgCKVKmbkgG2ZZnnmJg2lzmT72lwQfdcnv
  25. O6IjXVLoDLjAYqjGe6HXQchi5rBHgmoguyHP6nGJ67n50hQ+upecVyp7k7LvuXi/
  26. jHF8/zJfDZaEvjf6CwkePYk9XbOnvyls+RWZM1ZwX4xbk6nbONzo71uRrI0E8sKS
  27. kWFCtvdbNJ//PaugrQNRMTs5z8Q3qMIyXRPXrxPFM/3lECaIEYvRrPyEYfdANqod
  28. JrMru+hbHvutTPhDuOgJ+RVgirwfZpxPQS5aHHXQu8bMps9DEL15i6xKOVX5lqvL
  29. lEL0YmqmRo7Idb9D+l0pyPAg9X1AwTziION/1cOPvWmjGVZqqaBv+jsMVlB+1o0o
  30. BrJBy9SEzw5ya7sYi1BCwO6k7qAsB1qSmnu8Gg/RXAIz6D9nJiJbB5kwusVQretn
  31. RqTj8ldBOgo+1la3hHzW8INTAVrlnmZjNMEGN4olYcJv6vHK9XTk7ruIkteJYD8Y
  32. 2jIFU3evsPTs4ugYxArEmzYsr1ZJR91aWf7naKcUlsap9k2zgHVw7Ks31D8T1OT3
  33. mXQZdkY9hx+0kdh8iSYOkCSa237usV/TbYg12ncB8xSVsMQMNnEQHWIcgFUBeZoo
  34. KQ27ijLmy5YYx8KYDAm7UJZ3Z00OrFa1D5qjippXkrDKbBwM3SrDSSVBtfKMGxyi
  35. epF9hMBs6ecBBSIF9sZg0LHfMlbOIWyNLklHUtdBQ4+vavzbG1V66p0pB7HJp6rp
  36. YC3moNRhHXyUFpvkIis7gFQ4xdE6FMEJsrHeZQHuOzRIB4XlwiCiAIg+IDmnP0hd
  37. 8Sxv0drpFU+zjR2aMr4bfhYdBG35NE/xfOp+ba25yCWCilljCIj46+jD0E2UvSrw
  38. 9iDtf75OXF2njqaLwmnFtHyAOA54IcXi9Y3NaXUXFxmK9iif5UbKa/dR+8rmOCF2
  39. cozCs4Ujribcpgs3cqjkVX0Z12B7YdCZM1Tpj7BgPOLjpi0h0s5wbP9QMm3yb2S2
  40. SKteoIypVcUXdpPqSwXtsUOUSuj7MeNXW2mkmQsH+W/n2Zn5OxgFKZ0JZ4z/OHei
  41. hK1UFYPQ9BEBMzsJ2ttBLwak//hAMaUJDT8EKxEoBdqb
  42. -----END ENCRYPTED PRIVATE KEY-----`;
  43. class YunjiuyeService extends Service {
  44. // 检查用户是否和云就业有关联
  45. // 没关联就直接重定向到关联页
  46. // 有关联就直接去登录
  47. async checkUserIsConnect({ code, org, type }) {
  48. assert(code, '缺少用户标识');
  49. assert(org, '缺少机构');
  50. const yjycModel = this.ctx.model.Yjyconnect;
  51. const result = await yjycModel.findOne({ ycode: code, yorg: org, ytype: type }).lean();
  52. if (!result) return false;
  53. return result.suid;
  54. }
  55. /**
  56. * 用户与云就业关联
  57. * @param {string} type 用户角色
  58. * @param {string} mobile 电话
  59. * @param {string} code 身份编码
  60. * @param {string} org 云就业的组织机构编码
  61. * @param {string} ytype 云就业角色类型
  62. */
  63. async userBind({ type, mobile, code, org, ytype }) {
  64. assert(mobile, '登录账户不能为空');
  65. assert(type, '用户角色不能为空');
  66. assert(ytype, '身份不能为空');
  67. const userModel = this.ctx.model.User;
  68. let res = await userModel.findOne({ mobile, type });
  69. if (!res) {
  70. const userData = { name: code, mobile, type, status: '1' };
  71. // 没有账号,需要创建
  72. // 中心端,直接创建中心端账号即可
  73. // 教师,班主任,学校,对应创建数据,再形成用户数据
  74. if (type === '0') {
  75. // 中心没什么需要处理的
  76. userData.name = code;
  77. } else if (type === '1') {
  78. // 班主任,需要生成班主任数据
  79. const obj = { name: code, mobile };
  80. const res = await this.ctx.model.Headteacher.create(obj);
  81. if (res) userData.uid = ObjectId(res._id).toString();
  82. } else if (type === '2') {
  83. // 学校管理员
  84. const obj = { name: code };
  85. const res = await this.ctx.model.School.create(obj);
  86. if (res) userData.uid = ObjectId(res._id).toString();
  87. } else if (type === '3') {
  88. // 教师
  89. const data = { name: code, phone: mobile };
  90. const res = await this.ctx.model.Teacher.create(data);
  91. if (res) userData.uid = ObjectId(res._id).toString();
  92. }
  93. res = await userModel.create(userData);
  94. }
  95. const yjycModel = this.ctx.model.Yjyconnect;
  96. const obj = { ycode: code, yorg: org, suid: ObjectId(res._id).toString(), ytype };
  97. const isHas = await yjycModel.count({ suid: obj.suid });
  98. if (process.env.NODE_ENV === 'development') {
  99. if (isHas > 0) return obj.suid;
  100. else {
  101. await yjycModel.create(obj);
  102. return obj.suid;
  103. }
  104. } else {
  105. if (isHas > 0) throw new BusinessError(ErrorCode.DATA_EXISTED, '账户已绑定,无需再次绑定');
  106. await yjycModel.create(obj);
  107. return obj.suid;
  108. }
  109. }
  110. // 用户id获取用户信息,登录获取token返回
  111. async userToken(id) {
  112. assert(id, '缺少双困生平台用户标识');
  113. const userModel = this.ctx.model.User;
  114. const userService = this.ctx.service.login;
  115. const user = await userModel.findById(id);
  116. if (!user) throw new BusinessError(ErrorCode.USER_NOT_EXIST);
  117. const token = await userService.createJwt(user);
  118. return token;
  119. }
  120. async getBindInfo(suid) {
  121. const yjycModel = this.ctx.model.Yjyconnect;
  122. const info = await yjycModel.findOne({ suid }).lean();
  123. if (!info) throw new BusinessError(ErrorCode.SERVICE_FAULT, '为找到与云就业绑定信息');
  124. const data = { code: info.ycode, org: info.yorg };
  125. return data;
  126. }
  127. async yLogout(params) {
  128. const domain = await this.app.redis.get('yjyDomain');
  129. if (!domain) throw new BusinessError(ErrorCode.SERVICE_FAULT, '缺少登录时的域名');
  130. const url = `${domain}?params=${params}`;
  131. return url;
  132. }
  133. // 检查用户是否登录.未登录就跳走
  134. async checkYjyLogin(id) {
  135. if (!id) throw new BusinessError(ErrorCode.BADPARAM, '缺少参数');
  136. const redis = this.app.redis;
  137. const key = this.app.config.yjyLoginKey;
  138. const loginTime = await redis.get(`${key}${id}`);
  139. if (loginTime) return true;
  140. }
  141. // 加密,使用云就业提供的公钥对数据进行加密,供退出登录加密参数使用
  142. encryptData(data) {
  143. const enc = crypto.publicEncrypt(
  144. {
  145. key: publicKey,
  146. padding: crypto.constants.RSA_PKCS1_PADDING,
  147. },
  148. Buffer.from(JSON.stringify(data))
  149. );
  150. return enc.toString('base64');
  151. }
  152. // 解密,使用双困生提供的私钥对数据进行解密,供登录解析参数使用
  153. decryptData(encstr) {
  154. // encstr = encodeURIComponent(encstr);
  155. const sb = Buffer.from(encstr, 'base64');
  156. const dec = crypto.privateDecrypt(
  157. {
  158. key: privateKey,
  159. passphrase: 'sks_secret',
  160. padding: crypto.constants.RSA_PKCS1_PADDING,
  161. },
  162. sb
  163. );
  164. if (dec) return JSON.parse(dec.toString());
  165. return false;
  166. }
  167. async getDomain(origin) {
  168. // 整个退出登录的地址
  169. await this.app.redis.set('yjyDomain', origin);
  170. }
  171. }
  172. module.exports = YunjiuyeService;