user.js 3.1 KB

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