index.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. var passport = require('passport');
  2. var GitHubStrategy = require('passport-github').Strategy;
  3. var LocalStrategy = require('passport-local').Strategy;
  4. var r = require('../db');
  5. var bcrypt = require('bcryptjs');
  6. //This stores the user id in the session as a reference, and is used to call deserializeUser when it needs all info
  7. passport.serializeUser(function (user, done) {
  8. return done(null, user.id);
  9. });
  10. //This returns the user the user info from the user id
  11. passport.deserializeUser(function (id, done) {
  12. r
  13. .table('users')
  14. .get(id)
  15. .run(r.conn)
  16. .then(function (user) {
  17. delete user.password;
  18. done(null, user);
  19. });
  20. });
  21. //This function gets called when trying to log in, to make the code more efficient and not using repetitive code
  22. var loginCallbackHandler = function (objectMapper, type) {
  23. return function (arg1, arg2, arg3, arg4) {
  24. /*
  25. * If the type is github
  26. * arg1 is the accessToken
  27. * arg2 is the refresh token
  28. * arg3 is profile object
  29. * arg4 is done callback
  30. *
  31. * if the type is local
  32. * arg1 is username
  33. * arg2 is password
  34. * arg3 is done callback
  35. * */
  36. var username, done;
  37. if (type === "github") {
  38. username = arg3.username;
  39. done = arg4;
  40. } else {
  41. username = arg1;
  42. done = arg3;
  43. }
  44. //Arg1 is the accessToken when using GitHub, so we are checking if it's not null to make sure everything is fine
  45. if (arg1 !== null) {
  46. r
  47. .table('users')
  48. .getAll(username.toLowerCase(), { index: 'usernameL' })
  49. .run(r.conn)
  50. .then(function (cursor) {
  51. return cursor.toArray()
  52. .then(function (users) {
  53. if (users.length > 0) {
  54. var userType = users[0].type;
  55. if (userType === "github" && type === userType) {
  56. return done(null, users[0]);
  57. } else if (userType === "local" && userType === type) {
  58. var hash = users[0].password;
  59. console.log("Checking password...");
  60. //This compares the user hash with the password put in
  61. bcrypt.compare(arg2, hash, function(err, isMatch) {
  62. if (err || isMatch === false) {
  63. //Incorrect password/error occured
  64. //TODO Throw error
  65. } else {
  66. var user = users[0];
  67. delete user.password;
  68. return done(null, user);
  69. }
  70. });
  71. } else {
  72. // If this gets called, a user tried to sign in with a GitHub account even though a normal account with that username already exists, or the other way around
  73. if (userType === "local") {
  74. return done(null, false, {message: "This account has been registered via email, not via GitHub."});
  75. } else {
  76. return done(null, false, {message: "This account has been registered via GitHub, not via email."});
  77. }
  78. }
  79. } else if (type === "github") {
  80. //TODO Check if this allows you to have duplicate emails/usernames
  81. //This gets called to create an account with GitHub if none exist yet
  82. return r.table('users')
  83. .insert(objectMapper(arg3))
  84. .run(r.conn)
  85. .then(function (response) {
  86. return r.table('users')
  87. .get(response.generated_keys[0])
  88. .run(r.conn);
  89. })
  90. .then(function (newUser) {
  91. done(null, newUser);
  92. });
  93. } else {
  94. console.log("User not found");
  95. done(null, false, {message: 'Account not found.'});
  96. // TODO Say account not found
  97. }
  98. });
  99. })
  100. .catch(function (err) {
  101. console.log('Error Getting User', err);
  102. });
  103. }
  104. };
  105. };
  106. //This is the callback url which gets used with the GitHub authentication
  107. //TODO Make this config dependent so it's not hardcoded
  108. var callbackURL = 'http://127.0.0.1:3000/auth/login/callback';
  109. //Github strategy
  110. passport.use(new GitHubStrategy({
  111. clientID: "c5516f218aa8682ac67d",
  112. clientSecret: "5a3ee482ab2eb4ade56ab6ea01fd7544dd9a9be9",//TODO Make this secret
  113. callbackURL: callbackURL + '/github'
  114. },
  115. loginCallbackHandler(function (profile) {
  116. //The object that gets created with the GitHub API response, which will be inserted into the users table
  117. return {
  118. 'username': profile.username,
  119. 'usernameL': profile.username.toLowerCase(),
  120. 'name': profile.displayName || undefined,
  121. 'email': 'email',
  122. 'type': 'github'
  123. };
  124. }, 'github')
  125. ));
  126. //Local strategy
  127. passport.use(new LocalStrategy(
  128. {},
  129. loginCallbackHandler(undefined, 'local')
  130. ));
  131. //Function to check if user is logged in
  132. passport.checkIfLoggedIn = function (req, res, next) {
  133. if (req.user) {
  134. return next();
  135. }
  136. return res.status(401).send('You\'re not logged in');
  137. };
  138. module.exports = passport;