login_controller.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  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. // if (ctx.request.body && ctx.request.body.project && parseInt(ctx.request.body.hide_code)) {
  181. // ctx.redirect('/login/' + ctx.request.body.project);
  182. // } else {
  183. ctx.redirect('/login');
  184. // }
  185. }
  186. }
  187. /**
  188. * 退出登录
  189. *
  190. * @param {Object} ctx - egg全局变量
  191. * @return {void}
  192. */
  193. async logout(ctx) {
  194. // 删除session并跳转
  195. const code = ctx.session.sessionProject && ctx.session.sessionProject.code ? ctx.session.sessionProject.code : null;
  196. ctx.session = null;
  197. if (code) {
  198. ctx.redirect('/login/' + code);
  199. } else {
  200. ctx.redirect('/');
  201. }
  202. }
  203. /**
  204. * 获取项目名
  205. *
  206. * @param {Object} ctx - egg全局context
  207. * @return {void}
  208. */
  209. async projectName(ctx) {
  210. const response = {
  211. err: 0,
  212. msg: '',
  213. };
  214. const code = ctx.query.code;
  215. try {
  216. const data = await ctx.service.project.getProjectByCode(code);
  217. if (data) {
  218. response.data = data.name;
  219. } else {
  220. throw '项目不存在';
  221. }
  222. } catch (err) {
  223. response.err = 1;
  224. response.msg = err;
  225. }
  226. ctx.body = response;
  227. }
  228. /**
  229. * 忘记密码-重置密码
  230. * @param ctx
  231. * @returns {Promise<void>}
  232. */
  233. async resetPassword(ctx) {
  234. const response = {
  235. err: 0,
  236. index: 0,
  237. msg: '',
  238. };
  239. const code = ctx.request.body.code;
  240. const name = ctx.request.body.name;
  241. try {
  242. const data = await ctx.service.project.getProjectByCode(code);
  243. if (data) {
  244. const pa = await ctx.service.projectAccount.getDataByCondition({ account: name, project_id: data.id });
  245. if (!pa) {
  246. response.index = 2;
  247. throw '登录账号不存在,请检查是否输入错误。';
  248. }
  249. if (!pa.auth_mobile) {
  250. response.index = 2;
  251. throw '登录账号还没有认证手机,请联系项目管理员。';
  252. }
  253. // 重置密码并发短信
  254. const newpwd = ctx.helper.generateRandomString(6, 2);
  255. console.log(newpwd);
  256. const result = await ctx.service.projectAccount.resetPassword(pa.id, newpwd);
  257. if (!result) {
  258. throw '修改密码失败';
  259. }
  260. response.data = {
  261. pName: data.name,
  262. name: pa.name,
  263. mobile: pa.auth_mobile.substr(0, 3) + '****' + pa.auth_mobile.substr(7),
  264. account: pa.account,
  265. };
  266. } else {
  267. response.index = 1;
  268. throw '项目不存在,请检查是否输入有误。';
  269. }
  270. } catch (err) {
  271. response.err = 1;
  272. response.msg = err;
  273. }
  274. ctx.body = response;
  275. }
  276. /**
  277. * 接口登录页面
  278. *
  279. * @param {Object} ctx - egg全局页面
  280. * @return {void}
  281. */
  282. async port(ctx) {
  283. // 获取系统维护信息
  284. const maintainData = await ctx.service.maintain.getDataById(1);
  285. if (!ctx.app.config.is_debug) {
  286. await ctx.service.maintain.syncMaintainData();
  287. }
  288. let pa;
  289. try {
  290. if (ctx.session.loginError !== null && ctx.session.loginError !== undefined) {
  291. throw ctx.session.loginError;
  292. }
  293. if (!ctx.query.mobile) {
  294. throw '参数有误';
  295. }
  296. pa = await ctx.service.projectAccount.getDataByCondition({ mobile: ctx.query.mobile, project_id: ctx.projectData.id });
  297. if (!pa) {
  298. throw '您无权限登录系统。';
  299. }
  300. if (pa.bind === 0) {
  301. // 先绑定再登录
  302. throw '';
  303. } else {
  304. if (pa.enable !== 1) {
  305. throw '该账号已被停用,请联系销售人员';
  306. }
  307. const result = await ctx.service.projectAccount.accountLogin({ project: ctx.projectData, accountData: pa }, 3);
  308. if (!result) {
  309. throw '登录出错';
  310. }
  311. const returnUrl = ctx.projectData.after_login_url ? ctx.projectData.after_login_url : '/dashboard';
  312. ctx.redirect(returnUrl);
  313. }
  314. } catch (error) {
  315. // this.log(error);
  316. console.log(error);
  317. ctx.session.loginError = error;
  318. }
  319. const errorMessage = ctx.session.loginError;
  320. // 显示完删除
  321. ctx.session.loginError = null;
  322. const renderData = {
  323. maintainData,
  324. maintainConst,
  325. errorMessage,
  326. projectData: ctx.projectData,
  327. accountData: pa,
  328. };
  329. await ctx.render('login/login_port.ejs', renderData);
  330. }
  331. /**
  332. * 登录操作
  333. *
  334. * @param {Object} ctx - egg全局变量
  335. * @return {void}
  336. */
  337. async loginPort(ctx) {
  338. let loginType = ctx.request.body.type;
  339. try {
  340. loginType = parseInt(loginType);
  341. const data = await ctx.service.project.getProjectByCode(ctx.request.body.code.toString().trim());
  342. if (data === null) {
  343. throw '不存在项目数据';
  344. }
  345. if (data.custom === 0) {
  346. throw '无法通过接口登录本系统';
  347. }
  348. if (data && data.custom === 1) {
  349. const pa = await ctx.service.projectAccount.getDataById(ctx.request.body.accountId);
  350. if (!pa) {
  351. throw '您无权限登录系统。';
  352. }
  353. if (pa.enable !== 1) {
  354. throw '该账号已被停用,请联系销售人员';
  355. }
  356. const updateData = {
  357. bind: 1,
  358. };
  359. await ctx.service.projectAccount.update(updateData, { id: pa.id });
  360. const result = await ctx.service.projectAccount.accountLogin({ project: data, accountData: pa }, loginType);
  361. if (!result) {
  362. throw '绑定登录出错,请使用账号密码登录';
  363. }
  364. const projectData = await this.ctx.service.project.getProjectByCode(ctx.request.body.code.toString().trim());
  365. const returnUrl = projectData.after_login_url ? projectData.after_login_url : '/dashboard';
  366. ctx.redirect(returnUrl);
  367. // ctx.redirect('/dashboard');
  368. }
  369. } catch (error) {
  370. this.log(error);
  371. ctx.session.loginError = error;
  372. if (ctx.request.body && ctx.request.body.code) {
  373. ctx.redirect('/login/' + ctx.request.body.code);
  374. } else {
  375. ctx.redirect('/login');
  376. }
  377. }
  378. }
  379. /**
  380. * (项目管理)获取账号
  381. * @param {Object} ctx - egg全局变量
  382. */
  383. async account(ctx) {
  384. const data = ctx.data;
  385. const response = {
  386. code: 0,
  387. data: 0,
  388. msg: '',
  389. };
  390. try {
  391. const project = await ctx.service.project.getProjectByCode(data.code);
  392. if (!project) throw '未找到该项目';
  393. const pa = await ctx.service.projectAccount.getAccountInfoByAccountWithPid(data.account, project.id);
  394. if (!pa ) throw '该账号不存在,请联系管理员';
  395. const manager = await ctx.service.manager.getDataById(project.manager_id)
  396. const { is_admin: isAdmin, account_group: accountGroup, ...otherObj } = pa
  397. response.data = {
  398. account: { ...otherObj, accountGroup, isAdmin},
  399. project: {
  400. code: project.code,
  401. name: project.name,
  402. categoryId: project.manager_office,
  403. category: office.list[project.manager_office],
  404. staff: manager.real_name
  405. }
  406. }
  407. } catch (error) {
  408. console.log(error);
  409. response.code = -1;
  410. response.msg = error.toString();
  411. }
  412. ctx.body = response;
  413. }
  414. /**
  415. * (项目管理)获取项目
  416. * @param {Object} ctx - egg全局变量
  417. */
  418. async project(ctx) {
  419. const data = ctx.data;
  420. const response = {
  421. code: 0,
  422. data: 0,
  423. msg: '',
  424. };
  425. try {
  426. const project = await ctx.service.project.getProjectByCode(data.code);
  427. if (!project) throw '未找到该项目';
  428. response.data = project;
  429. } catch (error) {
  430. response.code = -1;
  431. response.msg = error.toString();
  432. }
  433. ctx.body = response;
  434. }
  435. /**
  436. * (项目管理)校验项目
  437. * @param {Object} ctx - egg全局变量
  438. */
  439. async vertifyProject(ctx) {
  440. const response = {
  441. code: 0,
  442. data: 0,
  443. msg: '',
  444. };
  445. try {
  446. const code = ctx.session.sessionProject.code
  447. const accountData = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId)
  448. if (!code || !accountData) {
  449. throw new Error('参数错误')
  450. }
  451. const result = await ctx.service.project.verifyManagementProject(ctx.helper.createJWT({ code }));
  452. const token = ctx.helper.createJWT({ code, account: accountData.account })
  453. const redirect = `${app.config.managementPath}/auth?token=${token}`
  454. response.data = { ...result, is_admin: accountData.is_admin, redirect, env: app.config.env};
  455. } catch (error) {
  456. response.code = -1;
  457. response.msg = error.toString();
  458. }
  459. ctx.body = response;
  460. }
  461. /**
  462. * (项目管理)新增项目
  463. * @param {Object} ctx - egg全局变量
  464. */
  465. async addProject(ctx) {
  466. const response = {
  467. code: 0,
  468. data: {},
  469. msg: '',
  470. };
  471. try {
  472. const result = await ctx.service.project.addProjectFromManagement()
  473. if (!result) {
  474. throw new Error('请求失败')
  475. }
  476. const { code = -1, data: { token = ''} = { token: ''}, msg = '请求失败' } = result
  477. if ( code === 0 && token) {
  478. response.data = {
  479. redirect: `${app.config.managementPath}/auth?token=${token}`,
  480. }
  481. } else {
  482. throw new Error(msg)
  483. }
  484. } catch (error) {
  485. response.code = -1;
  486. response.msg = error.toString();
  487. }
  488. ctx.body = response;
  489. }
  490. /**
  491. * 项目管理授权页面
  492. *
  493. * @param {Object} ctx - egg全局页面
  494. * @return {void}
  495. */
  496. async management(ctx) {
  497. const data = ctx.data;
  498. // 获取系统维护信息
  499. const maintainData = await ctx.service.maintain.getDataById(1);
  500. if (!ctx.app.config.is_debug) {
  501. await ctx.service.maintain.syncMaintainData();
  502. }
  503. let account, project;
  504. try {
  505. if (ctx.session.loginError !== null) {
  506. throw ctx.session.loginError;
  507. }
  508. if (!data) {
  509. throw '参数有误';
  510. }
  511. project = await ctx.service.project.getDataByCondition({ code: data.code })
  512. if (!project) {
  513. throw '未找到该项目';
  514. }
  515. account = await ctx.service.projectAccount.getDataByCondition({ project_id: project.id, account: data.account });
  516. if (!account) {
  517. throw '您无权限登录系统。';
  518. }
  519. if (account.enable !== 1) {
  520. throw '该账号已被停用,请联系销售人员';
  521. }
  522. const result = await ctx.service.projectAccount.accountLogin({ project, accountData: account }, 3);
  523. if (!result) {
  524. throw '登录出错';
  525. }
  526. ctx.redirect('/dashboard');
  527. } catch (error) {
  528. // this.log(error);
  529. console.log(error);
  530. ctx.session.loginError = error;
  531. }
  532. const errorMessage = ctx.session.loginError;
  533. // 显示完删除
  534. ctx.session.loginError = null;
  535. const renderData = {
  536. maintainData,
  537. maintainConst,
  538. errorMessage,
  539. projectData: project,
  540. accountData: account,
  541. };
  542. await ctx.render('login/login_management.ejs', renderData);
  543. }
  544. /** 拉取项目下所有计量账号至项目管理 */
  545. async syncProjectAccount(ctx) {
  546. const response = {
  547. code: 0,
  548. data: [],
  549. msg: '',
  550. };
  551. try {
  552. const { code = ''} = ctx.data
  553. if (!code) throw '参数错误';
  554. const projectData = await ctx.service.project.getProjectByCode(code)
  555. if (!projectData) throw '未找到项目';
  556. const data = await ctx.service.projectAccount.getAllProjectAccountByPid(projectData.id)
  557. response.data = data || []
  558. } catch (error) {
  559. response.code = -1
  560. response.msg = error.toString()
  561. }
  562. ctx.body = response
  563. }
  564. }
  565. return LoginController;
  566. };