add revoke action

This commit is contained in:
jenny-s51 2021-06-09 14:01:14 -04:00
parent 0647b88083
commit aefac52144
3 changed files with 69 additions and 8 deletions

View file

@ -1,7 +1,12 @@
import React from "react"; import React, { useState } from "react";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Chip, ChipGroup } from "@patternfly/react-core"; import {
AlertVariant,
ButtonVariant,
Chip,
ChipGroup,
} from "@patternfly/react-core";
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState"; import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable"; import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
import { emptyFormatter } from "../util"; import { emptyFormatter } from "../util";
@ -11,9 +16,16 @@ import _ from "lodash";
import type UserConsentRepresentation from "keycloak-admin/lib/defs/userConsentRepresentation"; import type UserConsentRepresentation from "keycloak-admin/lib/defs/userConsentRepresentation";
import { CubesIcon } from "@patternfly/react-icons"; import { CubesIcon } from "@patternfly/react-icons";
import moment from "moment"; import moment from "moment";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { useAlerts } from "../components/alert/Alerts";
export const UserConsents = () => { export const UserConsents = () => {
const [selectedClient, setSelectedClient] = useState<
UserConsentRepresentation
>();
const { t } = useTranslation("roles"); const { t } = useTranslation("roles");
const { addAlert } = useAlerts();
const [key, setKey] = useState(0);
const adminClient = useAdminClient(); const adminClient = useAdminClient();
const { id } = useParams<{ id: string }>(); const { id } = useParams<{ id: string }>();
@ -21,6 +33,8 @@ export const UserConsents = () => {
return _.sortBy(consentsList, (client) => client.clientId?.toUpperCase()); return _.sortBy(consentsList, (client) => client.clientId?.toUpperCase());
}; };
const refresh = () => setKey(new Date().getTime());
const loader = async () => { const loader = async () => {
const getConsents = await adminClient.users.listConsents({ id }); const getConsents = await adminClient.users.listConsents({ id });
@ -56,10 +70,34 @@ export const UserConsents = () => {
return <>{moment(lastUpdatedDate).format("MM/DD/YY hh:MM A")}</>; return <>{moment(lastUpdatedDate).format("MM/DD/YY hh:MM A")}</>;
}; };
const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({
titleKey: "users:revokeClientScopesTitle",
messageKey: t("users:revokeClientScopes") + selectedClient?.clientId + "?",
continueButtonLabel: "common:delete",
continueButtonVariant: ButtonVariant.danger,
onConfirm: async () => {
try {
await adminClient.users.revokeConsent({
id,
// realm: realm,
clientId: selectedClient!.clientId!,
});
refresh();
addAlert(t("deleteGrantsSuccess"), AlertVariant.success);
} catch (error) {
addAlert(t("deleteGrantsError", { error }), AlertVariant.danger);
}
},
});
return ( return (
<> <>
<DeleteConfirm />
<KeycloakDataTable <KeycloakDataTable
loader={loader} loader={loader}
key={key}
ariaLabelKey="roles:roleList" ariaLabelKey="roles:roleList"
searchPlaceholderKey=" " searchPlaceholderKey=" "
columns={[ columns={[
@ -88,7 +126,16 @@ export const UserConsents = () => {
displayKey: "clients:lastUpdated", displayKey: "clients:lastUpdated",
cellFormatters: [emptyFormatter()], cellFormatters: [emptyFormatter()],
cellRenderer: lastUpdatedRenderer, cellRenderer: lastUpdatedRenderer,
transforms: [cellWidth(20)], transforms: [cellWidth(10)],
},
]}
actions={[
{
title: t("users:revoke"),
onRowClick: (client) => {
setSelectedClient(client);
toggleDeleteDialog();
},
}, },
]} ]}
emptyState={ emptyState={

View file

@ -60,6 +60,11 @@
"noConsents": "No consents", "noConsents": "No consents",
"noConsentsText": "The consents will only be recorded when users try to access a client that is configured to require consent. In that case, users will get a consent page which asks them to grant access to the client.", "noConsentsText": "The consents will only be recorded when users try to access a client that is configured to require consent. In that case, users will get a consent page which asks them to grant access to the client.",
"whoWillAppearLinkText": "Who will appear in this group list?", "whoWillAppearLinkText": "Who will appear in this group list?",
"whoWillAppearPopoverText": "Groups are hierarchical. When you select Direct Membership, you see only the child group that the user joined. Ancestor groups are not included." "whoWillAppearPopoverText": "Groups are hierarchical. When you select Direct Membership, you see only the child group that the user joined. Ancestor groups are not included.",
"revoke": "Revoke",
"revokeClientScopesTitle": "Revoke all granted client scopes?",
"revokeClientScopes": "Are you sure you want to revoke all granted client scopes for ",
"deleteGrantsSuccess": "Grants successfully revoked.",
"deleteGrantsError": "Error deleting grants."
} }
} }

View file

@ -87,12 +87,21 @@ td.pf-c-table__check > input {
content: ", "; content: ", ";
} }
.pf-c-chip-group.kc-consents-chip-group div.pf-c-chip-group.kc-consents-chip-group
> div.pf-c-chip-group__main > div.pf-c-chip-group__main
> ul.pf-c-chip-group__list > ul.pf-c-chip-group__list
.pf-m-overflow > li.pf-c-chip-group__list-item:last-child
.pf-c-chip__text::before { > button.pf-c-chip.pf-m-overflow::before {
content: "";
margin-left: var(--pf-global--spacer--sm);
}
div.pf-c-chip-group.kc-consents-chip-group
> div.pf-c-chip-group__main
> ul.pf-c-chip-group__list
> li.pf-c-chip-group__list-item:last-child
> button.pf-c-chip.pf-m-overflow
> span::before {
content: ""; content: "";
margin-left: var(--pf-global--spacer--sm); margin-left: var(--pf-global--spacer--sm);
padding-left: 0px;
} }