f088b0009c
* initial screen Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * more screens Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * added members tab Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * added the backend Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * added member add / invite models Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * initial version of the identity provider section Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * add link and unlink providers Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * small fix Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * PR comments Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Do not validate broker domain when the domain is an empty string Closes #29759 Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * added filter and value Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * added test Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * added first name last name Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * refresh menu when realm organization is changed Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * changed to record Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * changed to form data Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * fixed lint error Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Changing name of invitation parameters Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Chancing name of parameters on the client Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Enable organization at the realm before running tests Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Domain help message Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Handling model validation errors when creating organizations Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Message key for organizationDetails Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Do not change kc.org attribute on group Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * add realm into the context Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * tests Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Changing button in invitation model to use Send instead of Save Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Better message when validating the organization domain Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * Fixing compilation error after rebase Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * fixed test Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * removed wait as it no longer required and skip flacky test Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * skip tests that are flaky Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * stabilize user create test Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> --------- Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Co-authored-by: Pedro Igor <pigor.craveiro@gmail.com>
196 lines
5.5 KiB
TypeScript
196 lines
5.5 KiB
TypeScript
import IdentityProviderRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderRepresentation";
|
|
import {
|
|
Button,
|
|
ButtonVariant,
|
|
PageSection,
|
|
Switch,
|
|
ToolbarItem,
|
|
} from "@patternfly/react-core";
|
|
import { BellIcon } from "@patternfly/react-icons";
|
|
import { useState } from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { useParams } from "react-router-dom";
|
|
import { useAdminClient } from "../admin-client";
|
|
import { useAlerts } from "../components/alert/Alerts";
|
|
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
|
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
|
|
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
|
|
import { useFetch } from "../utils/useFetch";
|
|
import useToggle from "../utils/useToggle";
|
|
import { LinkIdentityProviderModal } from "./LinkIdentityProviderModal";
|
|
import { EditOrganizationParams } from "./routes/EditOrganization";
|
|
|
|
type ShownOnLoginPageCheckProps = {
|
|
row: IdentityProviderRepresentation;
|
|
refresh: () => void;
|
|
};
|
|
|
|
const ShownOnLoginPageCheck = ({
|
|
row,
|
|
refresh,
|
|
}: ShownOnLoginPageCheckProps) => {
|
|
const { adminClient } = useAdminClient();
|
|
const { addAlert, addError } = useAlerts();
|
|
const { t } = useTranslation();
|
|
|
|
const toggle = async (value: boolean) => {
|
|
try {
|
|
await adminClient.identityProviders.update(
|
|
{ alias: row.alias! },
|
|
{
|
|
...row,
|
|
config: {
|
|
...row.config,
|
|
"kc.org.broker.public": `${value}`,
|
|
},
|
|
},
|
|
);
|
|
addAlert(t("linkUpdatedSuccessful"));
|
|
|
|
refresh();
|
|
} catch (error) {
|
|
addError("linkUpdatedError", error);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Switch
|
|
label={t("on")}
|
|
labelOff={t("off")}
|
|
isChecked={row.config?.["kc.org.broker.public"] === "true"}
|
|
onChange={(_, value) => toggle(value)}
|
|
/>
|
|
);
|
|
};
|
|
|
|
export const IdentityProviders = () => {
|
|
const { adminClient } = useAdminClient();
|
|
const { t } = useTranslation();
|
|
const { id: orgId } = useParams<EditOrganizationParams>();
|
|
const { addAlert, addError } = useAlerts();
|
|
|
|
const [key, setKey] = useState(0);
|
|
const refresh = () => setKey(key + 1);
|
|
|
|
const [hasProviders, setHasProviders] = useState(false);
|
|
const [selectedRow, setSelectedRow] =
|
|
useState<IdentityProviderRepresentation>();
|
|
const [open, toggleOpen] = useToggle();
|
|
|
|
useFetch(
|
|
async () => adminClient.identityProviders.find({ max: 1 }),
|
|
(providers) => {
|
|
setHasProviders(providers.length === 1);
|
|
},
|
|
[],
|
|
);
|
|
|
|
const loader = () =>
|
|
adminClient.organizations.listIdentityProviders({ orgId: orgId! });
|
|
|
|
const [toggleUnlinkDialog, UnlinkConfirm] = useConfirmDialog({
|
|
titleKey: "identityProviderUnlink",
|
|
messageKey: "identityProviderUnlinkConfirm",
|
|
continueButtonLabel: "unLinkIdentityProvider",
|
|
continueButtonVariant: ButtonVariant.danger,
|
|
onConfirm: async () => {
|
|
try {
|
|
await adminClient.organizations.unLinkIdp({
|
|
orgId: orgId!,
|
|
alias: selectedRow!.alias! as string,
|
|
});
|
|
setSelectedRow(undefined);
|
|
addAlert(t("unLinkSuccessful"));
|
|
refresh();
|
|
} catch (error) {
|
|
addError("unLinkError", error);
|
|
}
|
|
},
|
|
});
|
|
|
|
return (
|
|
<PageSection variant="light">
|
|
<UnlinkConfirm />
|
|
{open && (
|
|
<LinkIdentityProviderModal
|
|
orgId={orgId!}
|
|
identityProvider={selectedRow}
|
|
onClose={() => {
|
|
toggleOpen();
|
|
refresh();
|
|
}}
|
|
/>
|
|
)}
|
|
{!hasProviders ? (
|
|
<ListEmptyState
|
|
icon={BellIcon}
|
|
message={t("noIdentityProvider")}
|
|
instructions={t("noIdentityProviderInstructions")}
|
|
/>
|
|
) : (
|
|
<KeycloakDataTable
|
|
key={key}
|
|
loader={loader}
|
|
ariaLabelKey="identityProviders"
|
|
searchPlaceholderKey="searchProvider"
|
|
toolbarItem={
|
|
<ToolbarItem>
|
|
<Button
|
|
onClick={() => {
|
|
setSelectedRow(undefined);
|
|
toggleOpen();
|
|
}}
|
|
>
|
|
{t("linkIdentityProvider")}
|
|
</Button>
|
|
</ToolbarItem>
|
|
}
|
|
actions={[
|
|
{
|
|
title: t("edit"),
|
|
onRowClick: (row) => {
|
|
setSelectedRow(row);
|
|
toggleOpen();
|
|
},
|
|
},
|
|
{
|
|
title: t("unLinkIdentityProvider"),
|
|
onRowClick: (row) => {
|
|
setSelectedRow(row);
|
|
toggleUnlinkDialog();
|
|
},
|
|
},
|
|
]}
|
|
columns={[
|
|
{
|
|
name: "alias",
|
|
},
|
|
{
|
|
name: "config['kc.org.domain']",
|
|
displayKey: "domain",
|
|
},
|
|
{
|
|
name: "providerId",
|
|
displayKey: "providerDetails",
|
|
},
|
|
{
|
|
name: "config['kc.org.broker.public']",
|
|
displayKey: "shownOnLoginPage",
|
|
cellRenderer: (row) => (
|
|
<ShownOnLoginPageCheck row={row} refresh={refresh} />
|
|
),
|
|
},
|
|
]}
|
|
emptyState={
|
|
<ListEmptyState
|
|
message={t("emptyIdentityProviderLink")}
|
|
instructions={t("emptyIdentityProviderLinkInstructions")}
|
|
primaryActionText={t("linkIdentityProvider")}
|
|
onPrimaryAction={toggleOpen}
|
|
/>
|
|
}
|
|
/>
|
|
)}
|
|
</PageSection>
|
|
);
|
|
};
|