import express from 'express'; import bcrypt from 'bcrypt'; import jwt from 'jsonwebtoken'; import db from '../database.js'; import { authenticateToken } from '../middleware/auth.js'; const router = express.Router(); // Register new user router.post('/register', async (req, res) => { const { username, email, password } = req.body; if (!username || !email || !password) { return res.status(400).json({ error: 'Username, email, and password are required' }); } if (password.length < 6) { return res.status(400).json({ error: 'Password must be at least 6 characters long' }); } try { const hashedPassword = await bcrypt.hash(password, 10); const query = 'INSERT INTO users (username, email, password_hash) VALUES (?, ?, ?)'; db.run(query, [username, email, hashedPassword], function (err) { if (err) { if (err.message.includes('UNIQUE')) { return res.status(400).json({ error: 'Username or email already exists' }); } return res.status(500).json({ error: err.message }); } const token = jwt.sign( { id: this.lastID, username, email }, process.env.JWT_SECRET, { expiresIn: '7d' } ); res.status(201).json({ message: 'User registered successfully', token, user: { id: this.lastID, username, email } }); }); } catch (error) { res.status(500).json({ error: 'Error hashing password' }); } }); // Login router.post('/login', (req, res) => { const { username, password } = req.body; if (!username || !password) { return res.status(400).json({ error: 'Username and password are required' }); } const query = 'SELECT * FROM users WHERE username = ?'; db.get(query, [username], async (err, user) => { if (err) { return res.status(500).json({ error: err.message }); } if (!user) { return res.status(401).json({ error: 'Invalid username or password' }); } try { const validPassword = await bcrypt.compare(password, user.password_hash); if (!validPassword) { return res.status(401).json({ error: 'Invalid username or password' }); } const token = jwt.sign( { id: user.id, username: user.username, email: user.email }, process.env.JWT_SECRET, { expiresIn: '7d' } ); res.json({ message: 'Login successful', token, user: { id: user.id, username: user.username, email: user.email } }); } catch (error) { res.status(500).json({ error: 'Error verifying password' }); } }); }); // Get current user router.get('/me', authenticateToken, (req, res) => { const query = 'SELECT id, username, email, theme, created_at FROM users WHERE id = ?'; db.get(query, [req.user.id], (err, user) => { if (err) { return res.status(500).json({ error: err.message }); } if (!user) { return res.status(404).json({ error: 'User not found' }); } res.json({ user }); }); }); // Update user theme preference router.put('/me/theme', authenticateToken, (req, res) => { const { theme } = req.body; if (!['light', 'dark'].includes(theme)) { return res.status(400).json({ error: 'Theme must be "light" or "dark"' }); } const query = 'UPDATE users SET theme = ? WHERE id = ?'; db.run(query, [theme, req.user.id], (err) => { if (err) { return res.status(500).json({ error: err.message }); } res.json({ message: 'Theme updated', theme }); }); }); // Update user email router.put('/me/email', authenticateToken, async (req, res) => { const { newEmail, password } = req.body; if (!newEmail || !password) { return res.status(400).json({ error: 'New email and password are required' }); } try { // Get current user const userQuery = 'SELECT * FROM users WHERE id = ?'; db.get(userQuery, [req.user.id], async (err, user) => { if (err) { return res.status(500).json({ error: err.message }); } if (!user) { return res.status(404).json({ error: 'User not found' }); } // Verify password const validPassword = await bcrypt.compare(password, user.password_hash); if (!validPassword) { return res.status(401).json({ error: 'Invalid password' }); } // Check if email already exists const emailCheckQuery = 'SELECT id FROM users WHERE email = ? AND id != ?'; db.get(emailCheckQuery, [newEmail, req.user.id], (err, existingUser) => { if (err) { return res.status(500).json({ error: err.message }); } if (existingUser) { return res.status(400).json({ error: 'Email already in use' }); } // Update email const updateQuery = 'UPDATE users SET email = ? WHERE id = ?'; db.run(updateQuery, [newEmail, req.user.id], (err) => { if (err) { return res.status(500).json({ error: err.message }); } res.json({ message: 'Email updated successfully', email: newEmail }); }); }); }); } catch (error) { res.status(500).json({ error: 'Error updating email' }); } }); // Update user password router.put('/me/password', authenticateToken, async (req, res) => { const { currentPassword, newPassword } = req.body; if (!currentPassword || !newPassword) { return res.status(400).json({ error: 'Current and new password are required' }); } if (newPassword.length < 6) { return res.status(400).json({ error: 'New password must be at least 6 characters long' }); } try { // Get current user const userQuery = 'SELECT * FROM users WHERE id = ?'; db.get(userQuery, [req.user.id], async (err, user) => { if (err) { return res.status(500).json({ error: err.message }); } if (!user) { return res.status(404).json({ error: 'User not found' }); } // Verify current password const validPassword = await bcrypt.compare(currentPassword, user.password_hash); if (!validPassword) { return res.status(401).json({ error: 'Invalid current password' }); } // Hash new password const hashedPassword = await bcrypt.hash(newPassword, 10); // Update password const updateQuery = 'UPDATE users SET password_hash = ? WHERE id = ?'; db.run(updateQuery, [hashedPassword, req.user.id], (err) => { if (err) { return res.status(500).json({ error: err.message }); } res.json({ message: 'Password updated successfully' }); }); }); } catch (error) { res.status(500).json({ error: 'Error updating password' }); } }); export default router;