From ed0949a44f4cf7e24bb3b0bc3629988c43752cbb Mon Sep 17 00:00:00 2001 From: Jon Koops Date: Fri, 1 Oct 2021 16:36:36 +0200 Subject: [PATCH] Add a human readable name for client protocol (#1283) --- .../manage/clients/CreateClientPage.ts | 2 +- src/client-scopes/details/ScopeForm.tsx | 7 ++++++- src/clients/ClientDetails.tsx | 15 ++++++++------- src/clients/ClientsSection.tsx | 9 +++++++-- src/clients/add/GeneralSettings.tsx | 6 +++++- src/clients/help.ts | 4 ++-- src/clients/messages.ts | 6 +++++- src/clients/utils.ts | 15 +++++++++++++++ 8 files changed, 49 insertions(+), 15 deletions(-) diff --git a/cypress/support/pages/admin_console/manage/clients/CreateClientPage.ts b/cypress/support/pages/admin_console/manage/clients/CreateClientPage.ts index 159f068ee3..95cd98535a 100644 --- a/cypress/support/pages/admin_console/manage/clients/CreateClientPage.ts +++ b/cypress/support/pages/admin_console/manage/clients/CreateClientPage.ts @@ -41,7 +41,7 @@ export default class CreateClientPage { //#region General Settings selectClientType(clientType: string) { cy.get(this.clientTypeDrpDwn).click(); - cy.get(this.clientTypeList).contains(clientType).click(); + cy.get(this.clientTypeList).findByTestId(`option-${clientType}`).click(); return this; } diff --git a/src/client-scopes/details/ScopeForm.tsx b/src/client-scopes/details/ScopeForm.tsx index 203f778680..ae65dbd6d6 100644 --- a/src/client-scopes/details/ScopeForm.tsx +++ b/src/client-scopes/details/ScopeForm.tsx @@ -27,6 +27,7 @@ import { HelpItem } from "../../components/help-enabler/HelpItem"; import { useLoginProviders } from "../../context/server-info/ServerInfoProvider"; import { convertToFormValues } from "../../util"; import { useRealm } from "../../context/realm-context/RealmContext"; +import { getProtocolName } from "../../clients/utils"; type ScopeFormProps = { clientScope: ClientScopeRepresentation; @@ -35,6 +36,7 @@ type ScopeFormProps = { export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => { const { t } = useTranslation("client-scopes"); + const { t: tc } = useTranslation("clients"); const { register, control, handleSubmit, errors, setValue } = useForm({ defaultValues: { attributes: { "display-on-consent-screen": "true" } }, @@ -186,7 +188,10 @@ export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => { selected={option === value} key={option} value={option} - /> + data-testid={`option-${option}`} + > + {getProtocolName(tc, option)} + ))} )} diff --git a/src/clients/ClientDetails.tsx b/src/clients/ClientDetails.tsx index a6e38ab69f..7ee88b28c5 100644 --- a/src/clients/ClientDetails.tsx +++ b/src/clients/ClientDetails.tsx @@ -52,7 +52,7 @@ import { toClients } from "./routes/Clients"; import { ClientScopes } from "./scopes/ClientScopes"; import { EvaluateScopes } from "./scopes/EvaluateScopes"; import { ServiceAccount } from "./service-account/ServiceAccount"; -import { isRealmClient } from "./utils"; +import { isRealmClient, getProtocolName } from "./utils"; type ClientDetailHeaderProps = { onChange: (value: boolean) => void; @@ -83,9 +83,10 @@ const ClientDetailHeader = ({ }); const badges = useMemo(() => { - if (!client.protocol) { - return []; - } + const protocolName = getProtocolName( + t, + client.protocol ?? "openid-connect" + ); const text = client.bearerOnly ? ( } > - {client.protocol} + {protocolName} ) : ( - + ); return [{ text }]; - }, [client]); + }, [client, t]); const dropdownItems = [ toggleDownloadDialog()}> diff --git a/src/clients/ClientsSection.tsx b/src/clients/ClientsSection.tsx index fcaf4d9fdb..c5886cfb54 100644 --- a/src/clients/ClientsSection.tsx +++ b/src/clients/ClientsSection.tsx @@ -29,7 +29,7 @@ import { InitialAccessTokenList } from "./initial-access/InitialAccessTokenList" import { toAddClient } from "./routes/AddClient"; import { toClient } from "./routes/Client"; import { toImportClient } from "./routes/ImportClient"; -import { isRealmClient } from "./utils"; +import { isRealmClient, getProtocolName } from "./utils"; export const ClientsSection = () => { const { t } = useTranslation("clients"); @@ -166,7 +166,12 @@ export const ClientsSection = () => { displayKey: "common:clientId", cellRenderer: ClientDetailLink, }, - { name: "protocol", displayKey: "common:type" }, + { + name: "protocol", + displayKey: "common:type", + cellRenderer: (client) => + getProtocolName(t, client.protocol ?? "openid-connect"), + }, { name: "description", displayKey: "common:description", diff --git a/src/clients/add/GeneralSettings.tsx b/src/clients/add/GeneralSettings.tsx index 913fd92d33..aa1b0abc56 100644 --- a/src/clients/add/GeneralSettings.tsx +++ b/src/clients/add/GeneralSettings.tsx @@ -12,6 +12,7 @@ import { useLoginProviders } from "../../context/server-info/ServerInfoProvider" import { ClientDescription } from "../ClientDescription"; import { FormAccess } from "../../components/form-access/FormAccess"; import { HelpItem } from "../../components/help-enabler/HelpItem"; +import { getProtocolName } from "../utils"; export const GeneralSettings = () => { const { t } = useTranslation("clients"); @@ -56,7 +57,10 @@ export const GeneralSettings = () => { selected={option === value} key={option} value={option} - /> + data-testid={`option-${option}`} + > + {getProtocolName(t, option)} + ))} )} diff --git a/src/clients/help.ts b/src/clients/help.ts index 334b228f08..ffd2907b26 100644 --- a/src/clients/help.ts +++ b/src/clients/help.ts @@ -3,7 +3,7 @@ export default { enableDisable: "Disabled clients cannot initiate a login or have obtained access tokens.", clientType: - "'OpenID connect' allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server.'SAML' enables web-based authentication and authorization scenarios including cross-domain single sign-on (SSO) and uses security tokens containing assertions to pass information.", + "'OpenID Connect' allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server.'SAML' enables web-based authentication and authorization scenarios including cross-domain single sign-on (SSO) and uses security tokens containing assertions to pass information.", serviceAccount: "Allows you to authenticate this client to Keycloak and retrieve access token dedicated to this client. In terms of OAuth2 specification, this enables support of 'Client Credentials Grant' for this client.", authentication: @@ -68,7 +68,7 @@ export default { nodeReRegistrationTimeout: "Interval to specify max time for registered clients cluster nodes to re-register. If cluster node will not send re-registration request to Keycloak within this time, it will be unregistered from Keycloak", fineGrainOpenIdConnectConfiguration: - "This section is used to configure advanced settings of this client related to OpenID connect protocol.", + "This section is used to configure advanced settings of this client related to OpenID Connect protocol.", fineGrainSamlEndpointConfig: "This section to configure exact URLs for Assertion Consumer and Single Logout Service.", accessTokenSignatureAlgorithm: diff --git a/src/clients/messages.ts b/src/clients/messages.ts index fe38b80269..b6df40f8c5 100644 --- a/src/clients/messages.ts +++ b/src/clients/messages.ts @@ -1,5 +1,9 @@ export default { clients: { + protocol: { + openIdConnect: "OpenID Connect", + saml: "SAML", + }, clientType: "Client type", clientAuthorization: "Authorization", implicitFlow: "Implicit flow", @@ -193,7 +197,7 @@ export default { testClusterAvailability: "Test cluster availability", registerNodeManually: "Register node manually", fineGrainOpenIdConnectConfiguration: - "Fine grain OpenID connect configuration", + "Fine grain OpenID Connect configuration", fineGrainSamlEndpointConfig: "Fine Grain SAML Endpoint Configuration", accessTokenSignatureAlgorithm: "Access token signature algorithm", idTokenSignatureAlgorithm: "ID token signature algorithm", diff --git a/src/clients/utils.ts b/src/clients/utils.ts index 7fae296d7a..3a48759ca6 100644 --- a/src/clients/utils.ts +++ b/src/clients/utils.ts @@ -1,6 +1,21 @@ import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation"; +import type { TFunction } from "react-i18next"; /** * Checks if a client is intended to be used for authenticating a to a realm. */ export const isRealmClient = (client: ClientRepresentation) => !client.protocol; + +/** + * Gets a human readable name for the specified protocol. + */ +export const getProtocolName = (t: TFunction<"clients">, protocol: string) => { + switch (protocol) { + case "openid-connect": + return t("clients:protocol:openIdConnect"); + case "saml": + return t("clients:protocol:saml"); + } + + return protocol; +};