userController.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /**
  2. * user login & register & logout operation
  3. *
  4. */
  5. let config = require("../config/config");
  6. let log = require("../util/log");
  7. let responseFormat = require("../util/responseFormat");
  8. let userRegisterRules = require("../validation/userRegisterRules");
  9. let userLoginRules = require("../validation/userLoginRules");
  10. let validator = require("../util/validator");
  11. let db = require("../database");
  12. let redis = require("../database/redisStorage");
  13. let incUtil = require("../util/incUtil");
  14. let cryptoUtil = require("../util/cryptoUtil");
  15. let userUtil = require("../util/userUtil");
  16. let avatarConfig = require("../config/avatarConfig");
  17. let loginService = require("../service/login");
  18. class UserController {
  19. /**
  20. * user openid login
  21. *
  22. * @param {Object} ctx request object
  23. */
  24. async userOpenIdLogin(ctx) {
  25. let userInfo = await loginService.login(ctx);
  26. if (!userInfo) {
  27. throw new Error("login fail, no userInfo return");
  28. }
  29. if (!userInfo.userName) {
  30. throw new Error("login fail, userInfo.userName is required");
  31. }
  32. await this.appThirdLogin(ctx, userInfo);
  33. }
  34. /**
  35. * app login
  36. *
  37. * @param {Object} ctx request object
  38. * @param {Object} userInfo user info
  39. * @return {void}
  40. */
  41. async appThirdLogin(ctx, userInfo) {
  42. let existUser = await db.user.findOne(
  43. {
  44. userName: userInfo.userName,
  45. },
  46. global.globalConfig.userExportFields
  47. );
  48. // exist go login or go register
  49. if (existUser) {
  50. await this.userThirdLogin(ctx, existUser);
  51. } else {
  52. await this.userThirdRegister(ctx, {
  53. userName: userInfo.userName,
  54. password: userInfo.password,
  55. email: userInfo.email,
  56. nickName: userInfo.nickname,
  57. fullName: userInfo.fullname,
  58. });
  59. }
  60. }
  61. /**
  62. * app third user login
  63. *
  64. * @param {Object} ctx request object
  65. * @param {Object} userInfo user info from app database
  66. */
  67. async userThirdLogin(ctx, userInfo) {
  68. let sessionId = await userUtil.setIconSession(userInfo.userId, ctx);
  69. let autoLoginSessionId = await userUtil.setIconAutoLoginSession(
  70. userInfo.userId,
  71. ctx
  72. );
  73. // generate session to redis and set cookie to client
  74. userUtil.setIconSessionCookie(sessionId, false, ctx);
  75. userUtil.setIconAutoLoginSessionCookie(autoLoginSessionId, false, ctx);
  76. // redirect to index page after login success
  77. // todo redirect to where request come from
  78. ctx.redirect(config.url);
  79. }
  80. /**
  81. * app third user register use user info from openid login
  82. *
  83. * @param {Object} ctx request object
  84. * @param {Object} params openid userInfo
  85. */
  86. async userThirdRegister(ctx, params) {
  87. // get increment userId
  88. let userId = await incUtil.getIncId({ model: "user", field: "userId" });
  89. // set random avatar
  90. let index = parseInt(Math.random() * 105);
  91. let avatar = avatarConfig[index];
  92. // build register userInfo
  93. Object.assign(params, {
  94. createTime: global.globalConfig.nowTime,
  95. updateTime: global.globalConfig.nowTime,
  96. avatar: avatar,
  97. userId: userId,
  98. });
  99. log.debug(`user register and info: ${JSON.stringify(params)}`);
  100. // save userInfo to app database
  101. await db.user.add(params);
  102. let sessionId = await userUtil.setIconSession(userId, ctx);
  103. let autoLoginSessionId = await userUtil.setIconAutoLoginSession(
  104. userId,
  105. ctx
  106. );
  107. // generate session to redis and set cookie to client
  108. userUtil.setIconSessionCookie(sessionId, false, ctx);
  109. userUtil.setIconAutoLoginSessionCookie(autoLoginSessionId, false, ctx);
  110. ctx.redirect(config.url);
  111. }
  112. /**
  113. * 用户登录
  114. *
  115. * @param {Object} ctx 请求对象
  116. */
  117. async userLogin(ctx) {
  118. let params = ctx.request.body || {};
  119. // 验证数据完整性
  120. validator.validateParamsField(params, userLoginRules, ctx);
  121. // 查询数据库,判断唯一性
  122. let userInfo = await db.user.findOne({
  123. userName: params.userName,
  124. });
  125. if (userInfo) {
  126. // 密码校验,正确则生成session
  127. if (userInfo.password === params.password) {
  128. let sessionId = await userUtil.setIconSession(userInfo.userId, ctx);
  129. let autoLoginSessionId = await userUtil.setIconAutoLoginSession(
  130. userInfo.userId,
  131. ctx
  132. );
  133. // 生成session后给给客户端写cookie
  134. userUtil.setIconSessionCookie(sessionId, false, ctx);
  135. userUtil.setIconAutoLoginSessionCookie(autoLoginSessionId, false, ctx);
  136. delete userInfo.password;
  137. ctx.body = responseFormat.responseFormat(200, "", userInfo);
  138. } else {
  139. ctx.body = responseFormat.responseFormat(
  140. 200,
  141. {
  142. password: {
  143. message: `密码错误`,
  144. success: false,
  145. },
  146. },
  147. false
  148. );
  149. }
  150. } else {
  151. ctx.body = responseFormat.responseFormat(
  152. 200,
  153. {
  154. userName: {
  155. message: `账号不存在!`,
  156. success: false,
  157. },
  158. },
  159. false
  160. );
  161. }
  162. }
  163. /**
  164. * 用户注册
  165. *
  166. * @param {Object} ctx 请求对象
  167. */
  168. async userRegister(ctx) {
  169. let params = ctx.request.body || {};
  170. // 验证数据完整性
  171. validator.validateParamsField(params, userRegisterRules, ctx);
  172. // 查询数据库,判断唯一性
  173. let userResult = await db.user.findOne({
  174. userName: params.userName,
  175. });
  176. if (userResult) {
  177. ctx.body = responseFormat.responseFormat(
  178. 200,
  179. {
  180. userName: {
  181. message: `用户名已经存在, 请直接登录`,
  182. success: false,
  183. },
  184. },
  185. false
  186. );
  187. return;
  188. }
  189. // 获取唯一自增Id
  190. let userId = await incUtil.getIncId({ model: "user", field: "userId" });
  191. // set random avatar
  192. let index = parseInt(Math.random() * 105);
  193. let avatar = avatarConfig[index];
  194. // 构建完整用户注册数据
  195. Object.assign(params, {
  196. createTime: global.globalConfig.nowTime,
  197. updateTime: global.globalConfig.nowTime,
  198. avatar: avatar,
  199. userId: userId,
  200. userName: String(params.userName),
  201. });
  202. // 保存用户信息到数据库
  203. await db.user.add(params);
  204. let sessionId = await userUtil.setIconSession(userId, ctx);
  205. let autoLoginSessionId = await userUtil.setIconAutoLoginSession(
  206. userId,
  207. ctx
  208. );
  209. // 生成session后给给客户端写cookie
  210. userUtil.setIconSessionCookie(sessionId, false, ctx);
  211. userUtil.setIconAutoLoginSessionCookie(autoLoginSessionId, false, ctx);
  212. delete params.password;
  213. ctx.body = responseFormat.responseFormat(200, "", params);
  214. }
  215. /**
  216. * app user logout
  217. *
  218. * @param {Object} ctx request object
  219. */
  220. async userLogout(ctx) {
  221. const sessionId = ctx.cookies.get("ICON_SESSION", {
  222. domain: config.host,
  223. path: "/",
  224. httpOnly: true,
  225. });
  226. const autoLoginSessionId = ctx.cookies.get("ICON_AUTO_LOGIN_SESSION", {
  227. domain: config.host,
  228. path: "/",
  229. httpOnly: true,
  230. });
  231. await redis.destroy(sessionId);
  232. await redis.destroy(autoLoginSessionId);
  233. userUtil.setIconSessionCookie(sessionId, true, ctx);
  234. userUtil.setIconAutoLoginSessionCookie(autoLoginSessionId, true, ctx);
  235. ctx.body = responseFormat.responseFormat(200, "", {
  236. loginUrl: loginService.config.loginUrl,
  237. });
  238. }
  239. /**
  240. * get current login userInfo
  241. *
  242. * @param {Object} ctx request object
  243. */
  244. async getCurLoginUserInfo(ctx) {
  245. const autoLoginSessionId = ctx.cookies.get("ICON_AUTO_LOGIN_SESSION", {
  246. domain: config.host,
  247. path: "/",
  248. httpOnly: true,
  249. });
  250. // return loginUrl if not login
  251. let userInfo = {
  252. loginUrl: loginService.config.loginUrl,
  253. };
  254. if (autoLoginSessionId) {
  255. // return userInfo and cookie ICON_SESSION if user exist
  256. let exist = await redis.get(autoLoginSessionId);
  257. // decrypt cookie for get userId
  258. let userInfoCur = cryptoUtil.decrypt(autoLoginSessionId, "");
  259. userInfoCur = await db.user.findOne(
  260. { userId: userInfoCur.userId },
  261. global.globalConfig.userExportFields
  262. );
  263. if (userInfoCur) {
  264. userInfo = userInfoCur;
  265. }
  266. if (exist && userInfoCur && userInfoCur.userId) {
  267. // set cookie to client
  268. let sessionId = await userUtil.setIconSession(userInfoCur.userId, ctx);
  269. userUtil.setIconSessionCookie(sessionId, false, ctx);
  270. } else if (userInfoCur && userInfoCur.userId) {
  271. // user exist but session expired in redis, need to generate session to redis then auto login
  272. let autoLoginSessionId = await userUtil.setIconAutoLoginSession(
  273. userInfoCur.userId,
  274. ctx
  275. );
  276. let sessionId = await userUtil.setIconSession(userInfoCur.userId, ctx);
  277. userUtil.setIconSessionCookie(sessionId, false, ctx);
  278. userUtil.setIconAutoLoginSessionCookie(autoLoginSessionId, false, ctx);
  279. }
  280. }
  281. ctx.body = responseFormat.responseFormat(200, "", userInfo);
  282. }
  283. /**
  284. * get specific userInfo
  285. *
  286. * @param {Object} ctx request object
  287. */
  288. async getUserInfo(ctx) {
  289. let params = ctx.params;
  290. let userInfo = await db.user.findOne(
  291. { userId: params.userId },
  292. global.globalConfig.userExportFields
  293. );
  294. if (!userInfo) {
  295. ctx.body = responseFormat.responseFormat(500, "user not exist", false);
  296. } else {
  297. ctx.body = responseFormat.responseFormat(200, "", userInfo);
  298. }
  299. }
  300. }
  301. module.exports = UserController;