309 lines
No EOL
8.2 KiB
JavaScript
309 lines
No EOL
8.2 KiB
JavaScript
// 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; |