diff --git a/Data/Server/WebUI/src/Admin/User_Management.jsx b/Data/Server/WebUI/src/Admin/User_Management.jsx index f992f11..794131f 100644 --- a/Data/Server/WebUI/src/Admin/User_Management.jsx +++ b/Data/Server/WebUI/src/Admin/User_Management.jsx @@ -89,6 +89,8 @@ export default function UserManagement({ isAdmin = false }) { const [warnMessage, setWarnMessage] = useState(""); const [me, setMe] = useState(null); const [mfaBusyUser, setMfaBusyUser] = useState(null); + const [resetMfaOpen, setResetMfaOpen] = useState(false); + const [resetMfaTarget, setResetMfaTarget] = useState(null); // Columns and filters const columns = useMemo(() => ([ @@ -243,6 +245,43 @@ export default function UserManagement({ isAdmin = false }) { } }; + const openResetMfa = (user) => { + if (!user) return; + setResetMfaTarget(user); + setResetMfaOpen(true); + }; + + const doResetMfa = async () => { + const user = resetMfaTarget; + setResetMfaOpen(false); + setResetMfaTarget(null); + if (!user) return; + const username = user.username; + const keepEnabled = Boolean(user.mfa_enabled); + setMfaBusyUser(username); + try { + const resp = await fetch(`/api/users/${encodeURIComponent(username)}/mfa`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + credentials: "include", + body: JSON.stringify({ enabled: keepEnabled, reset_secret: true }) + }); + const data = await resp.json(); + if (!resp.ok) { + setWarnMessage(data?.error || "Failed to reset MFA for this user."); + setWarnOpen(true); + return; + } + await fetchUsers(); + } catch (err) { + console.error(err); + setWarnMessage("Failed to reset MFA for this user."); + setWarnOpen(true); + } finally { + setMfaBusyUser(null); + } + }; + const toggleMfa = async (user, enabled) => { if (!user) return; const previous = Boolean(user.mfa_enabled); @@ -509,6 +548,9 @@ export default function UserManagement({ isAdmin = false }) { > Change Role + { const u = menuUser; closeMenu(); openResetMfa(u); }}> + Reset MFA + setResetOpen(false)} PaperProps={{ sx: { bgcolor: "#121212", color: "#fff" } }}> @@ -621,6 +663,12 @@ export default function UserManagement({ isAdmin = false }) { onCancel={() => setConfirmChangeRoleOpen(false)} onConfirm={doChangeRole} /> + { setResetMfaOpen(false); setResetMfaTarget(null); }} + onConfirm={doResetMfa} + />