From 5f84b04ef5a42219cb44a64987c6d87ea27fc030 Mon Sep 17 00:00:00 2001 From: Erik Jan de Wit Date: Thu, 22 Jan 2026 17:24:30 +0100 Subject: [PATCH] use helptext field from condition instead of message bundle Also removed some duplictate state fixes: #45586 Signed-off-by: Erik Jan de Wit Signed-off-by: Alexander Schwartz Co-authored-by: Alexander Schwartz --- .../admin/messages/messages_en.properties | 13 ------- .../NewClientPolicyCondition.tsx | 35 +++++-------------- 2 files changed, 8 insertions(+), 40 deletions(-) diff --git a/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties b/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties index d485f2f01a0..8087aff30b9 100644 --- a/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties +++ b/js/apps/admin-ui/maven-resources/theme/keycloak.v2/admin/messages/messages_en.properties @@ -220,7 +220,6 @@ diagramView=Diagram view removeImportedUsers=Remove imported users? accountLinkingOnly=Account linking only clientPoliciesPoliciesHelpText=Client Policy allows binding client profiles with various conditions to specify when enforced behavior is specified by executors of the particular client profile. -anyClient=The condition is satisfied by any client on any event. editFlow=Edit flow noDefaultGroupsInstructions=Default groups allow you to automatically assign group membership whenever any new user is created or imported throughout <1>identity brokering. Add default groups to get started. tokenSaveSuccess=New initial access token has been created @@ -437,7 +436,6 @@ logoutServiceRedirectBindingURL=Logout Service Redirect Binding URL createIdentityProviderSuccess=Identity provider successfully created emptyMappersInstructions=If you want to add mappers, please click the button below to add some predefined mappers or to configure a new mapper. dayMonth=Day -clientRolesHelp=The condition checks whether one of the specified client roles exists on the client to determine whether the policy is applied. This condition effectively allows the client administrator to create a client role of a specified name on the client to make sure that particular client policy will be applied on requests of this client. The condition is checked during most OpenID Connect requests (Authorization requests, token requests, introspection endpoint request, and so on). validatingX509Certs=Validating X509 certificates eventTypes.CLIENT_UPDATE.description=Client update searchInitialAccessToken=Search token @@ -503,7 +501,6 @@ unlock=Unlock validateRealm=You must enter a realm attributeValue=Attribute Value eventTypes.CLIENT_DELETE_ERROR.description=Client delete error -clientScopesHelp=It uses the scopes requested or assigned in advance to the client to determine whether the policy is applied to this client. Condition is evaluated during OpenID Connect authorization request and/or token request. revokeRefreshToken=Revoke Refresh Token mappingUpdatedSuccess=Mapping successfully updated logoUrlHelp=URL that references a logo for the Client application @@ -1279,7 +1276,6 @@ publicKey=Public key emptyEventsInstructions=There are no more events types left to add periodicFullSync=Periodic full sync removeConfirmTitle_other=Remove groups? -clientAccesstypeTooltip=Access Type of the client, for which the condition will be applied. emptyBuiltInMappersInstructions=All built in mappers were added to this client assertionLifespanHelp=Lifespan set in the SAML assertion conditions. After that time the assertion will be invalid. The "SessionNotOnOrAfter" attribute is not modified and continue using the "SSO Session Max" time defined at realm level. noTokensInstructions=You haven't created any initial access tokens. Create an initial access token by clicking "Create". @@ -1629,7 +1625,6 @@ signOut=Sign out deleteExecutorError=Could not delete executor\: {{error}} userProfileError=Could not update user profile settings\: {{error}} validatorDialogColNames.colName=Role name -clientUpdaterSourceRolesTooltip=The condition is checked during client registration or update requests; it evaluates to true if the entity (usually a user) is creating or updating a client that belongs to the specified role. To reference the realm role, you can use a realm role name such as 'my_realm_role'. To reference a client role, you can use the client_id.role_name; for example, 'my_client.my_client_role' refers to the client role 'my_client_role' of client 'my_client'. UPDATE_PASSWORD=Update password (UPDATE_PASSWORD) version=Version synchronizationSettings=Synchronization settings @@ -1743,7 +1738,6 @@ saveProviderError=Error saving provider\: {{error}} port=Port searchForPermission=Search for permission ldapFilterHelp=LDAP Filter adds an additional custom filter to the whole query for retrieve LDAP groups. Leave this empty if no additional filtering is needed and you want to retrieve all groups from LDAP. Otherwise make sure that filter starts with '(' and ends with ')'. -clientUpdaterSourceGroupsTooltip=Name of groups to check. The condition evaluates to true if the entity, who creates or updates client, is a member of one or more of the specified groups. The configured groups are specified by their simple name, which must match the name of the Keycloak group. No support for group hierarchy is used here. addRequestUri=Add valid request URIs selectACondition=Select a condition ldapAttributeValue=LDAP attribute value @@ -1938,7 +1932,6 @@ Sunday=Sunday editMode=Edit mode updatePasswordPolicySuccess=Password policies successfully updated passwordHelp=SMTP password. This field is able to obtain its value from vault, use ${vault.ID} format. -clientUpdaterContext=The condition checks the context of how the client is created or updated to determine whether the policy is applied. For example, it checks if the client is created with admin REST API or OIDC dynamic client registration. For the latter case, it checks if it is an ANONYMOUS client registration or an AUTHENTICATED client registration with Initial access token or Registration access token and so on. removedGroupMembership=Removed group membership deleteScopeWarning=The permissions below will be removed when they are no longer used by other authorization scopes\: compositeRoleOff=Composite role turned off @@ -2134,7 +2127,6 @@ backchannelLogoutUrl=Backchannel logout URL requestObjectEncodingHelp=JWE algorithm, which the client needs to use when encrypting the content of the OIDC request object specified by the 'request' or 'request_uri' parameters. If set to 'any', any algorithm is allowed. minimumQuickLoginWaitSeconds=Minimum quick login wait duplicate=Duplicate -clientAccesstype=Client Access Type roleDeleteConfirm=Delete role? createClientProfileNameHelperText=The name must be unique within the realm disabledHelp=A disabled user cannot log in. @@ -2324,7 +2316,6 @@ roleImportError=Could not import role regexAttributeValuesHelp=If enabled, attribute values are interpreted as regular expressions. userCreated=The user has been created residentKey.not\ specified=Not specified -clientUpdaterSourceHost=The condition checks the host/domain of the entity who tries to create/update the client to determine whether the policy is applied. alwaysReadValueFromLdapHelp=If on, then during reading of the LDAP attribute value will always be used instead of the value from Keycloak database. usermodel.clientRoleMapping.tokenClaimName.tooltip=Name of the claim to insert into the token. This can be a fully qualified name such as 'address.street'. In this case, a nested JSON object is created. To prevent nesting and to use the dot literally, escape the dot with a backslash (\\.). You can use the special token ${client_id}; it will be replaced by the actual client ID. An example usage is 'resource_access.${client_id}.roles'. This option is especially useful when you add roles from all the clients, meaning 'Client ID' is disabled, and you want client roles of each client stored separately. scopePermissions.clients.map-roles-description=Policies that decide if an administrator can map roles defined by this client @@ -2459,7 +2450,6 @@ eventTypes.REGISTER_NODE.name=Register node addToFilter=Add to filter CONFIGURE_TOTP=Configure OTP (CONFIGURE_TOTP) eventTypes.EXECUTE_ACTIONS.description=Execute actions -clientUpdaterSourceRolesHelp=The condition checks the role of the entity who tries to create/update the client to determine whether the policy is applied. userModelAttributeName=User model attribute name importResourceError=Could not import the resource due to {{error}} dynamicScope=Dynamic scope @@ -2549,7 +2539,6 @@ fullNameLdapWriteOnlyHelp=For Write-only, data is propagated to LDAP when a user userFedDeleteError=Could not delete user federation provider\: '{{error}}' id=ID join=Join -clientUpdaterSourceGroupsHelp=The condition checks the group of the entity who tries to create/update the client to determine whether the policy is applied. idTokenEncryptionContentEncryptionAlgorithmHelp=JWA Algorithm used for content encryption in encrypting ID tokens. This option is needed just if you want encrypted ID tokens. If left empty, ID Tokens are just signed, but not encrypted. idTokenAsDetachedSignatureHelp=This makes ID token returned from Authorization Endpoint in OIDC Hybrid flow use as a detached signature defined in FAPI 1.0 Advanced Security Profile. Therefore, this ID token does not include an authenticated user's information. messageBundleDescription=You can only edit the supported locales. If you haven't selected supported locales yet, you can only edit the English locale. @@ -2575,7 +2564,6 @@ deleteConfirmTitle_other=Delete groups? profilesConfigTypes.jsonEditor=JSON editor testingConnection=Testing connection noUsersFoundError=No users found due to {{error}} -clientUpdaterSourceGroups=Groups executorDetails=Executor details maxDeltaTimeSeconds=Failure reset time backchannelLogoutHelp=Does the external IDP support backchannel logout? @@ -2852,7 +2840,6 @@ searchScope=Search scope dateFrom=Date(from) importAdded_one=One record added. clientAccessType=It uses the client's access type (confidential, public, bearer-only) to determine whether the policy is applied. Condition is checked during most of OpenID Connect requests (Authorization requests, token requests, introspection endpoint request, etc.). Confidential client has enabled client authentication when public client has disabled client authentication. Bearer-only is a deprecated client type. -identityProviderAlias=Condition that checks the Identity Provider that is involved in the client request. Only applies to operations in which an IdP is involved (for example JWT Authorization grant). firstName=First name emptySecondaryAction=Configure a new mapper defaultGroupAdded_one=New group added to the default groups diff --git a/js/apps/admin-ui/src/realm-settings/NewClientPolicyCondition.tsx b/js/apps/admin-ui/src/realm-settings/NewClientPolicyCondition.tsx index b27b16db5f4..d6c8c7ce31c 100644 --- a/js/apps/admin-ui/src/realm-settings/NewClientPolicyCondition.tsx +++ b/js/apps/admin-ui/src/realm-settings/NewClientPolicyCondition.tsx @@ -17,7 +17,6 @@ import { PageSection, SelectOption, } from "@patternfly/react-core"; -import { camelCase } from "lodash-es"; import { useState } from "react"; import { Controller, FormProvider, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; @@ -50,15 +49,10 @@ export default function NewClientPolicyCondition() { const [isGlobalPolicy, setIsGlobalPolicy] = useState(false); const [policies, setPolicies] = useState([]); - const [condition, setCondition] = useState< - ClientPolicyConditionRepresentation[] - >([]); const [conditionData, setConditionData] = useState(); const [conditionType, setConditionType] = useState(""); - const [conditionProperties, setConditionProperties] = useState< - ConfigPropertyRepresentation[] - >([]); + const [condition, setCondition] = useState(); const { policyName, conditionName } = useParams(); @@ -104,7 +98,7 @@ export default function NewClientPolicyCondition() { ); setConditionData(typeAndConfigData!); - setConditionProperties(currentCondition?.properties!); + setCondition(currentCondition); setupForm(typeAndConfigData!); } }, @@ -115,7 +109,7 @@ export default function NewClientPolicyCondition() { const configValues = configPolicy.config; const writeConfig = () => { - return conditionProperties.reduce((r: any, p) => { + return condition?.properties.reduce((r: any, p) => { r[p.name!] = configValues[p.name!]; return r; }, {}); @@ -155,7 +149,7 @@ export default function NewClientPolicyCondition() { } conditions = conditions.concat({ - condition: condition[0].condition, + condition: condition!.id, configuration: writeConfig(), }); @@ -207,11 +201,7 @@ export default function NewClientPolicyCondition() { fieldId="conditionType" labelIcon={ } @@ -230,15 +220,8 @@ export default function NewClientPolicyCondition() { onToggle={(toggle) => setOpenConditionType(toggle)} onSelect={(value) => { field.onChange(value); - setConditionProperties( - (value as ComponentTypeRepresentation).properties, - ); + setCondition(value as ComponentTypeRepresentation); setConditionType((value as ComponentTypeRepresentation).id); - setCondition([ - { - condition: (value as ComponentTypeRepresentation).id, - }, - ]); setOpenConditionType(false); }} selections={conditionName ? conditionName : conditionType} @@ -250,9 +233,7 @@ export default function NewClientPolicyCondition() { @@ -265,7 +246,7 @@ export default function NewClientPolicyCondition() { - + {!isGlobalPolicy && (