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
This commit is contained in:
Jenny 2021-06-03 16:40:48 -04:00 committed by GitHub
parent 2746109e78
commit 8a3c30b918
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 129 additions and 27 deletions

View file

@ -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 () => {},
});

View file

@ -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<ComponentData[]>(
[]
@ -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<boolean[]>(
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" && (
<ECDSAGeneratedModal
handleModalToggle={handleModalToggle}
providerType={defaultConsoleDisplayName}
refresh={refresh}
open={isCreateModalOpen}
/>
)} */}
{defaultConsoleDisplayName === "hmac-generated" && (
<HMACGeneratedModal
handleModalToggle={handleModalToggle}
@ -180,6 +219,7 @@ export const KeysTabInner = ({ components, refresh }: KeysTabInnerProps) => {
open={isCreateModalOpen}
/>
)}
<DeleteConfirm />
<PageSection variant="light" padding={{ default: "noPadding" }}>
<Toolbar>
<>
@ -276,14 +316,14 @@ export const KeysTabInner = ({ components, refresh }: KeysTabInnerProps) => {
{(filteredComponents.length === 0
? components
: filteredComponents
).map((component, idx) => (
).map((component: ComponentData, idx) => (
<DataListItem
draggable
aria-labelledby={"aria"}
key={`data${idx}`}
id={`data${idx}`}
>
<DataListItemRow data-testid={"data-list-row"}>
<DataListItemRow key={idx} data-testid={"data-list-row"}>
<DataListControl>
<DataListDragButton
className="row-drag-button"
@ -295,17 +335,50 @@ export const KeysTabInner = ({ components, refresh }: KeysTabInnerProps) => {
</DataListControl>
<DataListItemCells
dataListCells={[
<DataListCell key={"4"}>
<DataListCell key={`name-${idx}`}>
<>
<Button variant="link">{component.providerId}</Button>
<Button variant="link">{component.name}</Button>
</>
</DataListCell>,
<DataListCell key={"5"}>
<>{component.name}</>
<DataListCell key={`providerId-${idx}`}>
<>{component.providerId}</>
</DataListCell>,
<DataListCell key={"6"}>
<DataListCell key={`providerDescription-${idx}`}>
<>{component.providerDescription}</>
</DataListCell>,
<DataListAction
aria-labelledby="data-list-action"
aria-label="Actions"
isPlainButtonAction
key={`data-action-list-${idx}`}
id={`data-action-list-${idx}`}
>
<Dropdown
isPlain
position={DropdownPosition.right}
isOpen={actionListOpen[idx]}
toggle={
<KebabToggle
onToggle={() => {
toggleActionList(idx);
}}
/>
}
dropdownItems={[
<DropdownItem
key="action"
component="button"
onClick={() => {
setSelectedComponent(component);
toggleDeleteDialog();
toggleActionList(idx);
}}
>
Delete
</DropdownItem>,
]}
/>
</DataListAction>,
]}
/>
</DataListItemRow>
@ -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 (
<KeysTabInner
components={components?.map((component) => {
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}
/>
);

View file

@ -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);
}

View file

@ -131,7 +131,6 @@ export const RealmSettingsSection = () => {
const [realm, setRealm] = useState<RealmRepresentation>();
const [activeTab, setActiveTab] = useState(0);
const [key, setKey] = useState(0);
// const [keys, setKeys] = useState<KeyMetadataRepresentation[]>([]);
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={<TabTitleText>{t("providers")}</TabTitleText>}
>
<KeysProviderTab
refresh={refresh}
components={realmComponents}
realmComponents={realmComponents}
keyProviderComponentTypes={kpComponentTypes}
refresh={refresh}
/>
</Tab>
</Tabs>

View file

@ -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}}"
}
}