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. uuid: createUuid()
  50. });
  51. }
  52. /*
  53. Hash a password
  54. @param {String} - Password to hash
  55. @return {String} - Hashed password
  56. */
  57. const hashPass = async (password)=>{
  58. return await bcrypt.hash(password, 10);
  59. }
  60. /*
  61. Throw error if password does not match
  62. @param {String} password - Password to compare
  63. @param {String} hashedPass - Hashed password from database
  64. */
  65. const comparePass = async (password, hashedPass)=>{
  66. const result = await bcrypt.compare(password, hashedPass);
  67. if(result !== true) throw new HttpError(400, "Invalid credentials");
  68. }
  69. /*
  70. Create an authorization token for the user
  71. @param {User} user - User object
  72. @return {String} - User auth token
  73. */
  74. const createToken = (user)=>{
  75. return jwt.sign({
  76. id: user._id,
  77. token: user.uuid
  78. }, process.env.JWT_SECRET);
  79. }
  80. /*
  81. Set a cookie
  82. @param {Response} res - Response object containing the 'cookie' method
  83. @param {String} name - Name of the cookie to set
  84. @param {String} value - Value of the cookie
  85. */
  86. const setCookie = (res, name, value)=>{
  87. res.cookie(name, value, {
  88. httpOnly: true,
  89. secure: process.env.NODE_ENV === "production",
  90. signed: true,
  91. expires: new Date(2050, 12, 12)
  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. }