espid2sensor: User-Liste mit Passwort-Reset und Löschen im User-Tab
Ersetzt das manuelle E-Mail-Eingabefeld für den Passwort-Reset durch eine Liste aller angemeldeten User. Pro User stehen zwei Aktionen zur Verfügung: Passwort zurücksetzen (nutzt die bestehende /api/resetPassword-Route) und Löschen (neue DELETE /api/users/:id-Route, admin-only, verhindert Löschen des eigenen Accounts). Neue GET /api/users-Route liefert Email/Rolle aller User (admin-only).
This commit is contained in:
@@ -34,6 +34,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
userResult.textContent = 'User erfolgreich angelegt!';
|
||||
if (window.loadUsers) window.loadUsers();
|
||||
} else {
|
||||
userResult.textContent = data.error || 'Fehler beim Anlegen.';
|
||||
}
|
||||
@@ -77,34 +78,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
}
|
||||
|
||||
const resetPasswordBtn = document.getElementById('resetPasswordBtn');
|
||||
if (resetPasswordBtn) {
|
||||
resetPasswordBtn.addEventListener('click', async () => {
|
||||
const email = document.getElementById('resetEmail').value.trim();
|
||||
const newPassword = document.getElementById('resetNewPassword').value;
|
||||
const resetPasswordResult = document.getElementById('resetPasswordResult');
|
||||
if (!email || !newPassword) {
|
||||
resetPasswordResult.textContent = 'Email und neues Passwort erforderlich.';
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await fetch('/api/resetPassword', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email, newPassword })
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
resetPasswordResult.textContent = 'Passwort erfolgreich zurückgesetzt!';
|
||||
document.getElementById('resetPasswordForm').reset();
|
||||
} else {
|
||||
resetPasswordResult.textContent = data.error || 'Fehler beim Zurücksetzen.';
|
||||
}
|
||||
} catch (err) {
|
||||
resetPasswordResult.textContent = 'Serverfehler.';
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function updateSortArrows() {
|
||||
@@ -467,6 +440,73 @@ function showModal(message, showCancelButton, callback) {
|
||||
});
|
||||
}
|
||||
|
||||
async function loadUsers() {
|
||||
const usersTableBody = document.querySelector('#usersTable tbody');
|
||||
const usersResult = document.getElementById('usersResult');
|
||||
if (!usersTableBody) return;
|
||||
try {
|
||||
const res = await fetch('/api/users');
|
||||
const users = await res.json();
|
||||
usersTableBody.innerHTML = '';
|
||||
users.forEach(u => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.innerHTML = `
|
||||
<td>${u.email}</td>
|
||||
<td>${u.role}</td>
|
||||
<td>
|
||||
<div class="twobuttons">
|
||||
<button data-id="${u._id}" data-email="${u.email}" class="editBtn resetUserBtn" title="Passwort zurücksetzen">🔑</button>
|
||||
<button data-id="${u._id}" class="deleteBtn deleteUserBtn" title="Löschen">🗑️</button>
|
||||
</div>
|
||||
</td>
|
||||
`;
|
||||
usersTableBody.appendChild(tr);
|
||||
});
|
||||
|
||||
document.querySelectorAll('.resetUserBtn').forEach(btn => {
|
||||
btn.addEventListener('click', async () => {
|
||||
const email = btn.getAttribute('data-email');
|
||||
const newPassword = prompt(`Neues Passwort für ${email}:`);
|
||||
if (!newPassword) return;
|
||||
try {
|
||||
const res = await fetch('/api/resetPassword', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email, newPassword })
|
||||
});
|
||||
const data = await res.json();
|
||||
usersResult.textContent = data.success ? `Passwort für ${email} zurückgesetzt.` : (data.error || 'Fehler beim Zurücksetzen.');
|
||||
} catch (err) {
|
||||
usersResult.textContent = 'Serverfehler.';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('.deleteUserBtn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const id = btn.getAttribute('data-id');
|
||||
showModal('User wirklich löschen?', true, async (confirmed) => {
|
||||
if (!confirmed) return;
|
||||
try {
|
||||
const res = await fetch(`/api/users/${id}`, { method: 'DELETE' });
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
usersResult.textContent = 'User gelöscht.';
|
||||
await loadUsers();
|
||||
} else {
|
||||
usersResult.textContent = data.error || 'Fehler beim Löschen.';
|
||||
}
|
||||
} catch (err) {
|
||||
usersResult.textContent = 'Serverfehler.';
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
saveBtn.addEventListener('click', saveEntry);
|
||||
refreshBtn.addEventListener('click', loadEntries);
|
||||
cancelBtn.addEventListener('click', () => clearForm(true));
|
||||
@@ -475,9 +515,10 @@ function showModal(message, showCancelButton, callback) {
|
||||
tabInput.addEventListener('click', () => showTab('input'))
|
||||
tabList.addEventListener('click', () => showTab('list'))
|
||||
const tabUser = document.getElementById('tabUser');
|
||||
if (tabUser) tabUser.addEventListener('click', () => showTab('user'))
|
||||
if (tabUser) tabUser.addEventListener('click', () => { showTab('user'); loadUsers(); })
|
||||
|
||||
loadEntries();
|
||||
window.loadUsers = loadUsers;
|
||||
});
|
||||
|
||||
window.showTab = showTab;
|
||||
Reference in New Issue
Block a user