From ed1728feecda60f67e4c930c99bbeddeb25b609a Mon Sep 17 00:00:00 2001 From: Maurice Date: Thu, 12 Nov 2026 16:14:34 +0100 Subject: [PATCH] refactor(admin): the SSO unlink section is a component of its own The edit dialog's component crossed the complexity limit with the section's conditions; the section and its confirm step now live in SsoUnlinkSection, which decides itself when it shows. --- client/src/pages/admin/AdminUserModals.tsx | 77 +++++++++++++++------- 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/client/src/pages/admin/AdminUserModals.tsx b/client/src/pages/admin/AdminUserModals.tsx index ddb046c5b..ab2467d41 100644 --- a/client/src/pages/admin/AdminUserModals.tsx +++ b/client/src/pages/admin/AdminUserModals.tsx @@ -124,8 +124,6 @@ export default function AdminUserModals({ admin, t }: AdminUserModalsProps): Rea const [passkeyResetUser, setPasskeyResetUser] = React.useState(null); // Same for the two-factor reset; an admin turns off their own 2FA in Settings, not here. const [mfaResetUser, setMfaResetUser] = React.useState(null); - // Same for removing the SSO link, offered only while SSO is set up (#3065). - const [ssoUnlinkUser, setSsoUnlinkUser] = React.useState(null); const uid = useId(); const createId = `${uid}-create`; const editId = `${uid}-edit`; @@ -322,23 +320,13 @@ export default function AdminUserModals({ admin, t }: AdminUserModalsProps): Rea )} - {oidcConfigured && editingUser && editingUser.id !== currentUser?.id && ( - -
-

- {t('admin.sso.unlinkHint')} -

- -
-
- )} + )} @@ -502,14 +490,53 @@ docker run -d --name trek \\ danger /> + + ); +} + +/** + * Removing a user's SSO link (#3065): its section in the edit dialog and the + * question before it. Offered only while SSO is set up, and never for the + * admin's own account. + */ +function SsoUnlinkSection({ + user, + me, + ssoSetUp, + onUnlink, + t, +}: { + user: { id: number; username: string } | null; + me: { id: number } | null | undefined; + ssoSetUp: boolean; + onUnlink: (user: { id: number }) => Promise; + t: TranslationFn; +}): React.ReactElement | null { + const [asking, setAsking] = React.useState(false); + if (!ssoSetUp || !user || user.id === me?.id) return null; + return ( + <> + +
+

+ {t('admin.sso.unlinkHint')} +

+ +
+
setSsoUnlinkUser(null)} - onConfirm={() => { - if (ssoUnlinkUser) void unlinkSso(ssoUnlinkUser); - }} + isOpen={asking} + onClose={() => setAsking(false)} + onConfirm={() => void onUnlink(user)} title={t('admin.sso.unlink')} - message={ssoUnlinkUser ? t('admin.sso.unlinkConfirm', { name: ssoUnlinkUser.username }) : ''} + message={t('admin.sso.unlinkConfirm', { name: user.username })} confirmLabel={t('admin.sso.unlink')} danger />