login_controller.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. 'use strict';
  2. /**
  3. * 登录页面控制器
  4. *
  5. * @author CaiAoLin
  6. * @date 2017/11/15
  7. * @version
  8. */
  9. const URL = require('url');
  10. const maintainConst = require('../const/maintain');
  11. const OAuth = require('co-wechat-oauth');
  12. const office = require('../const/cld_office')
  13. module.exports = app => {
  14. class LoginController extends app.BaseController {
  15. /**
  16. * 登录页面
  17. *
  18. * @param {Object} ctx - egg全局页面
  19. * @return {void}
  20. */
  21. async index(ctx) {
  22. if (ctx.helper.isMobile(ctx.request.header['user-agent'])) {
  23. ctx.redirect('/wap');
  24. return;
  25. }
  26. let projectData = null;
  27. // 判断是否有编号且存在
  28. if (ctx.params.code) {
  29. const projectInfo = await ctx.service.project.getProjectByCode(ctx.params.code.toString().trim());
  30. if (projectInfo) {
  31. projectData = projectInfo;
  32. } else {
  33. ctx.redirect('/');
  34. return;
  35. }
  36. }
  37. const errorMessage = ctx.session.loginError;
  38. // 显示完删除
  39. ctx.session.loginError = null;
  40. // 获取系统维护信息
  41. const maintainData = await ctx.service.maintain.getDataById(1);
  42. if (!ctx.app.config.is_debug) {
  43. await ctx.service.maintain.syncMaintainData();
  44. }
  45. const renderData = {
  46. projectData,
  47. maintainData,
  48. maintainConst,
  49. errorMessage,
  50. hostUrl: ctx.protocol + '://' + ctx.host,
  51. appid: ctx.app.config.wxCode.appid,
  52. };
  53. await ctx.render('login/login.ejs', renderData);
  54. }
  55. /**
  56. * 微信扫码认证并返回
  57. *
  58. * @param {Object} ctx - egg全局页面
  59. * @return {void}
  60. */
  61. async wxAuth(ctx) {
  62. const code = ctx.query.code;
  63. try {
  64. const client = new OAuth(ctx.app.config.wxCode.appid, ctx.app.config.wxCode.appsecret);
  65. const token = await client.getAccessToken(code);
  66. // const user = await client.getUser(token.data.openid);
  67. // console.log(user);
  68. if (!token) {
  69. throw '微信扫码获取信息失败';
  70. }
  71. // 判断扫码者项目是否只有一个,是则直接跳到登录页,否则显示项目选择页
  72. const paList = await ctx.service.projectAccount.getAllDataByCondition({ where: { wx_unionid: token.data.unionid } });
  73. if (paList && paList.length === 1) {
  74. const pro = await ctx.service.project.getDataById(paList[0].project_id);
  75. let redirect_url = ctx.protocol + '://' + ctx.host;
  76. redirect_url += ctx.query.state ? ctx.query.state : '/dashboard';
  77. ctx.redirect('/wx/url2web?project=' + pro.code + '&url=' + redirect_url + '&unionid=' + token.data.unionid);
  78. } else {
  79. ctx.session.wechatLogin = token.data.unionid;
  80. ctx.redirect('/wxproject');
  81. }
  82. } catch (error) {
  83. this.log(error);
  84. ctx.session.loginError = error;
  85. ctx.redirect('/login');
  86. }
  87. }
  88. async wxProject(ctx) {
  89. try {
  90. const unionid = ctx.session.wechatLogin;
  91. if (!unionid) {
  92. throw '扫码信息已失效,请重新登录';
  93. }
  94. ctx.session.wechatLogin = null;
  95. const paList = await ctx.service.projectAccount.getAllDataByCondition({ where: { wx_unionid: unionid } });
  96. const pidList = ctx.app._.uniq(ctx.app._.map(paList, 'project_id'));
  97. const pList = [];
  98. const redirect_url = ctx.protocol + '://' + ctx.host + '/dashboard';
  99. for (const p of pidList) {
  100. const pro = await ctx.service.project.getDataById(p);
  101. pro.userMsg = ctx.app._.find(paList, { project_id: p });
  102. pList.push(pro);
  103. }
  104. // 获取系统维护信息
  105. const maintainData = await ctx.service.maintain.getDataById(1);
  106. const renderData = {
  107. maintainData,
  108. maintainConst,
  109. unionid,
  110. pList,
  111. redirect_url,
  112. };
  113. await ctx.render('login/wxproject.ejs', renderData);
  114. } catch (error) {
  115. this.log(error);
  116. ctx.session.loginError = error;
  117. ctx.redirect('/login');
  118. }
  119. }
  120. // 设置用户微信登录项目,跳转到对应wap页面
  121. async url2web(ctx) {
  122. try {
  123. if (!ctx.query.project || !ctx.query.url || !ctx.query.unionid) {
  124. throw '参数有误';
  125. }
  126. const code = ctx.query.project;
  127. // 查找项目数据
  128. const projectData = await ctx.service.project.getProjectByCode(code.toString().trim());
  129. if (projectData === null) {
  130. throw '不存在项目数据';
  131. }
  132. const pa = await ctx.service.projectAccount.getDataByCondition({ project_id: projectData.id, wx_unionid: ctx.query.unionid });
  133. if (!pa) {
  134. throw '该微信号未绑定此项目';
  135. }
  136. if (pa.enable !== 1) {
  137. throw '该账号已被停用,请联系销售人员';
  138. }
  139. // 设置项目和用户session记录
  140. const result = await ctx.service.projectAccount.accountLogin({ project: projectData, accountData: pa }, 3);
  141. if (!result) {
  142. throw '登录出错';
  143. }
  144. ctx.redirect(ctx.query.url);
  145. } catch (error) {
  146. const renderData = {
  147. status: 1,
  148. msg: error,
  149. };
  150. await ctx.render('wechat/tips.ejs', renderData);
  151. }
  152. }
  153. /**
  154. * 登录操作
  155. *
  156. * @param {Object} ctx - egg全局变量
  157. * @return {void}
  158. */
  159. async login(ctx) {
  160. let loginType = ctx.request.body.type;
  161. try {
  162. loginType = parseInt(loginType);
  163. const result = await ctx.service.projectAccount.accountLogin(ctx.request.body, loginType);
  164. if (!result) {
  165. throw '用户名或密码错误';
  166. }
  167. if (result === 2) {
  168. throw '该账号已被停用,请联系销售人员';
  169. }
  170. // 调用 rotateCsrfSecret 刷新用户的 CSRF token
  171. ctx.rotateCsrfSecret();
  172. // 判断是否已经有对应用户信息,没有则跳转初始化页面
  173. const needBoot = await ctx.service.customer.isNeedBoot(ctx.request.body);
  174. const url = needBoot ? '/boot' : '/dashboard';
  175. const query = URL.parse(ctx.request.header.referer, true).query;
  176. ctx.redirect(query.referer ? query.referer : url);
  177. } catch (error) {
  178. this.log(error);
  179. ctx.session.loginError = error;
  180. ctx.redirect('/login');
  181. }
  182. }
  183. /**
  184. * 退出登录
  185. *
  186. * @param {Object} ctx - egg全局变量
  187. * @return {void}
  188. */
  189. async logout(ctx) {
  190. // 删除session并跳转
  191. const code = ctx.session.sessionProject.code ? ctx.session.sessionProject.code : null;
  192. ctx.session = null;
  193. if (code) {
  194. ctx.redirect('/login/' + code);
  195. } else {
  196. ctx.redirect('/');
  197. }
  198. }
  199. /**
  200. * 获取项目名
  201. *
  202. * @param {Object} ctx - egg全局context
  203. * @return {void}
  204. */
  205. async projectName(ctx) {
  206. const response = {
  207. err: 0,
  208. msg: '',
  209. };
  210. const code = ctx.query.code;
  211. try {
  212. const data = await ctx.service.project.getProjectByCode(code);
  213. if (data) {
  214. response.data = data.name;
  215. } else {
  216. throw '项目不存在';
  217. }
  218. } catch (err) {
  219. response.err = 1;
  220. response.msg = err;
  221. }
  222. ctx.body = response;
  223. }
  224. /**
  225. * 忘记密码-重置密码
  226. * @param ctx
  227. * @returns {Promise<void>}
  228. */
  229. async resetPassword(ctx) {
  230. const response = {
  231. err: 0,
  232. index: 0,
  233. msg: '',
  234. };
  235. const code = ctx.request.body.code;
  236. const name = ctx.request.body.name;
  237. try {
  238. const data = await ctx.service.project.getProjectByCode(code);
  239. if (data) {
  240. const pa = await ctx.service.projectAccount.getDataByCondition({ account: name, project_id: data.id });
  241. if (!pa) {
  242. response.index = 2;
  243. throw '登录账号不存在,请检查是否输入错误。';
  244. }
  245. if (!pa.auth_mobile) {
  246. response.index = 2;
  247. throw '登录账号还没有认证手机,请联系项目管理员。';
  248. }
  249. // 重置密码并发短信
  250. const newpwd = ctx.helper.generateRandomString(6, 2);
  251. console.log(newpwd);
  252. const result = await ctx.service.projectAccount.resetPassword(pa.id, newpwd);
  253. if (!result) {
  254. throw '修改密码失败';
  255. }
  256. response.data = {
  257. pName: data.name,
  258. name: pa.name,
  259. mobile: pa.auth_mobile.substr(0, 3) + '****' + pa.auth_mobile.substr(7),
  260. account: pa.account,
  261. };
  262. } else {
  263. response.index = 1;
  264. throw '项目不存在,请检查是否输入有误。';
  265. }
  266. } catch (err) {
  267. response.err = 1;
  268. response.msg = err;
  269. }
  270. ctx.body = response;
  271. }
  272. /**
  273. * 接口登录页面
  274. *
  275. * @param {Object} ctx - egg全局页面
  276. * @return {void}
  277. */
  278. async port(ctx) {
  279. // 获取系统维护信息
  280. const maintainData = await ctx.service.maintain.getDataById(1);
  281. if (!ctx.app.config.is_debug) {
  282. await ctx.service.maintain.syncMaintainData();
  283. }
  284. let pa;
  285. try {
  286. if (ctx.session.loginError !== null) {
  287. throw ctx.session.loginError;
  288. }
  289. if (!ctx.query.mobile) {
  290. throw '参数有误';
  291. }
  292. pa = await ctx.service.projectAccount.getDataByCondition({ mobile: ctx.query.mobile, project_id: ctx.projectData.id });
  293. if (!pa) {
  294. throw '您无权限登录系统。';
  295. }
  296. if (pa.bind === 0) {
  297. // 先绑定再登录
  298. throw '';
  299. } else {
  300. if (pa.enable !== 1) {
  301. throw '该账号已被停用,请联系销售人员';
  302. }
  303. const result = await ctx.service.projectAccount.accountLogin({ project: ctx.projectData, accountData: pa }, 3);
  304. if (!result) {
  305. throw '登录出错';
  306. }
  307. ctx.redirect('/dashboard');
  308. }
  309. } catch (error) {
  310. // this.log(error);
  311. ctx.session.loginError = error;
  312. }
  313. const errorMessage = ctx.session.loginError;
  314. // 显示完删除
  315. ctx.session.loginError = null;
  316. const renderData = {
  317. maintainData,
  318. maintainConst,
  319. errorMessage,
  320. projectData: ctx.projectData,
  321. accountData: pa,
  322. };
  323. await ctx.render('login/login_port.ejs', renderData);
  324. }
  325. /**
  326. * 登录操作
  327. *
  328. * @param {Object} ctx - egg全局变量
  329. * @return {void}
  330. */
  331. async loginPort(ctx) {
  332. let loginType = ctx.request.body.type;
  333. try {
  334. loginType = parseInt(loginType);
  335. const data = await ctx.service.project.getProjectByCode(ctx.request.body.code.toString().trim());
  336. if (data === null) {
  337. throw '不存在项目数据';
  338. }
  339. if (data.custom === 0) {
  340. throw '无法通过接口登录本系统';
  341. }
  342. if (data && data.custom === 1) {
  343. const pa = await ctx.service.projectAccount.getDataById(ctx.request.body.accountId);
  344. if (!pa) {
  345. throw '您无权限登录系统。';
  346. }
  347. if (pa.enable !== 1) {
  348. throw '该账号已被停用,请联系销售人员';
  349. }
  350. const updateData = {
  351. bind: 1,
  352. };
  353. await ctx.service.projectAccount.update(updateData, { id: pa.id });
  354. const result = await ctx.service.projectAccount.accountLogin({ project: data, accountData: pa }, loginType);
  355. if (!result) {
  356. throw '绑定登录出错,请使用账号密码登录';
  357. }
  358. ctx.redirect('/dashboard');
  359. }
  360. } catch (error) {
  361. this.log(error);
  362. ctx.session.loginError = error;
  363. ctx.redirect('/login');
  364. }
  365. }
  366. /**
  367. * (项目管理)获取账号
  368. * @param {Object} ctx - egg全局变量
  369. */
  370. async account(ctx) {
  371. const data = ctx.data;
  372. const response = {
  373. code: 0,
  374. data: 0,
  375. msg: '',
  376. };
  377. try {
  378. const project = await ctx.service.project.getProjectByCode(data.code);
  379. if (!project) throw '未找到该项目';
  380. const pa = await ctx.service.projectAccount.getAccountInfoByAccountWithPid(data.account, project.id);
  381. if (!pa ) throw '该账号不存在,请联系管理员';
  382. const manager = await ctx.service.manager.getDataById(project.manager_id)
  383. const { is_admin: isAdmin, account_group: accountGroup, ...otherObj } = pa
  384. response.data = {
  385. account: { ...otherObj, accountGroup, isAdmin},
  386. project: {
  387. code: project.code,
  388. name: project.name,
  389. categoryId: project.manager_office,
  390. category: office.list[project.manager_office],
  391. staff: manager.real_name
  392. }
  393. }
  394. } catch (error) {
  395. console.log(error);
  396. response.code = -1;
  397. response.msg = error.toString();
  398. }
  399. ctx.body = response;
  400. }
  401. /**
  402. * (项目管理)获取项目
  403. * @param {Object} ctx - egg全局变量
  404. */
  405. async project(ctx) {
  406. const data = ctx.data;
  407. const response = {
  408. code: 0,
  409. data: 0,
  410. msg: '',
  411. };
  412. try {
  413. const project = await ctx.service.project.getProjectByCode(data.code);
  414. if (!project) throw '未找到该项目';
  415. response.data = project;
  416. } catch (error) {
  417. response.code = -1;
  418. response.msg = error.toString();
  419. }
  420. ctx.body = response;
  421. }
  422. /**
  423. * (项目管理)校验项目
  424. * @param {Object} ctx - egg全局变量
  425. */
  426. async vertifyProject(ctx) {
  427. const response = {
  428. code: 0,
  429. data: 0,
  430. msg: '',
  431. };
  432. try {
  433. const code = ctx.session.sessionProject.code
  434. const accountData = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId)
  435. if (!code || !accountData) {
  436. throw new Error('参数错误')
  437. }
  438. const result = await ctx.service.project.verifyManagementProject(ctx.helper.createJWT({ code }));
  439. const token = ctx.helper.createJWT({ code, account: accountData.account })
  440. const redirect = `${app.config.managementPath}/auth?token=${token}`
  441. response.data = { ...result, is_admin: accountData.is_admin, redirect, env: app.config.env};
  442. } catch (error) {
  443. response.code = -1;
  444. response.msg = error.toString();
  445. }
  446. ctx.body = response;
  447. }
  448. /**
  449. * (项目管理)新增项目
  450. * @param {Object} ctx - egg全局变量
  451. */
  452. async addProject(ctx) {
  453. const response = {
  454. code: 0,
  455. data: {},
  456. msg: '',
  457. };
  458. try {
  459. const result = await ctx.service.project.addProjectFromManagement()
  460. if (!result) {
  461. throw new Error('请求失败')
  462. }
  463. const { code = -1, data: { token = ''} = { token: ''}, msg = '请求失败' } = result
  464. if ( code === 0 && token) {
  465. response.data = {
  466. redirect: `${app.config.managementPath}/auth?token=${token}`,
  467. }
  468. } else {
  469. throw new Error(msg)
  470. }
  471. } catch (error) {
  472. response.code = -1;
  473. response.msg = error.toString();
  474. }
  475. ctx.body = response;
  476. }
  477. /**
  478. * 项目管理授权页面
  479. *
  480. * @param {Object} ctx - egg全局页面
  481. * @return {void}
  482. */
  483. async management(ctx) {
  484. const data = ctx.data;
  485. // 获取系统维护信息
  486. const maintainData = await ctx.service.maintain.getDataById(1);
  487. if (!ctx.app.config.is_debug) {
  488. await ctx.service.maintain.syncMaintainData();
  489. }
  490. let account, project;
  491. try {
  492. if (ctx.session.loginError !== null) {
  493. throw ctx.session.loginError;
  494. }
  495. if (!data) {
  496. throw '参数有误';
  497. }
  498. project = await ctx.service.project.getDataByCondition({ code: data.code })
  499. if (!project) {
  500. throw '未找到该项目';
  501. }
  502. account = await ctx.service.projectAccount.getDataByCondition({ project_id: project.id, account: data.account });
  503. if (!account) {
  504. throw '您无权限登录系统。';
  505. }
  506. if (account.enable !== 1) {
  507. throw '该账号已被停用,请联系销售人员';
  508. }
  509. const result = await ctx.service.projectAccount.accountLogin({ project, accountData: account }, 3);
  510. if (!result) {
  511. throw '登录出错';
  512. }
  513. ctx.redirect('/dashboard');
  514. } catch (error) {
  515. // this.log(error);
  516. console.log(error);
  517. ctx.session.loginError = error;
  518. }
  519. const errorMessage = ctx.session.loginError;
  520. // 显示完删除
  521. ctx.session.loginError = null;
  522. const renderData = {
  523. maintainData,
  524. maintainConst,
  525. errorMessage,
  526. projectData: project,
  527. accountData: account,
  528. };
  529. await ctx.render('login/login_management.ejs', renderData);
  530. }
  531. /** 拉取项目下所有计量账号至项目管理 */
  532. async syncProjectAccount(ctx) {
  533. const response = {
  534. code: 0,
  535. data: [],
  536. msg: '',
  537. };
  538. try {
  539. const { code = ''} = ctx.data
  540. if (!code) throw '参数错误';
  541. const projectData = await ctx.service.project.getProjectByCode(code)
  542. if (!projectData) throw '未找到项目';
  543. const data = await ctx.service.projectAccount.getAllProjectAccountByPid(projectData.id)
  544. response.data = data || []
  545. } catch (error) {
  546. response.code = -1
  547. response.msg = error.toString()
  548. }
  549. ctx.body = response
  550. }
  551. }
  552. return LoginController;
  553. };