Files
gott/wwwroot/js/pages/admin-page.js
T
Meleki 3ef78b5eb1 feat: Admin-Benutzerverwaltung + Dashboard-Layout-Fixes
Backend:
- AdminEndpoint.cs: 5 Endpunkte (List, Create, Update, Reset PW, Delete) - Admin-only
- DatabaseService: CreateUser(), UpdateUserAdmin(), DeleteUser() (kaskadiert Tokens + Shares)
- Route in Program.cs registriert

Frontend:
- admin-page.js: User-Liste mit Edit/Delete, Inline-Formular Create/Edit
- api.js: 5 Admin-API-Funktionen
- index.html: Template tpl-admin, Script-Tag, Dashboard-Link 'Benutzerverwaltung'
- dashboard.js: Admin-Link nur für Admins sichtbar
- form.css: Styles für admin-user-list, admin-user-row, admin-checkbox-row
- dashboard.css: Header-Overflow-Fix, Agents vor Cronjobs
- index.html: Template-Reihenfolge Agents vor Cronjobs

TODO: User-Management als erledigt markiert
2026-03-05 19:19:16 +01:00

213 lines
6.7 KiB
JavaScript

// ── Admin Page (User Management) ──
registerPage('admin', {
async init() {
if (!currentUser || !currentUser.isAdmin) {
navigateTo('dashboard');
return;
}
var users = [];
var editingUserId = null;
var list = document.getElementById('adminUserList');
var newUserBtn = document.getElementById('adminNewUserBtn');
var userForm = document.getElementById('adminUserForm');
var formTitle = document.getElementById('adminFormTitle');
var usernameInput = document.getElementById('adminUsername');
var displayNameInput = document.getElementById('adminDisplayName');
var passwordInput = document.getElementById('adminPassword');
var passwordLabel = document.getElementById('adminPasswordLabel');
var isAdminCheckbox = document.getElementById('adminIsAdmin');
var saveBtn = document.getElementById('adminFormSaveBtn');
var formMessage = document.getElementById('adminFormMessage');
var pageMessage = document.getElementById('adminMessage');
// ── Hilfsfunktionen ──
function showFormMessage(text, isError) {
formMessage.textContent = text;
formMessage.className = 'profile-message ' + (isError ? 'profile-message-error' : 'profile-message-success');
formMessage.hidden = false;
if (!isError) {
setTimeout(function() { formMessage.hidden = true; }, 3000);
}
}
function showPageMessage(text, isError) {
pageMessage.textContent = text;
pageMessage.className = 'profile-message ' + (isError ? 'profile-message-error' : 'profile-message-success');
pageMessage.hidden = false;
setTimeout(function() { pageMessage.hidden = true; }, 4000);
}
function renderUsers() {
list.innerHTML = '';
users.forEach(function(user) {
var row = document.createElement('div');
row.className = 'admin-user-row';
var info = document.createElement('div');
info.className = 'admin-user-info';
var nameSpan = document.createElement('span');
nameSpan.className = 'admin-user-name';
nameSpan.textContent = user.displayName || user.username;
var metaSpan = document.createElement('span');
metaSpan.className = 'admin-user-meta';
var metaParts = ['@' + user.username];
if (user.isAdmin) metaParts.push('Administrator');
metaSpan.textContent = metaParts.join(' ▪ ');
info.appendChild(nameSpan);
info.appendChild(metaSpan);
var actions = document.createElement('div');
actions.className = 'admin-user-actions';
var editBtn = document.createElement('button');
editBtn.className = 'icon-btn';
editBtn.title = 'Bearbeiten';
editBtn.innerHTML = '<i class="fa fa-pencil"></i>';
editBtn.addEventListener('click', function() {
startEdit(user);
});
actions.appendChild(editBtn);
// Sich selbst kann man nicht löschen
if (user.userId !== currentUser.userId) {
var deleteBtn = document.createElement('button');
deleteBtn.className = 'icon-btn';
deleteBtn.title = 'Löschen';
deleteBtn.innerHTML = '<i class="fa fa-trash"></i>';
deleteBtn.addEventListener('click', function() {
deleteUser(user);
});
actions.appendChild(deleteBtn);
}
row.appendChild(info);
row.appendChild(actions);
list.appendChild(row);
});
}
async function loadUsers() {
try {
users = await apiAdminGetUsers();
renderUsers();
} catch (err) {
showPageMessage(err.message, true);
}
}
function startEdit(user) {
editingUserId = user.userId;
formTitle.textContent = 'Benutzer bearbeiten';
usernameInput.value = user.username;
usernameInput.disabled = false;
displayNameInput.value = user.displayName || '';
passwordInput.value = '';
passwordLabel.textContent = 'Neues Passwort (leer = unverändert)';
passwordInput.placeholder = 'Neues Passwort (optional)';
passwordInput.required = false;
isAdminCheckbox.checked = user.isAdmin;
saveBtn.textContent = 'Speichern';
formMessage.hidden = true;
userForm.hidden = false;
usernameInput.focus();
}
async function deleteUser(user) {
if (!confirm('Benutzer "' + (user.displayName || user.username) + '" wirklich löschen?\n\nAlle Tokens werden ebenfalls gelöscht.')) {
return;
}
try {
await apiAdminDeleteUser(user.userId);
await loadUsers();
} catch (err) {
showPageMessage(err.message, true);
}
}
// ── Event-Listener ──
// Neuer Benutzer
newUserBtn.addEventListener('click', function() {
editingUserId = null;
formTitle.textContent = 'Neuer Benutzer';
usernameInput.value = '';
usernameInput.disabled = false;
displayNameInput.value = '';
passwordInput.value = '';
passwordLabel.textContent = 'Passwort';
passwordInput.placeholder = 'Passwort';
passwordInput.required = true;
isAdminCheckbox.checked = false;
saveBtn.textContent = 'Erstellen';
formMessage.hidden = true;
userForm.hidden = false;
usernameInput.focus();
});
// Speichern
saveBtn.addEventListener('click', async function() {
formMessage.hidden = true;
saveBtn.disabled = true;
try {
if (editingUserId) {
// Update
var data = {
username: usernameInput.value.trim(),
displayName: displayNameInput.value.trim(),
isAdmin: isAdminCheckbox.checked
};
await apiAdminUpdateUser(editingUserId, data);
// Passwort nur wenn ausgefüllt
var pw = passwordInput.value;
if (pw) {
await apiAdminResetPassword(editingUserId, pw);
}
showFormMessage('Benutzer aktualisiert', false);
} else {
// Create
var username = usernameInput.value.trim();
var password = passwordInput.value;
if (!username || !password) {
showFormMessage('Benutzername und Passwort erforderlich', true);
return;
}
await apiAdminCreateUser({
username: username,
password: password,
displayName: displayNameInput.value.trim(),
isAdmin: isAdminCheckbox.checked
});
showFormMessage('Benutzer erstellt', false);
}
userForm.hidden = true;
await loadUsers();
} catch (err) {
showFormMessage(err.message, true);
} finally {
saveBtn.disabled = false;
}
});
// ── Init: User laden ──
await loadUsers();
},
destroy() {}
});