// routes/auth.js const express = require('express'); const router = express.Router(); const bcrypt = require('bcrypt'); const jwt = require('jsonwebtoken'); const db = require('../db'); const requireRole = require('../middleware/requireRole'); /** * @swagger * /auth/register: * post: * summary: Registriert einen neuen Benutzer * tags: [Auth] * requestBody: * required: true * content: * application/json: * schema: * type: object * required: * - username * - email * - password * properties: * username: * type: string * email: * type: string * password: * type: string * responses: * 201: * description: Benutzer erfolgreich registriert * content: * application/json: * schema: * type: object * properties: * user: * type: object * properties: * id: * type: integer * username: * type: string * email: * type: string * role: * type: string * token: * type: string * 400: * description: Ungültige Eingabedaten * 409: * description: Benutzer existiert bereits */ router.post('/register', async (req, res) => { const { username, email, password } = req.body; if (!username || !email || !password) { return res.status(400).json({ error: 'Missing required fields' }); } try { // Prüfen, ob Benutzer bereits existiert const existingUser = await db.get('SELECT id FROM users WHERE email = ?', [email]); if (existingUser) { return res.status(409).json({ error: 'User already exists' }); } // Passwort hashen const hashedPassword = await bcrypt.hash(password, 10); // Neuen Benutzer anlegen const result = await db.run( 'INSERT INTO users (username, email, password_hash, role) VALUES (?, ?, ?, ?)', [username, email, hashedPassword, 'user'] ); // Token generieren const token = jwt.sign( { id: result.lastID, username, email, role: 'user' }, process.env.JWT_SECRET, { expiresIn: '24h' } ); res.status(201).json({ user: { id: result.lastID, username, email, role: 'user' }, token }); } catch (err) { console.error(err); res.status(500).json({ error: 'Internal server error' }); } }); /** * @swagger * /auth/login: * post: * summary: Loggt einen Benutzer ein * tags: [Auth] * requestBody: * required: true * content: * application/json: * schema: * type: object * required: * - email * - password * properties: * email: * type: string * password: * type: string * responses: * 200: * description: Login erfolgreich * content: * application/json: * schema: * type: object * properties: * user: * type: object * properties: * id: * type: integer * username: * type: string * email: * type: string * role: * type: string * token: * type: string * 400: * description: Ungültige Eingabedaten * 401: * description: Falsche Anmeldedaten */ router.post('/login', async (req, res) => { const { email, password } = req.body; if (!email || !password) { return res.status(400).json({ error: 'Missing email or password' }); } try { const user = await db.get('SELECT id, username, email, password_hash, role FROM users WHERE email = ?', [email]); if (!user) { return res.status(401).json({ error: 'Invalid credentials' }); } const isValidPassword = await bcrypt.compare(password, user.password_hash); if (!isValidPassword) { return res.status(401).json({ error: 'Invalid credentials' }); } // Token generieren const token = jwt.sign( { id: user.id, username: user.username, email: user.email, role: user.role }, process.env.JWT_SECRET, { expiresIn: '24h' } ); res.json({ user: { id: user.id, username: user.username, email: user.email, role: user.role }, token }); } catch (err) { console.error(err); res.status(500).json({ error: 'Internal server error' }); } }); /** * @swagger * /auth/profile: * get: * summary: Holt das Profil des eingeloggten Benutzers * tags: [Auth] * security: * - bearerAuth: [] * responses: * 200: * description: Profil erfolgreich abgerufen * content: * application/json: * schema: * type: object * properties: * user: * type: object * properties: * id: * type: integer * username: * type: string * email: * type: string * role: * type: string * 401: * description: Nicht autorisiert */ router.get('/profile', requireRole(['user', 'moderator', 'admin']), async (req, res) => { try { const user = await db.get('SELECT id, username, email, role FROM users WHERE id = ?', [req.user.id]); if (!user) { return res.status(404).json({ error: 'User not found' }); } res.json({ user }); } catch (err) { console.error(err); res.status(500).json({ error: 'Internal server error' }); } }); /** * @swagger * /auth/profile: * put: * summary: Aktualisiert das Profil des eingeloggten Benutzers * tags: [Auth] * security: * - bearerAuth: [] * requestBody: * required: true * content: * application/json: * schema: * type: object * properties: * username: * type: string * email: * type: string * responses: * 200: * description: Profil erfolgreich aktualisiert * content: * application/json: * schema: * type: object * properties: * user: * type: object * properties: * id: * type: integer * username: * type: string * email: * type: string * role: * type: string * 400: * description: Ungültige Eingabedaten * 401: * description: Nicht autorisiert */ router.put('/profile', requireRole(['user', 'moderator', 'admin']), async (req, res) => { const { username, email } = req.body; if (!username && !email) { return res.status(400).json({ error: 'At least one field must be provided' }); } try { let updateFields = []; let values = []; if (username) { updateFields.push('username = ?'); values.push(username); } if (email) { updateFields.push('email = ?'); values.push(email); } values.push(req.user.id); const query = `UPDATE users SET ${updateFields.join(', ')} WHERE id = ?`; await db.run(query, values); // Aktualisierte Daten abrufen const updatedUser = await db.get('SELECT id, username, email, role FROM users WHERE id = ?', [req.user.id]); res.json({ user: updatedUser }); } catch (err) { console.error(err); res.status(500).json({ error: 'Internal server error' }); } }); module.exports = router;