Require admin password for destructive admin actions

This commit is contained in:
2026-02-08 15:05:10 +01:00
parent 96a47020d8
commit e666e7c603
13 changed files with 197 additions and 43 deletions

View File

@@ -29,6 +29,9 @@ export function openConfirmModal({
body,
confirmLabel,
cancelLabel = t("modal.cancel"),
confirmClass = null,
requirePassword = false,
passwordLabel = t("auth.password"),
onConfirm,
}) {
const overlay = document.createElement("div");
@@ -48,7 +51,9 @@ export function openConfirmModal({
const actions = document.createElement("div");
actions.className = "stack horizontal";
const confirmBtn = document.createElement("button");
if (confirmClass) confirmBtn.className = confirmClass;
confirmBtn.textContent = confirmLabel ?? t("modal.confirm");
confirmBtn.disabled = requirePassword;
actions.append(confirmBtn);
if (cancelLabel !== null && cancelLabel !== undefined) {
const cancelBtn = document.createElement("button");
@@ -58,7 +63,24 @@ export function openConfirmModal({
actions.append(cancelBtn);
cancelBtn.addEventListener("click", close);
}
panel.querySelector(".edit-body")?.appendChild(actions);
const bodyContainer = panel.querySelector(".edit-body");
let passwordInput = null;
if (requirePassword && bodyContainer) {
const field = document.createElement("label");
field.className = "stack";
const label = document.createElement("span");
label.className = "label";
label.textContent = passwordLabel;
passwordInput = document.createElement("input");
passwordInput.type = "password";
passwordInput.autocomplete = "current-password";
field.append(label, passwordInput);
bodyContainer.appendChild(field);
passwordInput.addEventListener("input", () => {
confirmBtn.disabled = !(passwordInput.value || "").trim();
});
}
bodyContainer?.appendChild(actions);
overlay.addEventListener("click", (e) => {
if (
@@ -70,7 +92,7 @@ export function openConfirmModal({
});
confirmBtn.addEventListener("click", async () => {
try {
await onConfirm?.(close);
await onConfirm?.(close, { password: passwordInput?.value ?? "" });
} catch (err) {
toast(err.message, true);
}