import { Dispatch, SetStateAction, useState } from "react"; import { faCheckCircle, faEllipsisV, faFilter, faMagnifyingGlass, faShieldHalved, faTrash, faUsers, faUserShield, faUserXmark, faXmark } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { AlertTriangleIcon, UserCogIcon } from "lucide-react"; import { twMerge } from "tailwind-merge"; import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal"; import { createNotification } from "@app/components/notifications"; import { Button, Checkbox, DeleteActionModal, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuTrigger, EmptyState, IconButton, Input, Pagination, Table, TableContainer, TableSkeleton, TBody, Td, Th, THead, Tooltip, Tr } from "@app/components/v2"; import { Badge } from "@app/components/v3"; import { useSubscription, useUser } from "@app/context"; import { getUserTablePreference, PreferenceKey, setUserTablePreference } from "@app/helpers/userTablePreferences"; import { useDebounce, usePagination, usePopUp } from "@app/hooks"; import { useAdminBulkDeleteUsers, useAdminDeleteUser, useAdminGetUsers, useAdminGrantServerAdminAccess, useRemoveUserServerAdminAccess } from "@app/hooks/api"; import { User } from "@app/hooks/api/users/types"; import { UsePopUpState } from "@app/hooks/usePopUp"; const UserPanelTable = ({ handlePopUpOpen, users, isPending, adminsOnly, searchUserFilter, setSearchUserFilter, setAdminsOnly, selectedUsers, setSelectedUsers, totalCount, page, perPage, setPage, handlePerPageChange }: { handlePopUpOpen: ( popUpName: keyof UsePopUpState< ["removeUser", "upgradePlan", "upgradeToServerAdmin", "removeServerAdmin"] >, data?: { username: string; id: string; text?: string; } ) => void; isPending: boolean; users: User[] | undefined; adminsOnly: boolean; setAdminsOnly: (adminsOnly: boolean) => void; searchUserFilter: string; setSearchUserFilter: (filter: string) => void; selectedUsers: User[]; setSelectedUsers: Dispatch>; totalCount: number; page: number; perPage: number; setPage: Dispatch>; handlePerPageChange: (newPerPage: number) => void; }) => { const { subscription } = useSubscription(); const isEmpty = !isPending && totalCount === 0; const isTableFiltered = Boolean(adminsOnly); const selectedUserIds = selectedUsers.map((user) => user.id); const isPageSelected = users?.length ? users.every((user) => selectedUserIds.includes(user.id)) : false; // eslint-disable-next-line no-nested-ternary const isPageIndeterminate = isPageSelected ? false : users?.length ? users?.some((user) => selectedUserIds.includes(user.id)) : false; return ( <>
setSearchUserFilter(e.target.value)} leftIcon={} placeholder="Search users..." className="flex-1" /> Filter By { e.preventDefault(); setAdminsOnly(!adminsOnly); }} icon={adminsOnly && } iconPos="right" >
Server Admins
{isPending && } {!isPending && users?.map((user) => { const { username, email, firstName, lastName, id, superAdmin } = user; const name = firstName || lastName ? `${firstName} ${lastName}` : null; const isSelected = selectedUserIds.includes(id); return ( ); })}
{ if (isPageSelected) { setSelectedUsers((prev) => prev.filter((u) => !users?.find((user) => user.id === u.id)) ); } else { setSelectedUsers((prev) => [ ...prev, ...(users?.filter((u) => !prev.find((user) => user.id === u.id)) ?? []) ]); } }} /> Name Username
{ e.stopPropagation(); setSelectedUsers((prev) => isSelected ? prev.filter((u) => u.id !== id) : [...prev, user] ); }} />

{name ?? Not Set}

{superAdmin && ( Server Admin )}

{username || email}

{ e.stopPropagation(); handlePopUpOpen("removeUser", { username, id }); }} icon={} > Remove User {!superAdmin && ( } onClick={(e) => { e.stopPropagation(); if (!subscription?.instanceUserManagement) { handlePopUpOpen("upgradePlan", { username, id, text: "Your current plan does not allow setting additional server admins. To unlock this feature, please upgrade to Infisical Pro plan." }); return; } handlePopUpOpen("upgradeToServerAdmin", { username, id }); }} > Make User Server Admin )} {superAdmin && (
} onClick={(e) => { e.stopPropagation(); if (!subscription?.instanceUserManagement) { handlePopUpOpen("upgradePlan", { username, id, text: "Your current plan does not allow removing server admins. To unlock this feature, please upgrade to Infisical Pro plan." }); return; } handlePopUpOpen("removeServerAdmin", { username, id }); }} > Remove Server Admin )}
{!isPending && isEmpty && }
{!isEmpty && ( setPage(newPage)} onChangePerPage={handlePerPageChange} /> )}
); }; export const UserIdentitiesTable = () => { const { handlePopUpToggle, popUp, handlePopUpOpen, handlePopUpClose } = usePopUp([ "removeUser", "upgradePlan", "upgradeToServerAdmin", "removeServerAdmin", "removeUsers" ] as const); const { user: { id: userId } } = useUser(); const { mutateAsync: deleteUser } = useAdminDeleteUser(); const { mutateAsync: deleteUsers } = useAdminBulkDeleteUsers(); const { mutateAsync: grantAdminAccess } = useAdminGrantServerAdminAccess(); const { mutateAsync: removeAdminAccess } = useRemoveUserServerAdminAccess(); const [selectedUsers, setSelectedUsers] = useState([]); const [searchUserFilter, setSearchUserFilter] = useState(""); const [adminsOnly, setAdminsOnly] = useState(false); const [debouncedSearchTerm] = useDebounce(searchUserFilter, 500); const { offset, limit, setPage, perPage, page, setPerPage } = usePagination("", { initPerPage: getUserTablePreference("ResourceOverviewUsersTable", PreferenceKey.PerPage, 20) }); const handlePerPageChange = (newPerPage: number) => { setPerPage(newPerPage); setUserTablePreference("ResourceOverviewUsersTable", PreferenceKey.PerPage, newPerPage); }; const { data, isPending } = useAdminGetUsers({ limit, offset, searchTerm: debouncedSearchTerm, adminsOnly }); const { users, totalCount = 0 } = data ?? {}; const handleRemoveUser = async () => { const { id } = popUp?.removeUser?.data as { id: string; username: string }; try { await deleteUser(id); createNotification({ type: "success", text: "Successfully deleted user" }); } catch { createNotification({ type: "error", text: "Error deleting user" }); } handlePopUpClose("removeUser"); }; const handleGrantServerAdminAccess = async () => { const { id } = popUp?.upgradeToServerAdmin?.data as { id: string; username: string }; try { await grantAdminAccess(id); createNotification({ type: "success", text: "Successfully granted server admin access to user" }); } catch { createNotification({ type: "error", text: "Error granting server admin access to user" }); } handlePopUpClose("upgradeToServerAdmin"); }; const handleRemoveServerAdminAccess = async () => { const { id } = popUp?.removeServerAdmin?.data as { id: string; username: string }; try { await removeAdminAccess(id); createNotification({ type: "success", text: "Successfully removed server admin access from user" }); } catch { createNotification({ type: "error", text: "Error removing server admin access from user" }); } handlePopUpClose("removeServerAdmin"); }; const handleRemoveUsers = async () => { try { await deleteUsers(selectedUsers.map((user) => user.id)); createNotification({ text: "Successfully removed users", type: "success" }); setSelectedUsers([]); handlePopUpClose("removeUsers"); } catch { createNotification({ text: "Failed to remove users", type: "error" }); } }; return ( <>
0 && "h-16" )} >
{selectedUsers.length} Selected

User Identities

Manage user identities across your instance.

handlePopUpToggle("removeUser", isOpen)} onDeleteApproved={handleRemoveUser} /> handlePopUpToggle("upgradeToServerAdmin", isOpen)} deleteKey="confirm" onDeleteApproved={handleGrantServerAdminAccess} buttonText="Grant Access" /> handlePopUpToggle("removeServerAdmin", isOpen)} deleteKey="confirm" onDeleteApproved={handleRemoveServerAdminAccess} buttonText="Remove Access" /> handlePopUpToggle("upgradePlan", isOpen)} text={popUp.upgradePlan.data?.text} /> handlePopUpToggle("removeUsers", isOpen)} deleteKey="confirm" onDeleteApproved={() => handleRemoveUsers()} buttonText="Delete" >
The following users will be deleted:
    {selectedUsers?.map((user) => { const email = user.email ?? user.username; return (
  • {user.firstName || user.lastName ? ( <> {`${`${user.firstName} ${user.lastName}`.trim()} `}( {email}) ) : ( {email} )}{" "}

    {userId === user.id && ( Deleting Yourself )}
  • ); })}
); };