manager_model.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /**
  2. * 后台管理员数据模型
  3. *
  4. * @author CaiAoLin
  5. * @date 2017/6/1
  6. * @version
  7. */
  8. import BaseModel from "../../common/base/base_model";
  9. import ManagerSchema from "./schemas/manager";
  10. import crypto from "crypto";
  11. import Request from "request";
  12. class ManagerModel extends BaseModel {
  13. /**
  14. * 超级用户用户名
  15. *
  16. * @var {String}
  17. */
  18. adminUsername = 'admin';
  19. /**
  20. * 用户权限
  21. *
  22. * @var
  23. */
  24. permission = {
  25. 'manager': '用户管理',
  26. 'notify': '通知管理',
  27. 'stdBillsmain': '清单规则编辑器',
  28. 'rationRepository': '定额编辑器',
  29. 'report': '报表模板',
  30. };
  31. /**
  32. * 构造函数
  33. *
  34. * @return {void}
  35. */
  36. constructor() {
  37. let parent = super();
  38. parent.model = ManagerSchema;
  39. parent.init();
  40. }
  41. /**
  42. * 设置场景
  43. *
  44. * @param {string} scene
  45. * @return {void}
  46. */
  47. setScene(scene = '') {
  48. switch (scene) {
  49. // 更改密码验证规则
  50. case 'changePassword':
  51. this.model.schema.path('password').required(true);
  52. break;
  53. // CLD新增
  54. case 'cldInsert':
  55. this.model.schema.path('username').required(true);
  56. this.model.schema.path('create_time').required(true);
  57. this.model.schema.path('office').required(true);
  58. break;
  59. }
  60. }
  61. /**
  62. * 获取列表
  63. *
  64. * @param {object} condition
  65. * @param {number} page
  66. * @return {Promise}
  67. */
  68. getList(condition = null, page = 1) {
  69. page = parseInt(page);
  70. page = page <= 1 ? 1 : page;
  71. let option = {page: page};
  72. return this.db.find(condition, null, option);
  73. }
  74. /**
  75. * 用户密码加密
  76. *
  77. * @param {string} token
  78. * @param {string} password
  79. * @return {string}
  80. */
  81. encryptPassword(token, password) {
  82. let encryptPassword = crypto.createHmac('sha1', token).update(password)
  83. .digest().toString('base64');
  84. return encryptPassword;
  85. }
  86. /**
  87. * 更改密码
  88. *
  89. * @param {string} username
  90. * @param {string} password
  91. * @param {string} newPassword
  92. * @throws {string}
  93. * @return {Promise}
  94. */
  95. async changePassword(username, password, newPassword) {
  96. // 查找对应用户
  97. let managerData = await this.findDataByCondition({username: username});
  98. if (managerData.length <= 0) {
  99. return false;
  100. }
  101. // 验证旧密码
  102. let encryptPassword = this.encryptPassword(managerData.token, password);
  103. if (encryptPassword !== managerData.password) {
  104. throw '用户名或密码错误';
  105. }
  106. // 加密新密码
  107. let encryptNewPassword = this.encryptPassword(managerData.token, newPassword);
  108. let result = await this.db.update({username: username}, {password: encryptNewPassword});
  109. return result.ok === 1;
  110. }
  111. /**
  112. * 登录信息校验
  113. *
  114. * @param {String} username
  115. * @param {String} password
  116. * @return {Promise}
  117. */
  118. async validLogin(username, password) {
  119. let managerData = await this.findDataByCondition({username: username});
  120. // 如果不是超级管理员登录则走CLD接口登录流程
  121. if (username !== this.adminUsername) {
  122. let CLDLoginInfo = await this.CLDLogin(username, password, managerData);
  123. managerData = CLDLoginInfo;
  124. } else {
  125. this.valid(password, managerData);
  126. }
  127. return managerData;
  128. }
  129. /**
  130. * 验证登录信息
  131. *
  132. * @param {String} password
  133. * @param {Object} managerData
  134. * @return {void}
  135. */
  136. valid(password, managerData) {
  137. // 没有找到对应数据
  138. if (managerData === null || managerData._id === undefined) {
  139. throw {code: 44001, err: '用户名或密码错误'};
  140. }
  141. // 是否禁止登录
  142. if (managerData.can_login !== 1) {
  143. throw {code: 44002, err: '用户名不存在'};
  144. }
  145. // 加密密码
  146. let encryptPassword = this.encryptPassword(managerData.token, password);
  147. if (encryptPassword !== managerData.password) {
  148. throw {code: 44001, err: '用户名或密码错误'};
  149. }
  150. }
  151. /**
  152. * CLD登录
  153. *
  154. * @param {String} username
  155. * @param {String} password
  156. * @param {Object} managerData
  157. * @return {Promise}
  158. */
  159. async CLDLogin(username, password, managerData) {
  160. let result = managerData;
  161. if (username === '' || password === '') {
  162. throw {code: 44001, err: '用户名或密码错误'};
  163. }
  164. // 库中不存在则不允许登录,需等同步到数据后才可以继续后面的流程
  165. if (!managerData) {
  166. throw {code: 44003, err: '用户不存在'};
  167. }
  168. let CLDUrl = 'http://cld.smartcost.com.cn/api/auth';
  169. // 生成加密token
  170. let [encryptToken, postTime] = this.generateCLDToken();
  171. let postData = {
  172. username: username,
  173. password: password,
  174. time: postTime,
  175. token: encryptToken,
  176. app: 'scConstruct'
  177. };
  178. let postOption = {
  179. url: CLDUrl,
  180. form: postData,
  181. encoding: 'utf8'
  182. };
  183. let responseData = await this.CLDRequest(postOption);
  184. // 登录成功后,存在此用户则直接返回
  185. if (managerData) {
  186. return result;
  187. }
  188. // 不存在则新增
  189. this.setScene('cldInsert');
  190. let current = new Date().getTime();
  191. let insertData = {
  192. username: username,
  193. password: '',
  194. token: '',
  195. create_time: current,
  196. last_login: current,
  197. office: responseData.office,
  198. can_login: 0
  199. };
  200. result = this.db.create(insertData);
  201. return result;
  202. }
  203. /**
  204. * CLD请求
  205. *
  206. * @param {Object} postOption
  207. * @return {Promise}
  208. */
  209. CLDRequest(postOption) {
  210. return new Promise(function(resolve, reject) {
  211. // 发起请求
  212. Request.post(postOption, function(error, response, body) {
  213. if (error || response.statusCode !== 200) {
  214. console.log(response.statusCode + ':' + error);
  215. reject({code: 44002, err: '接口请求出错'});
  216. return;
  217. }
  218. body = JSON.parse(body);
  219. // 如果接口返回错误
  220. if (body.err !== 0) {
  221. reject({code: body.err, err: '接口返回错误'});
  222. return;
  223. }
  224. resolve(body.data);
  225. });
  226. });
  227. }
  228. /**
  229. * 生成CLD Token
  230. *
  231. * @return {Array}
  232. */
  233. generateCLDToken() {
  234. // 加密内容
  235. let token = 'sc@ConS!tru@ct*88';
  236. let currentTime = new Date().getTime();
  237. currentTime = parseFloat(currentTime / 1000).toFixed(0);
  238. let encryptToken = this.encryptPassword(token, (token + currentTime));
  239. return [encryptToken, currentTime];
  240. }
  241. /**
  242. * 新增管理员
  243. *
  244. * @param {Object} data
  245. * @return {Promise}
  246. */
  247. async createManager(data) {
  248. if (Object.keys(data).length <= 0) {
  249. throw '数据格式错误';
  250. }
  251. let result = await this.db.create(data);
  252. return result;
  253. }
  254. }
  255. export default ManagerModel;