// noinspection SpellCheckingInspection import User from '../models/User.js' import asyncHandler from '../middleware/async.js' import ErrorResponse from '../utils/errorResponse.js' import sendEmail from '../utils/sendEmail.js' import crypto from 'crypto' // @desc Register user // @route POST /api/v1/auth/register // @access Public export const register = asyncHandler(async (req, res, next) => { const { name, displayName, email, password, role } = req.body //Create user const user = await User.create({ name, displayName, email, password, role, gamesCreated: [], gamesToAccess: [], }) sendTokenResponse(user, 200, res) }) // @desc Login user // @route POST /api/v1/auth/login // @access Public export const login = asyncHandler(async (req, res, next) => { const { email, password } = req.body // Validate email & password if (!email || !password) return next(new ErrorResponse('Please provide an email and password', 400)) // Check for user const user = await User.findOne({ email }).select('+password') if (!user) return next(new ErrorResponse('Invalid credentials', 401)) // Check is password matches const isMatched = await user.matchPassword(password) if (!isMatched) return next(new ErrorResponse('Invalid credentials', 401)) sendTokenResponse(user, 200, res) }) // @desc Logout User / Clear Cookie // @route GET /api/v1/auth/logout // @access Private export const logout = asyncHandler(async (req, res, next) => { res.cookie('token', 'none', { expires: new Date(Date.now() + 10 * 1000), httpOnly: true, }) res.status(200).json({ success: true, data: {}, }) }) // @desc Get current logged-in user // @route POST /api/v1/auth/me // @access Private export const getMe = asyncHandler(async (req, res, next) => { const user = await User.findById(req.user.id) res.status(200).json({ success: true, data: user, }) }) // @desc Update user details // @route PUT /api/v1/auth/updatedetails // @access Private export const updateDetails = asyncHandler(async (req, res, next) => { const fieldsToUpdate = { name: req.body.name, displayName: req.body.displayName, email: req.body.email, role: req.body.role, updateDate: Date.now(), } const user = await User.findByIdAndUpdate(req.user.id, fieldsToUpdate, { new: true, runValidators: true, }) res.status(200).json({ success: true, data: user, }) }) // @desc Update password // @route PUT /api/v1/auth/updatepassword // @access Private export const updatePassword = asyncHandler(async (req, res, next) => { const user = await User.findById(req.user.id).select('+password') // Check current password if (!(await user.matchPassword(req.body.currentPassword))) return next(new ErrorResponse('Password is incorrect', 401)) user.password = req.body.newPassword await user.save() sendTokenResponse(user, 200, res) }) // @desc Forgot password // @route POST /api/v1/auth/forgotpassword // @access Public export const forgotPassword = asyncHandler(async (req, res, next) => { const user = await User.findOne({ email: req.body.email }) if (!user) { console.error('user does not exist') return res.status(200).json({ success: true, data: 'Email has been sent', }) } // Get reset token const resetToken = await user.getResetPasswordToken() await user.save({ validateBeforeSave: false }) // Create reset url let resetUrl let message if (req.get('Referrer') === undefined) { const protocol = req.secure ? 'https' : 'http' const host = await req.get('host') resetUrl = `${protocol}://${host}/api/auth/resetpassword/${resetToken}` message = { text: `You are receiving this email because you (or someone else) has requested the reset of a password. Please make a PUT request to: \n\n${resetUrl}`, html: `

You are receiving this email because you (or someone else) has requested the reset of a password.
Please make a PUT request to:

${resetUrl}

` } } else { resetUrl = `${req.get('Referrer')}resetpassword/${resetToken}` message = { text: `You are receiving this email because you (or someone else) has requested the reset of a password. \nPlease visit the below URL to continue this request. \n\n${resetUrl}`, html: `

You are receiving this email because you (or someone else) has requested the reset of a password.
Please visit the below URL to continue this request.

${resetUrl}

`, } } try { await sendEmail({ email: user.email, subject: 'Games Database Password Reset Token', message, }) res.status(200).json({ success: true, data: 'Email has been sent', }) } catch (err) { console.log(err) user.resetPasswordToken = undefined user.resetPasswordExpire = undefined await user.save({ validateBeforeSave: false }) return next(new ErrorResponse('Email could not be sent', 500)) } }) // @desc Reset password // @route PUT /api/v1/auth/resetpassword/:resettoken // @access Public export const resetPassword = asyncHandler(async (req, res, next) => { // Get hashed token const resetPasswordToken = crypto .createHash('sha256') .update(req.params.resettoken) .digest('hex') const user = await User.findOne({ resetPasswordToken, resetPasswordExpire: { $gt: Date.now() }, }) if (!user) return next(new ErrorResponse('Invalid token', 400)) // Set new password user.password = req.body.password user.resetPasswordToken = undefined user.resetPasswordExpire = undefined await user.save() sendTokenResponse(user, 200, res) }) // Get token from model, create cookie and send response const sendTokenResponse = (user, statusCode, res) => { // Create token const token = user.getSignedJwtToken() const options = { expires: new Date( Date.now() + 24 * 60 * 60 * 1000, ), httpOnly: true, } if (Bun.env.NODE_ENV === 'production') options.secure = true res.status(statusCode).cookie('token', token, options).json({ success: true, token, }) }