File size: 4,916 Bytes
1dc8372 5db933c 1dc8372 5db933c 1dc8372 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
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 });
};
// @desc Register user
// @route POST /api/auth/register
// @access Public
exports.register = asyncHandler(async (req, res, next) => {
const { name, email, password, accessKey } = req.body;
// Verify Unique Secret Access Key
if (accessKey !== process.env.NEURAL_ACCESS_KEY) {
return next(new ErrorResponse('Invalid Neural Access Key.', 401));
}
// Create user
const user = await User.create({
name,
email,
password,
isVerified: true // Auto-verify for dev
});
sendTokenResponse(user, 200, res);
});
// @desc Login user
// @route POST /api/auth/login
// @access Public
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);
});
// @desc Get current logged in user
// @route GET /api/auth/me
// @access Private
exports.getMe = asyncHandler(async (req, res, next) => {
res.status(200).json({
success: true,
data: req.user,
});
});
// @desc Verify email (Dummy for compatibility)
// @route GET /api/auth/verify/:token
// @access Public
exports.verifyEmail = asyncHandler(async (req, res, next) => {
res.status(200).json({ success: true, data: 'Verified' });
});
// @desc Forgot password
// @route POST /api/auth/forgotpassword
// @access Public
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));
}
});
// @desc Reset password
// @route PUT /api/auth/resetpassword/:token
// @access Public
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);
});
// @desc Update password
// @route PUT /api/auth/updatepassword
// @access Private
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,
});
};
// @desc GitHub Auth Callback
// @route GET /api/auth/github/callback
// @access Public
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);
// Redirect to chat or home
res.redirect('/chat');
};
|