All Downloads are FREE. Search and download functionalities are using the official Maven repository.

theme.keycloak.v2.admin.resources.assets.ClientDetails-5c5hG1Sr.js.map Maven / Gradle / Ivy

There is a newer version: 26.0.7
Show newest version
{"version":3,"file":"ClientDetails-5c5hG1Sr.js","sources":["../../../../../node_modules/.pnpm/@[email protected]/node_modules/@patternfly/react-styles/css/components/CodeBlock/code-block.mjs","../../../../../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@patternfly/react-core/dist/esm/components/CodeBlock/CodeBlock.js","../../../../../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@patternfly/react-core/dist/esm/components/CodeBlock/CodeBlockAction.js","../../../../../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@patternfly/react-core/dist/esm/components/Panel/PanelHeader.js","../../../../../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@patternfly/react-core/dist/esm/components/Text/TextList.js","../../../../../node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules/@patternfly/react-core/dist/esm/components/Text/TextListItem.js","../../src/components/download-dialog/DownloadDialog.tsx","../../src/clients/advanced/TokenLifespan.tsx","../../src/clients/advanced/AdvancedSettings.tsx","../../src/clients/advanced/AuthenticationOverrides.tsx","../../src/components/time-selector/TimeSelectorForm.tsx","../../src/clients/advanced/AddHostDialog.tsx","../../src/clients/advanced/ClusteringPanel.tsx","../../src/clients/advanced/ApplicationUrls.tsx","../../src/clients/advanced/FineGrainOpenIdConnect.tsx","../../src/clients/advanced/FineGrainSamlEndpointConfig.tsx","../../src/clients/advanced/OpenIdConnectCompatibilityModes.tsx","../../src/clients/AdvancedTab.tsx","../../src/clients/ClientSessions.tsx","../../src/clients/add/AccessSettings.tsx","../../src/clients/add/LoginSettingsPanel.tsx","../../src/clients/add/LogoutPanel.tsx","../../src/clients/add/SamlConfig.tsx","../../src/clients/add/SamlSignature.tsx","../../src/clients/ClientSettings.tsx","../../src/clients/authorization/KeyBasedAttributeInput.tsx","../../src/clients/authorization/AuthorizationDataModal.tsx","../../src/clients/authorization/AuthorizationEvaluateResourcePolicies.tsx","../../src/clients/authorization/AuthorizationEvaluateResource.tsx","../../src/clients/authorization/evaluate/Results.tsx","../../src/clients/authorization/AuthorizationEvaluate.tsx","../../src/clients/authorization/AuthorizationExport.tsx","../../src/clients/authorization/DetailDescription.tsx","../../src/clients/authorization/EmptyPermissionsState.tsx","../../src/clients/authorization/MoreLabel.tsx","../../src/clients/authorization/SearchDropdown.tsx","../../src/clients/authorization/Permissions.tsx","../../src/clients/authorization/Policies.tsx","../../src/clients/authorization/DetailCell.tsx","../../src/clients/authorization/Resources.tsx","../../src/clients/authorization/Scopes.tsx","../../src/clients/authorization/ImportDialog.tsx","../../src/clients/authorization/Settings.tsx","../../src/utils/useQueryPermission.ts","../../src/clients/scopes/CopyToClipboardButton.tsx","../../src/clients/credentials/ClientSecret.tsx","../../src/clients/credentials/SignedJWT.tsx","../../src/clients/credentials/X509.tsx","../../src/clients/credentials/Credentials.tsx","../../src/clients/keys/Certificate.tsx","../../src/clients/keys/StoreSettings.tsx","../../src/clients/keys/GenerateKeyDialog.tsx","../../src/clients/keys/ImportKeyDialog.tsx","../../src/clients/keys/Keys.tsx","../../src/clients/keys/ExportSamlKeyDialog.tsx","../../src/clients/keys/SamlKeysDialog.tsx","../../src/clients/keys/SamlImportKeyDialog.tsx","../../src/clients/keys/SamlKeys.tsx","../../src/clients/scopes/ClientScopes.tsx","../../src/clients/scopes/GeneratedCodeTab.tsx","../../src/clients/scopes/EvaluateScopes.tsx","../../src/clients/service-account/ServiceAccount.tsx","../../src/clients/ClientDetails.tsx"],"sourcesContent":["import './code-block.css';\nexport default {\n  \"codeBlock\": \"pf-v5-c-code-block\",\n  \"codeBlockActions\": \"pf-v5-c-code-block__actions\",\n  \"codeBlockCode\": \"pf-v5-c-code-block__code\",\n  \"codeBlockContent\": \"pf-v5-c-code-block__content\",\n  \"codeBlockHeader\": \"pf-v5-c-code-block__header\",\n  \"codeBlockPre\": \"pf-v5-c-code-block__pre\"\n};","import { __rest } from \"tslib\";\nimport * as React from 'react';\nimport styles from '@patternfly/react-styles/css/components/CodeBlock/code-block.mjs';\nimport { css } from '@patternfly/react-styles';\nexport const CodeBlock = (_a) => {\n    var { children = null, className, actions = null } = _a, props = __rest(_a, [\"children\", \"className\", \"actions\"]);\n    return (React.createElement(\"div\", Object.assign({ className: css(styles.codeBlock, className) }, props),\n        actions && (React.createElement(\"div\", { className: css(styles.codeBlockHeader) },\n            React.createElement(\"div\", { className: css(styles.codeBlockActions) }, actions))),\n        React.createElement(\"div\", { className: css(styles.codeBlockContent) }, children)));\n};\nCodeBlock.displayName = 'CodeBlock';\n//# sourceMappingURL=CodeBlock.js.map","import { __rest } from \"tslib\";\nimport * as React from 'react';\nimport { css } from '@patternfly/react-styles';\nimport styles from '@patternfly/react-styles/css/components/CodeBlock/code-block.mjs';\nexport const CodeBlockAction = (_a) => {\n    var { children = null, className } = _a, props = __rest(_a, [\"children\", \"className\"]);\n    return (React.createElement(\"div\", Object.assign({ className: css(`${styles.codeBlockActions}-item`, className) }, props), children));\n};\nCodeBlockAction.displayName = 'CodeBlockAction';\n//# sourceMappingURL=CodeBlockAction.js.map","import { __rest } from \"tslib\";\nimport * as React from 'react';\nimport styles from '@patternfly/react-styles/css/components/Panel/panel.mjs';\nimport { css } from '@patternfly/react-styles';\nexport const PanelHeader = (_a) => {\n    var { className, children } = _a, props = __rest(_a, [\"className\", \"children\"]);\n    return (React.createElement(\"div\", Object.assign({ className: css(styles.panelHeader, className) }, props), children));\n};\nPanelHeader.displayName = 'PanelHeader';\n//# sourceMappingURL=PanelHeader.js.map","import { __rest } from \"tslib\";\nimport * as React from 'react';\nimport styles from '@patternfly/react-styles/css/components/Content/content.mjs';\nimport { css } from '@patternfly/react-styles';\nexport var TextListVariants;\n(function (TextListVariants) {\n    TextListVariants[\"ul\"] = \"ul\";\n    TextListVariants[\"ol\"] = \"ol\";\n    TextListVariants[\"dl\"] = \"dl\";\n})(TextListVariants || (TextListVariants = {}));\nexport const TextList = (_a) => {\n    var { children = null, className = '', component = TextListVariants.ul, isPlain = false } = _a, props = __rest(_a, [\"children\", \"className\", \"component\", \"isPlain\"]);\n    const Component = component;\n    return (React.createElement(Component, Object.assign({}, props, { className: css(isPlain && styles.modifiers.plain, className) }), children));\n};\nTextList.displayName = 'TextList';\n//# sourceMappingURL=TextList.js.map","import { __rest } from \"tslib\";\nimport * as React from 'react';\nimport { css } from '@patternfly/react-styles';\nexport var TextListItemVariants;\n(function (TextListItemVariants) {\n    TextListItemVariants[\"li\"] = \"li\";\n    TextListItemVariants[\"dt\"] = \"dt\";\n    TextListItemVariants[\"dd\"] = \"dd\";\n})(TextListItemVariants || (TextListItemVariants = {}));\nexport const TextListItem = (_a) => {\n    var { children = null, className = '', component = TextListItemVariants.li } = _a, props = __rest(_a, [\"children\", \"className\", \"component\"]);\n    const Component = component;\n    return (React.createElement(Component, Object.assign({}, props, { className: css(className) }), children));\n};\nTextListItem.displayName = 'TextListItem';\n//# sourceMappingURL=TextListItem.js.map","import { fetchWithError } from \"@keycloak/keycloak-admin-client\";\nimport { HelpItem, useHelp } from \"@keycloak/keycloak-ui-shared\";\nimport {\n  Form,\n  FormGroup,\n  MenuToggle,\n  ModalVariant,\n  Select,\n  SelectList,\n  SelectOption,\n  Stack,\n  StackItem,\n  TextArea,\n} from \"@patternfly/react-core\";\nimport { saveAs } from \"file-saver\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useAdminClient } from \"../../admin-client\";\nimport { useRealm } from \"../../context/realm-context/RealmContext\";\nimport { useServerInfo } from \"../../context/server-info/ServerInfoProvider\";\nimport { addTrailingSlash, prettyPrintJSON } from \"../../util\";\nimport { getAuthorizationHeaders } from \"../../utils/getAuthorizationHeaders\";\nimport { useFetch } from \"../../utils/useFetch\";\nimport { ConfirmDialogModal } from \"../confirm-dialog/ConfirmDialog\";\n\ntype DownloadDialogProps = {\n  id: string;\n  protocol?: string;\n  open: boolean;\n  toggleDialog: () => void;\n};\n\nexport const DownloadDialog = ({\n  id,\n  open,\n  toggleDialog,\n  protocol = \"openid-connect\",\n}: DownloadDialogProps) => {\n  const { adminClient } = useAdminClient();\n\n  const { realm } = useRealm();\n  const { t } = useTranslation();\n  const { enabled } = useHelp();\n  const serverInfo = useServerInfo();\n\n  const configFormats = serverInfo.clientInstallations![protocol];\n  const [selected, setSelected] = useState(\n    configFormats[configFormats.length - 1].id,\n  );\n  const [snippet, setSnippet] = useState();\n  const [openType, setOpenType] = useState(false);\n\n  const selectedConfig = useMemo(\n    () => configFormats.find((config) => config.id === selected) ?? null,\n    [selected],\n  );\n\n  const sanitizeSnippet = (snippet: string) =>\n    snippet.replace(\n      /.*<\\/PrivateKeyPem>/gs,\n      `${t(\"privateKeyMask\")}`,\n    );\n\n  useFetch(\n    async () => {\n      if (selectedConfig?.mediaType === \"application/zip\") {\n        const response = await fetchWithError(\n          `${addTrailingSlash(\n            adminClient.baseUrl,\n          )}admin/realms/${realm}/clients/${id}/installation/providers/${selected}`,\n          {\n            method: \"GET\",\n            headers: getAuthorizationHeaders(\n              await adminClient.getAccessToken(),\n            ),\n          },\n        );\n\n        return response.arrayBuffer();\n      } else {\n        const snippet = await adminClient.clients.getInstallationProviders({\n          id,\n          providerId: selected,\n        });\n        if (typeof snippet === \"string\") {\n          return sanitizeSnippet(snippet);\n        } else {\n          return prettyPrintJSON(snippet);\n        }\n      }\n    },\n    (snippet) => setSnippet(snippet),\n    [id, selected],\n  );\n\n  // Clear snippet when selected config changes, this prevents old snippets from being displayed during fetch.\n  useEffect(() => setSnippet(\"\"), [id, selected]);\n\n  return (\n     {\n        saveAs(\n          new Blob([snippet!], { type: selectedConfig?.mediaType }),\n          selectedConfig?.filename,\n        );\n      }}\n      open={open}\n      toggleDialog={toggleDialog}\n      variant={ModalVariant.medium}\n    >\n      
\n \n \n \n }\n >\n (\n setOpenType(!openType)}\n isExpanded={openType}\n >\n {selected}\n \n )}\n selected={selected}\n onSelect={(_, value) => {\n setSelected(value?.toString() || \"\");\n setOpenType(false);\n }}\n aria-label={t(\"selectOne\")}\n popperProps={{\n appendTo: document.body,\n }}\n >\n \n {configFormats.map((configFormat) => (\n \n {configFormat.displayType}\n \n ))}\n \n \n \n \n {!selectedConfig?.downloadOnly && (\n \n \n }\n >\n \n \n \n )}\n \n
\n \n );\n};\n","import {\n FormGroup,\n MenuToggle,\n Select,\n SelectList,\n SelectOption,\n Split,\n SplitItem,\n} from \"@patternfly/react-core\";\nimport { useState } from \"react\";\nimport { Controller, useFormContext } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { HelpItem } from \"@keycloak/keycloak-ui-shared\";\nimport {\n TimeSelector,\n Unit,\n} from \"../../components/time-selector/TimeSelector\";\n\ntype TokenLifespanProps = {\n id: string;\n name: string;\n defaultValue?: number;\n units?: Unit[];\n};\n\nconst inherited = \"tokenLifespan.inherited\";\nconst expires = \"tokenLifespan.expires\";\n\nexport const TokenLifespan = ({\n id,\n name,\n defaultValue,\n units,\n}: TokenLifespanProps) => {\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n\n const [focused, setFocused] = useState(false);\n const onFocus = () => setFocused(true);\n const onBlur = () => setFocused(false);\n\n const { control } = useFormContext();\n const isExpireSet = (value: string | number) =>\n typeof value === \"number\" ||\n (typeof value === \"string\" && value !== \"\") ||\n focused;\n\n return (\n }\n >\n (\n \n \n (\n setOpen(!open)}\n isExpanded={open}\n >\n {isExpireSet(field.value) ? t(expires) : t(inherited)}\n \n )}\n isOpen={open}\n onSelect={(_, value) => {\n field.onChange(value);\n setOpen(false);\n }}\n selected={isExpireSet(field.value) ? t(expires) : t(inherited)}\n >\n \n {t(inherited)}\n {t(expires)}\n \n \n \n \n \n )}\n />\n \n );\n};\n","import { HelpItem } from \"@keycloak/keycloak-ui-shared\";\nimport {\n ActionGroup,\n Button,\n FormGroup,\n MenuToggle,\n Select,\n SelectList,\n SelectOption,\n} from \"@patternfly/react-core\";\nimport { useState } from \"react\";\nimport { Controller, useFormContext } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { DefaultSwitchControl } from \"../../components/SwitchControl\";\nimport { FormAccess } from \"../../components/form/FormAccess\";\nimport { KeyValueInput } from \"../../components/key-value-form/KeyValueInput\";\nimport { MultiLineInput } from \"../../components/multi-line-input/MultiLineInput\";\nimport { TimeSelector } from \"../../components/time-selector/TimeSelector\";\nimport { useRealm } from \"../../context/realm-context/RealmContext\";\nimport { convertAttributeNameToForm } from \"../../util\";\nimport useIsFeatureEnabled, { Feature } from \"../../utils/useIsFeatureEnabled\";\nimport { FormFields } from \"../ClientDetails\";\nimport { TokenLifespan } from \"./TokenLifespan\";\n\ntype AdvancedSettingsProps = {\n save: () => void;\n reset: () => void;\n protocol?: string;\n hasConfigureAccess?: boolean;\n};\n\nexport const AdvancedSettings = ({\n save,\n reset,\n protocol,\n hasConfigureAccess,\n}: AdvancedSettingsProps) => {\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n\n const { realmRepresentation: realm } = useRealm();\n\n const isFeatureEnabled = useIsFeatureEnabled();\n const isDPoPEnabled = isFeatureEnabled(Feature.DPoP);\n\n const { control } = useFormContext();\n return (\n \n {protocol !== \"openid-connect\" && (\n \n }\n >\n (\n \"attributes.saml.assertion.lifespan\",\n )}\n defaultValue=\"\"\n control={control}\n render={({ field }) => (\n \n )}\n />\n \n )}\n {protocol === \"openid-connect\" && (\n <>\n \n \n \n \n (\n \"attributes.tls.client.certificate.bound.access.tokens\",\n )}\n label={t(\"oAuthMutual\")}\n labelIcon={t(\"oAuthMutualHelp\")}\n stringify\n />\n {isDPoPEnabled && (\n (\n \"attributes.dpop.bound.access.tokens\",\n )}\n label={t(\"oAuthDPoP\")}\n labelIcon={t(\"oAuthDPoPHelp\")}\n stringify\n />\n )}\n \n }\n >\n (\n \"attributes.pkce.code.challenge.method\",\n )}\n defaultValue=\"\"\n control={control}\n render={({ field }) => (\n (\n setOpen(!open)}\n isExpanded={open}\n >\n {[field.value || t(\"choose\")]}\n \n )}\n isOpen={open}\n onSelect={(_, value) => {\n field.onChange(value);\n setOpen(false);\n }}\n selected={field.value}\n >\n \n {[\"\", \"S256\", \"plain\"].map((v) => (\n \n {v || t(\"choose\")}\n \n ))}\n \n \n )}\n />\n \n (\n \"attributes.require.pushed.authorization.requests\",\n )}\n label={t(\"pushedAuthorizationRequestRequired\")}\n labelIcon={t(\"pushedAuthorizationRequestRequiredHelp\")}\n stringify\n />\n (\n \"attributes.client.use.lightweight.access.token.enabled\",\n )}\n label={t(\"lightweightAccessToken\")}\n labelIcon={t(\"lightweightAccessTokenHelp\")}\n stringify\n />\n\n (\n \"attributes.client.introspection.response.allow.jwt.claim.enabled\",\n )}\n label={t(\"supportJwtClaimInIntrospectionResponse\")}\n labelIcon={t(\"supportJwtClaimInIntrospectionResponseHelp\")}\n stringify\n />\n \n }\n >\n \n \n \n }\n >\n \n \n \n )}\n \n \n {t(\"save\")}\n \n \n \n \n );\n};\n","import AuthenticationFlowRepresentation from \"@keycloak/keycloak-admin-client/lib/defs/authenticationFlowRepresentation\";\nimport { ActionGroup, Button } from \"@patternfly/react-core\";\nimport { sortBy } from \"lodash-es\";\nimport { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { SelectControl } from \"@keycloak/keycloak-ui-shared\";\nimport { useAdminClient } from \"../../admin-client\";\nimport { FormAccess } from \"../../components/form/FormAccess\";\nimport { useFetch } from \"../../utils/useFetch\";\n\ntype AuthenticationOverridesProps = {\n save: () => void;\n reset: () => void;\n protocol?: string;\n hasConfigureAccess?: boolean;\n};\n\nexport const AuthenticationOverrides = ({\n protocol,\n save,\n reset,\n hasConfigureAccess,\n}: AuthenticationOverridesProps) => {\n const { adminClient } = useAdminClient();\n\n const { t } = useTranslation();\n const [flows, setFlows] = useState([]);\n\n useFetch(\n () => adminClient.authenticationManagement.getFlows(),\n (flows) => {\n let filteredFlows = [\n ...flows.filter((flow) => flow.providerId !== \"client-flow\"),\n ];\n filteredFlows = sortBy(filteredFlows, [(f) => f.alias]);\n setFlows(filteredFlows);\n },\n [],\n );\n\n return (\n \n ({ key: id!, value: alias! })),\n ]}\n />\n {protocol === \"openid-connect\" && (\n ({ key: id!, value: alias! })),\n ]}\n />\n )}\n \n \n {t(\"save\")}\n \n \n {t(\"revert\")}\n \n \n \n );\n};\n","import { useController } from \"react-hook-form\";\nimport { TimeSelector, TimeSelectorProps } from \"./TimeSelector\";\n\ntype TimeSelectorFormProps = TimeSelectorProps & {\n name: string;\n};\n\nexport const TimeSelectorForm = (props: TimeSelectorFormProps) => {\n const { field } = useController(props);\n\n return ;\n};\n","import {\n AlertVariant,\n Button,\n ButtonVariant,\n Form,\n Modal,\n} from \"@patternfly/react-core\";\nimport { FormProvider, useForm } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { TextControl } from \"@keycloak/keycloak-ui-shared\";\nimport { useAdminClient } from \"../../admin-client\";\nimport { useAlerts } from \"../../components/alert/Alerts\";\n\ntype FormFields = {\n node: string;\n};\n\ntype AddHostDialogProps = {\n clientId: string;\n isOpen: boolean;\n onAdded: (host: string) => void;\n onClose: () => void;\n};\n\nexport const AddHostDialog = ({\n clientId: id,\n isOpen,\n onAdded,\n onClose,\n}: AddHostDialogProps) => {\n const { adminClient } = useAdminClient();\n\n const { t } = useTranslation();\n const form = useForm();\n const {\n handleSubmit,\n formState: { isDirty, isValid },\n } = form;\n const { addAlert, addError } = useAlerts();\n\n async function onSubmit({ node }: FormFields) {\n try {\n await adminClient.clients.addClusterNode({\n id,\n node,\n });\n onAdded(node);\n addAlert(t(\"addedNodeSuccess\"), AlertVariant.success);\n } catch (error) {\n addError(\"addedNodeFail\", error);\n }\n\n onClose();\n }\n\n return (\n \n {t(\"save\")}\n ,\n \n {t(\"cancel\")}\n ,\n ]}\n >\n \n
\n \n \n
\n \n );\n};\n","import {\n AlertVariant,\n Button,\n ButtonVariant,\n ExpandableSection,\n FormGroup,\n Split,\n SplitItem,\n ToolbarItem,\n} from \"@patternfly/react-core\";\nimport { useState } from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { HelpItem } from \"@keycloak/keycloak-ui-shared\";\nimport { useAdminClient } from \"../../admin-client\";\nimport { useAlerts } from \"../../components/alert/Alerts\";\nimport { useConfirmDialog } from \"../../components/confirm-dialog/ConfirmDialog\";\nimport { FormAccess } from \"../../components/form/FormAccess\";\nimport { ListEmptyState } from \"../../components/list-empty-state/ListEmptyState\";\nimport {\n Action,\n KeycloakDataTable,\n} from \"../../components/table-toolbar/KeycloakDataTable\";\nimport { TimeSelectorForm } from \"../../components/time-selector/TimeSelectorForm\";\nimport useFormatDate, { FORMAT_DATE_AND_TIME } from \"../../utils/useFormatDate\";\nimport { AddHostDialog } from \".././advanced/AddHostDialog\";\nimport { AdvancedProps, parseResult } from \"../AdvancedTab\";\n\ntype Node = {\n host: string;\n registration: string;\n};\n\nexport const ClusteringPanel = ({\n save,\n client: { id, registeredNodes, access },\n}: AdvancedProps) => {\n const { adminClient } = useAdminClient();\n\n const { t } = useTranslation();\n const { addAlert, addError } = useAlerts();\n const formatDate = useFormatDate();\n\n const [nodes, setNodes] = useState(registeredNodes || {});\n const [expanded, setExpanded] = useState(false);\n const [selectedNode, setSelectedNode] = useState(\"\");\n const [addNodeOpen, setAddNodeOpen] = useState(false);\n const [key, setKey] = useState(0);\n const refresh = () => setKey(new Date().getTime());\n\n const testCluster = async () => {\n const result = await adminClient.clients.testNodesAvailable({ id: id! });\n parseResult(result, \"testCluster\", addAlert, t);\n };\n\n const [toggleDeleteNodeConfirm, DeleteNodeConfirm] = useConfirmDialog({\n titleKey: \"deleteNode\",\n messageKey: t(\"deleteNodeBody\", {\n node: selectedNode,\n }),\n continueButtonLabel: \"delete\",\n continueButtonVariant: ButtonVariant.danger,\n onConfirm: async () => {\n try {\n await adminClient.clients.deleteClusterNode({\n id: id!,\n node: selectedNode,\n });\n setNodes({\n ...Object.keys(nodes).reduce((object: any, key) => {\n if (key !== selectedNode) {\n object[key] = nodes[key];\n }\n return object;\n }, {}),\n });\n refresh();\n addAlert(t(\"deleteNodeSuccess\"), AlertVariant.success);\n } catch (error) {\n addError(\"deleteNodeFail\", error);\n }\n },\n });\n\n return (\n <>\n \n \n }\n >\n \n \n \n \n \n \n \n \n \n \n <>\n \n {\n nodes[node] = Date.now() / 1000;\n refresh();\n }}\n onClose={() => setAddNodeOpen(false)}\n />\n setExpanded(val)}\n isExpanded={expanded}\n >\n \n Promise.resolve(\n Object.entries(nodes || {}).map((entry) => {\n return { host: entry[0], registration: entry[1] };\n }),\n )\n }\n toolbarItem={\n <>\n \n \n {t(\"testClusterAvailability\")}\n \n \n \n setAddNodeOpen(true)}\n variant={ButtonVariant.tertiary}\n >\n {t(\"registerNodeManually\")}\n \n \n \n }\n actions={[\n {\n title: t(\"delete\"),\n onRowClick: (node) => {\n setSelectedNode(node.host);\n toggleDeleteNodeConfirm();\n },\n } as Action,\n ]}\n columns={[\n {\n name: \"host\",\n displayKey: \"nodeHost\",\n },\n {\n name: \"registration\",\n displayKey: \"lastRegistration\",\n cellFormatters: [\n (value) =>\n value\n ? formatDate(\n new Date(parseInt(value.toString()) * 1000),\n FORMAT_DATE_AND_TIME,\n )\n : \"\",\n ],\n },\n ]}\n emptyState={\n setAddNodeOpen(true)}\n />\n }\n />\n \n \n \n );\n};\n","import { useTranslation } from \"react-i18next\";\nimport { TextControl } from \"@keycloak/keycloak-ui-shared\";\n\ntype ApplicationUrlsProps = {\n isDisabled?: boolean;\n};\n\nexport const ApplicationUrls = (props: ApplicationUrlsProps) => {\n const { t } = useTranslation();\n\n return (\n <>\n \n \n \n \n );\n};\n","import { ProviderRepresentation } from \"@keycloak/keycloak-admin-client/lib/defs/serverInfoRepesentation\";\nimport { ActionGroup, Button, FormGroup } from \"@patternfly/react-core\";\nimport { useTranslation } from \"react-i18next\";\nimport { HelpItem, SelectControl } from \"@keycloak/keycloak-ui-shared\";\nimport { FormAccess } from \"../../components/form/FormAccess\";\nimport { MultiLineInput } from \"../../components/multi-line-input/MultiLineInput\";\nimport { useServerInfo } from \"../../context/server-info/ServerInfoProvider\";\nimport { convertAttributeNameToForm, sortProviders } from \"../../util\";\nimport { FormFields } from \"../ClientDetails\";\nimport { ApplicationUrls } from \"./ApplicationUrls\";\n\ntype FineGrainOpenIdConnectProps = {\n save: () => void;\n reset: () => void;\n hasConfigureAccess?: boolean;\n};\n\nexport const FineGrainOpenIdConnect = ({\n save,\n reset,\n hasConfigureAccess,\n}: FineGrainOpenIdConnectProps) => {\n const { t } = useTranslation();\n const providers = useServerInfo().providers;\n const clientSignatureProviders = providers?.clientSignature.providers;\n const contentEncryptionProviders = providers?.contentencryption.providers;\n const cekManagementProviders = providers?.cekmanagement.providers;\n const signatureProviders = providers?.signature.providers;\n\n const convert = (list: { [index: string]: ProviderRepresentation }) =>\n sortProviders(list).map((i) => ({ key: i, value: i }));\n\n const prependEmpty = (list: { [index: string]: ProviderRepresentation }) => [\n { key: \"\", value: t(\"choose\") },\n ...convert(list),\n ];\n\n const prependAny = (list: { [index: string]: ProviderRepresentation }) => [\n { key: \"any\", value: t(\"any\") },\n ...convert(list),\n ];\n\n const prependNone = (list: { [index: string]: ProviderRepresentation }) => [\n { key: \"none\", value: t(\"none\") },\n ...convert(list),\n ];\n\n return (\n \n \n (\n \"attributes.access.token.signed.response.alg\",\n )}\n label={t(\"accessTokenSignatureAlgorithm\")}\n labelIcon={t(\"accessTokenSignatureAlgorithmHelp\")}\n controller={{\n defaultValue: \"\",\n }}\n options={prependEmpty(clientSignatureProviders!)}\n />\n (\n \"attributes.id.token.signed.response.alg\",\n )}\n label={t(\"idTokenSignatureAlgorithm\")}\n labelIcon={t(\"idTokenSignatureAlgorithmHelp\")}\n controller={{\n defaultValue: \"\",\n }}\n options={prependEmpty(clientSignatureProviders!)}\n />\n (\n \"attributes.id.token.encrypted.response.alg\",\n )}\n label={t(\"idTokenEncryptionKeyManagementAlgorithm\")}\n labelIcon={t(\"idTokenEncryptionKeyManagementAlgorithmHelp\")}\n controller={{\n defaultValue: \"\",\n }}\n options={prependEmpty(cekManagementProviders!)}\n />\n (\n \"attributes.id.token.encrypted.response.enc\",\n )}\n label={t(\"idTokenEncryptionContentEncryptionAlgorithm\")}\n labelIcon={t(\"idTokenEncryptionContentEncryptionAlgorithmHelp\")}\n controller={{\n defaultValue: \"\",\n }}\n options={prependEmpty(contentEncryptionProviders!)}\n />\n (\n \"attributes.user.info.response.signature.alg\",\n )}\n label={t(\"userInfoSignedResponseAlgorithm\")}\n labelIcon={t(\"userInfoSignedResponseAlgorithmHelp\")}\n controller={{\n defaultValue: \"\",\n }}\n options={prependEmpty(signatureProviders!)}\n />\n (\n \"attributes.user.info.encrypted.response.alg\",\n )}\n label={t(\"userInfoResponseEncryptionKeyManagementAlgorithm\")}\n labelIcon={t(\"userInfoResponseEncryptionKeyManagementAlgorithmHelp\")}\n controller={{\n defaultValue: \"\",\n }}\n options={prependEmpty(cekManagementProviders!)}\n />\n (\n \"attributes.user.info.encrypted.response.enc\",\n )}\n label={t(\"userInfoResponseEncryptionContentEncryptionAlgorithm\")}\n labelIcon={t(\n \"userInfoResponseEncryptionContentEncryptionAlgorithmHelp\",\n )}\n controller={{\n defaultValue: \"\",\n }}\n options={prependEmpty(contentEncryptionProviders!)}\n />\n (\n \"attributes.request.object.signature.alg\",\n )}\n label={t(\"requestObjectSignatureAlgorithm\")}\n labelIcon={t(\"requestObjectSignatureAlgorithmHelp\")}\n controller={{\n defaultValue: \"\",\n }}\n options={[\n { key: \"any\", value: t(\"any\") },\n ...prependNone(clientSignatureProviders!),\n ]}\n />\n (\n \"attributes.request.object.encryption.alg\",\n )}\n label={t(\"requestObjectEncryption\")}\n labelIcon={t(\"requestObjectEncryptionHelp\")}\n controller={{\n defaultValue: \"\",\n }}\n options={prependAny(cekManagementProviders!)}\n />\n (\n \"attributes.request.object.encryption.enc\",\n )}\n label={t(\"requestObjectEncoding\")}\n labelIcon={t(\"requestObjectEncodingHelp\")}\n controller={{\n defaultValue: \"\",\n }}\n options={prependAny(contentEncryptionProviders!)}\n />\n (\n \"attributes.request.object.required\",\n )}\n label={t(\"requestObjectRequired\")}\n labelIcon={t(\"requestObjectRequiredHelp\")}\n controller={{\n defaultValue: \"\",\n }}\n options={[\n \"not required\",\n \"request or request_uri\",\n \"request only\",\n \"request_uri only\",\n ].map((p) => ({\n key: p,\n value: t(`requestObject.${p}`),\n }))}\n />\n \n }\n >\n \n \n (\n \"attributes.authorization.signed.response.alg\",\n )}\n label={t(\"authorizationSignedResponseAlg\")}\n labelIcon={t(\"authorizationSignedResponseAlgHelp\")}\n controller={{\n defaultValue: \"\",\n }}\n options={prependEmpty(signatureProviders!)}\n />\n (\n \"attributes.authorization.encrypted.response.alg\",\n )}\n label={t(\"authorizationEncryptedResponseAlg\")}\n labelIcon={t(\"authorizationEncryptedResponseAlgHelp\")}\n controller={{\n defaultValue: \"\",\n }}\n options={prependEmpty(cekManagementProviders!)}\n />\n (\n \"attributes.authorization.encrypted.response.enc\",\n )}\n label={t(\"authorizationEncryptedResponseEnc\")}\n labelIcon={t(\"authorizationEncryptedResponseEncHelp\")}\n controller={{\n defaultValue: \"\",\n }}\n options={prependEmpty(contentEncryptionProviders!)}\n />\n \n \n \n \n \n );\n};\n","import { ActionGroup, Button } from \"@patternfly/react-core\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { FormAccess } from \"../../components/form/FormAccess\";\nimport { TextControl } from \"@keycloak/keycloak-ui-shared\";\nimport { ApplicationUrls } from \"./ApplicationUrls\";\n\ntype FineGrainSamlEndpointConfigProps = {\n save: () => void;\n reset: () => void;\n};\n\nexport const FineGrainSamlEndpointConfig = ({\n save,\n reset,\n}: FineGrainSamlEndpointConfigProps) => {\n const { t } = useTranslation();\n return (\n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n );\n};\n","import { ActionGroup, Button, FormGroup, Switch } from \"@patternfly/react-core\";\nimport { Controller, useFormContext } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { FormAccess } from \"../../components/form/FormAccess\";\nimport { HelpItem } from \"@keycloak/keycloak-ui-shared\";\nimport { convertAttributeNameToForm } from \"../../util\";\nimport { FormFields } from \"../ClientDetails\";\n\ntype OpenIdConnectCompatibilityModesProps = {\n save: () => void;\n reset: () => void;\n hasConfigureAccess?: boolean;\n};\n\nexport const OpenIdConnectCompatibilityModes = ({\n save,\n reset,\n hasConfigureAccess,\n}: OpenIdConnectCompatibilityModesProps) => {\n const { t } = useTranslation();\n const { control } = useFormContext();\n return (\n \n \n }\n >\n (\n \"attributes.exclude.session.state.from.auth.response\",\n )}\n defaultValue=\"\"\n control={control}\n render={({ field }) => (\n field.onChange(value.toString())}\n aria-label={t(\"excludeSessionStateFromAuthenticationResponse\")}\n />\n )}\n />\n \n \n }\n >\n (\n \"attributes.exclude.issuer.from.auth.response\",\n )}\n defaultValue=\"\"\n control={control}\n render={({ field }) => (\n field.onChange(value.toString())}\n aria-label={t(\"excludeIssuerFromAuthenticationResponse\")}\n />\n )}\n />\n \n \n }\n >\n (\n \"attributes.use.refresh.tokens\",\n )}\n defaultValue=\"true\"\n control={control}\n render={({ field }) => (\n field.onChange(value.toString())}\n aria-label={t(\"useRefreshTokens\")}\n />\n )}\n />\n \n \n }\n >\n (\n \"attributes.client_credentials.use_refresh_token\",\n )}\n defaultValue=\"false\"\n control={control}\n render={({ field }) => (\n field.onChange(value.toString())}\n aria-label={t(\"useRefreshTokenForClientCredentialsGrant\")}\n />\n )}\n />\n \n \n }\n >\n (\n \"attributes.token.response.type.bearer.lower-case\",\n )}\n defaultValue=\"false\"\n control={control}\n render={({ field }) => (\n field.onChange(value.toString())}\n aria-label={t(\"useLowerCaseBearerType\")}\n />\n )}\n />\n \n \n \n {t(\"save\")}\n \n \n {t(\"revert\")}\n \n \n \n );\n};\n","import type ClientRepresentation from \"@keycloak/keycloak-admin-client/lib/defs/clientRepresentation\";\nimport type GlobalRequestResult from \"@keycloak/keycloak-admin-client/lib/defs/globalRequestResult\";\nimport { AlertVariant, PageSection, Text } from \"@patternfly/react-core\";\nimport type { TFunction } from \"i18next\";\nimport { useFormContext } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScrollForm } from \"@keycloak/keycloak-ui-shared\";\nimport type { AddAlertFunction } from \"../components/alert/Alerts\";\nimport { convertAttributeNameToForm, toUpperCase } from \"../util\";\nimport type { FormFields, SaveOptions } from \"./ClientDetails\";\nimport { AdvancedSettings } from \"./advanced/AdvancedSettings\";\nimport { AuthenticationOverrides } from \"./advanced/AuthenticationOverrides\";\nimport { ClusteringPanel } from \"./advanced/ClusteringPanel\";\nimport { FineGrainOpenIdConnect } from \"./advanced/FineGrainOpenIdConnect\";\nimport { FineGrainSamlEndpointConfig } from \"./advanced/FineGrainSamlEndpointConfig\";\nimport { OpenIdConnectCompatibilityModes } from \"./advanced/OpenIdConnectCompatibilityModes\";\n\nexport const parseResult = (\n result: GlobalRequestResult,\n prefixKey: string,\n addAlert: AddAlertFunction,\n t: TFunction,\n) => {\n const successCount = result.successRequests?.length || 0;\n const failedCount = result.failedRequests?.length || 0;\n\n if (successCount === 0 && failedCount === 0) {\n addAlert(t(\"noAdminUrlSet\"), AlertVariant.warning);\n } else if (failedCount > 0) {\n addAlert(\n t(prefixKey + \"Success\", { successNodes: result.successRequests }),\n AlertVariant.success,\n );\n addAlert(\n t(prefixKey + \"Fail\", { failedNodes: result.failedRequests }),\n AlertVariant.danger,\n );\n } else {\n addAlert(\n t(prefixKey + \"Success\", { successNodes: result.successRequests }),\n AlertVariant.success,\n );\n }\n};\n\nexport type AdvancedProps = {\n save: (options?: SaveOptions) => void;\n client: ClientRepresentation;\n};\n\nexport const AdvancedTab = ({ save, client }: AdvancedProps) => {\n const { t } = useTranslation();\n const openIdConnect = \"openid-connect\";\n\n const { setValue } = useFormContext();\n const {\n publicClient,\n attributes,\n protocol,\n authenticationFlowBindingOverrides,\n } = client;\n\n const resetFields = (names: string[]) => {\n for (const name of names) {\n setValue(\n convertAttributeNameToForm(`attributes.${name}`),\n attributes?.[name] || \"\",\n );\n }\n };\n\n return (\n \n ,\n },\n {\n title: t(\"fineGrainOpenIdConnectConfiguration\"),\n isHidden: protocol !== openIdConnect,\n panel: (\n <>\n \n {t(\"fineGrainOpenIdConnectConfigurationHelp\")}\n \n {\n resetFields([\n \"logoUri\",\n \"policyUri\",\n \"tosUri\",\n \"access.token.signed.response.alg\",\n \"id.token.signed.response.alg\",\n \"id.token.encrypted.response.alg\",\n \"id.token.encrypted.response.enc\",\n \"user.info.response.signature.alg\",\n \"user.info.encrypted.response.alg\",\n \"user.info.encrypted.response.enc\",\n \"request.object.signature.alg\",\n \"request.object.encryption.alg\",\n \"request.object.encryption.enc\",\n \"request.object.required\",\n \"request.uris\",\n \"authorization.signed.response.alg\",\n \"authorization.encrypted.response.alg\",\n \"authorization.encrypted.response.enc\",\n ]);\n }}\n />\n \n ),\n },\n {\n title: t(\"openIdConnectCompatibilityModes\"),\n isHidden: protocol !== openIdConnect,\n panel: (\n <>\n \n {t(\"openIdConnectCompatibilityModesHelp\")}\n \n save()}\n reset={() =>\n resetFields([\n \"exclude.session.state.from.auth.response\",\n \"use.refresh.tokens\",\n \"client_credentials.use_refresh_token\",\n \"token.response.type.bearer.lower-case\",\n ])\n }\n />\n \n ),\n },\n {\n title: t(\"fineGrainSamlEndpointConfig\"),\n isHidden: protocol === openIdConnect,\n panel: (\n <>\n \n {t(\"fineGrainSamlEndpointConfigHelp\")}\n \n save()}\n reset={() =>\n resetFields([\n \"logoUri\",\n \"policyUri\",\n \"tosUri\",\n \"saml_assertion_consumer_url_post\",\n \"saml_assertion_consumer_url_redirect\",\n \"saml_single_logout_service_url_post\",\n \"saml_single_logout_service_url_redirect\",\n \"saml_single_logout_service_url_artifact\",\n \"saml_artifact_binding_url\",\n \"saml_artifact_resolution_service_url\",\n ])\n }\n />\n \n ),\n },\n {\n title: t(\"advancedSettings\"),\n panel: (\n <>\n \n {t(\"advancedSettings\" + toUpperCase(protocol || \"\"))}\n \n save()}\n reset={() => {\n resetFields([\n \"saml.assertion.lifespan\",\n \"access.token.lifespan\",\n \"tls.client.certificate.bound.access.tokens\",\n \"pkce.code.challenge.method\",\n ]);\n }}\n />\n \n ),\n },\n {\n title: t(\"authenticationOverrides\"),\n panel: (\n <>\n \n {t(\"authenticationOverridesHelp\")}\n \n save()}\n reset={() => {\n setValue(\n \"authenticationFlowBindingOverrides.browser\",\n authenticationFlowBindingOverrides?.browser,\n );\n setValue(\n \"authenticationFlowBindingOverrides.direct_grant\",\n authenticationFlowBindingOverrides?.direct_grant,\n );\n }}\n />\n \n ),\n },\n ]}\n borders\n />\n \n );\n};\n","import type ClientRepresentation from \"@keycloak/keycloak-admin-client/lib/defs/clientRepresentation\";\nimport type UserSessionRepresentation from \"@keycloak/keycloak-admin-client/lib/defs/userSessionRepresentation\";\nimport { PageSection } from \"@patternfly/react-core\";\nimport { useTranslation } from \"react-i18next\";\nimport { useAdminClient } from \"../admin-client\";\nimport type { LoaderFunction } from \"../components/table-toolbar/KeycloakDataTable\";\nimport SessionsTable from \"../sessions/SessionsTable\";\n\ntype ClientSessionsProps = {\n client: ClientRepresentation;\n};\n\nexport const ClientSessions = ({ client }: ClientSessionsProps) => {\n const { adminClient } = useAdminClient();\n\n const { t } = useTranslation();\n\n const loader: LoaderFunction = async (\n first,\n max,\n ) => {\n const mapSessionsToType =\n (type: string) => (sessions: UserSessionRepresentation[]) =>\n sessions.map((session) => ({\n type,\n ...session,\n }));\n\n const allSessions = await Promise.all([\n adminClient.clients\n .listSessions({ id: client.id!, first, max })\n .then(mapSessionsToType(t(\"sessionsType.regularSSO\"))),\n adminClient.clients\n .listOfflineSessions({\n id: client.id!,\n first,\n max,\n })\n .then(mapSessionsToType(t(\"sessionsType.offline\"))),\n ]);\n\n return allSessions.flat();\n };\n\n return (\n \n \n \n );\n};\n","import { useFormContext } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { TextControl } from \"@keycloak/keycloak-ui-shared\";\n\nimport { FixedButtonsGroup } from \"../../components/form/FixedButtonGroup\";\nimport { FormAccess } from \"../../components/form/FormAccess\";\nimport { useAccess } from \"../../context/access/Access\";\nimport { FormFields } from \"../ClientDetails\";\nimport type { ClientSettingsProps } from \"../ClientSettings\";\nimport { LoginSettings } from \"./LoginSettings\";\n\nexport const AccessSettings = ({\n client,\n save,\n reset,\n}: ClientSettingsProps) => {\n const { t } = useTranslation();\n const { watch } = useFormContext();\n\n const { hasAccess } = useAccess();\n const isManager = hasAccess(\"manage-clients\") || client.access?.configure;\n\n const protocol = watch(\"protocol\");\n\n return (\n \n {!client.bearerOnly && }\n {protocol !== \"saml\" && (\n \n )}\n {client.bearerOnly && (\n \n )}\n \n );\n};\n","import { useFormContext } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { SelectControl, TextAreaControl } from \"@keycloak/keycloak-ui-shared\";\nimport { DefaultSwitchControl } from \"../../components/SwitchControl\";\nimport { FormAccess } from \"../../components/form/FormAccess\";\nimport { useServerInfo } from \"../../context/server-info/ServerInfoProvider\";\nimport { convertAttributeNameToForm } from \"../../util\";\nimport { FormFields } from \"../ClientDetails\";\n\nexport const LoginSettingsPanel = ({ access }: { access?: boolean }) => {\n const { t } = useTranslation();\n const { watch } = useFormContext();\n\n const loginThemes = useServerInfo().themes![\"login\"];\n const consentRequired = watch(\"consentRequired\");\n const displayOnConsentScreen: string = watch(\n convertAttributeNameToForm(\n \"attributes.display.on.consent.screen\",\n ),\n );\n\n return (\n \n ({ key: name, value: name })),\n ]}\n />\n \n (\n \"attributes.display.on.consent.screen\",\n )}\n label={t(\"displayOnClient\")}\n labelIcon={t(\"displayOnClientHelp\")}\n isDisabled={!consentRequired}\n stringify\n />\n (\n \"attributes.consent.screen.text\",\n )}\n label={t(\"consentScreenText\")}\n labelIcon={t(\"consentScreenTextHelp\")}\n isDisabled={!(consentRequired && displayOnConsentScreen === \"true\")}\n />\n \n );\n};\n","import { FormGroup, Switch } from \"@patternfly/react-core\";\nimport { Controller, useFormContext } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { HelpItem, TextControl } from \"@keycloak/keycloak-ui-shared\";\n\nimport { FixedButtonsGroup } from \"../../components/form/FixedButtonGroup\";\nimport { FormAccess } from \"../../components/form/FormAccess\";\nimport { useAccess } from \"../../context/access/Access\";\nimport { convertAttributeNameToForm } from \"../../util\";\nimport { FormFields } from \"../ClientDetails\";\nimport type { ClientSettingsProps } from \"../ClientSettings\";\n\nconst validateUrl = (uri: string | undefined, error: string) =>\n ((uri?.startsWith(\"https://\") || uri?.startsWith(\"http://\")) &&\n !uri.includes(\"*\")) ||\n uri === \"\" ||\n error;\n\nexport const LogoutPanel = ({\n save,\n reset,\n client: { access },\n}: ClientSettingsProps) => {\n const { t } = useTranslation();\n const { control, watch } = useFormContext();\n\n const { hasAccess } = useAccess();\n const isManager = hasAccess(\"manage-clients\") || access?.configure;\n\n const protocol = watch(\"protocol\");\n const frontchannelLogout = watch(\"frontchannelLogout\");\n\n return (\n \n \n }\n fieldId=\"kc-frontchannelLogout\"\n hasNoPaddingTop\n >\n (\n \n )}\n />\n \n {protocol === \"openid-connect\" && frontchannelLogout && (\n (\n \"attributes.frontchannel.logout.url\",\n )}\n label={t(\"frontchannelLogoutUrl\")}\n labelIcon={t(\"frontchannelLogoutUrlHelp\")}\n rules={{\n validate: (uri) =>\n validateUrl(uri, t(\"frontchannelUrlInvalid\").toString()),\n }}\n />\n )}\n {protocol === \"openid-connect\" && (\n <>\n (\n \"attributes.backchannel.logout.url\",\n )}\n label={t(\"backchannelLogoutUrl\")}\n labelIcon={t(\"backchannelLogoutUrlHelp\")}\n rules={{\n validate: (uri) =>\n validateUrl(uri, t(\"backchannelUrlInvalid\").toString()),\n }}\n />\n \n }\n fieldId=\"backchannelLogoutSessionRequired\"\n hasNoPaddingTop\n >\n (\n \"attributes.backchannel.logout.session.required\",\n )}\n defaultValue=\"true\"\n control={control}\n render={({ field }) => (\n field.onChange(value.toString())}\n aria-label={t(\"backchannelLogoutSessionRequired\")}\n />\n )}\n />\n \n \n }\n fieldId=\"backchannelLogoutRevokeOfflineSessions\"\n hasNoPaddingTop\n >\n (\n \"attributes.backchannel.logout.revoke.offline.tokens\",\n )}\n defaultValue=\"false\"\n control={control}\n render={({ field }) => (\n field.onChange(value.toString())}\n aria-label={t(\"backchannelLogoutRevokeOfflineSessions\")}\n />\n )}\n />\n \n \n )}\n \n \n );\n};\n","import { Path, PathValue } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { SelectControl } from \"@keycloak/keycloak-ui-shared\";\nimport { DefaultSwitchControl } from \"../../components/SwitchControl\";\nimport { FormAccess } from \"../../components/form/FormAccess\";\nimport { convertAttributeNameToForm } from \"../../util\";\nimport { FormFields } from \"../ClientDetails\";\n\ntype ToggleProps = {\n name: PathValue>;\n label: string;\n};\nexport const Toggle = ({ name, label }: ToggleProps) => {\n const { t } = useTranslation();\n\n return (\n \n );\n};\n\nexport const SamlConfig = () => {\n const { t } = useTranslation();\n\n return (\n \n \n \n \n \n \n \n \n \n \n );\n};\n","import { useFormContext } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { SelectControl } from \"@keycloak/keycloak-ui-shared\";\nimport { FormAccess } from \"../../components/form/FormAccess\";\nimport { convertAttributeNameToForm } from \"../../util\";\nimport { FormFields } from \"../ClientDetails\";\nimport { Toggle } from \"./SamlConfig\";\n\nconst SIGNATURE_ALGORITHMS = [\n \"RSA_SHA1\",\n \"RSA_SHA256\",\n \"RSA_SHA256_MGF1\",\n \"RSA_SHA512\",\n \"RSA_SHA512_MGF1\",\n \"DSA_SHA1\",\n] as const;\n\nconst KEYNAME_TRANSFORMER = [\"NONE\", \"KEY_ID\", \"CERT_SUBJECT\"] as const;\n\nconst CANONICALIZATION = [\n { name: \"EXCLUSIVE\", value: \"http://www.w3.org/2001/10/xml-exc-c14n#\" },\n {\n name: \"EXCLUSIVE_WITH_COMMENTS\",\n value: \"http://www.w3.org/2001/10/xml-exc-c14n#WithComments\",\n },\n {\n name: \"INCLUSIVE\",\n value: \"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\",\n },\n {\n name: \"INCLUSIVE_WITH_COMMENTS\",\n value: \"http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments\",\n },\n] as const;\n\nexport const SamlSignature = () => {\n const { t } = useTranslation();\n const { watch } = useFormContext();\n\n const signDocs = watch(\n convertAttributeNameToForm(\"attributes.saml.server.signature\"),\n );\n const signAssertion = watch(\n convertAttributeNameToForm(\n \"attributes.saml.assertion.signature\",\n ),\n );\n\n return (\n \n \n \n {(signDocs === \"true\" || signAssertion === \"true\") && (\n <>\n (\n \"attributes.saml.signature.algorithm\",\n )}\n label={t(\"signatureAlgorithm\")}\n labelIcon={t(\"signatureAlgorithmHelp\")}\n controller={{\n defaultValue: SIGNATURE_ALGORITHMS[0],\n }}\n options={[...SIGNATURE_ALGORITHMS]}\n />\n (\n \"attributes.saml.server.signature.keyinfo.xmlSigKeyInfoKeyNameTransformer\",\n )}\n label={t(\"signatureKeyName\")}\n labelIcon={t(\"signatureKeyNameHelp\")}\n controller={{\n defaultValue: KEYNAME_TRANSFORMER[0],\n }}\n options={[...KEYNAME_TRANSFORMER]}\n />\n ({\n key: value,\n value: name,\n }))}\n />\n \n )}\n \n );\n};\n","import type ClientRepresentation from \"@keycloak/keycloak-admin-client/lib/defs/clientRepresentation\";\nimport { Form } from \"@patternfly/react-core\";\nimport { useFormContext } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { ScrollForm } from \"@keycloak/keycloak-ui-shared\";\nimport { ClientDescription } from \"./ClientDescription\";\nimport { FormFields } from \"./ClientDetails\";\nimport { AccessSettings } from \"./add/AccessSettings\";\nimport { CapabilityConfig } from \"./add/CapabilityConfig\";\nimport { LoginSettingsPanel } from \"./add/LoginSettingsPanel\";\nimport { LogoutPanel } from \"./add/LogoutPanel\";\nimport { SamlConfig } from \"./add/SamlConfig\";\nimport { SamlSignature } from \"./add/SamlSignature\";\n\nexport type ClientSettingsProps = {\n client: ClientRepresentation;\n save: () => void;\n reset: () => void;\n};\n\nexport const ClientSettings = (props: ClientSettingsProps) => {\n const { t } = useTranslation();\n\n const { watch } = useFormContext();\n const protocol = watch(\"protocol\");\n\n const { client } = props;\n\n return (\n \n \n \n ),\n },\n {\n title: t(\"accessSettings\"),\n panel: ,\n },\n {\n title: t(\"samlCapabilityConfig\"),\n isHidden: protocol !== \"saml\" || client.bearerOnly,\n panel: ,\n },\n {\n title: t(\"signatureAndEncryption\"),\n isHidden: protocol !== \"saml\" || client.bearerOnly,\n panel: ,\n },\n {\n title: t(\"capabilityConfig\"),\n isHidden: protocol !== \"openid-connect\" || client.bearerOnly,\n panel: ,\n },\n {\n title: t(\"loginSettings\"),\n isHidden: client.bearerOnly,\n panel: ,\n },\n {\n title: t(\"logoutSettings\"),\n isHidden: client.bearerOnly,\n panel: ,\n },\n ]}\n />\n );\n};\n","import type ResourceRepresentation from \"@keycloak/keycloak-admin-client/lib/defs/resourceRepresentation\";\nimport { KeycloakSelect, SelectVariant } from \"@keycloak/keycloak-ui-shared\";\nimport { Button, SelectOption, TextInput } from \"@patternfly/react-core\";\nimport { MinusCircleIcon, PlusCircleIcon } from \"@patternfly/react-icons\";\nimport { Table, Tbody, Td, Th, Thead, Tr } from \"@patternfly/react-table\";\nimport { camelCase } from \"lodash-es\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { Controller, useFieldArray, useFormContext } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { defaultContextAttributes } from \"../utils\";\n\nimport \"./key-based-attribute-input.css\";\n\nexport type AttributeType = {\n key?: string;\n name: string;\n custom?: boolean;\n values?: {\n [key: string]: string;\n }[];\n};\n\ntype AttributeInputProps = {\n name: string;\n selectableValues?: AttributeType[];\n resources?: ResourceRepresentation[];\n};\n\ntype ValueInputProps = {\n name: string;\n rowIndex: number;\n attribute: any;\n selectableValues?: AttributeType[];\n resources?: ResourceRepresentation[];\n};\n\nconst ValueInput = ({\n name,\n rowIndex,\n attribute,\n selectableValues,\n resources,\n}: ValueInputProps) => {\n const { t } = useTranslation();\n const { control, register, getValues } = useFormContext();\n const [isValueOpenArray, setIsValueOpenArray] = useState([false]);\n\n const toggleValueSelect = (rowIndex: number, open: boolean) => {\n const arr = [...isValueOpenArray];\n arr[rowIndex] = open;\n setIsValueOpenArray(arr);\n };\n\n const attributeValues = useMemo(() => {\n let values: AttributeType[] | undefined = [];\n\n if (selectableValues) {\n values = defaultContextAttributes.find(\n (attr) => attr.key === getValues().context?.[rowIndex]?.key,\n )?.values;\n }\n\n return values;\n }, [getValues]);\n\n const renderSelectOptionType = () => {\n const scopeValues = resources?.find(\n (resource) => resource.name === getValues().resources?.[rowIndex]?.key,\n )?.scopes;\n\n if (attributeValues?.length && !resources) {\n return attributeValues.map((attr) => (\n \n {attr.name}\n \n ));\n } else if (scopeValues?.length) {\n return scopeValues.map((scope) => (\n \n {scope.name}\n \n ));\n }\n };\n\n const getMessageBundleKey = (attributeName: string) =>\n camelCase(attributeName).replace(/\\W/g, \"\");\n\n return (\n \n {resources || attributeValues?.length ? (\n (\n toggleValueSelect(rowIndex, open)}\n isOpen={isValueOpenArray[rowIndex]}\n variant={SelectVariant.typeahead}\n typeAheadAriaLabel={t(\"selectOrTypeAKey\")}\n placeholderText={t(\"selectOrTypeAKey\")}\n selections={field.value}\n onSelect={(v) => {\n field.onChange(v);\n\n toggleValueSelect(rowIndex, false);\n }}\n >\n {renderSelectOptionType()}\n \n )}\n />\n ) : (\n \n )}\n \n );\n};\n\nexport const KeyBasedAttributeInput = ({\n name,\n selectableValues,\n resources,\n}: AttributeInputProps) => {\n const { t } = useTranslation();\n const { control, watch } = useFormContext();\n const { fields, append, remove } = useFieldArray({\n control: control,\n name,\n });\n\n const [isKeyOpenArray, setIsKeyOpenArray] = useState([false]);\n const toggleKeySelect = (rowIndex: number, open: boolean) => {\n const arr = [...isKeyOpenArray];\n arr[rowIndex] = open;\n setIsKeyOpenArray(arr);\n };\n\n useEffect(() => {\n if (!fields.length) {\n append({ key: \"\", value: \"\" }, { shouldFocus: false });\n }\n }, [fields]);\n\n const watchLastValue = watch(`${name}.${fields.length - 1}.value`, \"\");\n\n return (\n \n \n \n {t(\"key\")}\n {t(\"value\")}\n \n \n \n {fields.map((attribute, rowIndex) => (\n \n \n (\n toggleKeySelect(rowIndex, open)}\n isOpen={isKeyOpenArray[rowIndex]}\n variant={SelectVariant.typeahead}\n typeAheadAriaLabel={t(\"selectOrTypeAKey\")}\n placeholderText={t(\"selectOrTypeAKey\")}\n selections={field.value}\n onSelect={(v) => {\n field.onChange(v.toString());\n\n toggleKeySelect(rowIndex, false);\n }}\n >\n {selectableValues?.map((attribute) => (\n \n {attribute.name}\n \n ))}\n \n )}\n />\n \n \n \n remove(rowIndex)}\n aria-label={t(\"remove\")}\n >\n \n \n \n \n ))}\n \n \n {\n append({ key: \"\", value: \"\" });\n setIsKeyOpenArray([...isKeyOpenArray, false]);\n }}\n icon={}\n isDisabled={!watchLastValue}\n data-testid=\"attribute-add-row\"\n >\n {t(\"addAttribute\", { label: t(\"attribute\") })}\n \n \n \n \n \n );\n};\n","import type AccessTokenRepresentation from \"@keycloak/keycloak-admin-client/lib/defs/accessTokenRepresentation\";\nimport {\n Button,\n Modal,\n ModalVariant,\n Text,\n TextArea,\n TextContent,\n TextVariants,\n} from \"@patternfly/react-core\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { prettyPrintJSON } from \"../../util\";\nimport useToggle from \"../../utils/useToggle\";\n\ntype AuthorizationDataModalProps = {\n data: AccessTokenRepresentation;\n};\n\nexport const AuthorizationDataModal = ({\n data,\n}: AuthorizationDataModalProps) => {\n const { t } = useTranslation();\n const [show, toggle] = useToggle();\n\n return (\n <>\n \n {t(\"showAuthData\")}\n \n \n {t(\"authData\")}\n {t(\"authDataDescription\")}\n \n }\n onClose={toggle}\n actions={[\n \n {t(\"cancel\")}\n ,\n ]}\n >\n