Benutzerverwaltung mit Rollen/Rechten und Urlaubsplanung
Führt Login mit vier Rollen (Admin, Teamleiter, Mitarbeiter, Beobachter) ein, über die Teammitglieder eigenen Urlaub inkl. Pflicht-Vertreter eintragen können. Die Auslastungsberechnung berücksichtigt Urlaub jetzt als reduzierte Kapazität. Neue Konten vergeben ihr Passwort selbst beim ersten Login. Migrationsskript für bestehende Mitarbeiter aus der Vorversion inklusive. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
// Einmalig beim Umstieg von der alten Version (ohne Login) auf die neue Version
|
||||
// (mit Benutzerverwaltung) auszuführen: legt für jeden bestehenden Mitarbeiter
|
||||
// mit hinterlegter E-Mail, der noch KEIN Benutzerkonto hat, automatisch eines an
|
||||
// (Rolle 'mitarbeiter', ohne Passwort — wie bei der Benutzerverwaltung üblich wird
|
||||
// das Passwort beim ersten Login vom jeweiligen Mitarbeiter selbst vergeben).
|
||||
//
|
||||
// Bestehende Projekte, Aufgaben, Zuweisungen und Teams werden dabei nicht
|
||||
// verändert — die Tabellen werden vom Server ohnehin additiv angelegt
|
||||
// (server/schema.sql, CREATE TABLE IF NOT EXISTS). Dieses Skript kümmert sich
|
||||
// ausschließlich darum, dass alle bestehenden Teammitglieder auch einen Login
|
||||
// bekommen, statt sie einzeln über die Benutzerverwaltung anlegen zu müssen.
|
||||
//
|
||||
// Aufruf:
|
||||
// node scripts/migrate-team-accounts.js
|
||||
// docker exec <container> node scripts/migrate-team-accounts.js (im laufenden Container)
|
||||
//
|
||||
// Rolle abweichend vom Default vergeben (z. B. alle als Teamleiter anlegen):
|
||||
// node scripts/migrate-team-accounts.js --role teamleiter
|
||||
|
||||
const db = require('../db');
|
||||
|
||||
function readArg(name) {
|
||||
const idx = process.argv.indexOf(`--${name}`);
|
||||
return idx !== -1 ? process.argv[idx + 1] : undefined;
|
||||
}
|
||||
|
||||
const role = readArg('role') || 'mitarbeiter';
|
||||
const VALID_ROLES = ['admin', 'teamleiter', 'mitarbeiter', 'beobachter'];
|
||||
if (!VALID_ROLES.includes(role)) {
|
||||
console.error(`Ungültige Rolle "${role}". Erlaubt: ${VALID_ROLES.join(', ')}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const employees = db.prepare('SELECT id, first_name, last_name, email FROM employees ORDER BY last_name, first_name').all();
|
||||
const existingUsers = db.prepare('SELECT employee_id, email FROM users').all();
|
||||
const employeeIdsWithAccount = new Set(existingUsers.map((u) => u.employee_id));
|
||||
const emailsInUse = new Set(existingUsers.map((u) => u.email));
|
||||
|
||||
const insert = db.prepare(
|
||||
'INSERT INTO users (employee_id, email, password_hash, role) VALUES (?, ?, NULL, ?)'
|
||||
);
|
||||
|
||||
let created = 0;
|
||||
let skippedNoEmail = 0;
|
||||
let skippedExisting = 0;
|
||||
let skippedEmailConflict = 0;
|
||||
|
||||
for (const e of employees) {
|
||||
const name = `${e.first_name} ${e.last_name}`;
|
||||
|
||||
if (employeeIdsWithAccount.has(e.id)) {
|
||||
skippedExisting += 1;
|
||||
continue;
|
||||
}
|
||||
if (!e.email) {
|
||||
console.log(`Übersprungen (keine E-Mail hinterlegt): ${name}`);
|
||||
skippedNoEmail += 1;
|
||||
continue;
|
||||
}
|
||||
if (emailsInUse.has(e.email)) {
|
||||
console.log(`Übersprungen (E-Mail bereits von einem anderen Konto verwendet): ${name} <${e.email}>`);
|
||||
skippedEmailConflict += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
insert.run(e.id, e.email, role);
|
||||
emailsInUse.add(e.email);
|
||||
created += 1;
|
||||
console.log(`Konto angelegt: ${name} <${e.email}> (Rolle: ${role})`);
|
||||
}
|
||||
|
||||
console.log('----------------------------------------------------------------');
|
||||
console.log(`Fertig. Neu angelegt: ${created}, bereits vorhanden: ${skippedExisting}, ` +
|
||||
`ohne E-Mail übersprungen: ${skippedNoEmail}, E-Mail-Konflikt übersprungen: ${skippedEmailConflict}.`);
|
||||
console.log('Alle neu angelegten Konten vergeben ihr Passwort selbst beim ersten Login.');
|
||||
@@ -0,0 +1,52 @@
|
||||
// Legt einen Admin-Zugang für einen bestehenden Mitarbeiter an oder setzt ihn zurück.
|
||||
//
|
||||
// Ohne --password: Konto wird (neu) angelegt, das Passwort wird beim nächsten
|
||||
// Login vom Nutzer selbst vergeben (gleicher Mechanismus wie bei der Benutzerverwaltung).
|
||||
// Mit --password: setzt sofort ein Passwort (Notfall-Wiederherstellung, falls der
|
||||
// Admin sich ausgesperrt hat).
|
||||
//
|
||||
// Aufruf:
|
||||
// node scripts/reset-admin.js --employee-id 3
|
||||
// node scripts/reset-admin.js --email admin@example.com --password neuesPasswort
|
||||
|
||||
const bcrypt = require('bcryptjs');
|
||||
const db = require('../db');
|
||||
|
||||
function readArg(name) {
|
||||
const idx = process.argv.indexOf(`--${name}`);
|
||||
return idx !== -1 ? process.argv[idx + 1] : undefined;
|
||||
}
|
||||
|
||||
const employeeId = readArg('employee-id');
|
||||
let email = readArg('email');
|
||||
const password = readArg('password');
|
||||
|
||||
if (!employeeId && !email) {
|
||||
console.error(
|
||||
'Nutzung: node scripts/reset-admin.js --employee-id <id> [--password <passwort>]\n' +
|
||||
' oder node scripts/reset-admin.js --email <email> [--password <passwort>]'
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (employeeId && !email) {
|
||||
const employee = db.prepare('SELECT email FROM employees WHERE id = ?').get(employeeId);
|
||||
if (!employee || !employee.email) {
|
||||
console.error(`Mitarbeiter ${employeeId} wurde nicht gefunden oder hat keine E-Mail hinterlegt.`);
|
||||
process.exit(1);
|
||||
}
|
||||
email = employee.email;
|
||||
}
|
||||
|
||||
const passwordHash = password ? bcrypt.hashSync(password, 10) : null;
|
||||
|
||||
db.prepare(
|
||||
`INSERT INTO users (employee_id, email, password_hash, role) VALUES (?, ?, ?, 'admin')
|
||||
ON CONFLICT (email) DO UPDATE SET role = 'admin', password_hash = excluded.password_hash`
|
||||
).run(employeeId || null, email, passwordHash);
|
||||
|
||||
console.log(
|
||||
password
|
||||
? `Admin-Zugang für ${email} wurde mit dem angegebenen Passwort gesetzt.`
|
||||
: `Admin-Zugang für ${email} wurde angelegt/zurückgesetzt. Passwort wird beim nächsten Login vergeben.`
|
||||
);
|
||||
Reference in New Issue
Block a user