2024-10-29 21:09:13 +01:00
|
|
|
const User = require('../models/User');
|
|
|
|
const bcrypt = require('bcryptjs');
|
|
|
|
const jwt = require('jsonwebtoken');
|
|
|
|
|
|
|
|
// Registrierungs-Controller
|
|
|
|
const register = async (req, res) => {
|
|
|
|
const { username, email, password } = req.body;
|
|
|
|
|
|
|
|
try {
|
|
|
|
// Überprüfen, ob Benutzername oder E-Mail bereits existieren
|
|
|
|
let user = await User.findOne({ $or: [{ username }, { email }] });
|
|
|
|
if (user) {
|
|
|
|
return res.status(400).json({ message: 'Benutzername oder E-Mail bereits vergeben' });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Überprüfen, ob es sich um den ersten Benutzer handelt
|
|
|
|
const userCount = await User.countDocuments();
|
|
|
|
const isAdmin = userCount === 0; // Erster Benutzer wird Admin
|
|
|
|
|
|
|
|
// Passwort hashen
|
|
|
|
const hashedPassword = await bcrypt.hash(password, 10);
|
|
|
|
|
|
|
|
// Neuen Benutzer erstellen
|
|
|
|
user = new User({
|
|
|
|
username,
|
|
|
|
email,
|
|
|
|
password: hashedPassword,
|
|
|
|
isAdmin,
|
|
|
|
});
|
|
|
|
|
|
|
|
await user.save();
|
|
|
|
|
|
|
|
res.status(201).json({ message: 'Registrierung erfolgreich' });
|
|
|
|
} catch (error) {
|
|
|
|
res.status(500).json({ message: 'Serverfehler' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Login-Controller
|
|
|
|
const login = async (req, res) => {
|
|
|
|
const { email, password } = req.body;
|
|
|
|
|
|
|
|
try {
|
|
|
|
// Benutzer anhand der E-Mail suchen
|
|
|
|
const user = await User.findOne({ email });
|
|
|
|
if (!user) {
|
|
|
|
return res.status(400).json({ message: 'Ungültige Anmeldedaten' });
|
|
|
|
}
|
|
|
|
|
2024-11-18 17:37:57 +01:00
|
|
|
// Check for too many failed login attempts (e.g., more than 5 in 15 minutes)
|
|
|
|
const maxAttempts = 5;
|
|
|
|
const lockTime = Math.pow(2, user.failedLoginAttempts) * 15 * 1000; // Exponentially increasing delay
|
|
|
|
const now = new Date();
|
|
|
|
|
|
|
|
if (user.failedLoginAttempts >= maxAttempts && user.lastFailedLogin) {
|
|
|
|
const timeDifference = now - new Date(user.lastFailedLogin);
|
|
|
|
if (timeDifference < lockTime) {
|
|
|
|
return res.status(429).json({
|
|
|
|
message: 'Zu viele fehlgeschlagene Versuche. Bitte versuchen Sie es später erneut.',
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
// Reset failed attempts if the lock time has passed
|
|
|
|
user.failedLoginAttempts = 0;
|
|
|
|
user.lastFailedLogin = null;
|
|
|
|
await user.save();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-29 21:09:13 +01:00
|
|
|
// Passwort überprüfen
|
|
|
|
const isMatch = await bcrypt.compare(password, user.password);
|
|
|
|
if (!isMatch) {
|
2024-11-18 17:37:57 +01:00
|
|
|
// Increment failed login attempts
|
|
|
|
user.failedLoginAttempts += 1;
|
|
|
|
user.lastFailedLogin = now; // Update the timestamp of the last failed attempt
|
|
|
|
await user.save();
|
|
|
|
|
|
|
|
// Calculate delay (using the exponential backoff strategy)
|
|
|
|
const delay = Math.pow(2, user.failedLoginAttempts) * 15 * 1000; // Delay in milliseconds
|
|
|
|
const delayInSeconds = delay / 1000;
|
|
|
|
|
|
|
|
// Return the delay time to the client
|
|
|
|
return res.status(400).json({
|
|
|
|
message: `Invalid credentials. Please wait for ${delayInSeconds} seconds before trying again.`,
|
|
|
|
});
|
2024-10-29 21:09:13 +01:00
|
|
|
}
|
|
|
|
|
2024-11-18 17:37:57 +01:00
|
|
|
// Reset failed login attempts on successful login
|
|
|
|
user.failedLoginAttempts = 0;
|
|
|
|
user.lastFailedLogin = null;
|
|
|
|
await user.save();
|
|
|
|
|
2024-10-29 21:09:13 +01:00
|
|
|
// JWT-Token erstellen mit benutzerdefinierten Daten
|
2024-11-18 17:04:10 +01:00
|
|
|
const token = jwt.sign({ id: user._id, username: user.username, isAdmin: user.isAdmin }, process.env.JWT_SECRET, { expiresIn: '1h' });
|
2024-10-29 21:09:13 +01:00
|
|
|
|
|
|
|
|
|
|
|
res.status(200).json({ token, message: 'Login erfolgreich' });
|
|
|
|
} catch (error) {
|
|
|
|
res.status(500).json({ message: 'Serverfehler' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = { register, login };
|