From a5d5d51d2a73fbab037391b5a01f5a7154bd3c99 Mon Sep 17 00:00:00 2001 From: michael Date: Sun, 22 Feb 2026 08:25:56 -0600 Subject: [PATCH] Add confirmation modal for Super Admin role assignment Prevents accidental Super Admin privilege grants by requiring users to type "make this user super admin" before the role change is applied. Modal blocks paste/drag input and reverts the dropdown on cancel. Co-Authored-By: Claude Opus 4.6 --- frontend/components/UserManagement.tsx | 102 +++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/frontend/components/UserManagement.tsx b/frontend/components/UserManagement.tsx index 19001b6..10843f0 100644 --- a/frontend/components/UserManagement.tsx +++ b/frontend/components/UserManagement.tsx @@ -25,6 +25,11 @@ export const UserManagement: React.FC = () => { const [savedUserId, setSavedUserId] = useState(null); const [successMessage, setSuccessMessage] = useState(null); + // Super Admin confirmation modal + const [pendingSuperAdminUser, setPendingSuperAdminUser] = useState<{ userId: string; userName: string } | null>(null); + const [confirmationText, setConfirmationText] = useState(''); + const [confirmationError, setConfirmationError] = useState(false); + // New agency form const [newAgencyName, setNewAgencyName] = useState(''); const [isCreatingAgency, setIsCreatingAgency] = useState(false); @@ -57,6 +62,13 @@ export const UserManagement: React.FC = () => { }; const handleRoleChange = async (userId: string, newRole: string) => { + const user = users.find(u => u.id === userId); + if (newRole === 'super_admin' && user?.role !== 'super_admin') { + setPendingSuperAdminUser({ userId, userName: user?.name || 'this user' }); + setConfirmationText(''); + setConfirmationError(false); + return; + } try { const updated = await apiService.updateUser(userId, { role: newRole }); setUsers(prev => prev.map(u => u.id === userId ? updated : u)); @@ -67,6 +79,32 @@ export const UserManagement: React.FC = () => { } }; + const handleConfirmSuperAdmin = async () => { + if (confirmationText !== 'make this user super admin') { + setConfirmationError(true); + return; + } + if (!pendingSuperAdminUser) return; + const { userId } = pendingSuperAdminUser; + setPendingSuperAdminUser(null); + setConfirmationText(''); + setConfirmationError(false); + try { + const updated = await apiService.updateUser(userId, { role: 'super_admin' }); + setUsers(prev => prev.map(u => u.id === userId ? updated : u)); + showSavedIndicator(userId); + } catch (err) { + console.error('Failed to update user role:', err); + setError('Failed to update user role.'); + } + }; + + const handleCancelSuperAdmin = () => { + setPendingSuperAdminUser(null); + setConfirmationText(''); + setConfirmationError(false); + }; + const handleAgencyChange = async (userId: string, agencyId: string | null) => { try { const updated = await apiService.updateUser(userId, { agency_id: agencyId }); @@ -224,6 +262,70 @@ export const UserManagement: React.FC = () => { + {/* Super Admin Confirmation Modal */} + {pendingSuperAdminUser && ( +
+
e.stopPropagation()} + > +
+
+ + + +
+

Confirm Super Admin Assignment

+
+

+ You are about to grant Super Admin privileges to {pendingSuperAdminUser.userName}. This gives full system access including user management. This action should only be performed intentionally. +

+

+ To confirm, type make this user super admin below: +

+ { + setConfirmationText(e.target.value); + setConfirmationError(false); + }} + onPaste={(e) => e.preventDefault()} + onDrop={(e) => e.preventDefault()} + onDragOver={(e) => e.preventDefault()} + placeholder="Type the phrase above..." + className={`w-full p-2 border-2 rounded-[10px] text-sm text-black-title focus:outline-none focus:ring-2 transition ${ + confirmationError + ? 'border-error focus:ring-error' + : 'border-grey-700 focus:ring-active-blue focus:border-active-blue' + }`} + autoFocus + /> + {confirmationError && ( +

Please type the exact phrase to confirm.

+ )} +
+ + +
+
+
+ )} + {/* Agency Management */}

Agencies ({agencies.length})