user.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import User from "../models/User.js";
  2. import {HttpError} from "../HttpError.js";
  3. import validate from "../validation/user.js";
  4. import bcrypt from "bcrypt";
  5. import crypto from "crypto";
  6. import jwt from "jsonwebtoken";
  7. const createRoute = async (req, res, next)=>{
  8. try{
  9. validate(req.body);
  10. const user = await createUser(req.body);
  11. await user.save();
  12. res.json({success: true});
  13. }catch(e){next(e)}
  14. }
  15. const loginRoute = async (req, res, next)=>{
  16. try{
  17. const user = await User.findOne({email: req.body.email.toLowerCase()});
  18. if(user === null) throw new HttpError(400, "Invalid credentials");
  19. await comparePass(req.body.pass, user.password);
  20. const token = createToken(user);
  21. setCookie(res, "userToken", token);
  22. res.json(responseUser(user));
  23. }catch(e){next(e)}
  24. }
  25. /*
  26. Create a new User object
  27. @param {Object} - Request body with user data
  28. @return {User} - User object
  29. */
  30. const createUser = async (data)=>{
  31. const email = data.email.toLowerCase();
  32. const user = await User.findOne({email: email});
  33. if(user !== null) throw new HttpError(400, "User with this email already exists");
  34. return new User({
  35. name: data.name,
  36. email: email,
  37. password: await hashPass(data.pass),
  38. workouts: [],
  39. uuid: createUuid()
  40. });
  41. }
  42. /*
  43. Hash a password
  44. @param {String} - Password to hash
  45. @return {String} - Hashed password
  46. */
  47. const hashPass = async (password)=>{
  48. return await bcrypt.hash(password, 10);
  49. }
  50. /*
  51. Throw error if password does not match
  52. @param {String} password - Password to compare
  53. @param {String} hashedPass - Hashed password from database
  54. */
  55. const comparePass = async (password, hashedPass)=>{
  56. const result = await bcrypt.compare(password, hashedPass);
  57. if(result !== true) throw new HttpError(400, "Invalid credentials");
  58. }
  59. /*
  60. Create an authorization token for the user
  61. @param {User} user - User object
  62. @return {String} - User auth token
  63. */
  64. const createToken = (user)=>{
  65. return jwt.sign({
  66. id: user._id,
  67. token: user.token
  68. }, process.env.JWT_SECRET);
  69. }
  70. /*
  71. Set a cookie
  72. @param {Response} res - Response object containing the 'cookie' method
  73. @param {String} name - Name of the cookie to set
  74. @param {String} value - Value of the cookie
  75. */
  76. const setCookie = (res, name, value)=>{
  77. res.cookie(name, value, {
  78. httpOnly: true,
  79. secure: process.env.NODE_ENV === "production",
  80. signed: true
  81. });
  82. }
  83. /*
  84. Create user object for sending to frontend
  85. @param {User} - User object
  86. @return {User} - Modified User object
  87. */
  88. const responseUser = (user)=>{
  89. return {
  90. id: user._id,
  91. name: user.name,
  92. email: user.email,
  93. workouts: user.workouts
  94. };
  95. }
  96. /*
  97. Create a new UUID token
  98. @return {String} - UUID token
  99. */
  100. const createUuid = ()=>{
  101. return crypto.randomUUID();
  102. }
  103. export {
  104. createRoute,
  105. loginRoute
  106. }