Spaces:
Sleeping
Sleeping
Production Fix: Resolve fs ReferenceError in Multer, fix profile auth failure, and optimize controller lookups
5db933c | 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'); | |
| }; | |