user.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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. const logoutRoute = async (req, res, next)=>{
  26. try{
  27. res.clearCookie("userToken");
  28. res.json({success: true});
  29. }catch(e){next(e)}
  30. }
  31. const getRoute = async (req, res, next)=>{
  32. try{
  33. res.json(res.locals.user);
  34. }catch(e){next(e)}
  35. }
  36. /*
  37. Create a new User object
  38. @param {Object} - Request body with user data
  39. @return {User} - User object
  40. */
  41. const createUser = async (data)=>{
  42. const email = data.email.toLowerCase();
  43. const user = await User.findOne({email: email});
  44. if(user !== null) throw new HttpError(400, "User with this email already exists");
  45. return new User({
  46. name: data.name,
  47. email: email,
  48. password: await hashPass(data.pass),
  49. workouts: [],
  50. uuid: createUuid()
  51. });
  52. }
  53. /*
  54. Hash a password
  55. @param {String} - Password to hash
  56. @return {String} - Hashed password
  57. */
  58. const hashPass = async (password)=>{
  59. return await bcrypt.hash(password, 10);
  60. }
  61. /*
  62. Throw error if password does not match
  63. @param {String} password - Password to compare
  64. @param {String} hashedPass - Hashed password from database
  65. */
  66. const comparePass = async (password, hashedPass)=>{
  67. const result = await bcrypt.compare(password, hashedPass);
  68. if(result !== true) throw new HttpError(400, "Invalid credentials");
  69. }
  70. /*
  71. Create an authorization token for the user
  72. @param {User} user - User object
  73. @return {String} - User auth token
  74. */
  75. const createToken = (user)=>{
  76. return jwt.sign({
  77. id: user._id,
  78. token: user.token
  79. }, process.env.JWT_SECRET);
  80. }
  81. /*
  82. Set a cookie
  83. @param {Response} res - Response object containing the 'cookie' method
  84. @param {String} name - Name of the cookie to set
  85. @param {String} value - Value of the cookie
  86. */
  87. const setCookie = (res, name, value)=>{
  88. res.cookie(name, value, {
  89. httpOnly: true,
  90. secure: process.env.NODE_ENV === "production",
  91. signed: true
  92. });
  93. }
  94. /*
  95. Create user object for sending to frontend
  96. @param {User} - User object
  97. @return {User} - Modified User object
  98. */
  99. const responseUser = (user)=>{
  100. return {
  101. id: user._id,
  102. name: user.name,
  103. email: user.email,
  104. workouts: user.workouts
  105. };
  106. }
  107. /*
  108. Create a new UUID token
  109. @return {String} - UUID token
  110. */
  111. const createUuid = ()=>{
  112. return crypto.randomUUID();
  113. }
  114. export {
  115. createRoute,
  116. loginRoute,
  117. logoutRoute,
  118. getRoute
  119. }