Add a human readable name for client protocol (#1283)

This commit is contained in:
Jon Koops 2021-10-01 16:36:36 +02:00 committed by GitHub
parent eb40cabf03
commit ed0949a44f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 49 additions and 15 deletions

View file

@ -41,7 +41,7 @@ export default class CreateClientPage {
//#region General Settings //#region General Settings
selectClientType(clientType: string) { selectClientType(clientType: string) {
cy.get(this.clientTypeDrpDwn).click(); cy.get(this.clientTypeDrpDwn).click();
cy.get(this.clientTypeList).contains(clientType).click(); cy.get(this.clientTypeList).findByTestId(`option-${clientType}`).click();
return this; return this;
} }

View file

@ -27,6 +27,7 @@ import { HelpItem } from "../../components/help-enabler/HelpItem";
import { useLoginProviders } from "../../context/server-info/ServerInfoProvider"; import { useLoginProviders } from "../../context/server-info/ServerInfoProvider";
import { convertToFormValues } from "../../util"; import { convertToFormValues } from "../../util";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
import { getProtocolName } from "../../clients/utils";
type ScopeFormProps = { type ScopeFormProps = {
clientScope: ClientScopeRepresentation; clientScope: ClientScopeRepresentation;
@ -35,6 +36,7 @@ type ScopeFormProps = {
export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => { export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => {
const { t } = useTranslation("client-scopes"); const { t } = useTranslation("client-scopes");
const { t: tc } = useTranslation("clients");
const { register, control, handleSubmit, errors, setValue } = const { register, control, handleSubmit, errors, setValue } =
useForm<ClientScopeRepresentation>({ useForm<ClientScopeRepresentation>({
defaultValues: { attributes: { "display-on-consent-screen": "true" } }, defaultValues: { attributes: { "display-on-consent-screen": "true" } },
@ -186,7 +188,10 @@ export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => {
selected={option === value} selected={option === value}
key={option} key={option}
value={option} value={option}
/> data-testid={`option-${option}`}
>
{getProtocolName(tc, option)}
</SelectOption>
))} ))}
</Select> </Select>
)} )}

View file

@ -52,7 +52,7 @@ import { toClients } from "./routes/Clients";
import { ClientScopes } from "./scopes/ClientScopes"; import { ClientScopes } from "./scopes/ClientScopes";
import { EvaluateScopes } from "./scopes/EvaluateScopes"; import { EvaluateScopes } from "./scopes/EvaluateScopes";
import { ServiceAccount } from "./service-account/ServiceAccount"; import { ServiceAccount } from "./service-account/ServiceAccount";
import { isRealmClient } from "./utils"; import { isRealmClient, getProtocolName } from "./utils";
type ClientDetailHeaderProps = { type ClientDetailHeaderProps = {
onChange: (value: boolean) => void; onChange: (value: boolean) => void;
@ -83,9 +83,10 @@ const ClientDetailHeader = ({
}); });
const badges = useMemo<ViewHeaderBadge[]>(() => { const badges = useMemo<ViewHeaderBadge[]>(() => {
if (!client.protocol) { const protocolName = getProtocolName(
return []; t,
} client.protocol ?? "openid-connect"
);
const text = client.bearerOnly ? ( const text = client.bearerOnly ? (
<Tooltip <Tooltip
@ -96,15 +97,15 @@ const ClientDetailHeader = ({
data-testid="bearer-only-explainer-label" data-testid="bearer-only-explainer-label"
icon={<InfoCircleIcon />} icon={<InfoCircleIcon />}
> >
{client.protocol} {protocolName}
</Label> </Label>
</Tooltip> </Tooltip>
) : ( ) : (
<Label>{client.protocol}</Label> <Label>{protocolName}</Label>
); );
return [{ text }]; return [{ text }];
}, [client]); }, [client, t]);
const dropdownItems = [ const dropdownItems = [
<DropdownItem key="download" onClick={() => toggleDownloadDialog()}> <DropdownItem key="download" onClick={() => toggleDownloadDialog()}>

View file

@ -29,7 +29,7 @@ import { InitialAccessTokenList } from "./initial-access/InitialAccessTokenList"
import { toAddClient } from "./routes/AddClient"; import { toAddClient } from "./routes/AddClient";
import { toClient } from "./routes/Client"; import { toClient } from "./routes/Client";
import { toImportClient } from "./routes/ImportClient"; import { toImportClient } from "./routes/ImportClient";
import { isRealmClient } from "./utils"; import { isRealmClient, getProtocolName } from "./utils";
export const ClientsSection = () => { export const ClientsSection = () => {
const { t } = useTranslation("clients"); const { t } = useTranslation("clients");
@ -166,7 +166,12 @@ export const ClientsSection = () => {
displayKey: "common:clientId", displayKey: "common:clientId",
cellRenderer: ClientDetailLink, cellRenderer: ClientDetailLink,
}, },
{ name: "protocol", displayKey: "common:type" }, {
name: "protocol",
displayKey: "common:type",
cellRenderer: (client) =>
getProtocolName(t, client.protocol ?? "openid-connect"),
},
{ {
name: "description", name: "description",
displayKey: "common:description", displayKey: "common:description",

View file

@ -12,6 +12,7 @@ import { useLoginProviders } from "../../context/server-info/ServerInfoProvider"
import { ClientDescription } from "../ClientDescription"; import { ClientDescription } from "../ClientDescription";
import { FormAccess } from "../../components/form-access/FormAccess"; import { FormAccess } from "../../components/form-access/FormAccess";
import { HelpItem } from "../../components/help-enabler/HelpItem"; import { HelpItem } from "../../components/help-enabler/HelpItem";
import { getProtocolName } from "../utils";
export const GeneralSettings = () => { export const GeneralSettings = () => {
const { t } = useTranslation("clients"); const { t } = useTranslation("clients");
@ -56,7 +57,10 @@ export const GeneralSettings = () => {
selected={option === value} selected={option === value}
key={option} key={option}
value={option} value={option}
/> data-testid={`option-${option}`}
>
{getProtocolName(t, option)}
</SelectOption>
))} ))}
</Select> </Select>
)} )}

View file

@ -3,7 +3,7 @@ export default {
enableDisable: enableDisable:
"Disabled clients cannot initiate a login or have obtained access tokens.", "Disabled clients cannot initiate a login or have obtained access tokens.",
clientType: 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: 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.", "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: authentication:
@ -68,7 +68,7 @@ export default {
nodeReRegistrationTimeout: 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", "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: 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: fineGrainSamlEndpointConfig:
"This section to configure exact URLs for Assertion Consumer and Single Logout Service.", "This section to configure exact URLs for Assertion Consumer and Single Logout Service.",
accessTokenSignatureAlgorithm: accessTokenSignatureAlgorithm:

View file

@ -1,5 +1,9 @@
export default { export default {
clients: { clients: {
protocol: {
openIdConnect: "OpenID Connect",
saml: "SAML",
},
clientType: "Client type", clientType: "Client type",
clientAuthorization: "Authorization", clientAuthorization: "Authorization",
implicitFlow: "Implicit flow", implicitFlow: "Implicit flow",
@ -193,7 +197,7 @@ export default {
testClusterAvailability: "Test cluster availability", testClusterAvailability: "Test cluster availability",
registerNodeManually: "Register node manually", registerNodeManually: "Register node manually",
fineGrainOpenIdConnectConfiguration: fineGrainOpenIdConnectConfiguration:
"Fine grain OpenID connect configuration", "Fine grain OpenID Connect configuration",
fineGrainSamlEndpointConfig: "Fine Grain SAML Endpoint Configuration", fineGrainSamlEndpointConfig: "Fine Grain SAML Endpoint Configuration",
accessTokenSignatureAlgorithm: "Access token signature algorithm", accessTokenSignatureAlgorithm: "Access token signature algorithm",
idTokenSignatureAlgorithm: "ID token signature algorithm", idTokenSignatureAlgorithm: "ID token signature algorithm",

View file

@ -1,6 +1,21 @@
import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation"; 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. * Checks if a client is intended to be used for authenticating a to a realm.
*/ */
export const isRealmClient = (client: ClientRepresentation) => !client.protocol; 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;
};