users.js 4.1 KB

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