From 8a3c30b918c44653d71ec51590a270161bdb17b1 Mon Sep 17 00:00:00 2001 From: Jenny <32821331+jenny-s51@users.noreply.github.com> Date: Thu, 3 Jun 2021 16:40:48 -0400 Subject: [PATCH] Realm settings(keys): add functionality to delete provider (#606) * wip keys keys adds keys table to realm settings wip key providers add providers and search functionality clean up stylesheet wip delete provider wip delete toggles add delete functionality to each provider in data list rebase format pr feedback from erik * Delete LocalizationTab.tsx --- src/realm-settings/KeysListTab.tsx | 2 - src/realm-settings/KeysProvidersTab.tsx | 119 ++++++++++++++++---- src/realm-settings/RealmSettingsSection.css | 4 + src/realm-settings/RealmSettingsSection.tsx | 25 +++- src/realm-settings/messages.json | 6 +- 5 files changed, 129 insertions(+), 27 deletions(-) diff --git a/src/realm-settings/KeysListTab.tsx b/src/realm-settings/KeysListTab.tsx index ea18825da1..254faa6529 100644 --- a/src/realm-settings/KeysListTab.tsx +++ b/src/realm-settings/KeysListTab.tsx @@ -53,7 +53,6 @@ export const KeysListTab = ({ realmComponents }: KeysListTabProps) => { messageKey: publicKey, continueButtonLabel: "common:close", continueButtonVariant: ButtonVariant.primary, - noCancelButton: true, onConfirm: async () => {}, }); @@ -62,7 +61,6 @@ export const KeysListTab = ({ realmComponents }: KeysListTabProps) => { messageKey: certificate, continueButtonLabel: "common:close", continueButtonVariant: ButtonVariant.primary, - noCancelButton: true, onConfirm: async () => {}, }); diff --git a/src/realm-settings/KeysProvidersTab.tsx b/src/realm-settings/KeysProvidersTab.tsx index 0c0272e2cd..aaad319115 100644 --- a/src/realm-settings/KeysProvidersTab.tsx +++ b/src/realm-settings/KeysProvidersTab.tsx @@ -1,9 +1,11 @@ import React, { useState, useEffect } from "react"; import { useTranslation } from "react-i18next"; import { + AlertVariant, Button, ButtonVariant, DataList, + DataListAction, DataListCell, DataListControl, DataListDragButton, @@ -12,8 +14,10 @@ import { DataListItemRow, Dropdown, DropdownItem, + DropdownPosition, DropdownToggle, InputGroup, + KebabToggle, PageSection, TextInput, Toolbar, @@ -34,10 +38,16 @@ import { HMACGeneratedModal } from "./HMACGeneratedModal"; import { JavaKeystoreModal } from "./JavaKeystoreModal"; import { RSAModal } from "./RSAModal"; import { RSAGeneratedModal } from "./RSAGeneratedModal"; +import { useAdminClient } from "../context/auth/AdminClient"; +import { useAlerts } from "../components/alert/Alerts"; +import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; +import { useRealm } from "../context/realm-context/RealmContext"; type ComponentData = KeyMetadataRepresentation & { providerDescription?: string; name?: string; + toggleHidden?: boolean; + config?: any; }; type KeysTabInnerProps = { @@ -48,9 +58,13 @@ type KeysTabInnerProps = { }; export const KeysTabInner = ({ components, refresh }: KeysTabInnerProps) => { - const { t } = useTranslation("roles"); + const { t } = useTranslation("realm-settings"); + const { addAlert } = useAlerts(); + const adminClient = useAdminClient(); + const { realm } = useRealm(); const [id, setId] = useState(""); + const [searchVal, setSearchVal] = useState(""); const [filteredComponents, setFilteredComponents] = useState( [] @@ -71,12 +85,37 @@ export const KeysTabInner = ({ components, refresh }: KeysTabInnerProps) => { "" ); + const [selectedComponent, setSelectedComponent] = useState< + ComponentRepresentation + >(); + const [liveText, setLiveText] = useState(""); useEffect(() => { setItemOrder(["data", ...itemIds]); }, [components, searchVal]); + const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({ + titleKey: "realm-settings:deleteProviderTitle", + messageKey: t("deleteProviderConfirm") + selectedComponent?.name + "?", + continueButtonLabel: "common:delete", + continueButtonVariant: ButtonVariant.danger, + onConfirm: async () => { + try { + await adminClient.components.del({ + id: selectedComponent!.id!, + realm: realm, + }); + + refresh(); + + addAlert(t("deleteProviderSuccess"), AlertVariant.success); + } catch (error) { + addAlert(t("deleteProviderError", { error }), AlertVariant.danger); + } + }, + }); + const onDragStart = (id: string) => { setLiveText(t("onDragStart", { id })); setId(id); @@ -122,6 +161,14 @@ export const KeysTabInner = ({ components, refresh }: KeysTabInnerProps) => { setIsCreateModalOpen(!isCreateModalOpen); }; + const [actionListOpen, setActionListOpen] = useState( + components.map(() => false) + ); + const toggleActionList = (index: number) => { + actionListOpen[index] = !actionListOpen[index]; + setActionListOpen([...actionListOpen]); + }; + return ( <> {defaultConsoleDisplayName === "aes-generated" && ( @@ -140,14 +187,6 @@ export const KeysTabInner = ({ components, refresh }: KeysTabInnerProps) => { open={isCreateModalOpen} /> )} - {/* {defaultConsoleDisplayName === "ecdsa-generated" && ( - - )} */} {defaultConsoleDisplayName === "hmac-generated" && ( { open={isCreateModalOpen} /> )} + <> @@ -276,14 +316,14 @@ export const KeysTabInner = ({ components, refresh }: KeysTabInnerProps) => { {(filteredComponents.length === 0 ? components : filteredComponents - ).map((component, idx) => ( + ).map((component: ComponentData, idx) => ( - + { + <> - + , - - <>{component.name} + + <>{component.providerId} , - + <>{component.providerDescription} , + + { + toggleActionList(idx); + }} + /> + } + dropdownItems={[ + { + setSelectedComponent(component); + toggleDeleteDialog(); + toggleActionList(idx); + }} + > + Delete + , + ]} + /> + , ]} /> @@ -321,29 +394,33 @@ export const KeysTabInner = ({ components, refresh }: KeysTabInnerProps) => { }; type KeysProps = { - components: ComponentRepresentation[]; + realmComponents: ComponentRepresentation[]; keyProviderComponentTypes: ComponentTypeRepresentation[]; refresh: () => void; }; export const KeysProviderTab = ({ - components, keyProviderComponentTypes, + realmComponents, refresh, ...props }: KeysProps) => { return ( { + components={realmComponents?.map((component) => { const provider = keyProviderComponentTypes.find( (componentType: ComponentTypeRepresentation) => component.providerId === componentType.id ); - return { ...component, providerDescription: provider?.helpText }; + + return { + ...component, + providerDescription: provider?.helpText, + }; })} keyProviderComponentTypes={keyProviderComponentTypes} refresh={refresh} - realmComponents={components} + realmComponents={realmComponents} {...props} /> ); diff --git a/src/realm-settings/RealmSettingsSection.css b/src/realm-settings/RealmSettingsSection.css index d03be71f0d..9797d3e2b8 100644 --- a/src/realm-settings/RealmSettingsSection.css +++ b/src/realm-settings/RealmSettingsSection.css @@ -40,6 +40,10 @@ button#kc-certificate.pf-c-button.pf-m-secondary { margin-left: var(--pf-global--spacer--md); } +.pf-c-data-list__item-row.test { + font-weight: bold; +} + .pf-c-data-list__item-content.data-list-cells { margin-left: var(--pf-global--spacer--xl); } diff --git a/src/realm-settings/RealmSettingsSection.tsx b/src/realm-settings/RealmSettingsSection.tsx index 90a5478f6a..0b3bbb212c 100644 --- a/src/realm-settings/RealmSettingsSection.tsx +++ b/src/realm-settings/RealmSettingsSection.tsx @@ -131,7 +131,6 @@ export const RealmSettingsSection = () => { const [realm, setRealm] = useState(); const [activeTab, setActiveTab] = useState(0); const [key, setKey] = useState(0); - // const [keys, setKeys] = useState([]); const [realmComponents, setRealmComponents] = useState< ComponentRepresentation[] >(); @@ -140,6 +139,26 @@ export const RealmSettingsSection = () => { "org.keycloak.keys.KeyProvider" ]; + useFetch( + () => adminClient.realms.findOne({ realm: realmName }), + (realm) => { + setupForm(realm); + setRealm(realm); + }, + [] + ); + + useEffect(() => { + const update = async () => { + const realmComponents = await adminClient.components.find({ + type: "org.keycloak.keys.KeyProvider", + realm: realmName, + }); + setRealmComponents(realmComponents); + }; + setTimeout(update, 100); + }, [key]); + useFetch( async () => { const realm = await adminClient.realms.findOne({ realm: realmName }); @@ -270,9 +289,9 @@ export const RealmSettingsSection = () => { title={{t("providers")}} > diff --git a/src/realm-settings/messages.json b/src/realm-settings/messages.json index 75a6a7f0d3..c38666d01e 100644 --- a/src/realm-settings/messages.json +++ b/src/realm-settings/messages.json @@ -6,6 +6,10 @@ "deleteRealm": "Delete realm", "deleteConfirmTitle": "Delete realm?", "deleteConfirm": "If you delete this realm, all associated data will be removed.", + "deleteProviderTitle": "Delete key provider?", + "deleteProviderConfirm": "Are you sure you want to permanently delete the key provider ", + "deleteProviderSuccess": "Success. The provider has been deleted.", + "deleteProviderError": "Error deleting the provider", "deletedSuccess": "The realm has been deleted", "deleteError": "Could not delete realm: {{error}}", "disableConfirmTitle": "Disable realm?", @@ -130,4 +134,4 @@ "onDragMove": "Dragging item {{id}}", "onDragCancel": "Dragging cancelled. List is unchanged.", "onDragFinish": "Dragging finished {{list}}" -} \ No newline at end of file +}