const jwt = require('jsonwebtoken'); const User = require('../models/User'); const Joi = require('joi'); // Validation schemas const registerSchema = Joi.object({ username: Joi.string().alphanum().min(3).max(30).required(), email: Joi.string().email().required(), password: Joi.string().min(6).required() }); const loginSchema = Joi.object({ email: Joi.string().email().required(), password: Joi.string().min(6).required() }); // Generate JWT token const generateToken = (userId) => { return jwt.sign({ userId }, process.env.JWT_SECRET, { expiresIn: process.env.JWT_EXPIRE || '7d' }); }; // Register user exports.register = async (req, res) => { try { // Validate input const { error } = registerSchema.validate(req.body); if (error) { return res.status(400).json({ error: error.details[0].message }); } const { username, email, password } = req.body; // Check if user already exists const existingUser = await User.findOne({ $or: [{ email }, { username }] }); if (existingUser) { return res.status(400).json({ error: existingUser.email === email ? 'Email already registered' : 'Username already taken' }); } // Create new user const user = new User({ username, email, password }); await user.save(); // Generate token const token = generateToken(user._id); res.status(201).json({ message: 'User registered successfully', token, user }); } catch (error) { console.error('Registration error:', error); res.status(500).json({ error: 'Internal server error' }); } }; // Login user exports.login = async (req, res) => { try { // Validate input const { error } = loginSchema.validate(req.body); if (error) { return res.status(400).json({ error: error.details[0].message }); } const { email, password } = req.body; // Find user and include password for comparison const user = await User.findOne({ email }).select('+password'); if (!user) { return res.status(401).json({ error: 'Invalid credentials' }); } // Check password const isPasswordValid = await user.comparePassword(password); if (!isPasswordValid) { return res.status(401).json({ error: 'Invalid credentials' }); } // Update last seen user.lastSeen = new Date(); await user.save(); // Generate token const token = generateToken(user._id); res.json({ message: 'Login successful', token, user }); } catch (error) { console.error('Login error:', error); res.status(500).json({ error: 'Internal server error' }); } }; // Get current user exports.getMe = async (req, res) => { try { const user = await User.findById(req.userId); if (!user) { return res.status(404).json({ error: 'User not found' }); } res.json({ user }); } catch (error) { console.error('Get user error:', error); res.status(500).json({ error: 'Internal server error' }); } }; // Update user profile exports.updateProfile = async (req, res) => { try { const { username, avatar } = req.body; const updates = {}; if (username) { // Check if username is already taken const existingUser = await User.findOne({ username, _id: { $ne: req.userId } }); if (existingUser) { return res.status(400).json({ error: 'Username already taken' }); } updates.username = username; } if (avatar) updates.avatar = avatar; const user = await User.findByIdAndUpdate( req.userId, updates, { new: true, runValidators: true } ); res.json({ message: 'Profile updated successfully', user }); } catch (error) { console.error('Update profile error:', error); res.status(500).json({ error: 'Internal server error' }); } };