login_controller.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  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. module.exports = app => {
  13. class LoginController extends app.BaseController {
  14. /**
  15. * 登录页面
  16. *
  17. * @param {Object} ctx - egg全局页面
  18. * @return {void}
  19. */
  20. async index(ctx) {
  21. if (ctx.helper.isMobile(ctx.request.header['user-agent'])) {
  22. ctx.redirect('/wap');
  23. return;
  24. }
  25. const errorMessage = ctx.session.loginError;
  26. // 显示完删除
  27. ctx.session.loginError = null;
  28. // 获取系统维护信息
  29. const maintainData = await ctx.service.maintain.getDataById(1);
  30. if (!ctx.app.config.is_debug) {
  31. await ctx.service.maintain.syncMaintainData();
  32. }
  33. const renderData = {
  34. maintainData,
  35. maintainConst,
  36. errorMessage,
  37. hostUrl: ctx.protocol + '://' + ctx.host,
  38. };
  39. await ctx.render('login/login.ejs', renderData);
  40. }
  41. /**
  42. * 微信扫码认证并返回
  43. *
  44. * @param {Object} ctx - egg全局页面
  45. * @return {void}
  46. */
  47. async wxAuth(ctx) {
  48. const code = ctx.query.code;
  49. try {
  50. const client = new OAuth('wx5320cd30cecdbd68', 'ca7c0dbd9e94dc3b1c3b0e73865743f4');
  51. const token = await client.getAccessToken(code);
  52. // const user = await client.getUser(token.data.openid);
  53. // console.log(user);
  54. if (!token) {
  55. throw '微信扫码获取信息失败';
  56. }
  57. // 判断扫码者项目是否只有一个,是则直接跳到登录页,否则显示项目选择页
  58. const paList = await ctx.service.projectAccount.getAllDataByCondition({ where: { wx_unionid: token.data.unionid } });
  59. if (paList && paList.length === 1) {
  60. const pro = await ctx.service.project.getDataById(paList[0].project_id);
  61. let redirect_url = ctx.protocol + '://' + ctx.host;
  62. redirect_url += ctx.query.state ? ctx.query.state : '/dashboard';
  63. ctx.redirect('/wx/url2web?project=' + pro.code + '&url=' + redirect_url + '&unionid=' + token.data.unionid);
  64. } else {
  65. ctx.session.wechatLogin = token.data.unionid;
  66. ctx.redirect('/wxproject');
  67. }
  68. } catch (error) {
  69. this.log(error);
  70. ctx.session.loginError = error;
  71. ctx.redirect('/login');
  72. }
  73. }
  74. async wxProject(ctx) {
  75. try {
  76. const unionid = ctx.session.wechatLogin;
  77. if (!unionid) {
  78. throw '扫码信息已失效,请重新登录';
  79. }
  80. ctx.session.wechatLogin = null;
  81. const paList = await ctx.service.projectAccount.getAllDataByCondition({ where: { wx_unionid: unionid } });
  82. const pidList = ctx.app._.uniq(ctx.app._.map(paList, 'project_id'));
  83. const pList = [];
  84. const redirect_url = ctx.protocol + '://' + ctx.host + '/dashboard';
  85. for (const p of pidList) {
  86. const pro = await ctx.service.project.getDataById(p);
  87. pro.userMsg = ctx.app._.find(paList, { project_id: p });
  88. pList.push(pro);
  89. }
  90. // 获取系统维护信息
  91. const maintainData = await ctx.service.maintain.getDataById(1);
  92. const renderData = {
  93. maintainData,
  94. maintainConst,
  95. unionid,
  96. pList,
  97. redirect_url,
  98. };
  99. await ctx.render('login/wxproject.ejs', renderData);
  100. } catch (error) {
  101. this.log(error);
  102. ctx.session.loginError = error;
  103. ctx.redirect('/login');
  104. }
  105. }
  106. // 设置用户微信登录项目,跳转到对应wap页面
  107. async url2web(ctx) {
  108. try {
  109. if (!ctx.query.project || !ctx.query.url || !ctx.query.unionid) {
  110. throw '参数有误';
  111. }
  112. const code = ctx.query.project;
  113. // 查找项目数据
  114. const projectData = await ctx.service.project.getProjectByCode(code.toString().trim());
  115. if (projectData === null) {
  116. throw '不存在项目数据';
  117. }
  118. const pa = await ctx.service.projectAccount.getDataByCondition({ project_id: projectData.id, wx_unionid: ctx.query.unionid });
  119. if (!pa) {
  120. throw '该微信号未绑定此项目';
  121. }
  122. if (pa.enable !== 1) {
  123. throw '该账号已被停用,请联系销售人员';
  124. }
  125. // 设置项目和用户session记录
  126. const result = await ctx.service.projectAccount.accountLogin({ project: projectData, accountData: pa }, 3);
  127. if (!result) {
  128. throw '登录出错';
  129. }
  130. ctx.redirect(ctx.query.url);
  131. } catch (error) {
  132. const renderData = {
  133. status: 1,
  134. msg: error,
  135. };
  136. await ctx.render('wechat/tips.ejs', renderData);
  137. }
  138. }
  139. /**
  140. * 登录操作
  141. *
  142. * @param {Object} ctx - egg全局变量
  143. * @return {void}
  144. */
  145. async login(ctx) {
  146. let loginType = ctx.request.body.type;
  147. try {
  148. loginType = parseInt(loginType);
  149. const result = await ctx.service.projectAccount.accountLogin(ctx.request.body, loginType);
  150. if (!result) {
  151. throw '用户名或密码错误';
  152. }
  153. if (result === 2) {
  154. throw '该账号已被停用,请联系销售人员';
  155. }
  156. // 调用 rotateCsrfSecret 刷新用户的 CSRF token
  157. ctx.rotateCsrfSecret();
  158. // 判断是否已经有对应用户信息,没有则跳转初始化页面
  159. const needBoot = await ctx.service.customer.isNeedBoot(ctx.request.body);
  160. const url = needBoot ? '/boot' : '/dashboard';
  161. const query = URL.parse(ctx.request.header.referer, true).query;
  162. ctx.redirect(query.referer ? query.referer : url);
  163. } catch (error) {
  164. this.log(error);
  165. ctx.session.loginError = error;
  166. ctx.redirect('/login');
  167. }
  168. }
  169. /**
  170. * 退出登录
  171. *
  172. * @param {Object} ctx - egg全局变量
  173. * @return {void}
  174. */
  175. async logout(ctx) {
  176. // 删除session并跳转
  177. ctx.session = null;
  178. ctx.redirect('/');
  179. }
  180. /**
  181. * 获取项目名
  182. *
  183. * @param {Object} ctx - egg全局context
  184. * @return {void}
  185. */
  186. async projectName(ctx) {
  187. const response = {
  188. err: 0,
  189. msg: '',
  190. };
  191. const code = ctx.query.code;
  192. try {
  193. const data = await ctx.service.project.getProjectByCode(code);
  194. if (data) {
  195. response.data = data.name;
  196. } else {
  197. throw '项目不存在';
  198. }
  199. } catch (err) {
  200. response.err = 1;
  201. response.msg = err;
  202. }
  203. ctx.body = response;
  204. }
  205. /**
  206. * 忘记密码-重置密码
  207. * @param ctx
  208. * @returns {Promise<void>}
  209. */
  210. async resetPassword(ctx) {
  211. const response = {
  212. err: 0,
  213. index: 0,
  214. msg: '',
  215. };
  216. const code = ctx.request.body.code;
  217. const name = ctx.request.body.name;
  218. try {
  219. const data = await ctx.service.project.getProjectByCode(code);
  220. if (data) {
  221. const pa = await ctx.service.projectAccount.getDataByCondition({ account: name, project_id: data.id });
  222. if (!pa) {
  223. response.index = 2;
  224. throw '登录账号不存在,请检查是否输入错误。';
  225. }
  226. if (!pa.auth_mobile) {
  227. response.index = 2;
  228. throw '登录账号还没有认证手机,请联系项目管理员。';
  229. }
  230. // 重置密码并发短信
  231. const newpwd = ctx.helper.generateRandomString(6, 2);
  232. console.log(newpwd);
  233. const result = await ctx.service.projectAccount.resetPassword(pa.id, newpwd);
  234. if (!result) {
  235. throw '修改密码失败';
  236. }
  237. response.data = {
  238. pName: data.name,
  239. name: pa.name,
  240. mobile: pa.auth_mobile.substr(0, 3) + '****' + pa.auth_mobile.substr(7),
  241. account: pa.account,
  242. };
  243. } else {
  244. response.index = 1;
  245. throw '项目不存在,请检查是否输入有误。';
  246. }
  247. } catch (err) {
  248. response.err = 1;
  249. response.msg = err;
  250. }
  251. ctx.body = response;
  252. }
  253. /**
  254. * 接口登录页面
  255. *
  256. * @param {Object} ctx - egg全局页面
  257. * @return {void}
  258. */
  259. async port(ctx) {
  260. // 获取系统维护信息
  261. const maintainData = await ctx.service.maintain.getDataById(1);
  262. if (!ctx.app.config.is_debug) {
  263. await ctx.service.maintain.syncMaintainData();
  264. }
  265. let pa;
  266. try {
  267. if (ctx.session.loginError !== null) {
  268. throw ctx.session.loginError;
  269. }
  270. if (!ctx.query.mobile) {
  271. throw '参数有误';
  272. }
  273. pa = await ctx.service.projectAccount.getDataByCondition({ mobile: ctx.query.mobile, project_id: ctx.projectData.id });
  274. if (!pa) {
  275. throw '您无权限登录系统。';
  276. }
  277. if (pa.bind === 0) {
  278. // 先绑定再登录
  279. throw '';
  280. } else {
  281. if (pa.enable !== 1) {
  282. throw '该账号已被停用,请联系销售人员';
  283. }
  284. const result = await ctx.service.projectAccount.accountLogin({ project: ctx.projectData, accountData: pa }, 3);
  285. if (!result) {
  286. throw '登录出错';
  287. }
  288. ctx.redirect('/dashboard');
  289. }
  290. } catch (error) {
  291. this.log(error);
  292. ctx.session.loginError = error;
  293. }
  294. const errorMessage = ctx.session.loginError;
  295. // 显示完删除
  296. ctx.session.loginError = null;
  297. const renderData = {
  298. maintainData,
  299. maintainConst,
  300. errorMessage,
  301. projectData: ctx.projectData,
  302. accountData: pa,
  303. };
  304. await ctx.render('login/login_port.ejs', renderData);
  305. }
  306. /**
  307. * 登录操作
  308. *
  309. * @param {Object} ctx - egg全局变量
  310. * @return {void}
  311. */
  312. async loginPort(ctx) {
  313. let loginType = ctx.request.body.type;
  314. try {
  315. loginType = parseInt(loginType);
  316. const data = await ctx.service.project.getProjectByCode(ctx.request.body.code.toString().trim());
  317. if (data === null) {
  318. throw '不存在项目数据';
  319. }
  320. if (data.custom === 0) {
  321. throw '无法通过接口登录本系统';
  322. }
  323. if (data && data.custom === 1) {
  324. const pa = await ctx.service.projectAccount.getDataById(ctx.request.body.accountId);
  325. if (!pa) {
  326. throw '您无权限登录系统。';
  327. }
  328. if (pa.enable !== 1) {
  329. throw '该账号已被停用,请联系销售人员';
  330. }
  331. const updateData = {
  332. bind: 1,
  333. };
  334. await ctx.service.projectAccount.update(updateData, { id: pa.id });
  335. const result = await ctx.service.projectAccount.accountLogin({ project: data, accountData: pa }, loginType);
  336. if (!result) {
  337. throw '绑定登录出错,请使用账号密码登录';
  338. }
  339. ctx.redirect('/dashboard');
  340. }
  341. } catch (error) {
  342. this.log(error);
  343. ctx.session.loginError = error;
  344. ctx.redirect('/login');
  345. }
  346. }
  347. }
  348. return LoginController;
  349. };