users.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. 'use strict';
  2. const async = require('async');
  3. const config = require('config');
  4. const request = require('request');
  5. const bcrypt = require('bcrypt');
  6. const db = require('../db');
  7. const cache = require('../cache');
  8. const utils = require('../utils');
  9. module.exports = {
  10. login: (sessionId, identifier, password, cb) => {
  11. async.waterfall([
  12. // check if a user with the requested identifier exists
  13. (next) => db.models.user.findOne({
  14. $or: [{ 'username': identifier }, { 'email.address': identifier }]
  15. }, next),
  16. // if the user doesn't exist, respond with a failure
  17. // otherwise compare the requested password and the actual users password
  18. (user, next) => {
  19. if (!user) return next(true, { status: 'failure', message: 'User not found' });
  20. bcrypt.compare(password, user.services.password.password, (err, match) => {
  21. if (err) return next(err);
  22. // if the passwords match
  23. if (match) {
  24. // store the session in the cache
  25. let userSessionId = utils.guid();
  26. cache.hset('userSessions', userSessionId, cache.schemas.userSession(user._id), (err) => {
  27. if (!err) {
  28. console.log(sessionId, 222);
  29. cache.hget('sessions', sessionId, (err, session) => {
  30. console.log(err, session, 333);
  31. session.userSessionId = userSessionId;
  32. cache.hset('sessions', sessionId, session, (err) => {
  33. next(null, { status: 'success', message: 'Login successful', user, SID: userSessionId });
  34. })
  35. })
  36. }
  37. });
  38. }
  39. else {
  40. next(null, { status: 'failure', message: 'User not found' });
  41. }
  42. });
  43. }
  44. ], (err, payload) => {
  45. // log this error somewhere
  46. if (err && err !== true) {
  47. console.error(err);
  48. return cb({ status: 'error', message: 'An error occurred while logging in' });
  49. }
  50. cb(payload);
  51. });
  52. },
  53. register: (session, username, email, password, recaptcha, cb) => {
  54. async.waterfall([
  55. // verify the request with google recaptcha
  56. /*(next) => {
  57. request({
  58. url: 'https://www.google.com/recaptcha/api/siteverify',
  59. method: 'POST',
  60. form: {
  61. //'secret': config.get("apis.recaptcha.secret"),
  62. 'response': recaptcha
  63. }
  64. }, next);
  65. },*/
  66. // check if the response from Google recaptcha is successful
  67. // if it is, we check if a user with the requested username already exists
  68. (/*response, body, */next) => {
  69. /*let json = JSON.parse(body);
  70. console.log(json);*/
  71. //if (json.success !== true) return next('Response from recaptcha was not successful');
  72. db.models.user.findOne({ username }, next);
  73. },
  74. // if the user already exists, respond with that
  75. // otherwise check if a user with the requested email already exists
  76. (user, next) => {
  77. if (user) return next(true, { status: 'failure', message: 'A user with that username already exists' });
  78. db.models.user.findOne({ 'email.address': email }, next);
  79. },
  80. // if the user already exists, respond with that
  81. // otherwise, generate a salt to use with hashing the new users password
  82. (user, next) => {
  83. if (user) return next(true, { status: 'failure', message: 'A user with that email already exists' });
  84. bcrypt.genSalt(10, next);
  85. },
  86. // hash the password
  87. (salt, next) => {
  88. bcrypt.hash(password, salt, next)
  89. },
  90. // save the new user to the database
  91. (hash, next) => {
  92. db.models.user.create({
  93. username,
  94. email: {
  95. address: email,
  96. verificationToken: utils.generateRandomString(64)
  97. },
  98. services: {
  99. password: {
  100. password: hash
  101. }
  102. }
  103. }, next);
  104. },
  105. // respond with the new user
  106. (newUser, next) => {
  107. next(null, { status: 'success', user: newUser })
  108. }
  109. ], (err, payload) => {
  110. // log this error somewhere
  111. if (err && err !== true) {
  112. console.error(err);
  113. return cb({ status: 'error', message: 'An error occurred while registering for an account' });
  114. }
  115. // respond with the payload that was passed to us earlier
  116. cb(payload);
  117. });
  118. },
  119. logout: (sessionId, cb) => {
  120. cache.hget('sessions', sessionId, (err, session) => {
  121. if (err || !session) return cb({ 'status': 'failure', message: 'Something went wrong while logging you out.' });
  122. if (!session.userSessionId) return cb({ 'status': 'failure', message: 'You are not logged in.' });
  123. cache.hget('userSessions', session.userSessionId, (err, userSession) => {
  124. if (err || !userSession) return cb({ 'status': 'failure', message: 'Something went wrong while logging you out.' });
  125. if (!userSession) return cb({ 'status': 'failure', message: 'You are not logged in.' });
  126. cache.hdel('userSessions', session.userSessionId, (err) => {
  127. if (err || !userSession) return cb({ 'status': 'failure', message: 'Something went wrong while logging you out.' });
  128. return cb({ 'status': 'success', message: 'You have been successfully logged out.' });
  129. });
  130. });
  131. });
  132. },
  133. findByUsername: (session, username, cb) => {
  134. db.models.user.find({ username }, (err, account) => {
  135. if (err) throw err;
  136. else if (account.length == 0) {
  137. return cb({
  138. status: 'error',
  139. message: 'Username cannot be found'
  140. });
  141. } else {
  142. account = account[0];
  143. return cb({
  144. status: 'success',
  145. data: {
  146. username: account.username,
  147. email: account.email.address,
  148. password: '',
  149. createdAt: account.createdAt,
  150. statistics: account.statistics
  151. }
  152. });
  153. }
  154. });
  155. },
  156. findBySession: (session, cb) => {
  157. return cb({
  158. status: 'success',
  159. data: session
  160. });
  161. },
  162. update: (session, user_id, property, value, cb) => {
  163. db.models.user.findOne({ _id: user_id }, (err, user) => {
  164. if (err) throw err;
  165. else if (!user) cb({ status: 'error', message: 'Invalid User ID' });
  166. else if (user[property] && user[property] !== value) {
  167. if (property == 'services.password.password') {
  168. bcrypt.compare(user[property], value, (err, res) => {
  169. if (err) throw err;
  170. bcrypt.genSalt(10, (err, salt) => {
  171. if (err) throw err;
  172. bcrypt.hash(value, salt, (err, hash) => {
  173. if (err) throw err;
  174. user[property] = hash;
  175. });
  176. });
  177. });
  178. } else user[property] = value;
  179. user.save(err => {
  180. if (err) cb({ status: 'error', message: err.message });
  181. });
  182. } else {
  183. cb({ status: 'error', message: 'Field has not changed' });
  184. }
  185. });
  186. },
  187. };