From 9ad9d6c314de4a24800d73656eb778f229350dcc Mon Sep 17 00:00:00 2001 From: Jenny <32821331+jenny-s51@users.noreply.github.com> Date: Mon, 12 Jul 2021 14:19:50 -0400 Subject: [PATCH] parent a03c8fc79bcb6f3d78c142b096d2a279dcf00106 (#729) author jenny-s51 1624022352 -0400 committer jenny-s51 1625159705 -0400 wip provider details provider details wip move files wip wip wip all provider details remove controllers save and update working address console warnings remove log stmt update test keep aes only remove comments remove unused hook and function remove unused props revert ldap logs fix conflict and remove duplicate function format and cypress test Partial import phase 2 (#702) * Process the JSON and present user options * Finish checkboxes. Refactor. * Add tests * Refactor after rebase * Add more test data for manual testing. * Fix linting errors * Put JsonFileUpload back the way it was. * Clean up comments * Update src/realm-settings/PartialImport.tsx Remove comment Co-authored-by: Jenny <32821331+jenny-s51@users.noreply.github.com> Co-authored-by: Jenny <32821331+jenny-s51@users.noreply.github.com> Localization tab (#685) * localization wip wip localization return key value data as array localization table css lint lint clean up log stmts clean up log stmts * PR feedback from Erik * fix logic for supported locales * update empty state text * set default value * fix cypress test * Update src/realm-settings/RealmSettingsSection.tsx Co-authored-by: Erik Jan de Wit * fix rsa-generated delete bug; PR feedback frog Erik * revert locale abbreviation * remove log stmts * PR feedback from Erik, fix undefined * fix loader w Erik Co-authored-by: Erik Jan de Wit add divider on section Prepare for first alpha release (#711) use typeahead for mapper list fix test Default roles: UI Changes from KEYCLOAK-14846 (#693) * defaultRoles wip default role changes done clean up log stmts update snapshot fix masthead test * fix cypress test * fix tabs Comment out Realm role CRUD test (#712) * Bogus change * Bogus change * Comment out Realm role CRUD test Bump postcss-cli from 7.1.1 to 8.3.1 (#718) Bumps [postcss-cli](https://github.com/postcss/postcss-cli) from 7.1.1 to 8.3.1. - [Release notes](https://github.com/postcss/postcss-cli/releases) - [Changelog](https://github.com/postcss/postcss-cli/blob/master/CHANGELOG.md) - [Commits](https://github.com/postcss/postcss-cli/compare/7.1.1...8.3.1) --- updated-dependencies: - dependency-name: postcss-cli dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Bump @testing-library/jest-dom from 5.12.0 to 5.14.1 (#717) Bumps [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) from 5.12.0 to 5.14.1. - [Release notes](https://github.com/testing-library/jest-dom/releases) - [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md) - [Commits](https://github.com/testing-library/jest-dom/compare/v5.12.0...v5.14.1) --- updated-dependencies: - dependency-name: "@testing-library/jest-dom" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> fixing issue (#709) * fixing issue fixing: #680 * added kebab on row * added more clear group seperation Bump cypress from 7.4.0 to 7.5.0 (#715) Bump @babel/preset-typescript from 7.13.0 to 7.14.5 (#714) Bumps [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) from 7.13.0 to 7.14.5. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.14.5/packages/babel-preset-typescript) --- updated-dependencies: - dependency-name: "@babel/preset-typescript" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Bump @testing-library/react from 10.4.6 to 11.2.7 (#716) Bumps [@testing-library/react](https://github.com/testing-library/react-testing-library) from 10.4.6 to 11.2.7. - [Release notes](https://github.com/testing-library/react-testing-library/releases) - [Changelog](https://github.com/testing-library/react-testing-library/blob/main/CHANGELOG.md) - [Commits](https://github.com/testing-library/react-testing-library/compare/v10.4.6...v11.2.7) --- updated-dependencies: - dependency-name: "@testing-library/react" dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> inherited roles disabled instead of non selectable more style fixes fixed size change title of tab add unassign kebab on row added help item on enable switch test email working, modal wip email connection done remove comment fix cypress test revert test file fdisable email prompting when user email entered prettier update cypress tests fix lint try fix cypress test try longer wait save and test connection make wait longer increase wait fix test disable test connection button if form fields not entered lint afix username/password fields fix test mark suggested change add modal button and input functions fixed default value warning fixing issue fixing: #650 remove provider form add delete cleanup function AESproviderDetails extend wait for video update test test wait after rebase remove comments remove log format format PR feedback from Jon Apply suggestions from Jon's code review Co-authored-by: Jon Koops remove duplicate form form use array desctructuring Apply suggestions from code review Co-authored-by: Jon Koops update useroutematch format format back to async pretty cypress test remove email verification switch toggle fix add provider on non-master realm cleaning up fix save fix save for other providers fix fetch fix runtime error remove unused import Apply suggestions from code review suggested changes for non-null assertions Co-authored-by: Jon Koops make props required make provider type required use realm-settings file for translation format and roll back route changes --- .../integration/realm_settings_test.spec.ts | 17 + .../realm_settings/RealmSettingsPage.ts | 15 +- src/realm-settings/AESGeneratedModal.tsx | 251 ------------ src/realm-settings/ECDSAGeneratedModal.tsx | 47 +-- src/realm-settings/HMACGeneratedModal.tsx | 43 +-- src/realm-settings/JavaKeystoreModal.tsx | 46 +-- src/realm-settings/KeysProvidersTab.tsx | 8 +- src/realm-settings/LocalizationTab.tsx | 2 - src/realm-settings/RSAGeneratedModal.tsx | 40 +- src/realm-settings/RSAModal.tsx | 66 ++-- src/realm-settings/RealmSettingsSection.tsx | 4 +- .../aes-generated/AESGeneratedForm.tsx | 360 ++++++++++++++++++ .../aes-generated/AESGeneratedModal.tsx | 36 ++ src/route-config.ts | 7 + 14 files changed, 558 insertions(+), 384 deletions(-) delete mode 100644 src/realm-settings/AESGeneratedModal.tsx create mode 100644 src/realm-settings/key-providers/aes-generated/AESGeneratedForm.tsx create mode 100644 src/realm-settings/key-providers/aes-generated/AESGeneratedModal.tsx diff --git a/cypress/integration/realm_settings_test.spec.ts b/cypress/integration/realm_settings_test.spec.ts index 037789e0bb..448ba6dc2f 100644 --- a/cypress/integration/realm_settings_test.spec.ts +++ b/cypress/integration/realm_settings_test.spec.ts @@ -40,6 +40,18 @@ describe("Realm settings", () => { return this; }; + const goToDetails = () => { + const keysUrl = `/auth/admin/realms/${realmName}/keys`; + cy.intercept(keysUrl).as("keysFetch"); + + cy.getId("rs-keys-tab").click(); + cy.getId("rs-providers-tab").click(); + cy.getId("provider-name-link").contains("test_aes-generated").click(); + cy.wait(["@keysFetch"]); + + return this; + }; + const addBundle = () => { const localizationUrl = `/auth/admin/realms/${realmName}/localization/en`; cy.intercept(localizationUrl).as("localizationFetch"); @@ -191,6 +203,11 @@ describe("Realm settings", () => { realmSettingsPage.addProvider(); }); + it("go to details", () => { + sidebarPage.goToRealmSettings(); + goToDetails(); + }); + it("Test keys", () => { sidebarPage.goToRealmSettings(); goToKeys(); diff --git a/cypress/support/pages/admin_console/manage/realm_settings/RealmSettingsPage.ts b/cypress/support/pages/admin_console/manage/realm_settings/RealmSettingsPage.ts index 2d9796eab0..81350a652f 100644 --- a/cypress/support/pages/admin_console/manage/realm_settings/RealmSettingsPage.ts +++ b/cypress/support/pages/admin_console/manage/realm_settings/RealmSettingsPage.ts @@ -43,6 +43,8 @@ export default class RealmSettingsPage { confirmAddBundle = "add-bundle-confirm-button"; keyInput = "key-input"; valueInput = "value-input"; + deleteAction = "delete-action"; + modalConfirm = "modalConfirm"; selectLoginThemeType(themeType: string) { cy.get(this.selectLoginTheme).click(); @@ -75,7 +77,7 @@ export default class RealmSettingsPage { } fillHostField(host: string) { - cy.get(this.hostInput).type(host); + cy.get(this.hostInput).clear().type(host); return this; } @@ -151,6 +153,17 @@ export default class RealmSettingsPage { return this; } + deleteProvider(providerName: string) { + cy.getId("provider-name-link") + .contains(providerName) + .parent() + .siblings(".pf-c-data-list__item-action") + .click() + .getId(this.deleteAction) + .click(); + cy.wait(500).getId(this.modalConfirm).click(); + } + enterConsoleDisplayName(name: string) { cy.getId(this.displayName).clear().type(name); } diff --git a/src/realm-settings/AESGeneratedModal.tsx b/src/realm-settings/AESGeneratedModal.tsx deleted file mode 100644 index 2e8c3b054b..0000000000 --- a/src/realm-settings/AESGeneratedModal.tsx +++ /dev/null @@ -1,251 +0,0 @@ -import React, { useState } from "react"; -import { - AlertVariant, - Button, - ButtonVariant, - Form, - FormGroup, - Modal, - ModalVariant, - Select, - SelectOption, - SelectVariant, - Switch, - TextInput, -} from "@patternfly/react-core"; -import { useTranslation } from "react-i18next"; -import { Controller, useForm } from "react-hook-form"; - -import { useAdminClient } from "../context/auth/AdminClient"; -import { useAlerts } from "../components/alert/Alerts"; -import type ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation"; -import { HelpItem } from "../components/help-enabler/HelpItem"; -import { useServerInfo } from "../context/server-info/ServerInfoProvider"; -import { useRealm } from "../context/realm-context/RealmContext"; - -type AESGeneratedModalProps = { - providerType?: string; - handleModalToggle?: () => void; - refresh?: () => void; - open: boolean; -}; - -export const AESGeneratedModal = ({ - providerType, - handleModalToggle, - open, - refresh, -}: // save, -AESGeneratedModalProps) => { - const { t } = useTranslation("groups"); - const serverInfo = useServerInfo(); - const adminClient = useAdminClient(); - const { addAlert } = useAlerts(); - const { handleSubmit, control } = useForm({}); - const [isKeySizeDropdownOpen, setIsKeySizeDropdownOpen] = useState(false); - const [displayName, setDisplayName] = useState(""); - const realm = useRealm(); - - const allComponentTypes = - serverInfo.componentTypes!["org.keycloak.keys.KeyProvider"]; - - const save = async (component: ComponentRepresentation) => { - try { - await adminClient.components.create({ - parentId: realm.realm, - name: displayName !== "" ? displayName : providerType, - providerId: providerType, - providerType: "org.keycloak.keys.KeyProvider", - ...component, - }); - refresh!(); - addAlert(t("realm-settings:saveProviderSuccess"), AlertVariant.success); - handleModalToggle!(); - } catch (error) { - addAlert( - t("realm-settings:saveProviderError") + - error.response?.data?.errorMessage || error, - AlertVariant.danger - ); - } - }; - - return ( - - {t("common:Add")} - , - , - ]} - > -
- - } - > - ( - { - onChange(value); - setDisplayName(value); - }} - data-testid="display-name-input" - > - )} - /> - - - } - > - ( - { - onChange([value + ""]); - }} - /> - )} - /> - - - } - > - ( - { - onChange([value + ""]); - }} - /> - )} - /> - - {providerType === "aes-generated" && ( - - } - > - ( - - )} - /> - - )} -
-
- ); -}; diff --git a/src/realm-settings/ECDSAGeneratedModal.tsx b/src/realm-settings/ECDSAGeneratedModal.tsx index 382a67c81a..d07ebc5474 100644 --- a/src/realm-settings/ECDSAGeneratedModal.tsx +++ b/src/realm-settings/ECDSAGeneratedModal.tsx @@ -22,12 +22,11 @@ import { useAlerts } from "../components/alert/Alerts"; import type ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation"; import { HelpItem } from "../components/help-enabler/HelpItem"; import { useServerInfo } from "../context/server-info/ServerInfoProvider"; -import { useRealm } from "../context/realm-context/RealmContext"; type ECDSAGeneratedModalProps = { - providerType?: string; - handleModalToggle?: () => void; - refresh?: () => void; + providerType: string; + handleModalToggle: () => void; + refresh: () => void; open: boolean; }; @@ -36,9 +35,8 @@ export const ECDSAGeneratedModal = ({ handleModalToggle, open, refresh, -}: // save, -ECDSAGeneratedModalProps) => { - const { t } = useTranslation("groups"); +}: ECDSAGeneratedModalProps) => { + const { t } = useTranslation("realm-settings"); const serverInfo = useServerInfo(); const adminClient = useAdminClient(); const { addAlert } = useAlerts(); @@ -46,31 +44,29 @@ ECDSAGeneratedModalProps) => { const [isEllipticCurveDropdownOpen, setIsEllipticCurveDropdownOpen] = useState(false); const [isRSAalgDropdownOpen, setIsRSAalgDropdownOpen] = useState(false); - const [displayName, setDisplayName] = useState(""); - const realm = useRealm(); const [keyFileName, setKeyFileName] = useState(""); const [certificateFileName, setCertificateFileName] = useState(""); const allComponentTypes = - serverInfo.componentTypes!["org.keycloak.keys.KeyProvider"]; + serverInfo.componentTypes?.["org.keycloak.keys.KeyProvider"] ?? []; const save = async (component: ComponentRepresentation) => { try { await adminClient.components.create({ - parentId: realm.realm, - name: displayName !== "" ? displayName : providerType, + ...component, + parentId: component.parentId, providerId: providerType, providerType: "org.keycloak.keys.KeyProvider", - ...component, }); - refresh!(); - addAlert(t("realm-settings:saveProviderSuccess"), AlertVariant.success); handleModalToggle!(); + addAlert(t("saveProviderSuccess"), AlertVariant.success); + refresh(); } catch (error) { addAlert( - t("realm-settings:saveProviderError") + - error.response?.data?.errorMessage || error, + t("saveProviderError", { + error: error.response?.data?.errorMessage || error, + }), AlertVariant.danger ); } @@ -80,7 +76,7 @@ ECDSAGeneratedModalProps) => { { onSubmit={handleSubmit(save!)} > { defaultValue={providerType} onChange={(value) => { onChange(value); - setDisplayName(value); }} data-testid="display-name-input" > @@ -173,7 +168,7 @@ ECDSAGeneratedModalProps) => { /> { {providerType === "rsa" && ( <> { /> { /> } > @@ -315,7 +310,7 @@ ECDSAGeneratedModalProps) => { )} {providerType === "ecdsa-generated" && ( void; - refresh?: () => void; + providerType: string; + handleModalToggle: () => void; + refresh: () => void; open: boolean; }; @@ -35,9 +34,8 @@ export const HMACGeneratedModal = ({ handleModalToggle, open, refresh, -}: // save, -HMACGeneratedModalProps) => { - const { t } = useTranslation("groups"); +}: HMACGeneratedModalProps) => { + const { t } = useTranslation("realm-settings"); const serverInfo = useServerInfo(); const adminClient = useAdminClient(); const { addAlert } = useAlerts(); @@ -45,28 +43,26 @@ HMACGeneratedModalProps) => { const [isKeySizeDropdownOpen, setIsKeySizeDropdownOpen] = useState(false); const [isEllipticCurveDropdownOpen, setIsEllipticCurveDropdownOpen] = useState(false); - const [displayName, setDisplayName] = useState(""); - const realm = useRealm(); const allComponentTypes = - serverInfo.componentTypes!["org.keycloak.keys.KeyProvider"]; + serverInfo.componentTypes?.["org.keycloak.keys.KeyProvider"] ?? []; const save = async (component: ComponentRepresentation) => { try { await adminClient.components.create({ - parentId: realm.realm, - name: displayName !== "" ? displayName : providerType, + ...component, + parentId: component.parentId, providerId: providerType, providerType: "org.keycloak.keys.KeyProvider", - ...component, }); - refresh!(); - addAlert(t("realm-settings:saveProviderSuccess"), AlertVariant.success); - handleModalToggle!(); + handleModalToggle(); + addAlert(t("saveProviderSuccess"), AlertVariant.success); + refresh(); } catch (error) { addAlert( - t("realm-settings:saveProviderError") + - error.response?.data?.errorMessage || error, + t("saveProviderError", { + error: error.response?.data?.errorMessage || error, + }), AlertVariant.danger ); } @@ -76,7 +72,7 @@ HMACGeneratedModalProps) => { { onSubmit={handleSubmit(save!)} > { defaultValue={providerType} onChange={(value) => { onChange(value); - setDisplayName(value); }} data-testid="display-name-input" > @@ -169,7 +164,7 @@ HMACGeneratedModalProps) => { /> { {providerType === "hmac-generated" && ( <> { /> void; - refresh?: () => void; + providerType: string; + handleModalToggle: () => void; + refresh: () => void; open: boolean; }; @@ -44,28 +43,26 @@ JavaKeystoreModalProps) => { const { handleSubmit, control } = useForm({}); const [isEllipticCurveDropdownOpen, setIsEllipticCurveDropdownOpen] = useState(false); - const [displayName, setDisplayName] = useState(""); - const realm = useRealm(); const allComponentTypes = - serverInfo.componentTypes!["org.keycloak.keys.KeyProvider"]; + serverInfo.componentTypes?.["org.keycloak.keys.KeyProvider"] ?? []; const save = async (component: ComponentRepresentation) => { try { await adminClient.components.create({ - parentId: realm.realm, - name: displayName !== "" ? displayName : providerType, + ...component, + parentId: component.parentId, providerId: providerType, providerType: "org.keycloak.keys.KeyProvider", - ...component, }); - refresh!(); - addAlert(t("realm-settings:saveProviderSuccess"), AlertVariant.success); - handleModalToggle!(); + handleModalToggle(); + addAlert(t("saveProviderSuccess"), AlertVariant.success); + refresh(); } catch (error) { addAlert( - t("realm-settings:saveProviderError") + - error.response?.data?.errorMessage || error, + t("saveProviderError", { + error: error.response?.data?.errorMessage || error, + }), AlertVariant.danger ); } @@ -75,7 +72,7 @@ JavaKeystoreModalProps) => { { onSubmit={handleSubmit(save!)} > { defaultValue={providerType} onChange={(value) => { onChange(value); - setDisplayName(value); }} data-testid="display-name-input" > @@ -168,7 +164,7 @@ JavaKeystoreModalProps) => { /> { {providerType === "java-keystore" && ( <> { /> { /> { aria-label={t("consoleDisplayName")} onChange={(value) => { onChange([value + ""]); - setDisplayName(value); }} data-testid="select-display-name" > @@ -303,7 +298,7 @@ JavaKeystoreModalProps) => { /> { /> { aria-label={t("consoleDisplayName")} onChange={(value) => { onChange([value + ""]); - setDisplayName(value); }} data-testid="select-display-name" > diff --git a/src/realm-settings/KeysProvidersTab.tsx b/src/realm-settings/KeysProvidersTab.tsx index 21a54c1eda..59f41dfb73 100644 --- a/src/realm-settings/KeysProvidersTab.tsx +++ b/src/realm-settings/KeysProvidersTab.tsx @@ -37,7 +37,7 @@ import { useAlerts } from "../components/alert/Alerts"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import { useRealm } from "../context/realm-context/RealmContext"; import { Link, useRouteMatch } from "react-router-dom"; -import { AESGeneratedModal } from "./AESGeneratedModal"; +import { AESGeneratedModal } from "./key-providers/aes-generated/AESGeneratedModal"; import { JavaKeystoreModal } from "./JavaKeystoreModal"; import { HMACGeneratedModal } from "./HMACGeneratedModal"; import { ECDSAGeneratedModal } from "./ECDSAGeneratedModal"; @@ -369,6 +369,7 @@ export const KeysTabInner = ({ components, refresh }: KeysTabInnerProps) => { isOpen={actionListOpen[idx]} toggle={ { toggleActionList(idx); }} @@ -378,13 +379,14 @@ export const KeysTabInner = ({ components, refresh }: KeysTabInnerProps) => { { setSelectedComponent(component); toggleDeleteDialog(); toggleActionList(idx); }} > - Delete + {t("common:delete")} , ]} /> @@ -409,7 +411,7 @@ type KeysProps = { refresh: () => void; }; -export const KeysProviderTab = ({ +export const KeysProvidersTab = ({ keyProviderComponentTypes, realmComponents, refresh, diff --git a/src/realm-settings/LocalizationTab.tsx b/src/realm-settings/LocalizationTab.tsx index 50122bae4d..b1c9cd9457 100644 --- a/src/realm-settings/LocalizationTab.tsx +++ b/src/realm-settings/LocalizationTab.tsx @@ -80,7 +80,6 @@ export const LocalizationTab = ({ }); return Object.keys(result).map((key) => [key, result[key]]); } - return [[]]; }; @@ -233,7 +232,6 @@ export const LocalizationTab = ({ onSelect={(_, value) => { onChange(value as string); setValueSelected(true); - // setSelectedLocale(value as string); setKey(new Date().getTime()); setDefaultLocaleOpen(false); }} diff --git a/src/realm-settings/RSAGeneratedModal.tsx b/src/realm-settings/RSAGeneratedModal.tsx index cc4434303a..b2908fd600 100644 --- a/src/realm-settings/RSAGeneratedModal.tsx +++ b/src/realm-settings/RSAGeneratedModal.tsx @@ -21,12 +21,11 @@ import { useAlerts } from "../components/alert/Alerts"; import type ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation"; import { HelpItem } from "../components/help-enabler/HelpItem"; import { useServerInfo } from "../context/server-info/ServerInfoProvider"; -import { useRealm } from "../context/realm-context/RealmContext"; type RSAGeneratedModalProps = { - providerType?: string; - handleModalToggle?: () => void; - refresh?: () => void; + providerType: string; + handleModalToggle: () => void; + refresh: () => void; open: boolean; }; @@ -36,35 +35,33 @@ export const RSAGeneratedModal = ({ open, refresh, }: RSAGeneratedModalProps) => { - const { t } = useTranslation("groups"); + const { t } = useTranslation("realm-settings"); const serverInfo = useServerInfo(); const adminClient = useAdminClient(); const { addAlert } = useAlerts(); const { handleSubmit, control } = useForm({}); const [isKeySizeDropdownOpen, setIsKeySizeDropdownOpen] = useState(false); const [isRSAalgDropdownOpen, setIsRSAalgDropdownOpen] = useState(false); - const [displayName, setDisplayName] = useState(""); - const realm = useRealm(); const allComponentTypes = - serverInfo.componentTypes!["org.keycloak.keys.KeyProvider"]; + serverInfo.componentTypes?.["org.keycloak.keys.KeyProvider"] ?? []; const save = async (component: ComponentRepresentation) => { try { await adminClient.components.create({ - parentId: realm.realm, - name: displayName !== "" ? displayName : providerType, + ...component, + parentId: component.parentId, providerId: providerType, providerType: "org.keycloak.keys.KeyProvider", - ...component, }); - refresh!(); - addAlert(t("realm-settings:saveProviderSuccess"), AlertVariant.success); - handleModalToggle!(); + handleModalToggle(); + addAlert(t("saveProviderSuccess"), AlertVariant.success); + refresh(); } catch (error) { addAlert( - t("realm-settings:saveProviderError") + - error.response?.data?.errorMessage || error, + t("saveProviderError", { + error: error.response?.data?.errorMessage || error, + }), AlertVariant.danger ); } @@ -74,7 +71,7 @@ export const RSAGeneratedModal = ({ { onChange(value); - setDisplayName(value); }} data-testid="display-name-input" > @@ -167,7 +163,7 @@ export const RSAGeneratedModal = ({ /> void; - refresh?: () => void; + providerType: string; + handleModalToggle: () => void; + refresh: () => void; open: boolean; }; @@ -37,37 +37,50 @@ export const RSAModal = ({ open, refresh, }: RSAModalProps) => { - const { t } = useTranslation("groups"); + const { t } = useTranslation("realm-settings"); const serverInfo = useServerInfo(); const adminClient = useAdminClient(); const { addAlert } = useAlerts(); const { handleSubmit, control } = useForm({}); const [isRSAalgDropdownOpen, setIsRSAalgDropdownOpen] = useState(false); - const [displayName, setDisplayName] = useState(""); - const realm = useRealm(); + + const { id } = useParams<{ id: string }>(); const [keyFileName, setKeyFileName] = useState(""); const [certificateFileName, setCertificateFileName] = useState(""); const allComponentTypes = - serverInfo.componentTypes!["org.keycloak.keys.KeyProvider"]; + serverInfo.componentTypes?.["org.keycloak.keys.KeyProvider"] ?? []; const save = async (component: ComponentRepresentation) => { try { - await adminClient.components.create({ - parentId: realm.realm, - name: displayName !== "" ? displayName : providerType, - providerId: providerType, - providerType: "org.keycloak.keys.KeyProvider", - ...component, - }); - refresh!(); - addAlert(t("realm-settings:saveProviderSuccess"), AlertVariant.success); - handleModalToggle!(); + if (id) { + await adminClient.components.update( + { id }, + { + ...component, + parentId: component.parentId, + providerId: providerType, + providerType: "org.keycloak.keys.KeyProvider", + } + ); + addAlert(t("saveProviderSuccess"), AlertVariant.success); + } else { + await adminClient.components.create({ + ...component, + parentId: component.parentId, + providerId: providerType, + providerType: "org.keycloak.keys.KeyProvider", + }); + handleModalToggle(); + addAlert(t("saveProviderSuccess"), AlertVariant.success); + refresh(); + } } catch (error) { addAlert( - t("realm-settings:saveProviderError") + - error.response?.data?.errorMessage || error, + t("saveProviderError", { + error: error.response?.data?.errorMessage || error, + }), AlertVariant.danger ); } @@ -77,7 +90,7 @@ export const RSAModal = ({ { onChange(value); - setDisplayName(value); }} data-testid="display-name-input" > @@ -170,7 +182,7 @@ export const RSAModal = ({ /> { eventKey={1} title={{t("providers")}} > - void; + refresh?: () => void; + editMode?: boolean; + providerType: string; +}; + +export interface MatchParams { + providerType: string; +} + +export const AESGeneratedForm = ({ + editMode, + providerType, + handleModalToggle, + refresh, +}: AESGeneratedFormProps) => { + const { t } = useTranslation("realm-settings"); + const serverInfo = useServerInfo(); + const [isKeySizeDropdownOpen, setIsKeySizeDropdownOpen] = useState(false); + + const adminClient = useAdminClient(); + const { addAlert } = useAlerts(); + + const { id } = useParams<{ id: string }>(); + + const providerId = + useRouteMatch("/:providerType?")?.params.providerType; + + const save = async (component: ComponentRepresentation) => { + try { + if (id) { + await adminClient.components.update( + { id }, + { + ...component, + parentId: component.parentId, + providerId: providerType, + providerType: "org.keycloak.keys.KeyProvider", + } + ); + addAlert(t("saveProviderSuccess"), AlertVariant.success); + } else { + await adminClient.components.create({ + ...component, + parentId: component.parentId, + providerId: providerType, + providerType: "org.keycloak.keys.KeyProvider", + }); + handleModalToggle?.(); + addAlert(t("saveProviderSuccess"), AlertVariant.success); + refresh?.(); + } + } catch (error) { + addAlert( + t("saveProviderError", { + error: error.response?.data?.errorMessage || error, + }), + AlertVariant.danger + ); + } + }; + + const form = useForm({ mode: "onChange" }); + + const setupForm = (component: ComponentRepresentation) => { + form.reset(); + Object.entries(component).map(([key, value]) => { + if ( + key === "config" && + component.config?.secretSize && + component.config?.active + ) { + form.setValue("config.secretSize", value.secretSize[0]); + + form.setValue("config.active", value.active[0]); + + convertToFormValues(value, "config", form.setValue); + } + form.setValue(key, value); + }); + }; + + useFetch( + async () => { + if (editMode) return await adminClient.components.findOne({ id: id }); + }, + (result) => { + if (result) { + setupForm(result); + } + }, + [] + ); + + const allComponentTypes = + serverInfo.componentTypes?.["org.keycloak.keys.KeyProvider"] ?? []; + + const aesSecretSizeOptions = allComponentTypes[0].properties[3].options; + + return ( + + {editMode && ( + + } + fieldId="id" + isRequired + validated={ + form.errors.name ? ValidatedOptions.error : ValidatedOptions.default + } + helperTextInvalid={t("common:required")} + > + + + )} + + } + fieldId="name" + isRequired + validated={ + form.errors.name ? ValidatedOptions.error : ValidatedOptions.default + } + helperTextInvalid={t("common:required")} + > + {!editMode && ( + { + return ( + onChange(value)} + data-testid="display-name-input" + /> + ); + }} + /> + )} + {editMode && ( + <> + + + )} + + + } + > + ( + { + onChange([value.toString()]); + }} + /> + )} + /> + + + } + > + { + return ( + { + onChange([value.toString()]); + }} + /> + ); + }} + /> + + + } + > + ( + + )} + /> + + + + + + + ); +}; + +export const AESGeneratedSettings = () => { + const { t } = useTranslation("realm-settings"); + const providerId = useRouteMatch( + "/:realm/realm-settings/keys/:id?/:providerType?/settings" + )?.params.providerType; + return ( + <> + + + + + + ); +}; diff --git a/src/realm-settings/key-providers/aes-generated/AESGeneratedModal.tsx b/src/realm-settings/key-providers/aes-generated/AESGeneratedModal.tsx new file mode 100644 index 0000000000..e6f44dc14e --- /dev/null +++ b/src/realm-settings/key-providers/aes-generated/AESGeneratedModal.tsx @@ -0,0 +1,36 @@ +import React from "react"; +import { Modal, ModalVariant } from "@patternfly/react-core"; +import { useTranslation } from "react-i18next"; +import { AESGeneratedForm } from "./AESGeneratedForm"; + +type AESGeneratedModalProps = { + providerType: string; + handleModalToggle: () => void; + refresh: () => void; + open: boolean; +}; + +export const AESGeneratedModal = ({ + providerType, + handleModalToggle, + open, + refresh, +}: AESGeneratedModalProps) => { + const { t } = useTranslation("realm-settings"); + + return ( + + + + ); +}; diff --git a/src/route-config.ts b/src/route-config.ts index 032e9d860e..dab4a5def1 100644 --- a/src/route-config.ts +++ b/src/route-config.ts @@ -36,6 +36,7 @@ import { } from "./identity-providers/add/AddIdentityProvider"; import { AddOpenIdConnect } from "./identity-providers/add/AddOpenIdConnect"; import { DetailSettings } from "./identity-providers/add/DetailSettings"; +import { AESGeneratedSettings } from "./realm-settings/key-providers/aes-generated/AESGeneratedForm"; export type RouteDef = BreadcrumbsRoute & { access: AccessType; @@ -183,6 +184,12 @@ export const routes: RoutesFn = (t: TFunction) => [ breadcrumb: t("realmSettings"), access: "view-realm", }, + { + path: "/:realm/realm-settings/keys/:id?/aes-generated/settings", + component: AESGeneratedSettings, + breadcrumb: t("realm-settings:editProvider"), + access: "view-realm", + }, { path: "/:realm/authentication", component: AuthenticationSection,