Dieser Commit ist enthalten in:
hendrik_gebhardt@gmx.de
2026-01-04 21:21:11 +00:00
committet von Server Deploy
Ursprung c21be47428
Commit 623bbdf5dd
19 geänderte Dateien mit 6290 neuen und 48 gelöschten Zeilen

Datei anzeigen

@ -31,8 +31,8 @@ router.get('/users', (req, res) => {
try {
const db = getDb();
const users = db.prepare(`
SELECT id, username, display_name, color, role, permissions, email,
created_at, last_login, failed_attempts, locked_until
SELECT id, email, initials, display_name, color, role, permissions,
created_at, last_login, failed_attempts, locked_until, custom_initials
FROM users
ORDER BY id
`).all();
@ -55,10 +55,10 @@ router.get('/users', (req, res) => {
*/
router.post('/users', async (req, res) => {
try {
const { username, password, displayName, email, role, permissions } = req.body;
const { initials, password, displayName, email, role, permissions } = req.body;
// Validierung
if (!username || !password || !displayName || !email) {
if (!initials || !password || !displayName || !email) {
return res.status(400).json({ error: 'Kürzel, Passwort, Anzeigename und E-Mail erforderlich' });
}
@ -69,8 +69,8 @@ router.post('/users', async (req, res) => {
}
// Kürzel muss genau 2 Buchstaben sein
const usernameUpper = username.toUpperCase();
if (!/^[A-Z]{2}$/.test(usernameUpper)) {
const initialsUpper = initials.toUpperCase();
if (!/^[A-Z]{2}$/.test(initialsUpper)) {
return res.status(400).json({ error: 'Kürzel muss genau 2 Buchstaben sein (z.B. HG)' });
}
@ -80,18 +80,18 @@ router.post('/users', async (req, res) => {
const db = getDb();
// Prüfen ob Kürzel bereits existiert
const existing = db.prepare('SELECT id FROM users WHERE username = ?').get(usernameUpper);
if (existing) {
return res.status(400).json({ error: 'Kürzel bereits vergeben' });
}
// Prüfen ob E-Mail bereits existiert
const existingEmail = db.prepare('SELECT id FROM users WHERE email = ?').get(email.toLowerCase());
if (existingEmail) {
return res.status(400).json({ error: 'E-Mail bereits vergeben' });
}
// Prüfen ob Kürzel bereits existiert
const existingInitials = db.prepare('SELECT id FROM users WHERE initials = ?').get(initialsUpper);
if (existingInitials) {
return res.status(400).json({ error: 'Kürzel bereits vergeben' });
}
// Passwort hashen
const passwordHash = await bcrypt.hash(password, 12);
@ -100,23 +100,24 @@ router.post('/users', async (req, res) => {
// Benutzer erstellen
const result = db.prepare(`
INSERT INTO users (username, password_hash, display_name, color, role, permissions, email)
VALUES (?, ?, ?, ?, ?, ?, ?)
INSERT INTO users (email, initials, password_hash, display_name, color, role, permissions, custom_initials)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`).run(
usernameUpper,
email.toLowerCase(),
initialsUpper,
passwordHash,
displayName,
defaultColor,
role || 'user',
JSON.stringify(permissions || []),
email.toLowerCase()
initialsUpper
);
logger.info(`Admin ${req.user.username} hat Benutzer ${usernameUpper} erstellt`);
logger.info(`Admin ${req.user.email} hat Benutzer ${initialsUpper} erstellt`);
res.status(201).json({
id: result.lastInsertRowid,
username: usernameUpper,
initials: initialsUpper,
displayName,
email: email.toLowerCase(),
color: defaultColor,
@ -135,7 +136,7 @@ router.post('/users', async (req, res) => {
router.put('/users/:id', async (req, res) => {
try {
const userId = parseInt(req.params.id);
const { displayName, color, role, permissions, password, unlockAccount, email } = req.body;
const { displayName, color, role, permissions, password, unlockAccount, email, initials } = req.body;
const db = getDb();
@ -206,6 +207,24 @@ router.put('/users/:id', async (req, res) => {
params.push(email.toLowerCase());
}
if (initials !== undefined) {
// Validierung: Genau 2 Buchstaben
const initialsUpper = initials.toUpperCase();
if (!/^[A-Z]{2}$/.test(initialsUpper)) {
return res.status(400).json({ error: 'Kürzel muss genau 2 Buchstaben sein (z.B. HG)' });
}
// Prüfen ob Kürzel bereits von anderem Benutzer verwendet wird
const existingInitials = db.prepare('SELECT id FROM users WHERE initials = ? AND id != ?').get(initialsUpper, userId);
if (existingInitials) {
return res.status(400).json({ error: 'Kürzel bereits vergeben' });
}
updates.push('initials = ?');
params.push(initialsUpper);
// Auch custom_initials aktualisieren für Kompatibilität
updates.push('custom_initials = ?');
params.push(initialsUpper);
}
if (updates.length === 0) {
return res.status(400).json({ error: 'Keine Änderungen angegeben' });
}
@ -218,7 +237,7 @@ router.put('/users/:id', async (req, res) => {
// Aktualisierten Benutzer zurueckgeben
const updatedUser = db.prepare(`
SELECT id, username, display_name, color, role, permissions, email,
created_at, last_login, failed_attempts, locked_until
created_at, last_login, failed_attempts, locked_until, custom_initials
FROM users WHERE id = ?
`).get(userId);

Datei anzeigen

@ -35,10 +35,15 @@ router.post('/login', async (req, res) => {
const db = getDb();
// Benutzer suchen: Zuerst nach Username "admin", dann nach E-Mail
// Benutzer suchen: Admin kann mit "admin" einloggen, alle anderen mit E-Mail
let user;
// User per Username suchen (kann E-Mail-Adresse oder admin sein)
user = db.prepare('SELECT * FROM users WHERE username = ?').get(username);
if (username.toLowerCase() === 'admin') {
// Admin-Login über spezielle E-Mail
user = db.prepare('SELECT * FROM users WHERE email = ? AND role = ?').get('admin@taskmate.local', 'admin');
} else {
// Normale User loggen sich mit E-Mail ein
user = db.prepare('SELECT * FROM users WHERE email = ?').get(username);
}
// Audit-Log Eintrag vorbereiten
const logAttempt = (userId, success) => {
@ -131,7 +136,8 @@ router.post('/login', async (req, res) => {
csrfToken,
user: {
id: user.id,
username: user.username,
email: user.email,
initials: user.initials,
displayName: user.display_name,
color: user.color,
role: user.role || 'user',
@ -345,14 +351,15 @@ router.get('/users', authenticateToken, (req, res) => {
const db = getDb();
// Nur regulaere Benutzer (nicht Admins) fuer Aufgaben-Zuweisung
const users = db.prepare(`
SELECT id, username, display_name, color
SELECT id, email, initials, display_name, color
FROM users
WHERE role != 'admin' OR role IS NULL
`).all();
res.json(users.map(u => ({
id: u.id,
username: u.username,
email: u.email,
initials: u.initials,
displayName: u.display_name,
color: u.color
})));