login_controller.js 14 KB

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