Fix custom userFed that doesn't implement CredentialInputUpdater (#20062)
* Fix custom userFed that doesn't implement CredentialInputUpdater Fixes #19491 * Cleanup from Jon's review * Specify dependency * Revert "Specify dependency" This reverts commit a52d5d993aa1f9cf4503e6101eb49c20b27b38fc.
This commit is contained in:
parent
fb4513d320
commit
51b0eec685
2 changed files with 75 additions and 104 deletions
|
@ -35,9 +35,10 @@ import { InlineLabelEdit } from "./user-credentials/InlineLabelEdit";
|
|||
import styles from "@patternfly/react-styles/css/components/Table/table";
|
||||
import { CredentialRow } from "./user-credentials/CredentialRow";
|
||||
import { toUpperCase } from "../util";
|
||||
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
|
||||
import { FederatedUserLink } from "./FederatedUserLink";
|
||||
|
||||
import "./user-credentials.css";
|
||||
import { FederatedCredentials } from "./user-credentials/FederatedCredentials";
|
||||
|
||||
type UserCredentialsProps = {
|
||||
user: UserRepresentation;
|
||||
|
@ -329,6 +330,26 @@ export const UserCredentials = ({ user }: UserCredentialsProps) => {
|
|||
}
|
||||
};
|
||||
|
||||
const useFederatedCredentials = user.federationLink || user.origin;
|
||||
const [credentialTypes, setCredentialTypes] = useState<string[]>([]);
|
||||
|
||||
useFetch(
|
||||
() => adminClient.users.getUserStorageCredentialTypes({ id: user.id! }),
|
||||
setCredentialTypes,
|
||||
[]
|
||||
);
|
||||
|
||||
if (!credentialTypes) {
|
||||
return <KeycloakSpinner />;
|
||||
}
|
||||
|
||||
const hasCredentialTypes = credentialTypes.length > 0;
|
||||
const noCredentials = groupedUserCredentials.length === 0;
|
||||
const noFederatedCredentials =
|
||||
!user.credentials || user.credentials.length === 0;
|
||||
const emptyState =
|
||||
noCredentials && noFederatedCredentials && !hasCredentialTypes;
|
||||
|
||||
return (
|
||||
<>
|
||||
{isOpen && (
|
||||
|
@ -346,7 +367,7 @@ export const UserCredentials = ({ user }: UserCredentialsProps) => {
|
|||
/>
|
||||
)}
|
||||
<DeleteConfirm />
|
||||
{user.email && (
|
||||
{user.email && !emptyState && (
|
||||
<Button
|
||||
className="kc-resetCredentialBtn-header"
|
||||
variant="primary"
|
||||
|
@ -372,7 +393,7 @@ export const UserCredentials = ({ user }: UserCredentialsProps) => {
|
|||
<Divider />
|
||||
</>
|
||||
)}
|
||||
{groupedUserCredentials.length !== 0 && (
|
||||
{groupedUserCredentials.length !== 0 && !hasCredentialTypes && (
|
||||
<PageSection variant={PageSectionVariants.light}>
|
||||
<TableComposable variant={"compact"}>
|
||||
<Thead>
|
||||
|
@ -485,30 +506,58 @@ export const UserCredentials = ({ user }: UserCredentialsProps) => {
|
|||
</TableComposable>
|
||||
</PageSection>
|
||||
)}
|
||||
{(user.federationLink || user.origin) && (
|
||||
<FederatedCredentials user={user} onSetPassword={toggleModal} />
|
||||
{useFederatedCredentials && hasCredentialTypes && (
|
||||
<PageSection variant={PageSectionVariants.light}>
|
||||
<TableComposable variant="compact">
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>{t("type")}</Th>
|
||||
<Th>{t("providedBy")}</Th>
|
||||
<Th />
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{credentialTypes.map((credential) => (
|
||||
<Tr key={credential}>
|
||||
<Td>
|
||||
<b>{credential}</b>
|
||||
</Td>
|
||||
<Td>
|
||||
<FederatedUserLink user={user} />
|
||||
</Td>
|
||||
{credential === "password" && (
|
||||
<Td modifier="fitContent">
|
||||
<Button variant="secondary" onClick={toggleModal}>
|
||||
{t("setPassword")}
|
||||
</Button>
|
||||
</Td>
|
||||
)}
|
||||
</Tr>
|
||||
))}
|
||||
</Tbody>
|
||||
</TableComposable>
|
||||
</PageSection>
|
||||
)}
|
||||
{emptyState && (
|
||||
<ListEmptyState
|
||||
hasIcon
|
||||
message={t("noCredentials")}
|
||||
instructions={t("noCredentialsText")}
|
||||
primaryActionText={t("setPassword")}
|
||||
onPrimaryAction={toggleModal}
|
||||
secondaryActions={
|
||||
user.email
|
||||
? [
|
||||
{
|
||||
text: t("credentialResetBtn"),
|
||||
onClick: toggleCredentialsResetModal,
|
||||
type: ButtonVariant.link,
|
||||
},
|
||||
]
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{groupedUserCredentials.length === 0 &&
|
||||
!(user.federationLink || user.origin) && (
|
||||
<ListEmptyState
|
||||
hasIcon
|
||||
message={t("noCredentials")}
|
||||
instructions={t("noCredentialsText")}
|
||||
primaryActionText={t("setPassword")}
|
||||
onPrimaryAction={toggleModal}
|
||||
secondaryActions={
|
||||
user.email
|
||||
? [
|
||||
{
|
||||
text: t("credentialResetBtn"),
|
||||
onClick: toggleCredentialsResetModal,
|
||||
type: ButtonVariant.link,
|
||||
},
|
||||
]
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
import {
|
||||
Button,
|
||||
PageSection,
|
||||
PageSectionVariants,
|
||||
} from "@patternfly/react-core";
|
||||
import {
|
||||
TableComposable,
|
||||
Tbody,
|
||||
Td,
|
||||
Th,
|
||||
Thead,
|
||||
Tr,
|
||||
} from "@patternfly/react-table";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
|
||||
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
|
||||
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
|
||||
import { FederatedUserLink } from "../FederatedUserLink";
|
||||
|
||||
type FederatedCredentialsProps = {
|
||||
user: UserRepresentation;
|
||||
onSetPassword: () => void;
|
||||
};
|
||||
|
||||
export const FederatedCredentials = ({
|
||||
user,
|
||||
onSetPassword,
|
||||
}: FederatedCredentialsProps) => {
|
||||
const { t } = useTranslation("users");
|
||||
const { adminClient } = useAdminClient();
|
||||
|
||||
const [credentialTypes, setCredentialTypes] = useState<string[]>();
|
||||
|
||||
useFetch(
|
||||
() => adminClient.users.getUserStorageCredentialTypes({ id: user.id! }),
|
||||
setCredentialTypes,
|
||||
[]
|
||||
);
|
||||
|
||||
if (!credentialTypes) {
|
||||
return <KeycloakSpinner />;
|
||||
}
|
||||
|
||||
return (
|
||||
<PageSection variant={PageSectionVariants.light}>
|
||||
<TableComposable variant={"compact"}>
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>{t("type")}</Th>
|
||||
<Th>{t("providedBy")}</Th>
|
||||
<Th />
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{credentialTypes.map((credential) => (
|
||||
<Tr key={credential}>
|
||||
<Td>
|
||||
<b>{credential}</b>
|
||||
</Td>
|
||||
<Td>
|
||||
<FederatedUserLink user={user} />
|
||||
</Td>
|
||||
{credential === "password" && (
|
||||
<Td modifier="fitContent">
|
||||
<Button variant="secondary" onClick={onSetPassword}>
|
||||
{t("setPassword")}
|
||||
</Button>
|
||||
</Td>
|
||||
)}
|
||||
</Tr>
|
||||
))}
|
||||
</Tbody>
|
||||
</TableComposable>
|
||||
</PageSection>
|
||||
);
|
||||
};
|
Loading…
Reference in a new issue