import React, { Fragment, useState } from "react"; import { AlertVariant, Button, ButtonVariant, Divider, } from "@patternfly/react-core"; import { TableComposable, Tbody, Td, Th, Thead, Tr, } from "@patternfly/react-table"; import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation"; import { useTranslation } from "react-i18next"; import { useAlerts } from "../components/alert/Alerts"; import { ListEmptyState } from "../components/list-empty-state/ListEmptyState"; import { useAdminClient, useFetch } from "../context/auth/AdminClient"; import { HelpItem } from "../components/help-enabler/HelpItem"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import type CredentialRepresentation from "@keycloak/keycloak-admin-client/lib/defs/credentialRepresentation"; import { ResetPasswordDialog } from "./user-credentials/ResetPasswordDialog"; import { ResetCredentialDialog } from "./user-credentials/ResetCredentialDialog"; import { InlineLabelEdit } from "./user-credentials/InlineLabelEdit"; import "./user-credentials.css"; import { CredentialRow } from "./user-credentials/CredentialRow"; import { toUpperCase } from "../util"; type UserCredentialsProps = { user: UserRepresentation; }; type ExpandableCredentialRepresentation = { key: string; value: CredentialRepresentation[]; isExpanded: boolean; }; export const UserCredentials = ({ user }: UserCredentialsProps) => { const { t } = useTranslation("users"); const { addAlert, addError } = useAlerts(); const [key, setKey] = useState(0); const refresh = () => setKey(key + 1); const [isOpen, setIsOpen] = useState(false); const [openCredentialReset, setOpenCredentialReset] = useState(false); const adminClient = useAdminClient(); const [userCredentials, setUserCredentials] = useState< CredentialRepresentation[] >([]); const [groupedUserCredentials, setGroupedUserCredentials] = useState< ExpandableCredentialRepresentation[] >([]); const [selectedCredential, setSelectedCredential] = useState({}); const [isResetPassword, setIsResetPassword] = useState(false); const [isUserLabelEdit, setIsUserLabelEdit] = useState<{ status: boolean; rowKey: string; }>(); useFetch( () => adminClient.users.getCredentials({ id: user.id! }), (credentials) => { setUserCredentials(credentials); const groupedCredentials = credentials.reduce((r, a) => { r[a.type!] = r[a.type!] || []; r[a.type!].push(a); return r; }, Object.create(null)); const groupedCredentialsArray = Object.keys(groupedCredentials).map( (key) => ({ key, value: groupedCredentials[key] }) ); setGroupedUserCredentials( groupedCredentialsArray.map((groupedCredential) => ({ ...groupedCredential, isExpanded: false, })) ); }, [key] ); const passwordTypeFinder = userCredentials.find( (credential) => credential.type === "password" ); const toggleModal = () => setIsOpen(!isOpen); const toggleCredentialsResetModal = () => { setOpenCredentialReset(!openCredentialReset); }; const resetPassword = () => { setIsResetPassword(true); toggleModal(); }; const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({ titleKey: t("deleteCredentialsConfirmTitle"), messageKey: t("deleteCredentialsConfirm"), continueButtonLabel: t("common:delete"), continueButtonVariant: ButtonVariant.danger, onConfirm: async () => { try { await adminClient.users.deleteCredential({ id: user.id!, credentialId: selectedCredential.id!, }); addAlert(t("deleteCredentialsSuccess"), AlertVariant.success); setKey((key) => key + 1); } catch (error) { addError("users:deleteCredentialsError", error); } }, }); const Row = ({ credential }: { credential: CredentialRepresentation }) => ( { setSelectedCredential(credential); toggleDeleteDialog(); }} resetPassword={resetPassword} > { setIsUserLabelEdit({ status: !isUserLabelEdit?.status, rowKey: credential.id!, }); if (isUserLabelEdit?.status) { refresh(); } }} /> ); return ( <> {isOpen && ( setIsOpen(false)} /> )} {openCredentialReset && ( setOpenCredentialReset(false)} /> )} {userCredentials.length !== 0 && passwordTypeFinder === undefined && ( <> )} {groupedUserCredentials.length !== 0 ? ( <> {user.email && ( )} {t("type")} {t("userLabel")} {t("data")} {groupedUserCredentials.map((groupedCredential, rowIndex) => ( {groupedCredential.value.length > 1 ? ( { const rows = groupedUserCredentials.map( (credential, index) => index === rowIndex ? { ...credential, isExpanded: !credential.isExpanded, } : credential ); setGroupedUserCredentials(rows); }, }} /> ) : ( )} {toUpperCase(groupedCredential.key)} {groupedCredential.value.length <= 1 && groupedCredential.value.map((credential) => ( ))} {groupedCredential.isExpanded && groupedCredential.value.map((credential) => ( {toUpperCase(credential.type!)} ))} ))} ) : ( )} ); };