users.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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: (session, 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 sessionId = utils.guid();
  26. cache.hset('sessions', sessionId, cache.schemas.session());
  27. next(null, { status: 'success', message: 'Login successful', user, sessionId: sessionId });
  28. }
  29. else {
  30. next(null, { status: 'failure', message: 'User not found' });
  31. }
  32. });
  33. }
  34. ], (err, payload) => {
  35. // log this error somewhere
  36. if (err && err !== true) {
  37. console.error(err);
  38. return cb({ status: 'error', message: 'An error occurred while logging in' });
  39. }
  40. cb(payload);
  41. });
  42. },
  43. register: (session, username, email, password, recaptcha, cb) => {
  44. async.waterfall([
  45. // verify the request with google recaptcha
  46. (next) => {
  47. request({
  48. url: 'https://www.google.com/recaptcha/api/siteverify',
  49. method: 'POST',
  50. form: {
  51. //'secret': config.get("apis.recaptcha.secret"),
  52. 'response': recaptcha
  53. }
  54. }, next);
  55. },
  56. // check if the response from Google recaptcha is successful
  57. // if it is, we check if a user with the requested username already exists
  58. (response, body, next) => {
  59. let json = JSON.parse(body);
  60. console.log(json);
  61. //if (json.success !== true) return next('Response from recaptcha was not successful');
  62. db.models.user.findOne({ 'username': username }, next);
  63. },
  64. // if the user already exists, respond with that
  65. // otherwise check if a user with the requested email already exists
  66. (user, next) => {
  67. if (user) return next(true, { status: 'failure', message: 'A user with that username already exists' });
  68. db.models.user.findOne({ 'email.address': email }, next);
  69. },
  70. // if the user already exists, respond with that
  71. // otherwise, generate a salt to use with hashing the new users password
  72. (user, next) => {
  73. if (user) return next(true, { status: 'failure', message: 'A user with that email already exists' });
  74. bcrypt.genSalt(10, next);
  75. },
  76. // hash the password
  77. (salt, next) => {
  78. bcrypt.hash(password, salt, next)
  79. },
  80. // save the new user to the database
  81. (hash, next) => {
  82. db.models.user.create({
  83. username: username,
  84. email: {
  85. address: email,
  86. verificationToken: utils.generateRandomString(64)
  87. },
  88. services: {
  89. password: {
  90. password: hash
  91. }
  92. }
  93. }, next);
  94. },
  95. // respond with the new user
  96. (newUser, next) => {
  97. next(null, { status: 'success', user: newUser })
  98. }
  99. ], (err, payload) => {
  100. // log this error somewhere
  101. if (err && err !== true) {
  102. console.error(err);
  103. return cb({ status: 'error', message: 'An error occurred while registering for an account' });
  104. }
  105. // respond with the payload that was passed to us earlier
  106. cb(payload);
  107. });
  108. },
  109. logout: (session, cb) => {
  110. if (!session) return cb({ status: 'failure', message: `You're not currently logged in` });
  111. //TODO Remove session
  112. session = null;
  113. cb({ status: 'success', message: `You've been successfully logged out` });
  114. },
  115. findByUsername: (session, username, cb) => {
  116. db.models.user.find({ username }, (err, account) => {
  117. if (err) throw err;
  118. account = account[0];
  119. cb({
  120. status: 'success',
  121. data: {
  122. username: account.username,
  123. createdAt: account.createdAt,
  124. statistics: account.statistics
  125. }
  126. });
  127. });
  128. }
  129. };