|
|
const crypto = require('crypto'); |
|
|
const bcrypt = require('bcryptjs'); |
|
|
const jwt = require('jsonwebtoken'); |
|
|
const User = require('../models/User'); |
|
|
const ErrorResponse = require('../utils/errorResponse'); |
|
|
const asyncHandler = require('../utils/asyncHandler'); |
|
|
const sendEmail = require('../services/emailService'); |
|
|
|
|
|
const getSignedJwtToken = (id) => { |
|
|
return jwt.sign({ id }, process.env.JWT_SECRET, { expiresIn: process.env.JWT_EXPIRE }); |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.register = asyncHandler(async (req, res, next) => { |
|
|
const { name, email, password, accessKey } = req.body; |
|
|
|
|
|
|
|
|
if (accessKey !== process.env.NEURAL_ACCESS_KEY) { |
|
|
return next(new ErrorResponse('Invalid Neural Access Key.', 401)); |
|
|
} |
|
|
|
|
|
|
|
|
const user = await User.create({ |
|
|
name, |
|
|
email, |
|
|
password, |
|
|
isVerified: true |
|
|
}); |
|
|
|
|
|
sendTokenResponse(user, 200, res); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.login = asyncHandler(async (req, res, next) => { |
|
|
const { email, password } = req.body; |
|
|
|
|
|
if (!email || !password) { |
|
|
return next(new ErrorResponse('Please provide email and password', 400)); |
|
|
} |
|
|
|
|
|
const user = await User.findOne({ email }).select('+password'); |
|
|
|
|
|
if (!user || !(await user.matchPassword(password))) { |
|
|
return next(new ErrorResponse('Invalid credentials', 401)); |
|
|
} |
|
|
|
|
|
if (!user.isVerified) { |
|
|
return next(new ErrorResponse('Please verify your email first', 401)); |
|
|
} |
|
|
|
|
|
sendTokenResponse(user, 200, res); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.getMe = asyncHandler(async (req, res, next) => { |
|
|
res.status(200).json({ |
|
|
success: true, |
|
|
data: req.user, |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.verifyEmail = asyncHandler(async (req, res, next) => { |
|
|
res.status(200).json({ success: true, data: 'Verified' }); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.forgotPassword = asyncHandler(async (req, res, next) => { |
|
|
const user = await User.findOne({ email: req.body.email }); |
|
|
if (!user) return next(new ErrorResponse('No user', 404)); |
|
|
|
|
|
const resetToken = user.getResetPasswordToken(); |
|
|
await user.save({ validateBeforeSave: false }); |
|
|
|
|
|
const resetUrl = `${process.env.CLIENT_URL}/resetpassword/${resetToken}`; |
|
|
try { |
|
|
await sendEmail({ email: user.email, subject: 'Codex Reset', message: resetUrl }); |
|
|
res.status(200).json({ success: true, data: 'Email sent' }); |
|
|
} catch (err) { |
|
|
user.resetPasswordToken = undefined; |
|
|
user.resetPasswordExpire = undefined; |
|
|
await user.save({ validateBeforeSave: false }); |
|
|
return next(new ErrorResponse('Email error', 500)); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.resetPassword = asyncHandler(async (req, res, next) => { |
|
|
const resetPasswordToken = crypto.createHash('sha256').update(req.params.token).digest('hex'); |
|
|
|
|
|
const user = await User.findOne({ |
|
|
resetPasswordToken, |
|
|
resetPasswordExpire: { $gt: Date.now() }, |
|
|
}); |
|
|
|
|
|
if (!user) { |
|
|
return next(new ErrorResponse('Invalid token', 400)); |
|
|
} |
|
|
|
|
|
user.password = req.body.password; |
|
|
user.resetPasswordToken = undefined; |
|
|
user.resetPasswordExpire = undefined; |
|
|
await user.save(); |
|
|
|
|
|
sendTokenResponse(user, 200, res); |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.updatePassword = asyncHandler(async (req, res, next) => { |
|
|
const user = req.user; |
|
|
|
|
|
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); |
|
|
}); |
|
|
|
|
|
const sendTokenResponse = (user, statusCode, res) => { |
|
|
const token = user.getSignedJwtToken(); |
|
|
|
|
|
const options = { |
|
|
expires: new Date( |
|
|
Date.now() + process.env.JWT_COOKIE_EXPIRE * 24 * 60 * 60 * 1000 |
|
|
), |
|
|
httpOnly: true, |
|
|
}; |
|
|
|
|
|
if (process.env.NODE_ENV === 'production') { |
|
|
options.secure = true; |
|
|
} |
|
|
|
|
|
res.status(statusCode).cookie('token', token, options).json({ |
|
|
success: true, |
|
|
token, |
|
|
}); |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.githubAuthCallback = (req, res) => { |
|
|
const token = req.user.getSignedJwtToken(); |
|
|
const options = { |
|
|
expires: new Date(Date.now() + process.env.JWT_COOKIE_EXPIRE * 24 * 60 * 60 * 1000), |
|
|
httpOnly: true |
|
|
}; |
|
|
if (process.env.NODE_ENV === 'production') options.secure = true; |
|
|
|
|
|
res.cookie('token', token, options); |
|
|
|
|
|
res.redirect('/chat'); |
|
|
}; |
|
|
|