keycloak-scim/src/clients/service-account/ServiceAccount.tsx

118 lines
3.4 KiB
TypeScript
Raw Normal View History

import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { AlertVariant } from "@patternfly/react-core";
import type UserRepresentation from "keycloak-admin/lib/defs/userRepresentation";
import type { RoleMappingPayload } from "keycloak-admin/lib/defs/roleRepresentation";
import type ClientRepresentation from "keycloak-admin/lib/defs/clientRepresentation";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { useAlerts } from "../../components/alert/Alerts";
import {
mapRoles,
RoleMapping,
Row,
} from "../../components/role-mapping/RoleMapping";
type ServiceAccountProps = {
client: ClientRepresentation;
};
export const ServiceAccount = ({ client }: ServiceAccountProps) => {
const { t } = useTranslation("clients");
const adminClient = useAdminClient();
const { addAlert } = useAlerts();
const [hide, setHide] = useState(false);
const [serviceAccount, setServiceAccount] = useState<UserRepresentation>();
useFetch(
() =>
adminClient.clients.getServiceAccountUser({
id: client.id!,
}),
(serviceAccount) => setServiceAccount(serviceAccount),
[]
);
const loader = async () => {
const serviceAccount = await adminClient.clients.getServiceAccountUser({
id: client.id!,
});
const id = serviceAccount.id!;
const assignedRoles = await adminClient.users.listRealmRoleMappings({ id });
const effectiveRoles = await adminClient.users.listCompositeRealmRoleMappings(
{ id }
);
const clients = await adminClient.clients.find();
const clientRoles = (
await Promise.all(
clients.map(async (client) => {
const clientAssignedRoles = await adminClient.users.listClientRoleMappings(
{
id,
clientUniqueId: client.id!,
}
);
const clientEffectiveRoles = await adminClient.users.listCompositeClientRoleMappings(
{
id,
clientUniqueId: client.id!,
}
);
return mapRoles(clientAssignedRoles, clientEffectiveRoles, hide);
})
)
).flat();
return [...mapRoles(assignedRoles, effectiveRoles, hide), ...clientRoles];
};
const assignRoles = async (rows: Row[]) => {
try {
const realmRoles = rows
.filter((row) => row.client === undefined)
.map((row) => row.role as RoleMappingPayload)
.flat();
adminClient.users.addRealmRoleMappings({
id: serviceAccount?.id!,
roles: realmRoles,
});
await Promise.all(
rows
.filter((row) => row.client !== undefined)
.map((row) =>
adminClient.users.addClientRoleMappings({
id: serviceAccount?.id!,
clientUniqueId: row.client!.id!,
roles: [row.role as RoleMappingPayload],
})
)
);
addAlert(t("roleMappingUpdatedSuccess"), AlertVariant.success);
} catch (error) {
addAlert(
t("roleMappingUpdatedError", {
error: error.response?.data?.errorMessage || error,
}),
AlertVariant.danger
);
}
};
return (
<>
{serviceAccount && (
<RoleMapping
name={client.clientId!}
id={serviceAccount.id!}
type="service-account"
loader={loader}
save={assignRoles}
onHideRolesToggle={() => setHide(!hide)}
/>
)}
</>
);
};