mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-10-26 23:41:58 -06:00
Added Ability to Reset MFA for Users
This commit is contained in:
@@ -89,6 +89,8 @@ export default function UserManagement({ isAdmin = false }) {
|
|||||||
const [warnMessage, setWarnMessage] = useState("");
|
const [warnMessage, setWarnMessage] = useState("");
|
||||||
const [me, setMe] = useState(null);
|
const [me, setMe] = useState(null);
|
||||||
const [mfaBusyUser, setMfaBusyUser] = useState(null);
|
const [mfaBusyUser, setMfaBusyUser] = useState(null);
|
||||||
|
const [resetMfaOpen, setResetMfaOpen] = useState(false);
|
||||||
|
const [resetMfaTarget, setResetMfaTarget] = useState(null);
|
||||||
|
|
||||||
// Columns and filters
|
// Columns and filters
|
||||||
const columns = useMemo(() => ([
|
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) => {
|
const toggleMfa = async (user, enabled) => {
|
||||||
if (!user) return;
|
if (!user) return;
|
||||||
const previous = Boolean(user.mfa_enabled);
|
const previous = Boolean(user.mfa_enabled);
|
||||||
@@ -509,6 +548,9 @@ export default function UserManagement({ isAdmin = false }) {
|
|||||||
>
|
>
|
||||||
Change Role
|
Change Role
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem onClick={() => { const u = menuUser; closeMenu(); openResetMfa(u); }}>
|
||||||
|
Reset MFA
|
||||||
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|
||||||
<Dialog open={resetOpen} onClose={() => setResetOpen(false)} PaperProps={{ sx: { bgcolor: "#121212", color: "#fff" } }}>
|
<Dialog open={resetOpen} onClose={() => setResetOpen(false)} PaperProps={{ sx: { bgcolor: "#121212", color: "#fff" } }}>
|
||||||
@@ -621,6 +663,12 @@ export default function UserManagement({ isAdmin = false }) {
|
|||||||
onCancel={() => setConfirmChangeRoleOpen(false)}
|
onCancel={() => setConfirmChangeRoleOpen(false)}
|
||||||
onConfirm={doChangeRole}
|
onConfirm={doChangeRole}
|
||||||
/>
|
/>
|
||||||
|
<ConfirmDeleteDialog
|
||||||
|
open={resetMfaOpen}
|
||||||
|
message={resetMfaTarget ? `Reset MFA enrollment for '${resetMfaTarget.username}'? This clears their existing authenticator.` : ""}
|
||||||
|
onCancel={() => { setResetMfaOpen(false); setResetMfaTarget(null); }}
|
||||||
|
onConfirm={doResetMfa}
|
||||||
|
/>
|
||||||
<ConfirmDeleteDialog
|
<ConfirmDeleteDialog
|
||||||
open={warnOpen}
|
open={warnOpen}
|
||||||
message={warnMessage}
|
message={warnMessage}
|
||||||
|
|||||||
@@ -1503,6 +1503,12 @@ def api_users_toggle_mfa(username):
|
|||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
now = _now_ts()
|
now = _now_ts()
|
||||||
if enabled:
|
if enabled:
|
||||||
|
if reset_secret:
|
||||||
|
cur.execute(
|
||||||
|
"UPDATE users SET mfa_enabled=1, mfa_secret=NULL, updated_at=? WHERE LOWER(username)=LOWER(?)",
|
||||||
|
(now, username)
|
||||||
|
)
|
||||||
|
else:
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"UPDATE users SET mfa_enabled=1, updated_at=? WHERE LOWER(username)=LOWER(?)",
|
"UPDATE users SET mfa_enabled=1, updated_at=? WHERE LOWER(username)=LOWER(?)",
|
||||||
(now, username)
|
(now, username)
|
||||||
|
|||||||
Reference in New Issue
Block a user