Remove useless React fragments (#1062)
This commit is contained in:
parent
b15c240d9e
commit
e062603ff2
62 changed files with 3157 additions and 3328 deletions
|
@ -30,6 +30,8 @@ module.exports = {
|
||||||
// react/prop-types cannot handle generic props, so we need to disable it.
|
// react/prop-types cannot handle generic props, so we need to disable it.
|
||||||
// https://github.com/yannickcr/eslint-plugin-react/issues/2777#issuecomment-814968432
|
// https://github.com/yannickcr/eslint-plugin-react/issues/2777#issuecomment-814968432
|
||||||
"react/prop-types": "off",
|
"react/prop-types": "off",
|
||||||
|
// Prevent fragments from being added that have only a single child.
|
||||||
|
"react/jsx-no-useless-fragment": "error"
|
||||||
},
|
},
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,37 +27,27 @@ export const Header = () => {
|
||||||
const adminClient = useAdminClient();
|
const adminClient = useAdminClient();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const ManageAccountDropdownItem = () => {
|
const ManageAccountDropdownItem = () =>
|
||||||
return (
|
adminClient.keycloak ? (
|
||||||
<>
|
<DropdownItem
|
||||||
{adminClient.keycloak && (
|
key="manage account"
|
||||||
<DropdownItem
|
id="manage-account"
|
||||||
key="manage account"
|
onClick={() => adminClient.keycloak?.accountManagement()}
|
||||||
id="manage-account"
|
>
|
||||||
onClick={() => adminClient.keycloak?.accountManagement()}
|
{t("manageAccount")}
|
||||||
>
|
</DropdownItem>
|
||||||
{t("manageAccount")}
|
) : null;
|
||||||
</DropdownItem>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const SignOutDropdownItem = () => {
|
const SignOutDropdownItem = () =>
|
||||||
return (
|
adminClient.keycloak ? (
|
||||||
<>
|
<DropdownItem
|
||||||
{adminClient.keycloak && (
|
id="sign-out"
|
||||||
<DropdownItem
|
key="sign out"
|
||||||
id="sign-out"
|
onClick={() => adminClient.keycloak?.logout({ redirectUri: "" })}
|
||||||
key="sign out"
|
>
|
||||||
onClick={() => adminClient.keycloak?.logout({ redirectUri: "" })}
|
{t("signOut")}
|
||||||
>
|
</DropdownItem>
|
||||||
{t("signOut")}
|
) : null;
|
||||||
</DropdownItem>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const ServerInfoDropdownItem = () => {
|
const ServerInfoDropdownItem = () => {
|
||||||
const { realm } = useRealm();
|
const { realm } = useRealm();
|
||||||
|
|
|
@ -107,22 +107,20 @@ export const ClientScopesSection = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const TypeSelector = (scope: ClientScopeDefaultOptionalType) => (
|
const TypeSelector = (scope: ClientScopeDefaultOptionalType) => (
|
||||||
<>
|
<CellDropdown
|
||||||
<CellDropdown
|
clientScope={scope}
|
||||||
clientScope={scope}
|
type={scope.type}
|
||||||
type={scope.type}
|
all
|
||||||
all
|
onSelect={async (value) => {
|
||||||
onSelect={async (value) => {
|
try {
|
||||||
try {
|
await changeScope(adminClient, scope, value);
|
||||||
await changeScope(adminClient, scope, value);
|
addAlert(t("clientScopeSuccess"), AlertVariant.success);
|
||||||
addAlert(t("clientScopeSuccess"), AlertVariant.success);
|
refresh();
|
||||||
refresh();
|
} catch (error) {
|
||||||
} catch (error) {
|
addError("client-scopes:clientScopeError", error);
|
||||||
addError("client-scopes:clientScopeError", error);
|
}
|
||||||
}
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const ClientScopeDetailLink = ({
|
const ClientScopeDetailLink = ({
|
||||||
|
@ -130,14 +128,12 @@ export const ClientScopesSection = () => {
|
||||||
type,
|
type,
|
||||||
name,
|
name,
|
||||||
}: ClientScopeDefaultOptionalType) => (
|
}: ClientScopeDefaultOptionalType) => (
|
||||||
<>
|
<Link
|
||||||
<Link
|
key={id}
|
||||||
key={id}
|
to={toClientScope({ realm, id: id!, type, tab: "settings" })}
|
||||||
to={toClientScope({ realm, id: id!, type, tab: "settings" })}
|
>
|
||||||
>
|
{name}
|
||||||
{name}
|
</Link>
|
||||||
</Link>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -128,10 +128,10 @@ export const AddMapperDialog = (props: AddMapperDialogProps) => {
|
||||||
<DataListItemCells
|
<DataListItemCells
|
||||||
dataListCells={[
|
dataListCells={[
|
||||||
<DataListCell key={`name-${mapper.id}`}>
|
<DataListCell key={`name-${mapper.id}`}>
|
||||||
<>{mapper.name}</>
|
{mapper.name}
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell key={`helpText-${mapper.id}`}>
|
<DataListCell key={`helpText-${mapper.id}`}>
|
||||||
<>{mapper.helpText}</>
|
{mapper.helpText}
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -99,11 +99,9 @@ export const MapperList = ({ clientScope, refresh }: MapperListProps) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const MapperLink = ({ id, name }: Row) => (
|
const MapperLink = ({ id, name }: Row) => (
|
||||||
<>
|
<Link to={toMapper({ realm, id: clientScope.id!, mapperId: id! })}>
|
||||||
<Link to={toMapper({ realm, id: clientScope.id!, mapperId: id! })}>
|
{name}
|
||||||
{name}
|
</Link>
|
||||||
</Link>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -164,40 +164,36 @@ export const MappingDetails = () => {
|
||||||
onSubmit={handleSubmit(save)}
|
onSubmit={handleSubmit(save)}
|
||||||
role="manage-clients"
|
role="manage-clients"
|
||||||
>
|
>
|
||||||
<>
|
{!mapperId.match(isGuid) && (
|
||||||
{!mapperId.match(isGuid) && (
|
<FormGroup
|
||||||
<FormGroup
|
label={t("common:name")}
|
||||||
label={t("common:name")}
|
labelIcon={
|
||||||
labelIcon={
|
<HelpItem
|
||||||
<HelpItem
|
helpText="client-scopes-help:mapperName"
|
||||||
helpText="client-scopes-help:mapperName"
|
forLabel={t("common:name")}
|
||||||
forLabel={t("common:name")}
|
forID="name"
|
||||||
forID="name"
|
/>
|
||||||
/>
|
}
|
||||||
}
|
fieldId="name"
|
||||||
fieldId="name"
|
isRequired
|
||||||
isRequired
|
validated={
|
||||||
|
errors.name ? ValidatedOptions.error : ValidatedOptions.default
|
||||||
|
}
|
||||||
|
helperTextInvalid={t("common:required")}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
ref={register({ required: true })}
|
||||||
|
type="text"
|
||||||
|
id="name"
|
||||||
|
name="name"
|
||||||
validated={
|
validated={
|
||||||
errors.name
|
errors.name
|
||||||
? ValidatedOptions.error
|
? ValidatedOptions.error
|
||||||
: ValidatedOptions.default
|
: ValidatedOptions.default
|
||||||
}
|
}
|
||||||
helperTextInvalid={t("common:required")}
|
/>
|
||||||
>
|
</FormGroup>
|
||||||
<TextInput
|
)}
|
||||||
ref={register({ required: true })}
|
|
||||||
type="text"
|
|
||||||
id="name"
|
|
||||||
name="name"
|
|
||||||
validated={
|
|
||||||
errors.name
|
|
||||||
? ValidatedOptions.error
|
|
||||||
: ValidatedOptions.default
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={t("realmRolePrefix")}
|
label={t("realmRolePrefix")}
|
||||||
labelIcon={
|
labelIcon={
|
||||||
|
|
|
@ -38,217 +38,215 @@ export const ClientSettings = ({ save, reset }: ClientSettingsProps) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<ScrollForm
|
||||||
<ScrollForm
|
className="pf-u-px-lg"
|
||||||
className="pf-u-px-lg"
|
sections={[
|
||||||
sections={[
|
t("generalSettings"),
|
||||||
t("generalSettings"),
|
t("capabilityConfig"),
|
||||||
t("capabilityConfig"),
|
t("accessSettings"),
|
||||||
t("accessSettings"),
|
t("loginSettings"),
|
||||||
t("loginSettings"),
|
]}
|
||||||
]}
|
>
|
||||||
>
|
<Form isHorizontal>
|
||||||
<Form isHorizontal>
|
<ClientDescription />
|
||||||
<ClientDescription />
|
</Form>
|
||||||
</Form>
|
<CapabilityConfig />
|
||||||
<CapabilityConfig />
|
<FormAccess isHorizontal role="manage-clients">
|
||||||
<FormAccess isHorizontal role="manage-clients">
|
<FormGroup
|
||||||
<FormGroup
|
label={t("rootUrl")}
|
||||||
label={t("rootUrl")}
|
fieldId="kc-root-url"
|
||||||
fieldId="kc-root-url"
|
labelIcon={
|
||||||
labelIcon={
|
<HelpItem
|
||||||
<HelpItem
|
helpText="clients-help:rootUrl"
|
||||||
helpText="clients-help:rootUrl"
|
forLabel={t("rootUrl")}
|
||||||
forLabel={t("rootUrl")}
|
forID="kc-root-url"
|
||||||
forID="kc-root-url"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<TextInput
|
|
||||||
type="text"
|
|
||||||
id="kc-root-url"
|
|
||||||
name="rootUrl"
|
|
||||||
ref={register}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
<FormGroup
|
>
|
||||||
label={t("validRedirectUri")}
|
<TextInput
|
||||||
fieldId="kc-redirect"
|
type="text"
|
||||||
labelIcon={
|
id="kc-root-url"
|
||||||
<HelpItem
|
name="rootUrl"
|
||||||
helpText="clients-help:validRedirectURIs"
|
ref={register}
|
||||||
forLabel={t("validRedirectUri")}
|
|
||||||
forID={t(`common:helpLabel`, { label: t("validRedirectUri") })}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<MultiLineInput
|
|
||||||
name="redirectUris"
|
|
||||||
aria-label={t("validRedirectUri")}
|
|
||||||
addButtonLabel="clients:addRedirectUri"
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("homeURL")}
|
|
||||||
fieldId="kc-home-url"
|
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="clients-help:homeURL"
|
|
||||||
forLabel={t("homeURL")}
|
|
||||||
forID={t(`common:helpLabel`, { label: t("homeURL") })}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<TextInput
|
|
||||||
type="text"
|
|
||||||
id="kc-home-url"
|
|
||||||
name="baseUrl"
|
|
||||||
ref={register}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("webOrigins")}
|
|
||||||
fieldId="kc-web-origins"
|
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="clients-help:webOrigins"
|
|
||||||
forLabel={t("webOrigins")}
|
|
||||||
forID={t(`common:helpLabel`, { label: t("webOrigins") })}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<MultiLineInput
|
|
||||||
name="webOrigins"
|
|
||||||
aria-label={t("webOrigins")}
|
|
||||||
addButtonLabel="clients:addWebOrigins"
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("adminURL")}
|
|
||||||
fieldId="kc-admin-url"
|
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="clients-help:adminURL"
|
|
||||||
forLabel={t("adminURL")}
|
|
||||||
forID="kc-admin-url"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<TextInput
|
|
||||||
type="text"
|
|
||||||
id="kc-admin-url"
|
|
||||||
name="adminUrl"
|
|
||||||
ref={register}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
</FormAccess>
|
|
||||||
<FormAccess isHorizontal role="manage-clients">
|
|
||||||
<FormGroup
|
|
||||||
label={t("loginTheme")}
|
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="clients-help:loginTheme"
|
|
||||||
forLabel={t("loginTheme")}
|
|
||||||
forID="loginTheme"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
fieldId="loginTheme"
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="attributes.login_theme"
|
|
||||||
defaultValue=""
|
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Select
|
|
||||||
toggleId="loginTheme"
|
|
||||||
onToggle={() => setLoginThemeOpen(!loginThemeOpen)}
|
|
||||||
onSelect={(_, value) => {
|
|
||||||
onChange(value as string);
|
|
||||||
setLoginThemeOpen(false);
|
|
||||||
}}
|
|
||||||
selections={value || t("common:choose")}
|
|
||||||
variant={SelectVariant.single}
|
|
||||||
aria-label={t("loginTheme")}
|
|
||||||
isOpen={loginThemeOpen}
|
|
||||||
>
|
|
||||||
<SelectOption key="empty" value="">
|
|
||||||
{t("common:choose")}
|
|
||||||
</SelectOption>
|
|
||||||
<>
|
|
||||||
{loginThemes?.map((theme) => (
|
|
||||||
<SelectOption
|
|
||||||
selected={theme.name === value}
|
|
||||||
key={theme.name}
|
|
||||||
value={theme.name}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
</Select>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("consentRequired")}
|
|
||||||
fieldId="kc-consent"
|
|
||||||
hasNoPaddingTop
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="consentRequired"
|
|
||||||
defaultValue={false}
|
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Switch
|
|
||||||
id="kc-consent-switch"
|
|
||||||
label={t("common:on")}
|
|
||||||
labelOff={t("common:off")}
|
|
||||||
isChecked={value}
|
|
||||||
onChange={onChange}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("displayOnClient")}
|
|
||||||
fieldId="kc-display-on-client"
|
|
||||||
hasNoPaddingTop
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="attributes.display-on-consent-screen"
|
|
||||||
defaultValue={false}
|
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Switch
|
|
||||||
id="kc-display-on-client-switch"
|
|
||||||
label={t("common:on")}
|
|
||||||
labelOff={t("common:off")}
|
|
||||||
isChecked={value === "true"}
|
|
||||||
onChange={(value) => onChange("" + value)}
|
|
||||||
isDisabled={!consentRequired}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("consentScreenText")}
|
|
||||||
fieldId="kc-consent-screen-text"
|
|
||||||
>
|
|
||||||
<TextArea
|
|
||||||
id="kc-consent-screen-text"
|
|
||||||
name="attributes.consent-screen-text"
|
|
||||||
ref={register}
|
|
||||||
isDisabled={
|
|
||||||
!(consentRequired && displayOnConsentScreen === "true")
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<SaveReset
|
|
||||||
className="keycloak__form_actions"
|
|
||||||
name="settings"
|
|
||||||
save={save}
|
|
||||||
reset={reset}
|
|
||||||
/>
|
/>
|
||||||
</FormAccess>
|
</FormGroup>
|
||||||
</ScrollForm>
|
<FormGroup
|
||||||
</>
|
label={t("validRedirectUri")}
|
||||||
|
fieldId="kc-redirect"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="clients-help:validRedirectURIs"
|
||||||
|
forLabel={t("validRedirectUri")}
|
||||||
|
forID={t(`common:helpLabel`, { label: t("validRedirectUri") })}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<MultiLineInput
|
||||||
|
name="redirectUris"
|
||||||
|
aria-label={t("validRedirectUri")}
|
||||||
|
addButtonLabel="clients:addRedirectUri"
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("homeURL")}
|
||||||
|
fieldId="kc-home-url"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="clients-help:homeURL"
|
||||||
|
forLabel={t("homeURL")}
|
||||||
|
forID={t(`common:helpLabel`, { label: t("homeURL") })}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
type="text"
|
||||||
|
id="kc-home-url"
|
||||||
|
name="baseUrl"
|
||||||
|
ref={register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("webOrigins")}
|
||||||
|
fieldId="kc-web-origins"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="clients-help:webOrigins"
|
||||||
|
forLabel={t("webOrigins")}
|
||||||
|
forID={t(`common:helpLabel`, { label: t("webOrigins") })}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<MultiLineInput
|
||||||
|
name="webOrigins"
|
||||||
|
aria-label={t("webOrigins")}
|
||||||
|
addButtonLabel="clients:addWebOrigins"
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("adminURL")}
|
||||||
|
fieldId="kc-admin-url"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="clients-help:adminURL"
|
||||||
|
forLabel={t("adminURL")}
|
||||||
|
forID="kc-admin-url"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
type="text"
|
||||||
|
id="kc-admin-url"
|
||||||
|
name="adminUrl"
|
||||||
|
ref={register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</FormAccess>
|
||||||
|
<FormAccess isHorizontal role="manage-clients">
|
||||||
|
<FormGroup
|
||||||
|
label={t("loginTheme")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="clients-help:loginTheme"
|
||||||
|
forLabel={t("loginTheme")}
|
||||||
|
forID="loginTheme"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
fieldId="loginTheme"
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="attributes.login_theme"
|
||||||
|
defaultValue=""
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Select
|
||||||
|
toggleId="loginTheme"
|
||||||
|
onToggle={() => setLoginThemeOpen(!loginThemeOpen)}
|
||||||
|
onSelect={(_, value) => {
|
||||||
|
onChange(value as string);
|
||||||
|
setLoginThemeOpen(false);
|
||||||
|
}}
|
||||||
|
selections={value || t("common:choose")}
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
aria-label={t("loginTheme")}
|
||||||
|
isOpen={loginThemeOpen}
|
||||||
|
>
|
||||||
|
<SelectOption key="empty" value="">
|
||||||
|
{t("common:choose")}
|
||||||
|
</SelectOption>
|
||||||
|
{/* The type for the children of Select are incorrect, so we need a fragment here. */}
|
||||||
|
{/* eslint-disable-next-line react/jsx-no-useless-fragment */}
|
||||||
|
<>
|
||||||
|
{loginThemes?.map((theme) => (
|
||||||
|
<SelectOption
|
||||||
|
selected={theme.name === value}
|
||||||
|
key={theme.name}
|
||||||
|
value={theme.name}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("consentRequired")}
|
||||||
|
fieldId="kc-consent"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="consentRequired"
|
||||||
|
defaultValue={false}
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id="kc-consent-switch"
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
isChecked={value}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("displayOnClient")}
|
||||||
|
fieldId="kc-display-on-client"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="attributes.display-on-consent-screen"
|
||||||
|
defaultValue={false}
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id="kc-display-on-client-switch"
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
isChecked={value === "true"}
|
||||||
|
onChange={(value) => onChange("" + value)}
|
||||||
|
isDisabled={!consentRequired}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("consentScreenText")}
|
||||||
|
fieldId="kc-consent-screen-text"
|
||||||
|
>
|
||||||
|
<TextArea
|
||||||
|
id="kc-consent-screen-text"
|
||||||
|
name="attributes.consent-screen-text"
|
||||||
|
ref={register}
|
||||||
|
isDisabled={!(consentRequired && displayOnConsentScreen === "true")}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<SaveReset
|
||||||
|
className="keycloak__form_actions"
|
||||||
|
name="settings"
|
||||||
|
save={save}
|
||||||
|
reset={reset}
|
||||||
|
/>
|
||||||
|
</FormAccess>
|
||||||
|
</ScrollForm>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -70,27 +70,23 @@ export const ClientsSection = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const ClientDetailLink = (client: ClientRepresentation) => (
|
const ClientDetailLink = (client: ClientRepresentation) => (
|
||||||
<>
|
<Link
|
||||||
<Link
|
key={client.id}
|
||||||
key={client.id}
|
to={toClient({ realm, clientId: client.id!, tab: "settings" })}
|
||||||
to={toClient({ realm, clientId: client.id!, tab: "settings" })}
|
>
|
||||||
>
|
{client.clientId}
|
||||||
{client.clientId}
|
{!client.enabled && (
|
||||||
{!client.enabled && (
|
<Badge key={`${client.id}-disabled`} isRead className="pf-u-ml-sm">
|
||||||
<Badge key={`${client.id}-disabled`} isRead className="pf-u-ml-sm">
|
{t("common:disabled")}
|
||||||
{t("common:disabled")}
|
</Badge>
|
||||||
</Badge>
|
)}
|
||||||
)}
|
</Link>
|
||||||
</Link>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const ClientDescription = (client: ClientRepresentation) => (
|
const ClientDescription = (client: ClientRepresentation) => (
|
||||||
<>
|
<TableText wrapModifier="truncate">
|
||||||
<TableText wrapModifier="truncate">
|
{emptyFormatter()(client.description)}
|
||||||
{emptyFormatter()(client.description)}
|
</TableText>
|
||||||
</TableText>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -38,264 +38,260 @@ export const CapabilityConfig = ({
|
||||||
unWrap={unWrap}
|
unWrap={unWrap}
|
||||||
className="keycloak__capability-config__form"
|
className="keycloak__capability-config__form"
|
||||||
>
|
>
|
||||||
<>
|
{protocol === "openid-connect" && (
|
||||||
{protocol === "openid-connect" && (
|
<>
|
||||||
<>
|
<FormGroup
|
||||||
<FormGroup
|
hasNoPaddingTop
|
||||||
hasNoPaddingTop
|
label={t("clientAuthentication")}
|
||||||
label={t("clientAuthentication")}
|
fieldId="kc-authentication"
|
||||||
fieldId="kc-authentication"
|
labelIcon={
|
||||||
labelIcon={
|
<HelpItem
|
||||||
<HelpItem
|
helpText="clients-help:authentication"
|
||||||
helpText="clients-help:authentication"
|
forLabel={t("authentication")}
|
||||||
forLabel={t("authentication")}
|
forID={t(`common:helpLabel`, { label: t("authentication") })}
|
||||||
forID={t(`common:helpLabel`, { label: t("authentication") })}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="publicClient"
|
|
||||||
defaultValue={false}
|
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Switch
|
|
||||||
data-testid="authentication"
|
|
||||||
id="kc-authentication-switch"
|
|
||||||
name="publicClient"
|
|
||||||
label={t("common:on")}
|
|
||||||
labelOff={t("common:off")}
|
|
||||||
isChecked={!value}
|
|
||||||
onChange={(value) => {
|
|
||||||
onChange(!value);
|
|
||||||
if (!value) {
|
|
||||||
setValue("authorizationServicesEnabled", false);
|
|
||||||
setValue("serviceAccountsEnabled", false);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
<FormGroup
|
>
|
||||||
hasNoPaddingTop
|
<Controller
|
||||||
label={t("clientAuthorization")}
|
name="publicClient"
|
||||||
fieldId="kc-authorization"
|
defaultValue={false}
|
||||||
labelIcon={
|
control={control}
|
||||||
<HelpItem
|
render={({ onChange, value }) => (
|
||||||
helpText="clients-help:authorization"
|
<Switch
|
||||||
forLabel={t("authorization")}
|
data-testid="authentication"
|
||||||
forID={t(`common:helpLabel`, { label: t("authorization") })}
|
id="kc-authentication-switch"
|
||||||
|
name="publicClient"
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
isChecked={!value}
|
||||||
|
onChange={(value) => {
|
||||||
|
onChange(!value);
|
||||||
|
if (!value) {
|
||||||
|
setValue("authorizationServicesEnabled", false);
|
||||||
|
setValue("serviceAccountsEnabled", false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
>
|
/>
|
||||||
<Controller
|
</FormGroup>
|
||||||
name="authorizationServicesEnabled"
|
<FormGroup
|
||||||
defaultValue={false}
|
hasNoPaddingTop
|
||||||
control={control}
|
label={t("clientAuthorization")}
|
||||||
render={({ onChange, value }) => (
|
fieldId="kc-authorization"
|
||||||
<Switch
|
labelIcon={
|
||||||
data-testid="authorization"
|
<HelpItem
|
||||||
id="kc-authorization-switch"
|
helpText="clients-help:authorization"
|
||||||
name="authorizationServicesEnabled"
|
forLabel={t("authorization")}
|
||||||
label={t("common:on")}
|
forID={t(`common:helpLabel`, { label: t("authorization") })}
|
||||||
labelOff={t("common:off")}
|
|
||||||
isChecked={value && !clientAuthentication}
|
|
||||||
onChange={(value) => {
|
|
||||||
onChange(value);
|
|
||||||
if (value) {
|
|
||||||
setValue("serviceAccountsEnabled", true);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
isDisabled={clientAuthentication}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
<FormGroup
|
>
|
||||||
hasNoPaddingTop
|
<Controller
|
||||||
label={t("authenticationFlow")}
|
name="authorizationServicesEnabled"
|
||||||
fieldId="kc-flow"
|
defaultValue={false}
|
||||||
>
|
control={control}
|
||||||
<Grid>
|
render={({ onChange, value }) => (
|
||||||
<GridItem lg={4} sm={6}>
|
<Switch
|
||||||
<Controller
|
data-testid="authorization"
|
||||||
name="standardFlowEnabled"
|
id="kc-authorization-switch"
|
||||||
defaultValue={true}
|
name="authorizationServicesEnabled"
|
||||||
control={control}
|
label={t("common:on")}
|
||||||
render={({ onChange, value }) => (
|
labelOff={t("common:off")}
|
||||||
<InputGroup>
|
isChecked={value && !clientAuthentication}
|
||||||
<Checkbox
|
onChange={(value) => {
|
||||||
data-testid="standard"
|
onChange(value);
|
||||||
label={t("standardFlow")}
|
if (value) {
|
||||||
id="kc-flow-standard"
|
setValue("serviceAccountsEnabled", true);
|
||||||
name="standardFlowEnabled"
|
}
|
||||||
isChecked={value}
|
}}
|
||||||
onChange={onChange}
|
isDisabled={clientAuthentication}
|
||||||
/>
|
|
||||||
<HelpItem
|
|
||||||
helpText="clients-help:standardFlow"
|
|
||||||
forLabel={t("standardFlow")}
|
|
||||||
forID={t(`common:helpLabel`, {
|
|
||||||
label: t("standardFlow"),
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</GridItem>
|
|
||||||
<GridItem lg={8} sm={6}>
|
|
||||||
<Controller
|
|
||||||
name="directAccessGrantsEnabled"
|
|
||||||
defaultValue={true}
|
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<InputGroup>
|
|
||||||
<Checkbox
|
|
||||||
data-testid="direct"
|
|
||||||
label={t("directAccess")}
|
|
||||||
id="kc-flow-direct"
|
|
||||||
name="directAccessGrantsEnabled"
|
|
||||||
isChecked={value}
|
|
||||||
onChange={onChange}
|
|
||||||
/>
|
|
||||||
<HelpItem
|
|
||||||
helpText="clients-help:directAccess"
|
|
||||||
forLabel={t("directAccess")}
|
|
||||||
forID={t(`common:helpLabel`, {
|
|
||||||
label: t("directAccess"),
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</GridItem>
|
|
||||||
<GridItem lg={4} sm={6}>
|
|
||||||
<Controller
|
|
||||||
name="implicitFlowEnabled"
|
|
||||||
defaultValue={false}
|
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<InputGroup>
|
|
||||||
<Checkbox
|
|
||||||
data-testid="implicit"
|
|
||||||
label={t("implicitFlow")}
|
|
||||||
id="kc-flow-implicit"
|
|
||||||
name="implicitFlowEnabled"
|
|
||||||
isChecked={value}
|
|
||||||
onChange={onChange}
|
|
||||||
/>
|
|
||||||
<HelpItem
|
|
||||||
helpText="clients-help:implicitFlow"
|
|
||||||
forLabel={t("implicitFlow")}
|
|
||||||
forID={t(`common:helpLabel`, {
|
|
||||||
label: t("implicitFlow"),
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</GridItem>
|
|
||||||
<GridItem lg={8} sm={6}>
|
|
||||||
<Controller
|
|
||||||
name="serviceAccountsEnabled"
|
|
||||||
defaultValue={false}
|
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<InputGroup>
|
|
||||||
<Checkbox
|
|
||||||
data-testid="service-account"
|
|
||||||
label={t("serviceAccount")}
|
|
||||||
id="kc-flow-service-account"
|
|
||||||
name="serviceAccountsEnabled"
|
|
||||||
isChecked={
|
|
||||||
value || (clientAuthentication && authorization)
|
|
||||||
}
|
|
||||||
onChange={onChange}
|
|
||||||
isDisabled={
|
|
||||||
(clientAuthentication && !authorization) ||
|
|
||||||
(!clientAuthentication && authorization)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<HelpItem
|
|
||||||
helpText="clients-help:serviceAccount"
|
|
||||||
forLabel={t("serviceAccount")}
|
|
||||||
forID={t(`common:helpLabel`, {
|
|
||||||
label: t("serviceAccount"),
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</GridItem>
|
|
||||||
</Grid>
|
|
||||||
</FormGroup>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
<>
|
|
||||||
{protocol === "saml" && (
|
|
||||||
<>
|
|
||||||
<FormGroup
|
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="clients-help:encryptAssertions"
|
|
||||||
forLabel={t("encryptAssertions")}
|
|
||||||
forID={t(`common:helpLabel`, {
|
|
||||||
label: t("encryptAssertions"),
|
|
||||||
})}
|
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
label={t("encryptAssertions")}
|
/>
|
||||||
fieldId="kc-encrypt"
|
</FormGroup>
|
||||||
hasNoPaddingTop
|
<FormGroup
|
||||||
>
|
hasNoPaddingTop
|
||||||
<Controller
|
label={t("authenticationFlow")}
|
||||||
name="attributes.saml_encrypt"
|
fieldId="kc-flow"
|
||||||
control={control}
|
>
|
||||||
defaultValue="false"
|
<Grid>
|
||||||
render={({ onChange, value }) => (
|
<GridItem lg={4} sm={6}>
|
||||||
<Switch
|
<Controller
|
||||||
data-testid="encrypt"
|
name="standardFlowEnabled"
|
||||||
id="kc-encrypt"
|
defaultValue={true}
|
||||||
label={t("common:on")}
|
control={control}
|
||||||
labelOff={t("common:off")}
|
render={({ onChange, value }) => (
|
||||||
isChecked={value === "true"}
|
<InputGroup>
|
||||||
onChange={(value) => onChange("" + value)}
|
<Checkbox
|
||||||
/>
|
data-testid="standard"
|
||||||
)}
|
label={t("standardFlow")}
|
||||||
/>
|
id="kc-flow-standard"
|
||||||
</FormGroup>
|
name="standardFlowEnabled"
|
||||||
<FormGroup
|
isChecked={value}
|
||||||
labelIcon={
|
onChange={onChange}
|
||||||
<HelpItem
|
/>
|
||||||
helpText="clients-help:clientSignature"
|
<HelpItem
|
||||||
forLabel={t("clientSignature")}
|
helpText="clients-help:standardFlow"
|
||||||
forID={t(`common:helpLabel`, { label: t("clientSignature") })}
|
forLabel={t("standardFlow")}
|
||||||
|
forID={t(`common:helpLabel`, {
|
||||||
|
label: t("standardFlow"),
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</InputGroup>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
}
|
</GridItem>
|
||||||
label={t("clientSignature")}
|
<GridItem lg={8} sm={6}>
|
||||||
fieldId="kc-client-signature"
|
<Controller
|
||||||
hasNoPaddingTop
|
name="directAccessGrantsEnabled"
|
||||||
>
|
defaultValue={true}
|
||||||
<Controller
|
control={control}
|
||||||
name="attributes.saml_client_signature"
|
render={({ onChange, value }) => (
|
||||||
control={control}
|
<InputGroup>
|
||||||
defaultValue="false"
|
<Checkbox
|
||||||
render={({ onChange, value }) => (
|
data-testid="direct"
|
||||||
<Switch
|
label={t("directAccess")}
|
||||||
data-testid="client-signature"
|
id="kc-flow-direct"
|
||||||
id="kc-client-signature"
|
name="directAccessGrantsEnabled"
|
||||||
label={t("common:on")}
|
isChecked={value}
|
||||||
labelOff={t("common:off")}
|
onChange={onChange}
|
||||||
isChecked={value === "true"}
|
/>
|
||||||
onChange={(value) => onChange("" + value)}
|
<HelpItem
|
||||||
/>
|
helpText="clients-help:directAccess"
|
||||||
)}
|
forLabel={t("directAccess")}
|
||||||
|
forID={t(`common:helpLabel`, {
|
||||||
|
label: t("directAccess"),
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</InputGroup>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
<GridItem lg={4} sm={6}>
|
||||||
|
<Controller
|
||||||
|
name="implicitFlowEnabled"
|
||||||
|
defaultValue={false}
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<InputGroup>
|
||||||
|
<Checkbox
|
||||||
|
data-testid="implicit"
|
||||||
|
label={t("implicitFlow")}
|
||||||
|
id="kc-flow-implicit"
|
||||||
|
name="implicitFlowEnabled"
|
||||||
|
isChecked={value}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
<HelpItem
|
||||||
|
helpText="clients-help:implicitFlow"
|
||||||
|
forLabel={t("implicitFlow")}
|
||||||
|
forID={t(`common:helpLabel`, {
|
||||||
|
label: t("implicitFlow"),
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</InputGroup>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
<GridItem lg={8} sm={6}>
|
||||||
|
<Controller
|
||||||
|
name="serviceAccountsEnabled"
|
||||||
|
defaultValue={false}
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<InputGroup>
|
||||||
|
<Checkbox
|
||||||
|
data-testid="service-account"
|
||||||
|
label={t("serviceAccount")}
|
||||||
|
id="kc-flow-service-account"
|
||||||
|
name="serviceAccountsEnabled"
|
||||||
|
isChecked={
|
||||||
|
value || (clientAuthentication && authorization)
|
||||||
|
}
|
||||||
|
onChange={onChange}
|
||||||
|
isDisabled={
|
||||||
|
(clientAuthentication && !authorization) ||
|
||||||
|
(!clientAuthentication && authorization)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<HelpItem
|
||||||
|
helpText="clients-help:serviceAccount"
|
||||||
|
forLabel={t("serviceAccount")}
|
||||||
|
forID={t(`common:helpLabel`, {
|
||||||
|
label: t("serviceAccount"),
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</InputGroup>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
</Grid>
|
||||||
|
</FormGroup>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{protocol === "saml" && (
|
||||||
|
<>
|
||||||
|
<FormGroup
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="clients-help:encryptAssertions"
|
||||||
|
forLabel={t("encryptAssertions")}
|
||||||
|
forID={t(`common:helpLabel`, {
|
||||||
|
label: t("encryptAssertions"),
|
||||||
|
})}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
</>
|
label={t("encryptAssertions")}
|
||||||
)}
|
fieldId="kc-encrypt"
|
||||||
</>
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="attributes.saml_encrypt"
|
||||||
|
control={control}
|
||||||
|
defaultValue="false"
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
data-testid="encrypt"
|
||||||
|
id="kc-encrypt"
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
isChecked={value === "true"}
|
||||||
|
onChange={(value) => onChange("" + value)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="clients-help:clientSignature"
|
||||||
|
forLabel={t("clientSignature")}
|
||||||
|
forID={t(`common:helpLabel`, { label: t("clientSignature") })}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={t("clientSignature")}
|
||||||
|
fieldId="kc-client-signature"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="attributes.saml_client_signature"
|
||||||
|
control={control}
|
||||||
|
defaultValue="false"
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
data-testid="client-signature"
|
||||||
|
id="kc-client-signature"
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
isChecked={value === "true"}
|
||||||
|
onChange={(value) => onChange("" + value)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</FormAccess>
|
</FormAccess>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,52 +21,50 @@ export const SignedJWT = () => {
|
||||||
|
|
||||||
const [open, isOpen] = useState(false);
|
const [open, isOpen] = useState(false);
|
||||||
return (
|
return (
|
||||||
<>
|
<FormGroup
|
||||||
<FormGroup
|
label={t("signatureAlgorithm")}
|
||||||
label={t("signatureAlgorithm")}
|
fieldId="kc-signature-algorithm"
|
||||||
fieldId="kc-signature-algorithm"
|
labelIcon={
|
||||||
labelIcon={
|
<HelpItem
|
||||||
<HelpItem
|
helpText="clients-help:signature-algorithm"
|
||||||
helpText="clients-help:signature-algorithm"
|
forLabel={t("signatureAlgorithm")}
|
||||||
forLabel={t("signatureAlgorithm")}
|
forID="kc-signature-algorithm"
|
||||||
forID="kc-signature-algorithm"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="attributes.token-endpoint-auth-signing-alg"
|
|
||||||
defaultValue=""
|
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Select
|
|
||||||
maxHeight={200}
|
|
||||||
toggleId="kc-signature-algorithm"
|
|
||||||
onToggle={() => isOpen(!open)}
|
|
||||||
onSelect={(_, value) => {
|
|
||||||
onChange(value as string);
|
|
||||||
isOpen(false);
|
|
||||||
}}
|
|
||||||
selections={value || t("anyAlgorithm")}
|
|
||||||
variant={SelectVariant.single}
|
|
||||||
aria-label={t("signatureAlgorithm")}
|
|
||||||
isOpen={open}
|
|
||||||
>
|
|
||||||
<SelectOption selected={value === ""} key="any" value="">
|
|
||||||
{t("anyAlgorithm")}
|
|
||||||
</SelectOption>
|
|
||||||
<>
|
|
||||||
{providers.map((option) => (
|
|
||||||
<SelectOption
|
|
||||||
selected={option === value}
|
|
||||||
key={option}
|
|
||||||
value={option}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
</Select>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
</>
|
>
|
||||||
|
<Controller
|
||||||
|
name="attributes.token-endpoint-auth-signing-alg"
|
||||||
|
defaultValue=""
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Select
|
||||||
|
maxHeight={200}
|
||||||
|
toggleId="kc-signature-algorithm"
|
||||||
|
onToggle={() => isOpen(!open)}
|
||||||
|
onSelect={(_, value) => {
|
||||||
|
onChange(value as string);
|
||||||
|
isOpen(false);
|
||||||
|
}}
|
||||||
|
selections={value || t("anyAlgorithm")}
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
aria-label={t("signatureAlgorithm")}
|
||||||
|
isOpen={open}
|
||||||
|
>
|
||||||
|
<SelectOption selected={value === ""} key="any" value="">
|
||||||
|
{t("anyAlgorithm")}
|
||||||
|
</SelectOption>
|
||||||
|
<>
|
||||||
|
{providers.map((option) => (
|
||||||
|
<SelectOption
|
||||||
|
selected={option === value}
|
||||||
|
key={option}
|
||||||
|
value={option}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -153,32 +153,29 @@ export const Keys = ({ clientId, save }: KeysProps) => {
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
{useJwksUrl !== "true" && (
|
{useJwksUrl !== "true" &&
|
||||||
<>
|
(keyInfo ? (
|
||||||
{keyInfo ? (
|
<FormGroup
|
||||||
<FormGroup
|
label={t("certificate")}
|
||||||
label={t("certificate")}
|
fieldId="certificate"
|
||||||
fieldId="certificate"
|
labelIcon={
|
||||||
labelIcon={
|
<HelpItem
|
||||||
<HelpItem
|
helpText="clients-help:certificate"
|
||||||
helpText="clients-help:certificate"
|
forLabel={t("certificate")}
|
||||||
forLabel={t("certificate")}
|
forID="certificate"
|
||||||
forID="certificate"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<TextArea
|
|
||||||
readOnly
|
|
||||||
rows={5}
|
|
||||||
id="certificate"
|
|
||||||
value={keyInfo.certificate}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
) : (
|
>
|
||||||
"No client certificate configured"
|
<TextArea
|
||||||
)}
|
readOnly
|
||||||
</>
|
rows={5}
|
||||||
)}
|
id="certificate"
|
||||||
|
value={keyInfo.certificate}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
) : (
|
||||||
|
"No client certificate configured"
|
||||||
|
))}
|
||||||
{useJwksUrl === "true" && (
|
{useJwksUrl === "true" && (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={t("jwksUrl")}
|
label={t("jwksUrl")}
|
||||||
|
|
|
@ -140,27 +140,25 @@ export const ClientScopes = ({ clientId, protocol }: ClientScopesProps) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const TypeSelector = (scope: Row) => (
|
const TypeSelector = (scope: Row) => (
|
||||||
<>
|
<CellDropdown
|
||||||
<CellDropdown
|
clientScope={scope}
|
||||||
clientScope={scope}
|
type={scope.type}
|
||||||
type={scope.type}
|
onSelect={async (value) => {
|
||||||
onSelect={async (value) => {
|
try {
|
||||||
try {
|
await changeScope(
|
||||||
await changeScope(
|
adminClient,
|
||||||
adminClient,
|
clientId,
|
||||||
clientId,
|
scope,
|
||||||
scope,
|
scope.type,
|
||||||
scope.type,
|
value as ClientScope
|
||||||
value as ClientScope
|
);
|
||||||
);
|
addAlert(t("clientScopeSuccess"), AlertVariant.success);
|
||||||
addAlert(t("clientScopeSuccess"), AlertVariant.success);
|
refresh();
|
||||||
refresh();
|
} catch (error) {
|
||||||
} catch (error) {
|
addError("clients:clientScopeError", error);
|
||||||
addError("clients:clientScopeError", error);
|
}
|
||||||
}
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -97,18 +97,14 @@ export const ServiceAccount = ({ client }: ServiceAccountProps) => {
|
||||||
addError("clients:roleMappingUpdatedError", error);
|
addError("clients:roleMappingUpdatedError", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return serviceAccount ? (
|
||||||
<>
|
<RoleMapping
|
||||||
{serviceAccount && (
|
name={client.clientId!}
|
||||||
<RoleMapping
|
id={serviceAccount.id!}
|
||||||
name={client.clientId!}
|
type="service-account"
|
||||||
id={serviceAccount.id!}
|
loader={loader}
|
||||||
type="service-account"
|
save={assignRoles}
|
||||||
loader={loader}
|
onHideRolesToggle={() => setHide(!hide)}
|
||||||
save={assignRoles}
|
/>
|
||||||
onHideRolesToggle={() => setHide(!hide)}
|
) : null;
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -75,60 +75,73 @@ export const AttributesForm = ({
|
||||||
}, [fields]);
|
}, [fields]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<FormAccess role="manage-realm" onSubmit={handleSubmit(save)}>
|
||||||
<FormAccess role="manage-realm" onSubmit={handleSubmit(save)}>
|
<TableComposable
|
||||||
<TableComposable
|
className="kc-attributes__table"
|
||||||
className="kc-attributes__table"
|
aria-label="Role attribute keys and values"
|
||||||
aria-label="Role attribute keys and values"
|
variant="compact"
|
||||||
variant="compact"
|
borders={false}
|
||||||
borders={false}
|
>
|
||||||
>
|
<Thead>
|
||||||
<Thead>
|
<Tr>
|
||||||
<Tr>
|
<Th id="key" width={40}>
|
||||||
<Th id="key" width={40}>
|
{columns[0]}
|
||||||
{columns[0]}
|
</Th>
|
||||||
</Th>
|
<Th id="value" width={40}>
|
||||||
<Th id="value" width={40}>
|
{columns[1]}
|
||||||
{columns[1]}
|
</Th>
|
||||||
</Th>
|
</Tr>
|
||||||
</Tr>
|
</Thead>
|
||||||
</Thead>
|
<Tbody>
|
||||||
<Tbody>
|
{fields.map((attribute, rowIndex) => (
|
||||||
{fields.map((attribute, rowIndex) => (
|
<Tr key={attribute.id}>
|
||||||
<Tr key={attribute.id}>
|
<Td
|
||||||
|
key={`${attribute.id}-key`}
|
||||||
|
id={`text-input-${rowIndex}-key`}
|
||||||
|
dataLabel={columns[0]}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
name={`attributes[${rowIndex}].key`}
|
||||||
|
ref={register()}
|
||||||
|
aria-label="key-input"
|
||||||
|
defaultValue={attribute.key}
|
||||||
|
validated={
|
||||||
|
errors.attributes?.[rowIndex] ? "error" : "default"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Td>
|
||||||
|
<Td
|
||||||
|
key={`${attribute}-value`}
|
||||||
|
id={`text-input-${rowIndex}-value`}
|
||||||
|
dataLabel={columns[1]}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
name={`attributes[${rowIndex}].value`}
|
||||||
|
ref={register()}
|
||||||
|
aria-label="value-input"
|
||||||
|
defaultValue={attribute.value}
|
||||||
|
/>
|
||||||
|
</Td>
|
||||||
|
{rowIndex !== fields.length - 1 && fields.length - 1 !== 0 && (
|
||||||
<Td
|
<Td
|
||||||
key={`${attribute.id}-key`}
|
key="minus-button"
|
||||||
id={`text-input-${rowIndex}-key`}
|
id={`kc-minus-button-${rowIndex}`}
|
||||||
dataLabel={columns[0]}
|
dataLabel={columns[2]}
|
||||||
>
|
>
|
||||||
<TextInput
|
<Button
|
||||||
name={`attributes[${rowIndex}].key`}
|
id={`minus-button-${rowIndex}`}
|
||||||
ref={register()}
|
aria-label={`remove ${attribute.key} with value ${attribute.value} `}
|
||||||
aria-label="key-input"
|
variant="link"
|
||||||
defaultValue={attribute.key}
|
className="kc-attributes__minus-icon"
|
||||||
validated={
|
onClick={() => remove(rowIndex)}
|
||||||
errors.attributes?.[rowIndex] ? "error" : "default"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Td>
|
|
||||||
<Td
|
|
||||||
key={`${attribute}-value`}
|
|
||||||
id={`text-input-${rowIndex}-value`}
|
|
||||||
dataLabel={columns[1]}
|
|
||||||
>
|
|
||||||
<TextInput
|
|
||||||
name={`attributes[${rowIndex}].value`}
|
|
||||||
ref={register()}
|
|
||||||
aria-label="value-input"
|
|
||||||
defaultValue={attribute.value}
|
|
||||||
/>
|
|
||||||
</Td>
|
|
||||||
{rowIndex !== fields.length - 1 && fields.length - 1 !== 0 && (
|
|
||||||
<Td
|
|
||||||
key="minus-button"
|
|
||||||
id={`kc-minus-button-${rowIndex}`}
|
|
||||||
dataLabel={columns[2]}
|
|
||||||
>
|
>
|
||||||
|
<MinusCircleIcon />
|
||||||
|
</Button>
|
||||||
|
</Td>
|
||||||
|
)}
|
||||||
|
{rowIndex === fields.length - 1 && (
|
||||||
|
<Td key="add-button" id="add-button" dataLabel={columns[2]}>
|
||||||
|
{fields.length !== 1 && (
|
||||||
<Button
|
<Button
|
||||||
id={`minus-button-${rowIndex}`}
|
id={`minus-button-${rowIndex}`}
|
||||||
aria-label={`remove ${attribute.key} with value ${attribute.value} `}
|
aria-label={`remove ${attribute.key} with value ${attribute.value} `}
|
||||||
|
@ -138,55 +151,36 @@ export const AttributesForm = ({
|
||||||
>
|
>
|
||||||
<MinusCircleIcon />
|
<MinusCircleIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</Td>
|
)}
|
||||||
)}
|
</Td>
|
||||||
{rowIndex === fields.length - 1 && (
|
)}
|
||||||
<Td key="add-button" id="add-button" dataLabel={columns[2]}>
|
|
||||||
{fields.length !== 1 && (
|
|
||||||
<Button
|
|
||||||
id={`minus-button-${rowIndex}`}
|
|
||||||
aria-label={`remove ${attribute.key} with value ${attribute.value} `}
|
|
||||||
variant="link"
|
|
||||||
className="kc-attributes__minus-icon"
|
|
||||||
onClick={() => remove(rowIndex)}
|
|
||||||
>
|
|
||||||
<MinusCircleIcon />
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</Td>
|
|
||||||
)}
|
|
||||||
</Tr>
|
|
||||||
))}
|
|
||||||
<Tr>
|
|
||||||
<Td>
|
|
||||||
<Button
|
|
||||||
aria-label={t("roles:addAttributeText")}
|
|
||||||
id="plus-icon"
|
|
||||||
variant="link"
|
|
||||||
className="kc-attributes__plus-icon"
|
|
||||||
onClick={() => append({ key: "", value: "" })}
|
|
||||||
icon={<PlusCircleIcon />}
|
|
||||||
isDisabled={!watchLast}
|
|
||||||
>
|
|
||||||
{t("roles:addAttributeText")}
|
|
||||||
</Button>
|
|
||||||
</Td>
|
|
||||||
</Tr>
|
</Tr>
|
||||||
</Tbody>
|
))}
|
||||||
</TableComposable>
|
<Tr>
|
||||||
<ActionGroup className="kc-attributes__action-group">
|
<Td>
|
||||||
<Button variant="primary" type="submit" isDisabled={!watchLast}>
|
<Button
|
||||||
{t("common:save")}
|
aria-label={t("roles:addAttributeText")}
|
||||||
</Button>
|
id="plus-icon"
|
||||||
<Button
|
variant="link"
|
||||||
onClick={reset}
|
className="kc-attributes__plus-icon"
|
||||||
variant="link"
|
onClick={() => append({ key: "", value: "" })}
|
||||||
isDisabled={!formState.isDirty}
|
icon={<PlusCircleIcon />}
|
||||||
>
|
isDisabled={!watchLast}
|
||||||
{t("common:revert")}
|
>
|
||||||
</Button>
|
{t("roles:addAttributeText")}
|
||||||
</ActionGroup>
|
</Button>
|
||||||
</FormAccess>
|
</Td>
|
||||||
</>
|
</Tr>
|
||||||
|
</Tbody>
|
||||||
|
</TableComposable>
|
||||||
|
<ActionGroup className="kc-attributes__action-group">
|
||||||
|
<Button variant="primary" type="submit" isDisabled={!watchLast}>
|
||||||
|
{t("common:save")}
|
||||||
|
</Button>
|
||||||
|
<Button onClick={reset} variant="link" isDisabled={!formState.isDirty}>
|
||||||
|
{t("common:revert")}
|
||||||
|
</Button>
|
||||||
|
</ActionGroup>
|
||||||
|
</FormAccess>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,37 +22,31 @@ export const GroupBreadCrumbs = () => {
|
||||||
});
|
});
|
||||||
}, [history]);
|
}, [history]);
|
||||||
|
|
||||||
return (
|
return subGroups.length !== 0 ? (
|
||||||
<>
|
<Breadcrumb>
|
||||||
{subGroups.length !== 0 && (
|
<BreadcrumbItem key="home">
|
||||||
<Breadcrumb>
|
<Link to={`/${realm}/groups`}>{t("groups")}</Link>
|
||||||
<BreadcrumbItem key="home">
|
</BreadcrumbItem>
|
||||||
<Link to={`/${realm}/groups`}>{t("groups")}</Link>
|
{subGroups.map((group, i) => {
|
||||||
</BreadcrumbItem>
|
const isLastGroup = i === subGroups.length - 1;
|
||||||
{subGroups.map((group, i) => {
|
return (
|
||||||
const isLastGroup = i === subGroups.length - 1;
|
<BreadcrumbItem key={group.id} isActive={isLastGroup}>
|
||||||
return (
|
{!isLastGroup && (
|
||||||
<BreadcrumbItem key={group.id} isActive={isLastGroup}>
|
<Link
|
||||||
{!isLastGroup && (
|
to={location.pathname.substr(
|
||||||
<Link
|
0,
|
||||||
to={location.pathname.substr(
|
location.pathname.indexOf(group.id!) + group.id!.length
|
||||||
0,
|
|
||||||
location.pathname.indexOf(group.id!) + group.id!.length
|
|
||||||
)}
|
|
||||||
onClick={() => remove(group)}
|
|
||||||
>
|
|
||||||
{group.name}
|
|
||||||
</Link>
|
|
||||||
)}
|
)}
|
||||||
{isLastGroup &&
|
onClick={() => remove(group)}
|
||||||
(group.id === "search"
|
>
|
||||||
? group.name
|
{group.name}
|
||||||
: t("groups:groupDetails"))}
|
</Link>
|
||||||
</BreadcrumbItem>
|
)}
|
||||||
);
|
{isLastGroup &&
|
||||||
})}
|
(group.id === "search" ? group.name : t("groups:groupDetails"))}
|
||||||
</Breadcrumb>
|
</BreadcrumbItem>
|
||||||
)}
|
);
|
||||||
</>
|
})}
|
||||||
);
|
</Breadcrumb>
|
||||||
|
) : null;
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,7 +37,7 @@ export const PageBreadCrumbs = () => {
|
||||||
{crumbs.map(({ match, breadcrumb: crumb }, i) => (
|
{crumbs.map(({ match, breadcrumb: crumb }, i) => (
|
||||||
<BreadcrumbItem key={i} isActive={crumbs.length - 1 === i}>
|
<BreadcrumbItem key={i} isActive={crumbs.length - 1 === i}>
|
||||||
{crumbs.length - 1 !== i && <Link to={match.url}>{crumb}</Link>}
|
{crumbs.length - 1 !== i && <Link to={match.url}>{crumb}</Link>}
|
||||||
{crumbs.length - 1 === i && <>{crumb}</>}
|
{crumbs.length - 1 === i && crumb}
|
||||||
</BreadcrumbItem>
|
</BreadcrumbItem>
|
||||||
))}
|
))}
|
||||||
</Breadcrumb>
|
</Breadcrumb>
|
||||||
|
|
|
@ -24,11 +24,9 @@ export const ErrorRenderer = ({ error, resetErrorBoundary }: FallbackProps) => {
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
actionLinks={
|
actionLinks={
|
||||||
<React.Fragment>
|
<AlertActionLink onClick={resetErrorBoundary}>
|
||||||
<AlertActionLink onClick={resetErrorBoundary}>
|
{t("retry")}
|
||||||
{t("retry")}
|
</AlertActionLink>
|
||||||
</AlertActionLink>
|
|
||||||
</React.Fragment>
|
|
||||||
}
|
}
|
||||||
></Alert>
|
></Alert>
|
||||||
</PageSection>
|
</PageSection>
|
||||||
|
|
|
@ -192,7 +192,7 @@ export const GroupPickerDialog = ({
|
||||||
{group.name}
|
{group.name}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{navigation.length - 1 === i && <>{group.name}</>}
|
{navigation.length - 1 === i && group.name}
|
||||||
</BreadcrumbItem>
|
</BreadcrumbItem>
|
||||||
))}
|
))}
|
||||||
</Breadcrumb>
|
</Breadcrumb>
|
||||||
|
@ -255,7 +255,7 @@ export const GroupPickerDialog = ({
|
||||||
dataListCells={[
|
dataListCells={[
|
||||||
<DataListCell key={`name-${group.id}`}>
|
<DataListCell key={`name-${group.id}`}>
|
||||||
{filter === "" ? (
|
{filter === "" ? (
|
||||||
<>{group.name}</>
|
group.name
|
||||||
) : (
|
) : (
|
||||||
<GroupPath group={findSubGroup(group, filter)} />
|
<GroupPath group={findSubGroup(group, filter)} />
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -23,30 +23,24 @@ export const HelpItem = ({
|
||||||
}: HelpItemProps) => {
|
}: HelpItemProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { enabled } = useHelp();
|
const { enabled } = useHelp();
|
||||||
return (
|
return enabled ? (
|
||||||
<>
|
<Popover
|
||||||
{enabled && (
|
bodyContent={isValidElement(helpText) ? helpText : t(helpText as string)}
|
||||||
<Popover
|
>
|
||||||
bodyContent={
|
<>
|
||||||
isValidElement(helpText) ? helpText : t(helpText as string)
|
{!unWrap && (
|
||||||
}
|
<button
|
||||||
>
|
id={id}
|
||||||
<>
|
aria-label={t(`helpLabel`, { label: forLabel })}
|
||||||
{!unWrap && (
|
onClick={(e) => e.preventDefault()}
|
||||||
<button
|
aria-describedby={forID}
|
||||||
id={id}
|
className="pf-c-form__group-label-help"
|
||||||
aria-label={t(`helpLabel`, { label: forLabel })}
|
>
|
||||||
onClick={(e) => e.preventDefault()}
|
<HelpIcon noVerticalAlign={noVerticalAlign} />
|
||||||
aria-describedby={forID}
|
</button>
|
||||||
className="pf-c-form__group-label-help"
|
)}
|
||||||
>
|
{unWrap && <HelpIcon noVerticalAlign={noVerticalAlign} />}
|
||||||
<HelpIcon noVerticalAlign={noVerticalAlign} />
|
</>
|
||||||
</button>
|
</Popover>
|
||||||
)}
|
) : null;
|
||||||
{unWrap && <HelpIcon noVerticalAlign={noVerticalAlign} />}
|
|
||||||
</>
|
|
||||||
</Popover>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,42 +40,40 @@ export const ListEmptyState = ({
|
||||||
icon,
|
icon,
|
||||||
}: ListEmptyStateProps) => {
|
}: ListEmptyStateProps) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<EmptyState data-testid="empty-state" variant="large">
|
||||||
<EmptyState data-testid="empty-state" variant="large">
|
{hasIcon && isSearchVariant ? (
|
||||||
{hasIcon && isSearchVariant ? (
|
<EmptyStateIcon icon={SearchIcon} />
|
||||||
<EmptyStateIcon icon={SearchIcon} />
|
) : (
|
||||||
) : (
|
hasIcon && <EmptyStateIcon icon={icon ? icon : PlusCircleIcon} />
|
||||||
hasIcon && <EmptyStateIcon icon={icon ? icon : PlusCircleIcon} />
|
)}
|
||||||
)}
|
<Title headingLevel="h1" size="lg">
|
||||||
<Title headingLevel="h1" size="lg">
|
{message}
|
||||||
{message}
|
</Title>
|
||||||
</Title>
|
<EmptyStateBody>{instructions}</EmptyStateBody>
|
||||||
<EmptyStateBody>{instructions}</EmptyStateBody>
|
{primaryActionText && (
|
||||||
{primaryActionText && (
|
<Button
|
||||||
<Button
|
data-testid={`${message
|
||||||
data-testid={`${message
|
.replace(/\W+/g, "-")
|
||||||
.replace(/\W+/g, "-")
|
.toLowerCase()}-empty-action`}
|
||||||
.toLowerCase()}-empty-action`}
|
variant="primary"
|
||||||
variant="primary"
|
onClick={onPrimaryAction}
|
||||||
onClick={onPrimaryAction}
|
>
|
||||||
>
|
{primaryActionText}
|
||||||
{primaryActionText}
|
</Button>
|
||||||
</Button>
|
)}
|
||||||
)}
|
{secondaryActions && (
|
||||||
{secondaryActions && (
|
<EmptyStateSecondaryActions>
|
||||||
<EmptyStateSecondaryActions>
|
{secondaryActions.map((action) => (
|
||||||
{secondaryActions.map((action) => (
|
<Button
|
||||||
<Button
|
key={action.text}
|
||||||
key={action.text}
|
variant={action.type || ButtonVariant.secondary}
|
||||||
variant={action.type || ButtonVariant.secondary}
|
onClick={action.onClick}
|
||||||
onClick={action.onClick}
|
>
|
||||||
>
|
{action.text}
|
||||||
{action.text}
|
</Button>
|
||||||
</Button>
|
))}
|
||||||
))}
|
</EmptyStateSecondaryActions>
|
||||||
</EmptyStateSecondaryActions>
|
)}
|
||||||
)}
|
</EmptyState>
|
||||||
</EmptyState>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -427,12 +427,7 @@ export function KeycloakDataTable<T>({
|
||||||
{loading && <Loading />}
|
{loading && <Loading />}
|
||||||
</PaginatingTableToolbar>
|
</PaginatingTableToolbar>
|
||||||
)}
|
)}
|
||||||
<>
|
{!loading && (!data || data?.length === 0) && search === "" && emptyState}
|
||||||
{!loading &&
|
|
||||||
(!data || data?.length === 0) &&
|
|
||||||
search === "" &&
|
|
||||||
emptyState}
|
|
||||||
</>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ export const PaginatingTableToolbar: FunctionComponent<TableToolbarProps> = ({
|
||||||
}
|
}
|
||||||
subToolbar={subToolbar}
|
subToolbar={subToolbar}
|
||||||
toolbarItemFooter={
|
toolbarItemFooter={
|
||||||
count !== 0 ? <ToolbarItem>{pagination("bottom")}</ToolbarItem> : <></>
|
count !== 0 ? <ToolbarItem>{pagination("bottom")}</ToolbarItem> : null
|
||||||
}
|
}
|
||||||
inputGroupName={inputGroupName}
|
inputGroupName={inputGroupName}
|
||||||
inputGroupPlaceholder={inputGroupPlaceholder}
|
inputGroupPlaceholder={inputGroupPlaceholder}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import React, {
|
import React, {
|
||||||
FormEvent,
|
FormEvent,
|
||||||
Fragment,
|
|
||||||
FunctionComponent,
|
FunctionComponent,
|
||||||
ReactNode,
|
ReactNode,
|
||||||
useState,
|
useState,
|
||||||
|
@ -74,35 +73,33 @@ export const TableToolbar: FunctionComponent<TableToolbarProps> = ({
|
||||||
<>
|
<>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<ToolbarContent>
|
<ToolbarContent>
|
||||||
<Fragment>
|
{inputGroupName && (
|
||||||
{inputGroupName && (
|
<ToolbarItem>
|
||||||
<ToolbarItem>
|
<InputGroup>
|
||||||
<InputGroup>
|
{searchTypeComponent}
|
||||||
{searchTypeComponent}
|
{inputGroupPlaceholder && (
|
||||||
{inputGroupPlaceholder && (
|
<>
|
||||||
<>
|
<TextInput
|
||||||
<TextInput
|
name={inputGroupName}
|
||||||
name={inputGroupName}
|
id={inputGroupName}
|
||||||
id={inputGroupName}
|
type="search"
|
||||||
type="search"
|
aria-label={t("search")}
|
||||||
aria-label={t("search")}
|
placeholder={inputGroupPlaceholder}
|
||||||
placeholder={inputGroupPlaceholder}
|
onChange={handleInputChange}
|
||||||
onChange={handleInputChange}
|
onKeyDown={handleKeyDown}
|
||||||
onKeyDown={handleKeyDown}
|
/>
|
||||||
/>
|
<Button
|
||||||
<Button
|
variant={ButtonVariant.control}
|
||||||
variant={ButtonVariant.control}
|
aria-label={t("search")}
|
||||||
aria-label={t("search")}
|
onClick={onSearch}
|
||||||
onClick={onSearch}
|
>
|
||||||
>
|
<SearchIcon />
|
||||||
<SearchIcon />
|
</Button>
|
||||||
</Button>
|
</>
|
||||||
</>
|
)}
|
||||||
)}
|
</InputGroup>
|
||||||
</InputGroup>
|
</ToolbarItem>
|
||||||
</ToolbarItem>
|
)}
|
||||||
)}
|
|
||||||
</Fragment>
|
|
||||||
{toolbarItem}
|
{toolbarItem}
|
||||||
</ToolbarContent>
|
</ToolbarContent>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
|
|
|
@ -101,7 +101,7 @@ export const ViewHeader = ({
|
||||||
</Badge>{" "}
|
</Badge>{" "}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
{isValidElement(badge.text) && <>{badge.text}</>}{" "}
|
{isValidElement(badge.text) && badge.text}{" "}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</LevelItem>
|
</LevelItem>
|
||||||
|
|
|
@ -125,14 +125,10 @@ const Dashboard = () => {
|
||||||
{feature}{" "}
|
{feature}{" "}
|
||||||
{isExperimentalFeature(feature) ? (
|
{isExperimentalFeature(feature) ? (
|
||||||
<Label color="orange">{t("experimental")}</Label>
|
<Label color="orange">{t("experimental")}</Label>
|
||||||
) : (
|
) : null}
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{isPreviewFeature(feature) ? (
|
{isPreviewFeature(feature) ? (
|
||||||
<Label color="blue">{t("preview")}</Label>
|
<Label color="blue">{t("preview")}</Label>
|
||||||
) : (
|
) : null}
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</ListItem>
|
</ListItem>
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
|
|
|
@ -137,165 +137,161 @@ export const AdminEvents = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const LinkResource = (row: AdminEventRepresentation) => (
|
const LinkResource = (row: AdminEventRepresentation) => (
|
||||||
<>
|
<Truncate text={row.resourcePath}>
|
||||||
<Truncate text={row.resourcePath}>
|
{(text) => (
|
||||||
{(text) => (
|
<>
|
||||||
<>
|
{row.resourceType !== "COMPONENT" && (
|
||||||
{row.resourceType !== "COMPONENT" && (
|
<Link
|
||||||
<Link
|
to={`/${realm}/${row.resourcePath}${
|
||||||
to={`/${realm}/${row.resourcePath}${
|
row.resourceType !== "GROUP" ? "/settings" : ""
|
||||||
row.resourceType !== "GROUP" ? "/settings" : ""
|
}`}
|
||||||
}`}
|
>
|
||||||
>
|
{text}
|
||||||
{text}
|
</Link>
|
||||||
</Link>
|
)}
|
||||||
)}
|
{row.resourceType === "COMPONENT" && <span>{text}</span>}
|
||||||
{row.resourceType === "COMPONENT" && <span>{text}</span>}
|
</>
|
||||||
</>
|
)}
|
||||||
)}
|
</Truncate>
|
||||||
</Truncate>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const adminEventSearchFormDisplay = () => {
|
const adminEventSearchFormDisplay = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<Flex
|
||||||
<Flex
|
direction={{ default: "column" }}
|
||||||
direction={{ default: "column" }}
|
spaceItems={{ default: "spaceItemsNone" }}
|
||||||
spaceItems={{ default: "spaceItemsNone" }}
|
>
|
||||||
>
|
<FlexItem>
|
||||||
<FlexItem>
|
<Dropdown
|
||||||
<Dropdown
|
id="admin-events-search-select"
|
||||||
id="admin-events-search-select"
|
data-testid="AdminEventsSearchSelector"
|
||||||
data-testid="AdminEventsSearchSelector"
|
className="pf-u-ml-md"
|
||||||
className="pf-u-ml-md"
|
toggle={
|
||||||
toggle={
|
<DropdownToggle
|
||||||
<DropdownToggle
|
data-testid="adminEventsSearchSelectorToggle"
|
||||||
data-testid="adminEventsSearchSelectorToggle"
|
onToggle={(isOpen) => setSearchDropdownOpen(isOpen)}
|
||||||
onToggle={(isOpen) => setSearchDropdownOpen(isOpen)}
|
className="keycloak__events_search_selector_dropdown__toggle"
|
||||||
className="keycloak__events_search_selector_dropdown__toggle"
|
|
||||||
>
|
|
||||||
{t("searchForAdminEvent")}
|
|
||||||
</DropdownToggle>
|
|
||||||
}
|
|
||||||
isOpen={searchDropdownOpen}
|
|
||||||
>
|
|
||||||
<Form
|
|
||||||
isHorizontal
|
|
||||||
className="keycloak__admin_events_search__form"
|
|
||||||
data-testid="searchForm"
|
|
||||||
>
|
>
|
||||||
<FormGroup
|
{t("searchForAdminEvent")}
|
||||||
label={t("resourceType")}
|
</DropdownToggle>
|
||||||
fieldId="kc-resourceType"
|
}
|
||||||
className="keycloak__events_search__form_multiline_label"
|
isOpen={searchDropdownOpen}
|
||||||
>
|
>
|
||||||
<Select
|
<Form
|
||||||
variant={SelectVariant.single}
|
isHorizontal
|
||||||
onToggle={(isOpen) => setSelectOpen(isOpen)}
|
className="keycloak__admin_events_search__form"
|
||||||
isOpen={selectOpen}
|
data-testid="searchForm"
|
||||||
></Select>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("operationType")}
|
|
||||||
fieldId="kc-operationType"
|
|
||||||
className="keycloak__events_search__form_multiline_label"
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
variant={SelectVariant.single}
|
|
||||||
onToggle={(isOpen) => setSelectOpen(isOpen)}
|
|
||||||
isOpen={selectOpen}
|
|
||||||
></Select>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("user")}
|
|
||||||
fieldId="kc-user"
|
|
||||||
className="keycloak__events_search__form_label"
|
|
||||||
>
|
|
||||||
<TextInput
|
|
||||||
ref={register()}
|
|
||||||
type="text"
|
|
||||||
id="kc-user"
|
|
||||||
name="user"
|
|
||||||
data-testid="user-searchField"
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("realm")}
|
|
||||||
fieldId="kc-realm"
|
|
||||||
className="keycloak__events_search__form_label"
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
variant={SelectVariant.single}
|
|
||||||
onToggle={(isOpen) => setSelectOpen(isOpen)}
|
|
||||||
isOpen={selectOpen}
|
|
||||||
></Select>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("ipAddress")}
|
|
||||||
fieldId="kc-ipAddress"
|
|
||||||
className="keycloak__events_search__form_label"
|
|
||||||
>
|
|
||||||
<TextInput
|
|
||||||
ref={register()}
|
|
||||||
type="text"
|
|
||||||
id="kc-ipAddress"
|
|
||||||
name="ipAddress"
|
|
||||||
data-testid="ipAddress-searchField"
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("dateFrom")}
|
|
||||||
fieldId="kc-dateFrom"
|
|
||||||
className="keycloak__events_search__form_label"
|
|
||||||
>
|
|
||||||
<TextInput
|
|
||||||
ref={register()}
|
|
||||||
type="text"
|
|
||||||
id="kc-dateFrom"
|
|
||||||
name="dateFrom"
|
|
||||||
className="pf-c-form-control pf-m-icon pf-m-calendar"
|
|
||||||
placeholder="yyyy-MM-dd"
|
|
||||||
data-testid="dateFrom-searchField"
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("dateTo")}
|
|
||||||
fieldId="kc-dateTo"
|
|
||||||
className="keycloak__events_search__form_label"
|
|
||||||
>
|
|
||||||
<TextInput
|
|
||||||
ref={register()}
|
|
||||||
type="text"
|
|
||||||
id="kc-dateTo"
|
|
||||||
name="dateTo"
|
|
||||||
className="pf-c-form-control pf-m-icon pf-m-calendar"
|
|
||||||
placeholder="yyyy-MM-dd"
|
|
||||||
data-testid="dateTo-searchField"
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<ActionGroup>
|
|
||||||
<Button
|
|
||||||
className="keycloak__admin_events_search__form_btn"
|
|
||||||
variant={"primary"}
|
|
||||||
data-testid="search-events-btn"
|
|
||||||
isDisabled={!isDirty}
|
|
||||||
>
|
|
||||||
{t("searchAdminEventsBtn")}
|
|
||||||
</Button>
|
|
||||||
</ActionGroup>
|
|
||||||
</Form>
|
|
||||||
</Dropdown>
|
|
||||||
<Button
|
|
||||||
className="pf-u-ml-md"
|
|
||||||
onClick={refresh}
|
|
||||||
data-testid="refresh-btn"
|
|
||||||
>
|
>
|
||||||
{t("refresh")}
|
<FormGroup
|
||||||
</Button>
|
label={t("resourceType")}
|
||||||
</FlexItem>
|
fieldId="kc-resourceType"
|
||||||
</Flex>
|
className="keycloak__events_search__form_multiline_label"
|
||||||
</>
|
>
|
||||||
|
<Select
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
onToggle={(isOpen) => setSelectOpen(isOpen)}
|
||||||
|
isOpen={selectOpen}
|
||||||
|
></Select>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("operationType")}
|
||||||
|
fieldId="kc-operationType"
|
||||||
|
className="keycloak__events_search__form_multiline_label"
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
onToggle={(isOpen) => setSelectOpen(isOpen)}
|
||||||
|
isOpen={selectOpen}
|
||||||
|
></Select>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("user")}
|
||||||
|
fieldId="kc-user"
|
||||||
|
className="keycloak__events_search__form_label"
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
ref={register()}
|
||||||
|
type="text"
|
||||||
|
id="kc-user"
|
||||||
|
name="user"
|
||||||
|
data-testid="user-searchField"
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("realm")}
|
||||||
|
fieldId="kc-realm"
|
||||||
|
className="keycloak__events_search__form_label"
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
onToggle={(isOpen) => setSelectOpen(isOpen)}
|
||||||
|
isOpen={selectOpen}
|
||||||
|
></Select>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("ipAddress")}
|
||||||
|
fieldId="kc-ipAddress"
|
||||||
|
className="keycloak__events_search__form_label"
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
ref={register()}
|
||||||
|
type="text"
|
||||||
|
id="kc-ipAddress"
|
||||||
|
name="ipAddress"
|
||||||
|
data-testid="ipAddress-searchField"
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("dateFrom")}
|
||||||
|
fieldId="kc-dateFrom"
|
||||||
|
className="keycloak__events_search__form_label"
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
ref={register()}
|
||||||
|
type="text"
|
||||||
|
id="kc-dateFrom"
|
||||||
|
name="dateFrom"
|
||||||
|
className="pf-c-form-control pf-m-icon pf-m-calendar"
|
||||||
|
placeholder="yyyy-MM-dd"
|
||||||
|
data-testid="dateFrom-searchField"
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("dateTo")}
|
||||||
|
fieldId="kc-dateTo"
|
||||||
|
className="keycloak__events_search__form_label"
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
ref={register()}
|
||||||
|
type="text"
|
||||||
|
id="kc-dateTo"
|
||||||
|
name="dateTo"
|
||||||
|
className="pf-c-form-control pf-m-icon pf-m-calendar"
|
||||||
|
placeholder="yyyy-MM-dd"
|
||||||
|
data-testid="dateTo-searchField"
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<ActionGroup>
|
||||||
|
<Button
|
||||||
|
className="keycloak__admin_events_search__form_btn"
|
||||||
|
variant={"primary"}
|
||||||
|
data-testid="search-events-btn"
|
||||||
|
isDisabled={!isDirty}
|
||||||
|
>
|
||||||
|
{t("searchAdminEventsBtn")}
|
||||||
|
</Button>
|
||||||
|
</ActionGroup>
|
||||||
|
</Form>
|
||||||
|
</Dropdown>
|
||||||
|
<Button
|
||||||
|
className="pf-u-ml-md"
|
||||||
|
onClick={refresh}
|
||||||
|
data-testid="refresh-btn"
|
||||||
|
>
|
||||||
|
{t("refresh")}
|
||||||
|
</Button>
|
||||||
|
</FlexItem>
|
||||||
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -77,17 +77,15 @@ export const GroupTable = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const GroupNameCell = (group: GroupRepresentation) => (
|
const GroupNameCell = (group: GroupRepresentation) => (
|
||||||
<>
|
<Link
|
||||||
<Link
|
key={group.id}
|
||||||
key={group.id}
|
to={`${location.pathname}/${group.id}`}
|
||||||
to={`${location.pathname}/${group.id}`}
|
onClick={() => {
|
||||||
onClick={() => {
|
setSubGroups([...subGroups, group]);
|
||||||
setSubGroups([...subGroups, group]);
|
}}
|
||||||
}}
|
>
|
||||||
>
|
{group.name}
|
||||||
{group.name}
|
</Link>
|
||||||
</Link>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleModalToggle = () => {
|
const handleModalToggle = () => {
|
||||||
|
|
|
@ -99,11 +99,9 @@ export const Members = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const UserDetailLink = (user: MembersOf) => (
|
const UserDetailLink = (user: MembersOf) => (
|
||||||
<>
|
<Link key={user.id} to={toUser({ realm, id: user.id!, tab: "settings" })}>
|
||||||
<Link key={user.id} to={toUser({ realm, id: user.id!, tab: "settings" })}>
|
{user.username}
|
||||||
{user.username}
|
</Link>
|
||||||
</Link>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -62,17 +62,15 @@ export const SearchGroups = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const GroupNameCell = (group: SearchGroup) => (
|
const GroupNameCell = (group: SearchGroup) => (
|
||||||
<>
|
<Link
|
||||||
<Link
|
key={group.id}
|
||||||
key={group.id}
|
to={`/${realm}/groups/search/${group.link}`}
|
||||||
to={`/${realm}/groups/search/${group.link}`}
|
onClick={() =>
|
||||||
onClick={() =>
|
setSubGroups([{ name: t("searchGroups"), id: "search" }, group])
|
||||||
setSubGroups([{ name: t("searchGroups"), id: "search" }, group])
|
}
|
||||||
}
|
>
|
||||||
>
|
{group.name}
|
||||||
{group.name}
|
</Link>
|
||||||
</Link>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const flatten = (
|
const flatten = (
|
||||||
|
|
|
@ -70,23 +70,21 @@ export const IdentityProvidersSection = () => {
|
||||||
const loader = () => Promise.resolve(_.sortBy(providers, "alias"));
|
const loader = () => Promise.resolve(_.sortBy(providers, "alias"));
|
||||||
|
|
||||||
const DetailLink = (identityProvider: IdentityProviderRepresentation) => (
|
const DetailLink = (identityProvider: IdentityProviderRepresentation) => (
|
||||||
<>
|
<Link
|
||||||
<Link
|
key={identityProvider.providerId}
|
||||||
key={identityProvider.providerId}
|
to={`/${realm}/identity-providers/${identityProvider.providerId}/settings`}
|
||||||
to={`/${realm}/identity-providers/${identityProvider.providerId}/settings`}
|
>
|
||||||
>
|
{identityProvider.alias}
|
||||||
{identityProvider.alias}
|
{!identityProvider.enabled && (
|
||||||
{!identityProvider.enabled && (
|
<Badge
|
||||||
<Badge
|
key={`${identityProvider.providerId}-disabled`}
|
||||||
key={`${identityProvider.providerId}-disabled`}
|
isRead
|
||||||
isRead
|
className="pf-u-ml-sm"
|
||||||
className="pf-u-ml-sm"
|
>
|
||||||
>
|
{t("common:disabled")}
|
||||||
{t("common:disabled")}
|
</Badge>
|
||||||
</Badge>
|
)}
|
||||||
)}
|
</Link>
|
||||||
</Link>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const navigateToCreate = (providerId: string) =>
|
const navigateToCreate = (providerId: string) =>
|
||||||
|
|
|
@ -64,6 +64,8 @@ const LoginFlow = ({
|
||||||
aria-label={t(label)}
|
aria-label={t(label)}
|
||||||
isOpen={open}
|
isOpen={open}
|
||||||
>
|
>
|
||||||
|
{/* The type for the children of Select are incorrect, so we need a fragment here. */}
|
||||||
|
{/* eslint-disable-next-line react/jsx-no-useless-fragment */}
|
||||||
<>
|
<>
|
||||||
{defaultValue === "" && (
|
{defaultValue === "" && (
|
||||||
<SelectOption key="empty" value={defaultValue}>
|
<SelectOption key="empty" value={defaultValue}>
|
||||||
|
@ -71,6 +73,8 @@ const LoginFlow = ({
|
||||||
</SelectOption>
|
</SelectOption>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
{/* The type for the children of Select are incorrect, so we need a fragment here. */}
|
||||||
|
{/* eslint-disable-next-line react/jsx-no-useless-fragment */}
|
||||||
<>
|
<>
|
||||||
{flows?.map((option) => (
|
{flows?.map((option) => (
|
||||||
<SelectOption
|
<SelectOption
|
||||||
|
|
|
@ -32,95 +32,90 @@ export const ExtendedNonDiscoverySettings = () => {
|
||||||
const [promptOpen, setPromptOpen] = useState(false);
|
const [promptOpen, setPromptOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<ExpandableSection
|
||||||
<ExpandableSection
|
toggleText={t("advanced")}
|
||||||
toggleText={t("advanced")}
|
onToggle={() => setIsExpanded(!isExpanded)}
|
||||||
onToggle={() => setIsExpanded(!isExpanded)}
|
isExpanded={isExpanded}
|
||||||
isExpanded={isExpanded}
|
>
|
||||||
>
|
<Form isHorizontal>
|
||||||
<Form isHorizontal>
|
<SwitchField label="passLoginHint" field="config.loginHint" />
|
||||||
<SwitchField label="passLoginHint" field="config.loginHint" />
|
<SwitchField label="passCurrentLocale" field="config.uiLocales" />
|
||||||
<SwitchField label="passCurrentLocale" field="config.uiLocales" />
|
<SwitchField
|
||||||
<SwitchField
|
field="config.backchannelSupported"
|
||||||
field="config.backchannelSupported"
|
label="backchannelLogout"
|
||||||
label="backchannelLogout"
|
/>
|
||||||
|
<SwitchField field="config.disableUserInfo" label="disableUserInfo" />
|
||||||
|
<TextField field="config.defaultScope" label="scopes" />
|
||||||
|
<FormGroupField label="prompt">
|
||||||
|
<Controller
|
||||||
|
name="config.prompt"
|
||||||
|
defaultValue={promptOptions[0]}
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Select
|
||||||
|
toggleId="prompt"
|
||||||
|
required
|
||||||
|
onToggle={() => setPromptOpen(!promptOpen)}
|
||||||
|
onSelect={(_, value) => {
|
||||||
|
onChange(value as string);
|
||||||
|
setPromptOpen(false);
|
||||||
|
}}
|
||||||
|
selections={value}
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
aria-label={t("prompt")}
|
||||||
|
isOpen={promptOpen}
|
||||||
|
>
|
||||||
|
{promptOptions.map((option) => (
|
||||||
|
<SelectOption
|
||||||
|
selected={option === value}
|
||||||
|
key={option}
|
||||||
|
value={option}
|
||||||
|
>
|
||||||
|
{t(`prompts.${option}`)}
|
||||||
|
</SelectOption>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<SwitchField field="config.disableUserInfo" label="disableUserInfo" />
|
</FormGroupField>
|
||||||
<TextField field="config.defaultScope" label="scopes" />
|
<SwitchField
|
||||||
<FormGroupField label="prompt">
|
field="config.acceptsPromptNoneForwardFromClient"
|
||||||
<Controller
|
label="acceptsPromptNone"
|
||||||
name="config.prompt"
|
/>
|
||||||
defaultValue={promptOptions[0]}
|
<FormGroup
|
||||||
control={control}
|
label={t("allowedClockSkew")}
|
||||||
render={({ onChange, value }) => (
|
labelIcon={
|
||||||
<Select
|
<HelpItem
|
||||||
toggleId="prompt"
|
helpText={"identity-providers-help:allowedClockSkew"}
|
||||||
required
|
forLabel={t("allowedClockSkew")}
|
||||||
onToggle={() => setPromptOpen(!promptOpen)}
|
forID="allowedClockSkew"
|
||||||
onSelect={(_, value) => {
|
|
||||||
onChange(value as string);
|
|
||||||
setPromptOpen(false);
|
|
||||||
}}
|
|
||||||
selections={value}
|
|
||||||
variant={SelectVariant.single}
|
|
||||||
aria-label={t("prompt")}
|
|
||||||
isOpen={promptOpen}
|
|
||||||
>
|
|
||||||
{promptOptions.map((option) => (
|
|
||||||
<SelectOption
|
|
||||||
selected={option === value}
|
|
||||||
key={option}
|
|
||||||
value={option}
|
|
||||||
>
|
|
||||||
{t(`prompts.${option}`)}
|
|
||||||
</SelectOption>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</FormGroupField>
|
}
|
||||||
<SwitchField
|
fieldId="allowedClockSkew"
|
||||||
field="config.acceptsPromptNoneForwardFromClient"
|
>
|
||||||
label="acceptsPromptNone"
|
<Controller
|
||||||
/>
|
name="config.allowedClockSkew"
|
||||||
<FormGroup
|
control={control}
|
||||||
label={t("allowedClockSkew")}
|
defaultValue={0}
|
||||||
labelIcon={
|
render={({ onChange, value }) => (
|
||||||
<HelpItem
|
<NumberInput
|
||||||
helpText={"identity-providers-help:allowedClockSkew"}
|
value={value}
|
||||||
forLabel={t("allowedClockSkew")}
|
data-testid="allowedClockSkew"
|
||||||
forID="allowedClockSkew"
|
onMinus={() => onChange(value - 1)}
|
||||||
|
onChange={onChange}
|
||||||
|
onPlus={() => onChange(value + 1)}
|
||||||
|
inputName="input"
|
||||||
|
inputAriaLabel={t("allowedClockSkew")}
|
||||||
|
minusBtnAriaLabel={t("common:minus")}
|
||||||
|
plusBtnAriaLabel={t("common:plus")}
|
||||||
|
min={0}
|
||||||
|
unit={t("common:times.seconds")}
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
fieldId="allowedClockSkew"
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="config.allowedClockSkew"
|
|
||||||
control={control}
|
|
||||||
defaultValue={0}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<NumberInput
|
|
||||||
value={value}
|
|
||||||
data-testid="allowedClockSkew"
|
|
||||||
onMinus={() => onChange(value - 1)}
|
|
||||||
onChange={onChange}
|
|
||||||
onPlus={() => onChange(value + 1)}
|
|
||||||
inputName="input"
|
|
||||||
inputAriaLabel={t("allowedClockSkew")}
|
|
||||||
minusBtnAriaLabel={t("common:minus")}
|
|
||||||
plusBtnAriaLabel={t("common:plus")}
|
|
||||||
min={0}
|
|
||||||
unit={t("common:times.seconds")}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<TextField
|
|
||||||
field="config.forwardParameters"
|
|
||||||
label="forwardParameters"
|
|
||||||
/>
|
/>
|
||||||
</Form>
|
</FormGroup>
|
||||||
</ExpandableSection>
|
<TextField field="config.forwardParameters" label="forwardParameters" />
|
||||||
</>
|
</Form>
|
||||||
|
</ExpandableSection>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,6 +41,6 @@ export const FontAwesomeIcon = ({ icon }: FontAwesomeIconProps) => {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return <></>;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,7 +28,7 @@ export const AliasRendererComponent = ({
|
||||||
}, [containerId]);
|
}, [containerId]);
|
||||||
|
|
||||||
if (filterType === "roles" || !containerName) {
|
if (filterType === "roles" || !containerName) {
|
||||||
return <>{name}</>;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filterType === "clients" || containerName) {
|
if (filterType === "clients" || containerName) {
|
||||||
|
|
|
@ -134,9 +134,8 @@ export const AssociatedRolesTab = ({
|
||||||
refresh();
|
refresh();
|
||||||
}, [additionalRoles, isInheritedHidden]);
|
}, [additionalRoles, isInheritedHidden]);
|
||||||
|
|
||||||
const InheritedRoleName = (role: RoleRepresentation) => {
|
const InheritedRoleName = (role: RoleRepresentation) =>
|
||||||
return <>{inheritanceMap.current[role.id!]}</>;
|
inheritanceMap.current[role.id!];
|
||||||
};
|
|
||||||
|
|
||||||
const AliasRenderer = ({ id, name, clientId }: Role) => {
|
const AliasRenderer = ({ id, name, clientId }: Role) => {
|
||||||
return (
|
return (
|
||||||
|
@ -201,98 +200,96 @@ export const AssociatedRolesTab = ({
|
||||||
|
|
||||||
const goToCreate = () => history.push(`${url}/add-role`);
|
const goToCreate = () => history.push(`${url}/add-role`);
|
||||||
return (
|
return (
|
||||||
<>
|
<PageSection variant="light" padding={{ default: "noPadding" }}>
|
||||||
<PageSection variant="light" padding={{ default: "noPadding" }}>
|
<DeleteConfirm />
|
||||||
<DeleteConfirm />
|
<DeleteAssociatedRolesConfirm />
|
||||||
<DeleteAssociatedRolesConfirm />
|
<AssociatedRolesModal
|
||||||
<AssociatedRolesModal
|
onConfirm={addComposites}
|
||||||
onConfirm={addComposites}
|
existingCompositeRoles={additionalRoles}
|
||||||
existingCompositeRoles={additionalRoles}
|
open={open}
|
||||||
open={open}
|
toggleDialog={() => setOpen(!open)}
|
||||||
toggleDialog={() => setOpen(!open)}
|
/>
|
||||||
/>
|
<KeycloakDataTable
|
||||||
<KeycloakDataTable
|
key={key}
|
||||||
key={key}
|
loader={loader}
|
||||||
loader={loader}
|
ariaLabelKey="roles:roleList"
|
||||||
ariaLabelKey="roles:roleList"
|
searchPlaceholderKey="roles:searchFor"
|
||||||
searchPlaceholderKey="roles:searchFor"
|
canSelectAll
|
||||||
canSelectAll
|
onSelect={(rows) => {
|
||||||
onSelect={(rows) => {
|
setSelectedRows([...rows]);
|
||||||
setSelectedRows([...rows]);
|
}}
|
||||||
}}
|
toolbarItem={
|
||||||
toolbarItem={
|
<>
|
||||||
<>
|
<ToolbarItem>
|
||||||
<ToolbarItem>
|
<Checkbox
|
||||||
<Checkbox
|
label="Hide inherited roles"
|
||||||
label="Hide inherited roles"
|
key="associated-roles-check"
|
||||||
key="associated-roles-check"
|
id="kc-hide-inherited-roles-checkbox"
|
||||||
id="kc-hide-inherited-roles-checkbox"
|
onChange={() => setIsInheritedHidden(!isInheritedHidden)}
|
||||||
onChange={() => setIsInheritedHidden(!isInheritedHidden)}
|
isChecked={isInheritedHidden}
|
||||||
isChecked={isInheritedHidden}
|
/>
|
||||||
/>
|
</ToolbarItem>
|
||||||
</ToolbarItem>
|
<ToolbarItem>
|
||||||
<ToolbarItem>
|
<Button
|
||||||
<Button
|
key="add-role-button"
|
||||||
key="add-role-button"
|
onClick={() => toggleModal()}
|
||||||
onClick={() => toggleModal()}
|
data-testid="add-role-button"
|
||||||
data-testid="add-role-button"
|
>
|
||||||
>
|
{t("addRole")}
|
||||||
{t("addRole")}
|
</Button>
|
||||||
</Button>
|
</ToolbarItem>
|
||||||
</ToolbarItem>
|
<ToolbarItem>
|
||||||
<ToolbarItem>
|
<Button
|
||||||
<Button
|
variant="link"
|
||||||
variant="link"
|
isDisabled={selectedRows.length === 0}
|
||||||
isDisabled={selectedRows.length === 0}
|
key="remove-role-button"
|
||||||
key="remove-role-button"
|
onClick={() => {
|
||||||
onClick={() => {
|
toggleDeleteAssociatedRolesDialog();
|
||||||
toggleDeleteAssociatedRolesDialog();
|
}}
|
||||||
}}
|
>
|
||||||
>
|
{t("removeRoles")}
|
||||||
{t("removeRoles")}
|
</Button>
|
||||||
</Button>
|
</ToolbarItem>
|
||||||
</ToolbarItem>
|
</>
|
||||||
</>
|
}
|
||||||
}
|
actions={[
|
||||||
actions={[
|
{
|
||||||
{
|
title: t("common:remove"),
|
||||||
title: t("common:remove"),
|
onRowClick: (role) => {
|
||||||
onRowClick: (role) => {
|
setSelectedRows([role]);
|
||||||
setSelectedRows([role]);
|
toggleDeleteDialog();
|
||||||
toggleDeleteDialog();
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
]}
|
},
|
||||||
columns={[
|
]}
|
||||||
{
|
columns={[
|
||||||
name: "name",
|
{
|
||||||
displayKey: "roles:roleName",
|
name: "name",
|
||||||
cellRenderer: AliasRenderer,
|
displayKey: "roles:roleName",
|
||||||
cellFormatters: [emptyFormatter()],
|
cellRenderer: AliasRenderer,
|
||||||
},
|
cellFormatters: [emptyFormatter()],
|
||||||
{
|
},
|
||||||
name: "containerId",
|
{
|
||||||
displayKey: "roles:inheritedFrom",
|
name: "containerId",
|
||||||
cellRenderer: InheritedRoleName,
|
displayKey: "roles:inheritedFrom",
|
||||||
cellFormatters: [emptyFormatter()],
|
cellRenderer: InheritedRoleName,
|
||||||
},
|
cellFormatters: [emptyFormatter()],
|
||||||
{
|
},
|
||||||
name: "description",
|
{
|
||||||
displayKey: "common:description",
|
name: "description",
|
||||||
cellFormatters: [emptyFormatter()],
|
displayKey: "common:description",
|
||||||
},
|
cellFormatters: [emptyFormatter()],
|
||||||
]}
|
},
|
||||||
emptyState={
|
]}
|
||||||
<ListEmptyState
|
emptyState={
|
||||||
hasIcon={true}
|
<ListEmptyState
|
||||||
message={t("noRoles")}
|
hasIcon={true}
|
||||||
instructions={t("noRolesInstructions")}
|
message={t("noRoles")}
|
||||||
primaryActionText={t("createRole")}
|
instructions={t("noRolesInstructions")}
|
||||||
onPrimaryAction={goToCreate}
|
primaryActionText={t("createRole")}
|
||||||
/>
|
onPrimaryAction={goToCreate}
|
||||||
}
|
/>
|
||||||
/>
|
}
|
||||||
</PageSection>
|
/>
|
||||||
</>
|
</PageSection>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,61 +45,74 @@ export const RoleAttributes = ({
|
||||||
const watchFirstKey = watch("attributes[0].key", "");
|
const watchFirstKey = watch("attributes[0].key", "");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<FormAccess role="manage-realm">
|
||||||
<FormAccess role="manage-realm">
|
<TableComposable
|
||||||
<TableComposable
|
className="kc-role-attributes__table"
|
||||||
className="kc-role-attributes__table"
|
aria-label="Role attribute keys and values"
|
||||||
aria-label="Role attribute keys and values"
|
variant="compact"
|
||||||
variant="compact"
|
borders={false}
|
||||||
borders={false}
|
>
|
||||||
>
|
<Thead>
|
||||||
<Thead>
|
<Tr>
|
||||||
<Tr>
|
<Th id="key" width={40}>
|
||||||
<Th id="key" width={40}>
|
{columns[0]}
|
||||||
{columns[0]}
|
</Th>
|
||||||
</Th>
|
<Th id="value" width={40}>
|
||||||
<Th id="value" width={40}>
|
{columns[1]}
|
||||||
{columns[1]}
|
</Th>
|
||||||
</Th>
|
</Tr>
|
||||||
</Tr>
|
</Thead>
|
||||||
</Thead>
|
<Tbody>
|
||||||
<Tbody>
|
{fields.map((attribute, rowIndex) => (
|
||||||
{fields.map((attribute, rowIndex) => (
|
<Tr key={attribute.id}>
|
||||||
<Tr key={attribute.id}>
|
<Td
|
||||||
|
key={`${attribute.id}-key`}
|
||||||
|
id={`text-input-${rowIndex}-key`}
|
||||||
|
dataLabel={columns[0]}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
name={`attributes[${rowIndex}].key`}
|
||||||
|
ref={register()}
|
||||||
|
aria-label="key-input"
|
||||||
|
defaultValue={attribute.key}
|
||||||
|
validated={
|
||||||
|
errors.attributes?.[rowIndex] ? "error" : "default"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Td>
|
||||||
|
<Td
|
||||||
|
key={`${attribute}-value`}
|
||||||
|
id={`text-input-${rowIndex}-value`}
|
||||||
|
dataLabel={columns[1]}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
name={`attributes[${rowIndex}].value`}
|
||||||
|
ref={register()}
|
||||||
|
aria-label="value-input"
|
||||||
|
defaultValue={attribute.value}
|
||||||
|
validated={errors.description ? "error" : "default"}
|
||||||
|
/>
|
||||||
|
</Td>
|
||||||
|
{rowIndex !== fields.length - 1 && fields.length - 1 !== 0 && (
|
||||||
<Td
|
<Td
|
||||||
key={`${attribute.id}-key`}
|
key="minus-button"
|
||||||
id={`text-input-${rowIndex}-key`}
|
id={`kc-minus-button-${rowIndex}`}
|
||||||
dataLabel={columns[0]}
|
dataLabel={columns[2]}
|
||||||
>
|
>
|
||||||
<TextInput
|
<Button
|
||||||
name={`attributes[${rowIndex}].key`}
|
id={`minus-button-${rowIndex}`}
|
||||||
ref={register()}
|
aria-label={`remove ${attribute.key} with value ${attribute.value} `}
|
||||||
aria-label="key-input"
|
variant="link"
|
||||||
defaultValue={attribute.key}
|
className="kc-role-attributes__minus-icon"
|
||||||
validated={
|
onClick={() => remove(rowIndex)}
|
||||||
errors.attributes?.[rowIndex] ? "error" : "default"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Td>
|
|
||||||
<Td
|
|
||||||
key={`${attribute}-value`}
|
|
||||||
id={`text-input-${rowIndex}-value`}
|
|
||||||
dataLabel={columns[1]}
|
|
||||||
>
|
|
||||||
<TextInput
|
|
||||||
name={`attributes[${rowIndex}].value`}
|
|
||||||
ref={register()}
|
|
||||||
aria-label="value-input"
|
|
||||||
defaultValue={attribute.value}
|
|
||||||
validated={errors.description ? "error" : "default"}
|
|
||||||
/>
|
|
||||||
</Td>
|
|
||||||
{rowIndex !== fields.length - 1 && fields.length - 1 !== 0 && (
|
|
||||||
<Td
|
|
||||||
key="minus-button"
|
|
||||||
id={`kc-minus-button-${rowIndex}`}
|
|
||||||
dataLabel={columns[2]}
|
|
||||||
>
|
>
|
||||||
|
<MinusCircleIcon />
|
||||||
|
</Button>
|
||||||
|
</Td>
|
||||||
|
)}
|
||||||
|
{rowIndex === fields.length - 1 && (
|
||||||
|
<Td key="add-button" id="add-button" dataLabel={columns[2]}>
|
||||||
|
{fields[rowIndex].key === "" && (
|
||||||
<Button
|
<Button
|
||||||
id={`minus-button-${rowIndex}`}
|
id={`minus-button-${rowIndex}`}
|
||||||
aria-label={`remove ${attribute.key} with value ${attribute.value} `}
|
aria-label={`remove ${attribute.key} with value ${attribute.value} `}
|
||||||
|
@ -109,50 +122,35 @@ export const RoleAttributes = ({
|
||||||
>
|
>
|
||||||
<MinusCircleIcon />
|
<MinusCircleIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</Td>
|
)}
|
||||||
)}
|
<Button
|
||||||
{rowIndex === fields.length - 1 && (
|
aria-label={t("roles:addAttributeText")}
|
||||||
<Td key="add-button" id="add-button" dataLabel={columns[2]}>
|
id="plus-icon"
|
||||||
{fields[rowIndex].key === "" && (
|
variant="link"
|
||||||
<Button
|
className="kc-role-attributes__plus-icon"
|
||||||
id={`minus-button-${rowIndex}`}
|
onClick={() => append({ key: "", value: "" })}
|
||||||
aria-label={`remove ${attribute.key} with value ${attribute.value} `}
|
icon={<PlusCircleIcon />}
|
||||||
variant="link"
|
isDisabled={!formState.isValid}
|
||||||
className="kc-role-attributes__minus-icon"
|
/>
|
||||||
onClick={() => remove(rowIndex)}
|
</Td>
|
||||||
>
|
)}
|
||||||
<MinusCircleIcon />
|
</Tr>
|
||||||
</Button>
|
))}
|
||||||
)}
|
</Tbody>
|
||||||
<Button
|
</TableComposable>
|
||||||
aria-label={t("roles:addAttributeText")}
|
<ActionGroup className="kc-role-attributes__action-group">
|
||||||
id="plus-icon"
|
<Button
|
||||||
variant="link"
|
data-testid="realm-roles-save-button"
|
||||||
className="kc-role-attributes__plus-icon"
|
variant="primary"
|
||||||
onClick={() => append({ key: "", value: "" })}
|
isDisabled={!watchFirstKey}
|
||||||
icon={<PlusCircleIcon />}
|
onClick={save}
|
||||||
isDisabled={!formState.isValid}
|
>
|
||||||
/>
|
{t("common:save")}
|
||||||
</Td>
|
</Button>
|
||||||
)}
|
<Button onClick={reset} variant="link">
|
||||||
</Tr>
|
{t("common:reload")}
|
||||||
))}
|
</Button>
|
||||||
</Tbody>
|
</ActionGroup>
|
||||||
</TableComposable>
|
</FormAccess>
|
||||||
<ActionGroup className="kc-role-attributes__action-group">
|
|
||||||
<Button
|
|
||||||
data-testid="realm-roles-save-button"
|
|
||||||
variant="primary"
|
|
||||||
isDisabled={!watchFirstKey}
|
|
||||||
onClick={save}
|
|
||||||
>
|
|
||||||
{t("common:save")}
|
|
||||||
</Button>
|
|
||||||
<Button onClick={reset} variant="link">
|
|
||||||
{t("common:reload")}
|
|
||||||
</Button>
|
|
||||||
</ActionGroup>
|
|
||||||
</FormAccess>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -126,11 +126,7 @@ export const RolesList = ({
|
||||||
ariaLabelKey="roles:roleList"
|
ariaLabelKey="roles:roleList"
|
||||||
searchPlaceholderKey="roles:searchFor"
|
searchPlaceholderKey="roles:searchFor"
|
||||||
isPaginated={paginated}
|
isPaginated={paginated}
|
||||||
toolbarItem={
|
toolbarItem={<Button onClick={goToCreate}>{t("createRole")}</Button>}
|
||||||
<>
|
|
||||||
<Button onClick={goToCreate}>{t("createRole")}</Button>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
actions={[
|
actions={[
|
||||||
{
|
{
|
||||||
title: t("common:delete"),
|
title: t("common:delete"),
|
||||||
|
|
|
@ -42,60 +42,22 @@ export const UsersInRoleTab = () => {
|
||||||
const { enabled } = useHelp();
|
const { enabled } = useHelp();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<PageSection data-testid="users-page" variant="light">
|
||||||
<PageSection data-testid="users-page" variant="light">
|
<KeycloakDataTable
|
||||||
<KeycloakDataTable
|
isPaginated
|
||||||
isPaginated
|
loader={loader}
|
||||||
loader={loader}
|
ariaLabelKey="roles:roleList"
|
||||||
ariaLabelKey="roles:roleList"
|
searchPlaceholderKey=""
|
||||||
searchPlaceholderKey=""
|
toolbarItem={
|
||||||
toolbarItem={
|
enabled && (
|
||||||
enabled && (
|
<Popover
|
||||||
<Popover
|
aria-label="Basic popover"
|
||||||
aria-label="Basic popover"
|
position="bottom"
|
||||||
position="bottom"
|
bodyContent={
|
||||||
bodyContent={
|
|
||||||
<div>
|
|
||||||
{t("roles:whoWillAppearPopoverText")}
|
|
||||||
<Button
|
|
||||||
className="kc-groups-link"
|
|
||||||
variant="link"
|
|
||||||
onClick={() => history.push(`/${realm}/groups`)}
|
|
||||||
>
|
|
||||||
{t("groups")}
|
|
||||||
</Button>
|
|
||||||
{t("or")}
|
|
||||||
<Button
|
|
||||||
className="kc-users-link"
|
|
||||||
variant="link"
|
|
||||||
onClick={() => history.push(`/${realm}/users`)}
|
|
||||||
>
|
|
||||||
{t("users")}.
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
footerContent={t("roles:whoWillAppearPopoverFooterText")}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
variant="link"
|
|
||||||
className="kc-who-will-appear-button"
|
|
||||||
key="who-will-appear-button"
|
|
||||||
icon={<QuestionCircleIcon />}
|
|
||||||
>
|
|
||||||
{t("roles:whoWillAppearLinkText")}
|
|
||||||
</Button>
|
|
||||||
</Popover>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
emptyState={
|
|
||||||
<ListEmptyState
|
|
||||||
hasIcon={true}
|
|
||||||
message={t("noDirectUsers")}
|
|
||||||
instructions={
|
|
||||||
<div>
|
<div>
|
||||||
{t("noUsersEmptyStateDescription")}
|
{t("roles:whoWillAppearPopoverText")}
|
||||||
<Button
|
<Button
|
||||||
className="kc-groups-link-empty-state"
|
className="kc-groups-link"
|
||||||
variant="link"
|
variant="link"
|
||||||
onClick={() => history.push(`/${realm}/groups`)}
|
onClick={() => history.push(`/${realm}/groups`)}
|
||||||
>
|
>
|
||||||
|
@ -103,41 +65,77 @@ export const UsersInRoleTab = () => {
|
||||||
</Button>
|
</Button>
|
||||||
{t("or")}
|
{t("or")}
|
||||||
<Button
|
<Button
|
||||||
className="kc-users-link-empty-state"
|
className="kc-users-link"
|
||||||
variant="link"
|
variant="link"
|
||||||
onClick={() => history.push(`/${realm}/users`)}
|
onClick={() => history.push(`/${realm}/users`)}
|
||||||
>
|
>
|
||||||
{t("users")}
|
{t("users")}.
|
||||||
</Button>
|
</Button>
|
||||||
{t("noUsersEmptyStateDescriptionContinued")}
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
/>
|
footerContent={t("roles:whoWillAppearPopoverFooterText")}
|
||||||
}
|
>
|
||||||
columns={[
|
<Button
|
||||||
{
|
variant="link"
|
||||||
name: "username",
|
className="kc-who-will-appear-button"
|
||||||
displayKey: "roles:userName",
|
key="who-will-appear-button"
|
||||||
cellFormatters: [emptyFormatter()],
|
icon={<QuestionCircleIcon />}
|
||||||
},
|
>
|
||||||
{
|
{t("roles:whoWillAppearLinkText")}
|
||||||
name: "email",
|
</Button>
|
||||||
displayKey: "roles:email",
|
</Popover>
|
||||||
cellFormatters: [emptyFormatter()],
|
)
|
||||||
},
|
}
|
||||||
{
|
emptyState={
|
||||||
name: "lastName",
|
<ListEmptyState
|
||||||
displayKey: "roles:lastName",
|
hasIcon={true}
|
||||||
cellFormatters: [emptyFormatter()],
|
message={t("noDirectUsers")}
|
||||||
},
|
instructions={
|
||||||
{
|
<div>
|
||||||
name: "firstName",
|
{t("noUsersEmptyStateDescription")}
|
||||||
displayKey: "roles:firstName",
|
<Button
|
||||||
cellFormatters: [upperCaseFormatter(), emptyFormatter()],
|
className="kc-groups-link-empty-state"
|
||||||
},
|
variant="link"
|
||||||
]}
|
onClick={() => history.push(`/${realm}/groups`)}
|
||||||
/>
|
>
|
||||||
</PageSection>
|
{t("groups")}
|
||||||
</>
|
</Button>
|
||||||
|
{t("or")}
|
||||||
|
<Button
|
||||||
|
className="kc-users-link-empty-state"
|
||||||
|
variant="link"
|
||||||
|
onClick={() => history.push(`/${realm}/users`)}
|
||||||
|
>
|
||||||
|
{t("users")}
|
||||||
|
</Button>
|
||||||
|
{t("noUsersEmptyStateDescriptionContinued")}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
columns={[
|
||||||
|
{
|
||||||
|
name: "username",
|
||||||
|
displayKey: "roles:userName",
|
||||||
|
cellFormatters: [emptyFormatter()],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "email",
|
||||||
|
displayKey: "roles:email",
|
||||||
|
cellFormatters: [emptyFormatter()],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "lastName",
|
||||||
|
displayKey: "roles:lastName",
|
||||||
|
cellFormatters: [emptyFormatter()],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "firstName",
|
||||||
|
displayKey: "roles:firstName",
|
||||||
|
cellFormatters: [upperCaseFormatter(), emptyFormatter()],
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</PageSection>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -49,172 +49,167 @@ export const RealmSettingsGeneralTab = ({
|
||||||
const requireSslTypes = ["all", "external", "none"];
|
const requireSslTypes = ["all", "external", "none"];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<PageSection variant="light">
|
||||||
<PageSection variant="light">
|
<FormAccess
|
||||||
<FormAccess
|
isHorizontal
|
||||||
isHorizontal
|
role="manage-realm"
|
||||||
role="manage-realm"
|
className="pf-u-mt-lg"
|
||||||
className="pf-u-mt-lg"
|
onSubmit={handleSubmit(save)}
|
||||||
onSubmit={handleSubmit(save)}
|
>
|
||||||
|
<FormGroup label={t("realmId")} fieldId="kc-realm-id" isRequired>
|
||||||
|
<Controller
|
||||||
|
name="realm"
|
||||||
|
control={control}
|
||||||
|
defaultValue=""
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<ClipboardCopy onChange={onChange}>{value}</ClipboardCopy>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup label={t("displayName")} fieldId="kc-display-name">
|
||||||
|
<TextInput
|
||||||
|
type="text"
|
||||||
|
id="kc-display-name"
|
||||||
|
name="displayName"
|
||||||
|
ref={register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup label={t("htmlDisplayName")} fieldId="kc-html-display-name">
|
||||||
|
<TextInput
|
||||||
|
type="text"
|
||||||
|
id="kc-html-display-name"
|
||||||
|
name="displayNameHtml"
|
||||||
|
ref={register}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("frontendUrl")}
|
||||||
|
fieldId="kc-frontend-url"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="realm-settings-help:frontendUrl"
|
||||||
|
forLabel={t("frontendUrl")}
|
||||||
|
forID={t(`common:helpLabel`, { label: t("frontendUrl") })}
|
||||||
|
/>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<FormGroup label={t("realmId")} fieldId="kc-realm-id" isRequired>
|
<TextInput
|
||||||
<Controller
|
type="text"
|
||||||
name="realm"
|
id="kc-frontend-url"
|
||||||
control={control}
|
name="attributes.frontendUrl"
|
||||||
defaultValue=""
|
ref={register}
|
||||||
render={({ onChange, value }) => (
|
/>
|
||||||
<ClipboardCopy onChange={onChange}>{value}</ClipboardCopy>
|
</FormGroup>
|
||||||
)}
|
<FormGroup
|
||||||
|
label={t("requireSsl")}
|
||||||
|
fieldId="kc-require-ssl"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="realm-settings-help:requireSsl"
|
||||||
|
forLabel={t("requireSsl")}
|
||||||
|
forID={t(`common:helpLabel`, { label: t("requireSsl") })}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
<FormGroup label={t("displayName")} fieldId="kc-display-name">
|
>
|
||||||
<TextInput
|
<Controller
|
||||||
type="text"
|
name="sslRequired"
|
||||||
id="kc-display-name"
|
defaultValue="none"
|
||||||
name="displayName"
|
control={control}
|
||||||
ref={register}
|
render={({ onChange, value }) => (
|
||||||
|
<Select
|
||||||
|
toggleId="kc-require-ssl"
|
||||||
|
onToggle={() => setOpen(!open)}
|
||||||
|
onSelect={(_, value) => {
|
||||||
|
onChange(value as string);
|
||||||
|
setOpen(false);
|
||||||
|
}}
|
||||||
|
selections={value}
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
aria-label={t("requireSsl")}
|
||||||
|
isOpen={open}
|
||||||
|
>
|
||||||
|
{requireSslTypes.map((sslType) => (
|
||||||
|
<SelectOption
|
||||||
|
selected={sslType === value}
|
||||||
|
key={sslType}
|
||||||
|
value={sslType}
|
||||||
|
>
|
||||||
|
{t(`sslType.${sslType}`)}
|
||||||
|
</SelectOption>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
hasNoPaddingTop
|
||||||
|
label={t("userManagedAccess")}
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="realm-settings-help:userManagedAccess"
|
||||||
|
forLabel={t("userManagedAccess")}
|
||||||
|
forID={t(`common:helpLabel`, { label: t("userManagedAccess") })}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
<FormGroup
|
fieldId="kc-user-manged-access"
|
||||||
label={t("htmlDisplayName")}
|
>
|
||||||
fieldId="kc-html-display-name"
|
<Controller
|
||||||
>
|
name="userManagedAccessAllowed"
|
||||||
<TextInput
|
control={control}
|
||||||
type="text"
|
defaultValue={false}
|
||||||
id="kc-html-display-name"
|
render={({ onChange, value }) => (
|
||||||
name="displayNameHtml"
|
<Switch
|
||||||
ref={register}
|
id="kc-user-managed-access"
|
||||||
/>
|
data-testid="user-managed-access-switch"
|
||||||
</FormGroup>
|
label={t("common:on")}
|
||||||
<FormGroup
|
labelOff={t("common:off")}
|
||||||
label={t("frontendUrl")}
|
isChecked={value}
|
||||||
fieldId="kc-frontend-url"
|
onChange={onChange}
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="realm-settings-help:frontendUrl"
|
|
||||||
forLabel={t("frontendUrl")}
|
|
||||||
forID={t(`common:helpLabel`, { label: t("frontendUrl") })}
|
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
>
|
/>
|
||||||
<TextInput
|
</FormGroup>
|
||||||
type="text"
|
<FormGroup
|
||||||
id="kc-frontend-url"
|
label={t("endpoints")}
|
||||||
name="attributes.frontendUrl"
|
labelIcon={
|
||||||
ref={register}
|
<HelpItem
|
||||||
|
helpText="realm-settings-help:endpoints"
|
||||||
|
forLabel={t("endpoints")}
|
||||||
|
forID={t(`common:helpLabel`, { label: t("endpoints") })}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
<FormGroup
|
fieldId="kc-endpoints"
|
||||||
label={t("requireSsl")}
|
>
|
||||||
fieldId="kc-require-ssl"
|
<Stack>
|
||||||
labelIcon={
|
<StackItem>
|
||||||
<HelpItem
|
<FormattedLink
|
||||||
helpText="realm-settings-help:requireSsl"
|
href={`${baseUrl}realms/${realmName}/.well-known/openid-configuration`}
|
||||||
forLabel={t("requireSsl")}
|
title={t("openIDEndpointConfiguration")}
|
||||||
forID={t(`common:helpLabel`, { label: t("requireSsl") })}
|
|
||||||
/>
|
/>
|
||||||
}
|
</StackItem>
|
||||||
>
|
<StackItem>
|
||||||
<Controller
|
<FormattedLink
|
||||||
name="sslRequired"
|
href={`${baseUrl}realms/${realmName}/protocol/saml/descriptor`}
|
||||||
defaultValue="none"
|
title={t("samlIdentityProviderMetadata")}
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Select
|
|
||||||
toggleId="kc-require-ssl"
|
|
||||||
onToggle={() => setOpen(!open)}
|
|
||||||
onSelect={(_, value) => {
|
|
||||||
onChange(value as string);
|
|
||||||
setOpen(false);
|
|
||||||
}}
|
|
||||||
selections={value}
|
|
||||||
variant={SelectVariant.single}
|
|
||||||
aria-label={t("requireSsl")}
|
|
||||||
isOpen={open}
|
|
||||||
>
|
|
||||||
{requireSslTypes.map((sslType) => (
|
|
||||||
<SelectOption
|
|
||||||
selected={sslType === value}
|
|
||||||
key={sslType}
|
|
||||||
value={sslType}
|
|
||||||
>
|
|
||||||
{t(`sslType.${sslType}`)}
|
|
||||||
</SelectOption>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
hasNoPaddingTop
|
|
||||||
label={t("userManagedAccess")}
|
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="realm-settings-help:userManagedAccess"
|
|
||||||
forLabel={t("userManagedAccess")}
|
|
||||||
forID={t(`common:helpLabel`, { label: t("userManagedAccess") })}
|
|
||||||
/>
|
/>
|
||||||
}
|
</StackItem>
|
||||||
fieldId="kc-user-manged-access"
|
</Stack>
|
||||||
>
|
</FormGroup>
|
||||||
<Controller
|
|
||||||
name="userManagedAccessAllowed"
|
|
||||||
control={control}
|
|
||||||
defaultValue={false}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Switch
|
|
||||||
id="kc-user-managed-access"
|
|
||||||
data-testid="user-managed-access-switch"
|
|
||||||
label={t("common:on")}
|
|
||||||
labelOff={t("common:off")}
|
|
||||||
isChecked={value}
|
|
||||||
onChange={onChange}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("endpoints")}
|
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="realm-settings-help:endpoints"
|
|
||||||
forLabel={t("endpoints")}
|
|
||||||
forID={t(`common:helpLabel`, { label: t("endpoints") })}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
fieldId="kc-endpoints"
|
|
||||||
>
|
|
||||||
<Stack>
|
|
||||||
<StackItem>
|
|
||||||
<FormattedLink
|
|
||||||
href={`${baseUrl}realms/${realmName}/.well-known/openid-configuration`}
|
|
||||||
title={t("openIDEndpointConfiguration")}
|
|
||||||
/>
|
|
||||||
</StackItem>
|
|
||||||
<StackItem>
|
|
||||||
<FormattedLink
|
|
||||||
href={`${baseUrl}realms/${realmName}/protocol/saml/descriptor`}
|
|
||||||
title={t("samlIdentityProviderMetadata")}
|
|
||||||
/>
|
|
||||||
</StackItem>
|
|
||||||
</Stack>
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<ActionGroup>
|
<ActionGroup>
|
||||||
<Button
|
<Button
|
||||||
variant="primary"
|
variant="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
data-testid="general-tab-save"
|
data-testid="general-tab-save"
|
||||||
isDisabled={!isDirty}
|
isDisabled={!isDirty}
|
||||||
>
|
>
|
||||||
{t("common:save")}
|
{t("common:save")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="link" onClick={reset}>
|
<Button variant="link" onClick={reset}>
|
||||||
{t("common:revert")}
|
{t("common:revert")}
|
||||||
</Button>
|
</Button>
|
||||||
</ActionGroup>
|
</ActionGroup>
|
||||||
</FormAccess>
|
</FormAccess>
|
||||||
</PageSection>
|
</PageSection>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -130,52 +130,46 @@ export const KeysListTab = ({ realmComponents }: KeysListTabProps) => {
|
||||||
|
|
||||||
const goToCreate = () => history.push(`${url}/add-role`);
|
const goToCreate = () => history.push(`${url}/add-role`);
|
||||||
|
|
||||||
const ProviderRenderer = ({ provider }: KeyData) => {
|
const ProviderRenderer = ({ provider }: KeyData) => provider;
|
||||||
return <>{provider}</>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const ButtonRenderer = ({ type, publicKey, certificate }: KeyData) => {
|
const ButtonRenderer = ({ type, publicKey, certificate }: KeyData) => {
|
||||||
if (type === "EC") {
|
if (type === "EC") {
|
||||||
return (
|
return (
|
||||||
<>
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
togglePublicKeyDialog();
|
||||||
|
setPublicKey(publicKey!);
|
||||||
|
}}
|
||||||
|
variant="secondary"
|
||||||
|
id="kc-public-key"
|
||||||
|
>
|
||||||
|
{t("realm-settings:publicKeys").slice(0, -1)}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
} else if (type === "RSA") {
|
||||||
|
return (
|
||||||
|
<div className="button-wrapper">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
togglePublicKeyDialog();
|
togglePublicKeyDialog();
|
||||||
setPublicKey(publicKey!);
|
setPublicKey(publicKey!);
|
||||||
}}
|
}}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
id="kc-public-key"
|
id="kc-rsa-public-key"
|
||||||
>
|
>
|
||||||
{t("realm-settings:publicKeys").slice(0, -1)}
|
{t("realm-settings:publicKeys").slice(0, -1)}
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
<Button
|
||||||
);
|
onClick={() => {
|
||||||
} else if (type === "RSA") {
|
toggleCertificateDialog();
|
||||||
return (
|
setCertificate(certificate!);
|
||||||
<>
|
}}
|
||||||
<div className="button-wrapper">
|
variant="secondary"
|
||||||
<Button
|
id="kc-certificate"
|
||||||
onClick={() => {
|
>
|
||||||
togglePublicKeyDialog();
|
{t("realm-settings:certificate")}
|
||||||
setPublicKey(publicKey!);
|
</Button>
|
||||||
}}
|
</div>
|
||||||
variant="secondary"
|
|
||||||
id="kc-rsa-public-key"
|
|
||||||
>
|
|
||||||
{t("realm-settings:publicKeys").slice(0, -1)}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
toggleCertificateDialog();
|
|
||||||
setCertificate(certificate!);
|
|
||||||
}}
|
|
||||||
variant="secondary"
|
|
||||||
id="kc-certificate"
|
|
||||||
>
|
|
||||||
{t("realm-settings:certificate")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -200,93 +194,91 @@ export const KeysListTab = ({ realmComponents }: KeysListTabProps) => {
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<PageSection variant="light" padding={{ default: "noPadding" }}>
|
||||||
<PageSection variant="light" padding={{ default: "noPadding" }}>
|
<PublicKeyDialog />
|
||||||
<PublicKeyDialog />
|
<CertificateDialog />
|
||||||
<CertificateDialog />
|
<KeycloakDataTable
|
||||||
<KeycloakDataTable
|
isNotCompact={true}
|
||||||
isNotCompact={true}
|
key={key}
|
||||||
key={key}
|
loader={
|
||||||
loader={
|
filterType === "Active keys"
|
||||||
filterType === "Active keys"
|
? activeKeysLoader
|
||||||
? activeKeysLoader
|
: filterType === "Passive keys"
|
||||||
: filterType === "Passive keys"
|
? passiveKeysLoader
|
||||||
? passiveKeysLoader
|
: filterType === "Disabled keys"
|
||||||
: filterType === "Disabled keys"
|
? disabledKeysLoader
|
||||||
? disabledKeysLoader
|
: loader
|
||||||
: loader
|
}
|
||||||
}
|
ariaLabelKey="realm-settings:keysList"
|
||||||
ariaLabelKey="realm-settings:keysList"
|
searchPlaceholderKey="realm-settings:searchKey"
|
||||||
searchPlaceholderKey="realm-settings:searchKey"
|
searchTypeComponent={
|
||||||
searchTypeComponent={
|
<Select
|
||||||
<Select
|
width={300}
|
||||||
width={300}
|
data-testid="filter-type-select"
|
||||||
data-testid="filter-type-select"
|
isOpen={filterDropdownOpen}
|
||||||
isOpen={filterDropdownOpen}
|
className="kc-filter-type-select"
|
||||||
className="kc-filter-type-select"
|
variant={SelectVariant.single}
|
||||||
variant={SelectVariant.single}
|
onToggle={() => setFilterDropdownOpen(!filterDropdownOpen)}
|
||||||
onToggle={() => setFilterDropdownOpen(!filterDropdownOpen)}
|
toggleIcon={<FilterIcon />}
|
||||||
toggleIcon={<FilterIcon />}
|
onSelect={(_, value) => {
|
||||||
onSelect={(_, value) => {
|
setFilterType(value as string);
|
||||||
setFilterType(value as string);
|
refresh();
|
||||||
refresh();
|
setFilterDropdownOpen(false);
|
||||||
setFilterDropdownOpen(false);
|
}}
|
||||||
}}
|
selections={filterType}
|
||||||
selections={filterType}
|
>
|
||||||
>
|
{options}
|
||||||
{options}
|
</Select>
|
||||||
</Select>
|
}
|
||||||
}
|
canSelectAll
|
||||||
canSelectAll
|
columns={[
|
||||||
columns={[
|
{
|
||||||
{
|
name: "algorithm",
|
||||||
name: "algorithm",
|
displayKey: "realm-settings:algorithm",
|
||||||
displayKey: "realm-settings:algorithm",
|
cellFormatters: [emptyFormatter()],
|
||||||
cellFormatters: [emptyFormatter()],
|
transforms: [cellWidth(15)],
|
||||||
transforms: [cellWidth(15)],
|
},
|
||||||
},
|
{
|
||||||
{
|
name: "type",
|
||||||
name: "type",
|
displayKey: "realm-settings:type",
|
||||||
displayKey: "realm-settings:type",
|
cellFormatters: [emptyFormatter()],
|
||||||
cellFormatters: [emptyFormatter()],
|
transforms: [cellWidth(10)],
|
||||||
transforms: [cellWidth(10)],
|
},
|
||||||
},
|
{
|
||||||
{
|
name: "kid",
|
||||||
name: "kid",
|
displayKey: "realm-settings:kid",
|
||||||
displayKey: "realm-settings:kid",
|
cellFormatters: [emptyFormatter()],
|
||||||
cellFormatters: [emptyFormatter()],
|
transforms: [cellWidth(10)],
|
||||||
transforms: [cellWidth(10)],
|
},
|
||||||
},
|
{
|
||||||
{
|
name: "provider",
|
||||||
name: "provider",
|
displayKey: "realm-settings:provider",
|
||||||
displayKey: "realm-settings:provider",
|
cellRenderer: ProviderRenderer,
|
||||||
cellRenderer: ProviderRenderer,
|
cellFormatters: [emptyFormatter()],
|
||||||
cellFormatters: [emptyFormatter()],
|
transforms: [cellWidth(10)],
|
||||||
transforms: [cellWidth(10)],
|
},
|
||||||
},
|
{
|
||||||
{
|
name: "publicKeys",
|
||||||
name: "publicKeys",
|
displayKey: "realm-settings:publicKeys",
|
||||||
displayKey: "realm-settings:publicKeys",
|
cellRenderer: ButtonRenderer,
|
||||||
cellRenderer: ButtonRenderer,
|
cellFormatters: [],
|
||||||
cellFormatters: [],
|
transforms: [cellWidth(20)],
|
||||||
transforms: [cellWidth(20)],
|
},
|
||||||
},
|
]}
|
||||||
]}
|
isSearching={!!filterType}
|
||||||
isSearching={!!filterType}
|
emptyState={
|
||||||
emptyState={
|
<ListEmptyState
|
||||||
<ListEmptyState
|
hasIcon={true}
|
||||||
hasIcon={true}
|
message={t("realm-settings:noKeys")}
|
||||||
message={t("realm-settings:noKeys")}
|
instructions={
|
||||||
instructions={
|
t(`realm-settings:noKeysDescription`) +
|
||||||
t(`realm-settings:noKeysDescription`) +
|
`${filterType.toLocaleLowerCase()}.`
|
||||||
`${filterType.toLocaleLowerCase()}.`
|
}
|
||||||
}
|
primaryActionText={t("createRole")}
|
||||||
primaryActionText={t("createRole")}
|
onPrimaryAction={goToCreate}
|
||||||
onPrimaryAction={goToCreate}
|
/>
|
||||||
/>
|
}
|
||||||
}
|
/>
|
||||||
/>
|
</PageSection>
|
||||||
</PageSection>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -256,60 +256,58 @@ export const KeysTabInner = ({ components, refresh }: KeysTabInnerProps) => {
|
||||||
<DeleteConfirm />
|
<DeleteConfirm />
|
||||||
<PageSection variant="light" padding={{ default: "noPadding" }}>
|
<PageSection variant="light" padding={{ default: "noPadding" }}>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<>
|
<ToolbarGroup className="providers-toolbar">
|
||||||
<ToolbarGroup className="providers-toolbar">
|
<ToolbarItem>
|
||||||
<ToolbarItem>
|
<InputGroup>
|
||||||
<InputGroup>
|
<TextInput
|
||||||
<TextInput
|
name={"inputGroupName"}
|
||||||
name={"inputGroupName"}
|
id={"inputGroupName"}
|
||||||
id={"inputGroupName"}
|
type="search"
|
||||||
type="search"
|
aria-label={t("common:search")}
|
||||||
aria-label={t("common:search")}
|
placeholder={t("common:search")}
|
||||||
placeholder={t("common:search")}
|
onChange={handleInputChange}
|
||||||
onChange={handleInputChange}
|
onKeyDown={handleKeyDown}
|
||||||
onKeyDown={handleKeyDown}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
variant={ButtonVariant.control}
|
|
||||||
aria-label={t("common:search")}
|
|
||||||
>
|
|
||||||
<SearchIcon />
|
|
||||||
</Button>
|
|
||||||
</InputGroup>
|
|
||||||
</ToolbarItem>
|
|
||||||
<ToolbarItem>
|
|
||||||
<Dropdown
|
|
||||||
data-testid="addProviderDropdown"
|
|
||||||
className="add-provider-dropdown"
|
|
||||||
isOpen={providerDropdownOpen}
|
|
||||||
toggle={
|
|
||||||
<DropdownToggle
|
|
||||||
onToggle={(val) => setProviderDropdownOpen(val)}
|
|
||||||
isPrimary
|
|
||||||
>
|
|
||||||
{t("realm-settings:addProvider")}
|
|
||||||
</DropdownToggle>
|
|
||||||
}
|
|
||||||
dropdownItems={[
|
|
||||||
providerTypes.map((item) => (
|
|
||||||
<DropdownItem
|
|
||||||
onClick={() => {
|
|
||||||
handleModalToggle();
|
|
||||||
|
|
||||||
setProviderDropdownOpen(false);
|
|
||||||
setDefaultConsoleDisplayName(item);
|
|
||||||
}}
|
|
||||||
data-testid={`option-${item}`}
|
|
||||||
key={item}
|
|
||||||
>
|
|
||||||
{item}
|
|
||||||
</DropdownItem>
|
|
||||||
)),
|
|
||||||
]}
|
|
||||||
/>
|
/>
|
||||||
</ToolbarItem>
|
<Button
|
||||||
</ToolbarGroup>
|
variant={ButtonVariant.control}
|
||||||
</>
|
aria-label={t("common:search")}
|
||||||
|
>
|
||||||
|
<SearchIcon />
|
||||||
|
</Button>
|
||||||
|
</InputGroup>
|
||||||
|
</ToolbarItem>
|
||||||
|
<ToolbarItem>
|
||||||
|
<Dropdown
|
||||||
|
data-testid="addProviderDropdown"
|
||||||
|
className="add-provider-dropdown"
|
||||||
|
isOpen={providerDropdownOpen}
|
||||||
|
toggle={
|
||||||
|
<DropdownToggle
|
||||||
|
onToggle={(val) => setProviderDropdownOpen(val)}
|
||||||
|
isPrimary
|
||||||
|
>
|
||||||
|
{t("realm-settings:addProvider")}
|
||||||
|
</DropdownToggle>
|
||||||
|
}
|
||||||
|
dropdownItems={[
|
||||||
|
providerTypes.map((item) => (
|
||||||
|
<DropdownItem
|
||||||
|
onClick={() => {
|
||||||
|
handleModalToggle();
|
||||||
|
|
||||||
|
setProviderDropdownOpen(false);
|
||||||
|
setDefaultConsoleDisplayName(item);
|
||||||
|
}}
|
||||||
|
data-testid={`option-${item}`}
|
||||||
|
key={item}
|
||||||
|
>
|
||||||
|
{item}
|
||||||
|
</DropdownItem>
|
||||||
|
)),
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</ToolbarItem>
|
||||||
|
</ToolbarGroup>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
<DataList
|
<DataList
|
||||||
aria-label={t("groups")}
|
aria-label={t("groups")}
|
||||||
|
@ -375,21 +373,19 @@ export const KeysTabInner = ({ components, refresh }: KeysTabInnerProps) => {
|
||||||
data-testid="provider-name"
|
data-testid="provider-name"
|
||||||
key={`name-${idx}`}
|
key={`name-${idx}`}
|
||||||
>
|
>
|
||||||
<>
|
<Link
|
||||||
<Link
|
key={component.name}
|
||||||
key={component.name}
|
data-testid="provider-name-link"
|
||||||
data-testid="provider-name-link"
|
to={`${url}/${component.id}/${component.providerId}/settings`}
|
||||||
to={`${url}/${component.id}/${component.providerId}/settings`}
|
>
|
||||||
>
|
{component.name}
|
||||||
{component.name}
|
</Link>
|
||||||
</Link>
|
|
||||||
</>
|
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell key={`providerId-${idx}`}>
|
<DataListCell key={`providerId-${idx}`}>
|
||||||
<>{component.providerId}</>
|
{component.providerId}
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell key={`providerDescription-${idx}`}>
|
<DataListCell key={`providerDescription-${idx}`}>
|
||||||
<>{component.providerDescription}</>
|
{component.providerDescription}
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListAction
|
<DataListAction
|
||||||
aria-labelledby="data-list-action"
|
aria-labelledby="data-list-action"
|
||||||
|
|
|
@ -18,198 +18,193 @@ export const RealmSettingsLoginTab = ({
|
||||||
const { t } = useTranslation("realm-settings");
|
const { t } = useTranslation("realm-settings");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<PageSection variant="light">
|
||||||
<PageSection variant="light">
|
<FormPanel className="kc-login-screen" title="Login screen customization">
|
||||||
<FormPanel
|
<FormAccess isHorizontal role="manage-realm">
|
||||||
className="kc-login-screen"
|
<FormGroup
|
||||||
title="Login screen customization"
|
label={t("userRegistration")}
|
||||||
>
|
fieldId="kc-user-reg"
|
||||||
<FormAccess isHorizontal role="manage-realm">
|
labelIcon={
|
||||||
<FormGroup
|
<HelpItem
|
||||||
label={t("userRegistration")}
|
helpText={t("userRegistrationHelpText")}
|
||||||
fieldId="kc-user-reg"
|
forLabel={t("userRegistration")}
|
||||||
labelIcon={
|
forID={t(`common:helpLabel`, {
|
||||||
<HelpItem
|
label: t("userRegistration"),
|
||||||
helpText={t("userRegistrationHelpText")}
|
})}
|
||||||
forLabel={t("userRegistration")}
|
|
||||||
forID={t(`common:helpLabel`, {
|
|
||||||
label: t("userRegistration"),
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
hasNoPaddingTop
|
|
||||||
>
|
|
||||||
<Switch
|
|
||||||
id="kc-user-reg-switch"
|
|
||||||
data-testid="user-reg-switch"
|
|
||||||
name="registrationAllowed"
|
|
||||||
label={t("common:on")}
|
|
||||||
labelOff={t("common:off")}
|
|
||||||
isChecked={realm?.registrationAllowed}
|
|
||||||
onChange={(value) => {
|
|
||||||
save({ ...realm, registrationAllowed: value });
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
<FormGroup
|
hasNoPaddingTop
|
||||||
label={t("forgotPassword")}
|
>
|
||||||
fieldId="kc-forgot-pw"
|
<Switch
|
||||||
labelIcon={
|
id="kc-user-reg-switch"
|
||||||
<HelpItem
|
data-testid="user-reg-switch"
|
||||||
helpText={t("forgotPasswordHelpText")}
|
name="registrationAllowed"
|
||||||
forLabel={t("forgotPassword")}
|
label={t("common:on")}
|
||||||
forID={t(`common:helpLabel`, { label: t("forgotPassword") })}
|
labelOff={t("common:off")}
|
||||||
/>
|
isChecked={realm?.registrationAllowed}
|
||||||
}
|
onChange={(value) => {
|
||||||
hasNoPaddingTop
|
save({ ...realm, registrationAllowed: value });
|
||||||
>
|
}}
|
||||||
<Switch
|
/>
|
||||||
id="kc-forgot-pw-switch"
|
</FormGroup>
|
||||||
data-testid="forgot-pw-switch"
|
<FormGroup
|
||||||
name="resetPasswordAllowed"
|
label={t("forgotPassword")}
|
||||||
label={t("common:on")}
|
fieldId="kc-forgot-pw"
|
||||||
labelOff={t("common:off")}
|
labelIcon={
|
||||||
isChecked={realm?.resetPasswordAllowed}
|
<HelpItem
|
||||||
onChange={(value) => {
|
helpText={t("forgotPasswordHelpText")}
|
||||||
save({ ...realm, resetPasswordAllowed: value });
|
forLabel={t("forgotPassword")}
|
||||||
}}
|
forID={t(`common:helpLabel`, { label: t("forgotPassword") })}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
<FormGroup
|
hasNoPaddingTop
|
||||||
label={t("rememberMe")}
|
>
|
||||||
fieldId="kc-remember-me"
|
<Switch
|
||||||
labelIcon={
|
id="kc-forgot-pw-switch"
|
||||||
<HelpItem
|
data-testid="forgot-pw-switch"
|
||||||
helpText={t("rememberMeHelpText")}
|
name="resetPasswordAllowed"
|
||||||
forLabel={t("rememberMe")}
|
label={t("common:on")}
|
||||||
forID={t(`common:helpLabel`, { label: t("rememberMe") })}
|
labelOff={t("common:off")}
|
||||||
/>
|
isChecked={realm?.resetPasswordAllowed}
|
||||||
}
|
onChange={(value) => {
|
||||||
hasNoPaddingTop
|
save({ ...realm, resetPasswordAllowed: value });
|
||||||
>
|
}}
|
||||||
<Switch
|
/>
|
||||||
id="kc-remember-me-switch"
|
</FormGroup>
|
||||||
data-testid="remember-me-switch"
|
<FormGroup
|
||||||
name="rememberMe"
|
label={t("rememberMe")}
|
||||||
label={t("common:on")}
|
fieldId="kc-remember-me"
|
||||||
labelOff={t("common:off")}
|
labelIcon={
|
||||||
isChecked={realm?.rememberMe}
|
<HelpItem
|
||||||
onChange={(value) => {
|
helpText={t("rememberMeHelpText")}
|
||||||
save({ ...realm, rememberMe: value });
|
forLabel={t("rememberMe")}
|
||||||
}}
|
forID={t(`common:helpLabel`, { label: t("rememberMe") })}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
</FormAccess>
|
hasNoPaddingTop
|
||||||
</FormPanel>
|
>
|
||||||
<FormPanel className="kc-email-settings" title="Email settings">
|
<Switch
|
||||||
<FormAccess isHorizontal role="manage-realm">
|
id="kc-remember-me-switch"
|
||||||
<FormGroup
|
data-testid="remember-me-switch"
|
||||||
label={t("emailAsUsername")}
|
name="rememberMe"
|
||||||
fieldId="kc-email-as-username"
|
label={t("common:on")}
|
||||||
labelIcon={
|
labelOff={t("common:off")}
|
||||||
<HelpItem
|
isChecked={realm?.rememberMe}
|
||||||
helpText={t("emailAsUsernameHelpText")}
|
onChange={(value) => {
|
||||||
forLabel={t("emailAsUsername")}
|
save({ ...realm, rememberMe: value });
|
||||||
forID={t(`common:helpLabel`, { label: t("emailAsUsername") })}
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
</FormGroup>
|
||||||
hasNoPaddingTop
|
</FormAccess>
|
||||||
>
|
</FormPanel>
|
||||||
<Switch
|
<FormPanel className="kc-email-settings" title="Email settings">
|
||||||
id="kc-email-as-username-switch"
|
<FormAccess isHorizontal role="manage-realm">
|
||||||
data-testid="email-as-username-switch"
|
<FormGroup
|
||||||
name="registrationEmailAsUsername"
|
label={t("emailAsUsername")}
|
||||||
label={t("common:on")}
|
fieldId="kc-email-as-username"
|
||||||
labelOff={t("common:off")}
|
labelIcon={
|
||||||
isChecked={realm?.registrationEmailAsUsername}
|
<HelpItem
|
||||||
onChange={(value) => {
|
helpText={t("emailAsUsernameHelpText")}
|
||||||
save({ ...realm, registrationEmailAsUsername: value });
|
forLabel={t("emailAsUsername")}
|
||||||
}}
|
forID={t(`common:helpLabel`, { label: t("emailAsUsername") })}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
<FormGroup
|
hasNoPaddingTop
|
||||||
label={t("loginWithEmail")}
|
>
|
||||||
fieldId="kc-login-with-email"
|
<Switch
|
||||||
labelIcon={
|
id="kc-email-as-username-switch"
|
||||||
<HelpItem
|
data-testid="email-as-username-switch"
|
||||||
helpText={t("loginWithEmailHelpText")}
|
name="registrationEmailAsUsername"
|
||||||
forLabel={t("loginWithEmail")}
|
label={t("common:on")}
|
||||||
forID={t(`common:helpLabel`, { label: t("loginWithEmail") })}
|
labelOff={t("common:off")}
|
||||||
/>
|
isChecked={realm?.registrationEmailAsUsername}
|
||||||
}
|
onChange={(value) => {
|
||||||
hasNoPaddingTop
|
save({ ...realm, registrationEmailAsUsername: value });
|
||||||
>
|
}}
|
||||||
<Switch
|
/>
|
||||||
id="kc-login-with-email-switch"
|
</FormGroup>
|
||||||
data-testid="login-with-email-switch"
|
<FormGroup
|
||||||
name="loginWithEmailAllowed"
|
label={t("loginWithEmail")}
|
||||||
label={t("common:on")}
|
fieldId="kc-login-with-email"
|
||||||
labelOff={t("common:off")}
|
labelIcon={
|
||||||
isChecked={realm?.loginWithEmailAllowed}
|
<HelpItem
|
||||||
onChange={(value) => {
|
helpText={t("loginWithEmailHelpText")}
|
||||||
save({ ...realm, loginWithEmailAllowed: value });
|
forLabel={t("loginWithEmail")}
|
||||||
}}
|
forID={t(`common:helpLabel`, { label: t("loginWithEmail") })}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
<FormGroup
|
hasNoPaddingTop
|
||||||
label={t("duplicateEmails")}
|
>
|
||||||
fieldId="kc-duplicate-emails"
|
<Switch
|
||||||
labelIcon={
|
id="kc-login-with-email-switch"
|
||||||
<HelpItem
|
data-testid="login-with-email-switch"
|
||||||
helpText={t("duplicateEmailsHelpText")}
|
name="loginWithEmailAllowed"
|
||||||
forLabel={t("duplicateEmails")}
|
label={t("common:on")}
|
||||||
forID={t(`common:helpLabel`, { label: t("duplicateEmails") })}
|
labelOff={t("common:off")}
|
||||||
/>
|
isChecked={realm?.loginWithEmailAllowed}
|
||||||
}
|
onChange={(value) => {
|
||||||
hasNoPaddingTop
|
save({ ...realm, loginWithEmailAllowed: value });
|
||||||
>
|
}}
|
||||||
<Switch
|
/>
|
||||||
id="kc-duplicate-emails-switch"
|
</FormGroup>
|
||||||
data-testid="duplicate-emails-switch"
|
<FormGroup
|
||||||
label={t("common:on")}
|
label={t("duplicateEmails")}
|
||||||
labelOff={t("common:off")}
|
fieldId="kc-duplicate-emails"
|
||||||
name="duplicateEmailsAllowed"
|
labelIcon={
|
||||||
isChecked={
|
<HelpItem
|
||||||
realm?.duplicateEmailsAllowed &&
|
helpText={t("duplicateEmailsHelpText")}
|
||||||
!realm?.loginWithEmailAllowed &&
|
forLabel={t("duplicateEmails")}
|
||||||
!realm?.registrationEmailAsUsername
|
forID={t(`common:helpLabel`, { label: t("duplicateEmails") })}
|
||||||
}
|
|
||||||
onChange={(value) => {
|
|
||||||
save({ ...realm, duplicateEmailsAllowed: value });
|
|
||||||
}}
|
|
||||||
isDisabled={
|
|
||||||
realm?.loginWithEmailAllowed ||
|
|
||||||
realm?.registrationEmailAsUsername
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
<FormGroup
|
hasNoPaddingTop
|
||||||
label={t("verifyEmail")}
|
>
|
||||||
fieldId="kc-verify-email"
|
<Switch
|
||||||
labelIcon={
|
id="kc-duplicate-emails-switch"
|
||||||
<HelpItem
|
data-testid="duplicate-emails-switch"
|
||||||
helpText={t("verifyEmailHelpText")}
|
label={t("common:on")}
|
||||||
forLabel={t("verifyEmail")}
|
labelOff={t("common:off")}
|
||||||
forID={t(`common:helpLabel`, { label: t("verifyEmail") })}
|
name="duplicateEmailsAllowed"
|
||||||
/>
|
isChecked={
|
||||||
|
realm?.duplicateEmailsAllowed &&
|
||||||
|
!realm?.loginWithEmailAllowed &&
|
||||||
|
!realm?.registrationEmailAsUsername
|
||||||
}
|
}
|
||||||
hasNoPaddingTop
|
onChange={(value) => {
|
||||||
>
|
save({ ...realm, duplicateEmailsAllowed: value });
|
||||||
<Switch
|
}}
|
||||||
id="kc-verify-email-switch"
|
isDisabled={
|
||||||
data-testid="verify-email-switch"
|
realm?.loginWithEmailAllowed ||
|
||||||
name="verifyEmail"
|
realm?.registrationEmailAsUsername
|
||||||
label={t("common:on")}
|
}
|
||||||
labelOff={t("common:off")}
|
/>
|
||||||
isChecked={realm?.verifyEmail}
|
</FormGroup>
|
||||||
onChange={(value) => {
|
<FormGroup
|
||||||
save({ ...realm, verifyEmail: value });
|
label={t("verifyEmail")}
|
||||||
}}
|
fieldId="kc-verify-email"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText={t("verifyEmailHelpText")}
|
||||||
|
forLabel={t("verifyEmail")}
|
||||||
|
forID={t(`common:helpLabel`, { label: t("verifyEmail") })}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
</FormAccess>
|
hasNoPaddingTop
|
||||||
</FormPanel>
|
>
|
||||||
</PageSection>
|
<Switch
|
||||||
</>
|
id="kc-verify-email-switch"
|
||||||
|
data-testid="verify-email-switch"
|
||||||
|
name="verifyEmail"
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
|
isChecked={realm?.verifyEmail}
|
||||||
|
onChange={(value) => {
|
||||||
|
save({ ...realm, verifyEmail: value });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</FormAccess>
|
||||||
|
</FormPanel>
|
||||||
|
</PageSection>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -53,19 +53,17 @@ export const EditProviderCrumb = () => {
|
||||||
const { realm } = useRealm();
|
const { realm } = useRealm();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Breadcrumb>
|
||||||
<Breadcrumb>
|
<BreadcrumbItem
|
||||||
<BreadcrumbItem
|
render={(props) => (
|
||||||
render={(props) => (
|
<Link {...props} to={toRealmSettings({ realm, tab: "keys" })}>
|
||||||
<Link {...props} to={toRealmSettings({ realm, tab: "keys" })}>
|
{t("keys")}
|
||||||
{t("keys")}
|
</Link>
|
||||||
</Link>
|
)}
|
||||||
)}
|
/>
|
||||||
/>
|
<BreadcrumbItem>{t("providers")}</BreadcrumbItem>
|
||||||
<BreadcrumbItem>{t("providers")}</BreadcrumbItem>
|
<BreadcrumbItem isActive>{t("editProvider")}</BreadcrumbItem>
|
||||||
<BreadcrumbItem isActive>{t("editProvider")}</BreadcrumbItem>
|
</Breadcrumb>
|
||||||
</Breadcrumb>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -70,337 +70,294 @@ export const RealmSettingsSessionsTab = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<PageSection variant="light">
|
||||||
<PageSection variant="light">
|
<FormPanel
|
||||||
<FormPanel
|
title={t("SSOSessionSettings")}
|
||||||
title={t("SSOSessionSettings")}
|
className="kc-sso-session-template"
|
||||||
className="kc-sso-session-template"
|
>
|
||||||
|
<FormAccess
|
||||||
|
isHorizontal
|
||||||
|
role="manage-realm"
|
||||||
|
onSubmit={handleSubmit(save)}
|
||||||
>
|
>
|
||||||
<FormAccess
|
<FormGroup
|
||||||
isHorizontal
|
label={t("SSOSessionIdle")}
|
||||||
role="manage-realm"
|
fieldId="SSOSessionIdle"
|
||||||
onSubmit={handleSubmit(save)}
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="realm-settings-help:ssoSessionIdle"
|
||||||
|
forLabel={t("SSOSessionIdle")}
|
||||||
|
forID="SSOSessionIdle"
|
||||||
|
id="SSOSessionIdle"
|
||||||
|
/>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<FormGroup
|
<Controller
|
||||||
label={t("SSOSessionIdle")}
|
name="ssoSessionIdleTimeout"
|
||||||
fieldId="SSOSessionIdle"
|
defaultValue={realm?.ssoSessionIdleTimeout}
|
||||||
labelIcon={
|
control={control}
|
||||||
<HelpItem
|
render={({ onChange, value }) => (
|
||||||
helpText="realm-settings-help:ssoSessionIdle"
|
<TimeSelector
|
||||||
forLabel={t("SSOSessionIdle")}
|
className="kc-sso-session-idle"
|
||||||
forID="SSOSessionIdle"
|
data-testid="sso-session-idle-input"
|
||||||
id="SSOSessionIdle"
|
aria-label="sso-session-idle-input"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
>
|
/>
|
||||||
<Controller
|
</FormGroup>
|
||||||
name="ssoSessionIdleTimeout"
|
|
||||||
defaultValue={realm?.ssoSessionIdleTimeout}
|
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<TimeSelector
|
|
||||||
className="kc-sso-session-idle"
|
|
||||||
data-testid="sso-session-idle-input"
|
|
||||||
aria-label="sso-session-idle-input"
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={t("SSOSessionMax")}
|
label={t("SSOSessionMax")}
|
||||||
fieldId="SSOSessionMax"
|
fieldId="SSOSessionMax"
|
||||||
labelIcon={
|
labelIcon={
|
||||||
<HelpItem
|
<HelpItem
|
||||||
helpText="realm-settings-help:ssoSessionMax"
|
helpText="realm-settings-help:ssoSessionMax"
|
||||||
forLabel={t("SSOSessionMax")}
|
forLabel={t("SSOSessionMax")}
|
||||||
forID="SSOSessionMax"
|
forID="SSOSessionMax"
|
||||||
id="SSOSessionMax"
|
id="SSOSessionMax"
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="ssoSessionMaxLifespan"
|
|
||||||
defaultValue=""
|
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<TimeSelector
|
|
||||||
className="kc-sso-session-max"
|
|
||||||
data-testid="sso-session-max-input"
|
|
||||||
aria-label="sso-session-max-input"
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="ssoSessionMaxLifespan"
|
||||||
|
defaultValue=""
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<TimeSelector
|
||||||
|
className="kc-sso-session-max"
|
||||||
|
data-testid="sso-session-max-input"
|
||||||
|
aria-label="sso-session-max-input"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={t("SSOSessionIdleRememberMe")}
|
label={t("SSOSessionIdleRememberMe")}
|
||||||
fieldId="SSOSessionIdleRememberMe"
|
fieldId="SSOSessionIdleRememberMe"
|
||||||
labelIcon={
|
labelIcon={
|
||||||
<HelpItem
|
<HelpItem
|
||||||
helpText="realm-settings-help:ssoSessionIdleRememberMe"
|
helpText="realm-settings-help:ssoSessionIdleRememberMe"
|
||||||
forLabel={t("SSOSessionIdleRememberMe")}
|
forLabel={t("SSOSessionIdleRememberMe")}
|
||||||
forID="SSOSessionIdleRememberMe"
|
forID="SSOSessionIdleRememberMe"
|
||||||
id="SSOSessionIdleRememberMe"
|
id="SSOSessionIdleRememberMe"
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="ssoSessionIdleTimeoutRememberMe"
|
|
||||||
defaultValue=""
|
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<TimeSelector
|
|
||||||
className="kc-sso-session-idle-remember-me"
|
|
||||||
data-testid="sso-session-idle-remember-me-input"
|
|
||||||
aria-label="sso-session-idle-remember-me-input"
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="ssoSessionIdleTimeoutRememberMe"
|
||||||
|
defaultValue=""
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<TimeSelector
|
||||||
|
className="kc-sso-session-idle-remember-me"
|
||||||
|
data-testid="sso-session-idle-remember-me-input"
|
||||||
|
aria-label="sso-session-idle-remember-me-input"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={t("SSOSessionMaxRememberMe")}
|
label={t("SSOSessionMaxRememberMe")}
|
||||||
fieldId="SSOSessionMaxRememberMe"
|
fieldId="SSOSessionMaxRememberMe"
|
||||||
labelIcon={
|
labelIcon={
|
||||||
<HelpItem
|
<HelpItem
|
||||||
helpText="realm-settings-help:ssoSessionMaxRememberMe"
|
helpText="realm-settings-help:ssoSessionMaxRememberMe"
|
||||||
forLabel={t("SSOSessionMaxRememberMe")}
|
forLabel={t("SSOSessionMaxRememberMe")}
|
||||||
forID="SSOSessionMaxRememberMe"
|
forID="SSOSessionMaxRememberMe"
|
||||||
id="SSOSessionMaxRememberMe"
|
id="SSOSessionMaxRememberMe"
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="ssoSessionMaxLifespanRememberMe"
|
|
||||||
defaultValue=""
|
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<TimeSelector
|
|
||||||
className="kc-sso-session-max-remember-me"
|
|
||||||
aria-label="sso-session-max-remember-me-input"
|
|
||||||
data-testid="sso-session-max-remember-me-input"
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
</FormAccess>
|
>
|
||||||
</FormPanel>
|
<Controller
|
||||||
<FormPanel
|
name="ssoSessionMaxLifespanRememberMe"
|
||||||
title={t("clientSessionSettings")}
|
defaultValue=""
|
||||||
className="kc-client-session-template"
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<TimeSelector
|
||||||
|
className="kc-sso-session-max-remember-me"
|
||||||
|
aria-label="sso-session-max-remember-me-input"
|
||||||
|
data-testid="sso-session-max-remember-me-input"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</FormAccess>
|
||||||
|
</FormPanel>
|
||||||
|
<FormPanel
|
||||||
|
title={t("clientSessionSettings")}
|
||||||
|
className="kc-client-session-template"
|
||||||
|
>
|
||||||
|
<FormAccess
|
||||||
|
isHorizontal
|
||||||
|
role="manage-realm"
|
||||||
|
className="pf-u-mt-lg"
|
||||||
|
onSubmit={handleSubmit(save)}
|
||||||
>
|
>
|
||||||
<FormAccess
|
<FormGroup
|
||||||
isHorizontal
|
label={t("clientSessionIdle")}
|
||||||
role="manage-realm"
|
fieldId="clientSessionIdle"
|
||||||
className="pf-u-mt-lg"
|
labelIcon={
|
||||||
onSubmit={handleSubmit(save)}
|
<HelpItem
|
||||||
>
|
helpText="realm-settings-help:clientSessionIdle"
|
||||||
<FormGroup
|
forLabel={t("clientSessionIdle")}
|
||||||
label={t("clientSessionIdle")}
|
forID="clientSessionIdle"
|
||||||
fieldId="clientSessionIdle"
|
id="clientSessionIdle"
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="realm-settings-help:clientSessionIdle"
|
|
||||||
forLabel={t("clientSessionIdle")}
|
|
||||||
forID="clientSessionIdle"
|
|
||||||
id="clientSessionIdle"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="clientSessionIdleTimeout"
|
|
||||||
defaultValue=""
|
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<TimeSelector
|
|
||||||
className="kc-client-session-idle"
|
|
||||||
data-testid="client-session-idle-input"
|
|
||||||
aria-label="client-session-idle-input"
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="clientSessionIdleTimeout"
|
||||||
|
defaultValue=""
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<TimeSelector
|
||||||
|
className="kc-client-session-idle"
|
||||||
|
data-testid="client-session-idle-input"
|
||||||
|
aria-label="client-session-idle-input"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={t("clientSessionMax")}
|
label={t("clientSessionMax")}
|
||||||
fieldId="clientSessionMax"
|
fieldId="clientSessionMax"
|
||||||
labelIcon={
|
labelIcon={
|
||||||
<HelpItem
|
<HelpItem
|
||||||
helpText="realm-settings-help:clientSessionMax"
|
helpText="realm-settings-help:clientSessionMax"
|
||||||
forLabel={t("clientSessionMax")}
|
forLabel={t("clientSessionMax")}
|
||||||
forID="clientSessionMax"
|
forID="clientSessionMax"
|
||||||
id="clientSessionMax"
|
id="clientSessionMax"
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="clientSessionMaxLifespan"
|
|
||||||
defaultValue=""
|
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<TimeSelector
|
|
||||||
className="kc-client-session-max"
|
|
||||||
data-testid="client-session-max-input"
|
|
||||||
aria-label="client-session-max-input"
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
</FormAccess>
|
|
||||||
</FormPanel>
|
|
||||||
<FormPanel
|
|
||||||
title={t("offlineSessionSettings")}
|
|
||||||
className="kc-offline-session-template"
|
|
||||||
>
|
|
||||||
<FormAccess
|
|
||||||
isHorizontal
|
|
||||||
role="manage-realm"
|
|
||||||
className="pf-u-mt-lg"
|
|
||||||
onSubmit={handleSubmit(save)}
|
|
||||||
>
|
>
|
||||||
<FormGroup
|
<Controller
|
||||||
label={t("offlineSessionIdle")}
|
name="clientSessionMaxLifespan"
|
||||||
fieldId="offlineSessionIdle"
|
defaultValue=""
|
||||||
labelIcon={
|
control={control}
|
||||||
<HelpItem
|
render={({ onChange, value }) => (
|
||||||
helpText="realm-settings-help:offlineSessionIdle"
|
<TimeSelector
|
||||||
forLabel={t("offlineSessionIdle")}
|
className="kc-client-session-max"
|
||||||
forID="offlineSessionIdle"
|
data-testid="client-session-max-input"
|
||||||
id="offlineSessionIdle"
|
aria-label="client-session-max-input"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
>
|
/>
|
||||||
<Controller
|
</FormGroup>
|
||||||
name="offlineSessionIdleTimeout"
|
</FormAccess>
|
||||||
defaultValue=""
|
</FormPanel>
|
||||||
control={control}
|
<FormPanel
|
||||||
render={({ onChange, value }) => (
|
title={t("offlineSessionSettings")}
|
||||||
<TimeSelector
|
className="kc-offline-session-template"
|
||||||
className="kc-offline-session-idle"
|
>
|
||||||
data-testid="offline-session-idle-input"
|
<FormAccess
|
||||||
aria-label="offline-session-idle-input"
|
isHorizontal
|
||||||
value={value}
|
role="manage-realm"
|
||||||
onChange={onChange}
|
className="pf-u-mt-lg"
|
||||||
units={["minutes", "hours", "days"]}
|
onSubmit={handleSubmit(save)}
|
||||||
/>
|
>
|
||||||
)}
|
<FormGroup
|
||||||
|
label={t("offlineSessionIdle")}
|
||||||
|
fieldId="offlineSessionIdle"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="realm-settings-help:offlineSessionIdle"
|
||||||
|
forLabel={t("offlineSessionIdle")}
|
||||||
|
forID="offlineSessionIdle"
|
||||||
|
id="offlineSessionIdle"
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="offlineSessionIdleTimeout"
|
||||||
|
defaultValue=""
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<TimeSelector
|
||||||
|
className="kc-offline-session-idle"
|
||||||
|
data-testid="offline-session-idle-input"
|
||||||
|
aria-label="offline-session-idle-input"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
hasNoPaddingTop
|
hasNoPaddingTop
|
||||||
label={t("offlineSessionMaxLimited")}
|
label={t("offlineSessionMaxLimited")}
|
||||||
fieldId="kc-offlineSessionMaxLimited"
|
fieldId="kc-offlineSessionMaxLimited"
|
||||||
labelIcon={
|
labelIcon={
|
||||||
<HelpItem
|
<HelpItem
|
||||||
helpText="realm-settings-help:offlineSessionMaxLimited"
|
helpText="realm-settings-help:offlineSessionMaxLimited"
|
||||||
forLabel={t("offlineSessionMaxLimited")}
|
forLabel={t("offlineSessionMaxLimited")}
|
||||||
forID="offlineSessionMaxLimited"
|
forID="offlineSessionMaxLimited"
|
||||||
id="offlineSessionMaxLimited"
|
id="offlineSessionMaxLimited"
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="offlineSessionMaxLifespanEnabled"
|
|
||||||
control={control}
|
|
||||||
defaultValue={false}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Switch
|
|
||||||
id="kc-offline-session-max"
|
|
||||||
data-testid="offline-session-max-switch"
|
|
||||||
aria-label="offline-session-max-switch"
|
|
||||||
label={t("common:enabled")}
|
|
||||||
labelOff={t("common:disabled")}
|
|
||||||
isChecked={value}
|
|
||||||
onChange={(value) => onChange(value.toString())}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
{offlineSessionMaxEnabled && (
|
|
||||||
<FormGroup
|
|
||||||
label={t("offlineSessionMax")}
|
|
||||||
fieldId="offlineSessionMax"
|
|
||||||
id="offline-session-max-label"
|
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="realm-settings-help:offlineSessionMax"
|
|
||||||
forLabel={t("offlineSessionMax")}
|
|
||||||
forID="offlineSessionMax"
|
|
||||||
id="offlineSessionMax"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="offlineSessionMaxLifespan"
|
|
||||||
defaultValue=""
|
|
||||||
control={control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<TimeSelector
|
|
||||||
className="kc-offline-session-max"
|
|
||||||
data-testid="offline-session-max-input"
|
|
||||||
aria-label="offline-session-max-input"
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FormAccess>
|
|
||||||
</FormPanel>
|
|
||||||
<FormPanel
|
|
||||||
className="kc-login-settings-template"
|
|
||||||
title={t("loginSettings")}
|
|
||||||
>
|
|
||||||
<FormAccess
|
|
||||||
isHorizontal
|
|
||||||
role="manage-realm"
|
|
||||||
className="pf-u-mt-lg"
|
|
||||||
onSubmit={handleSubmit(save)}
|
|
||||||
>
|
>
|
||||||
|
<Controller
|
||||||
|
name="offlineSessionMaxLifespanEnabled"
|
||||||
|
control={control}
|
||||||
|
defaultValue={false}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id="kc-offline-session-max"
|
||||||
|
data-testid="offline-session-max-switch"
|
||||||
|
aria-label="offline-session-max-switch"
|
||||||
|
label={t("common:enabled")}
|
||||||
|
labelOff={t("common:disabled")}
|
||||||
|
isChecked={value}
|
||||||
|
onChange={(value) => onChange(value.toString())}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
{offlineSessionMaxEnabled && (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={t("loginTimeout")}
|
label={t("offlineSessionMax")}
|
||||||
id="kc-login-timeout-label"
|
fieldId="offlineSessionMax"
|
||||||
fieldId="offlineSessionIdle"
|
id="offline-session-max-label"
|
||||||
labelIcon={
|
labelIcon={
|
||||||
<HelpItem
|
<HelpItem
|
||||||
helpText="realm-settings-help:loginTimeout"
|
helpText="realm-settings-help:offlineSessionMax"
|
||||||
forLabel={t("loginTimeout")}
|
forLabel={t("offlineSessionMax")}
|
||||||
forID="loginTimeout"
|
forID="offlineSessionMax"
|
||||||
id="loginTimeout"
|
id="offlineSessionMax"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Controller
|
<Controller
|
||||||
name="accessCodeLifespanLogin"
|
name="offlineSessionMaxLifespan"
|
||||||
defaultValue=""
|
defaultValue=""
|
||||||
control={control}
|
control={control}
|
||||||
render={({ onChange, value }) => (
|
render={({ onChange, value }) => (
|
||||||
<TimeSelector
|
<TimeSelector
|
||||||
className="kc-login-timeout"
|
className="kc-offline-session-max"
|
||||||
data-testid="login-timeout-input"
|
data-testid="offline-session-max-input"
|
||||||
aria-label="login-timeout-input"
|
aria-label="offline-session-max-input"
|
||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
units={["minutes", "hours", "days"]}
|
units={["minutes", "hours", "days"]}
|
||||||
|
@ -408,51 +365,92 @@ export const RealmSettingsSessionsTab = ({
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup
|
)}
|
||||||
label={t("loginActionTimeout")}
|
</FormAccess>
|
||||||
fieldId="loginActionTimeout"
|
</FormPanel>
|
||||||
id="login-action-timeout-label"
|
<FormPanel
|
||||||
labelIcon={
|
className="kc-login-settings-template"
|
||||||
<HelpItem
|
title={t("loginSettings")}
|
||||||
helpText="realm-settings-help:loginActionTimeout"
|
>
|
||||||
forLabel={t("loginActionTimeout")}
|
<FormAccess
|
||||||
forID="loginActionTimeout"
|
isHorizontal
|
||||||
id="loginActionTimeout"
|
role="manage-realm"
|
||||||
/>
|
className="pf-u-mt-lg"
|
||||||
}
|
onSubmit={handleSubmit(save)}
|
||||||
>
|
>
|
||||||
<Controller
|
<FormGroup
|
||||||
name="accessCodeLifespanUserAction"
|
label={t("loginTimeout")}
|
||||||
defaultValue=""
|
id="kc-login-timeout-label"
|
||||||
control={control}
|
fieldId="offlineSessionIdle"
|
||||||
render={({ onChange, value }) => (
|
labelIcon={
|
||||||
<TimeSelector
|
<HelpItem
|
||||||
className="kc-login-action-timeout"
|
helpText="realm-settings-help:loginTimeout"
|
||||||
data-testid="login-action-timeout-input"
|
forLabel={t("loginTimeout")}
|
||||||
aria-label="login-action-timeout-input"
|
forID="loginTimeout"
|
||||||
value={value}
|
id="loginTimeout"
|
||||||
onChange={onChange}
|
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
<ActionGroup>
|
>
|
||||||
<Button
|
<Controller
|
||||||
variant="primary"
|
name="accessCodeLifespanLogin"
|
||||||
type="submit"
|
defaultValue=""
|
||||||
data-testid="sessions-tab-save"
|
control={control}
|
||||||
isDisabled={!formState.isDirty}
|
render={({ onChange, value }) => (
|
||||||
>
|
<TimeSelector
|
||||||
{t("common:save")}
|
className="kc-login-timeout"
|
||||||
</Button>
|
data-testid="login-timeout-input"
|
||||||
<Button variant="link" onClick={reset}>
|
aria-label="login-timeout-input"
|
||||||
{t("common:revert")}
|
value={value}
|
||||||
</Button>
|
onChange={onChange}
|
||||||
</ActionGroup>
|
units={["minutes", "hours", "days"]}
|
||||||
</FormAccess>
|
/>
|
||||||
</FormPanel>
|
)}
|
||||||
</PageSection>
|
/>
|
||||||
</>
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("loginActionTimeout")}
|
||||||
|
fieldId="loginActionTimeout"
|
||||||
|
id="login-action-timeout-label"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="realm-settings-help:loginActionTimeout"
|
||||||
|
forLabel={t("loginActionTimeout")}
|
||||||
|
forID="loginActionTimeout"
|
||||||
|
id="loginActionTimeout"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="accessCodeLifespanUserAction"
|
||||||
|
defaultValue=""
|
||||||
|
control={control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<TimeSelector
|
||||||
|
className="kc-login-action-timeout"
|
||||||
|
data-testid="login-action-timeout-input"
|
||||||
|
aria-label="login-action-timeout-input"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<ActionGroup>
|
||||||
|
<Button
|
||||||
|
variant="primary"
|
||||||
|
type="submit"
|
||||||
|
data-testid="sessions-tab-save"
|
||||||
|
isDisabled={!formState.isDirty}
|
||||||
|
>
|
||||||
|
{t("common:save")}
|
||||||
|
</Button>
|
||||||
|
<Button variant="link" onClick={reset}>
|
||||||
|
{t("common:revert")}
|
||||||
|
</Button>
|
||||||
|
</ActionGroup>
|
||||||
|
</FormAccess>
|
||||||
|
</FormPanel>
|
||||||
|
</PageSection>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -55,314 +55,308 @@ export const RealmSettingsThemesTab = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<PageSection variant="light">
|
||||||
<PageSection variant="light">
|
<FormAccess
|
||||||
<FormAccess
|
isHorizontal
|
||||||
isHorizontal
|
role="manage-realm"
|
||||||
role="manage-realm"
|
className="pf-u-mt-lg"
|
||||||
className="pf-u-mt-lg"
|
onSubmit={handleSubmit(save)}
|
||||||
onSubmit={handleSubmit(save)}
|
>
|
||||||
|
<FormGroup
|
||||||
|
label={t("loginTheme")}
|
||||||
|
fieldId="kc-login-theme"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="realm-settings-help:loginTheme"
|
||||||
|
forLabel={t("loginTheme")}
|
||||||
|
forID="kc-login-theme"
|
||||||
|
/>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<FormGroup
|
<Controller
|
||||||
label={t("loginTheme")}
|
name="loginTheme"
|
||||||
fieldId="kc-login-theme"
|
control={control}
|
||||||
labelIcon={
|
defaultValue=""
|
||||||
<HelpItem
|
render={({ onChange, value }) => (
|
||||||
helpText="realm-settings-help:loginTheme"
|
<Select
|
||||||
forLabel={t("loginTheme")}
|
toggleId="kc-login-theme"
|
||||||
forID="kc-login-theme"
|
onToggle={() => setLoginThemeOpen(!loginThemeOpen)}
|
||||||
/>
|
onSelect={(_, value) => {
|
||||||
}
|
onChange(value as string);
|
||||||
>
|
setLoginThemeOpen(false);
|
||||||
<Controller
|
}}
|
||||||
name="loginTheme"
|
selections={value}
|
||||||
control={control}
|
variant={SelectVariant.single}
|
||||||
defaultValue=""
|
aria-label={t("loginTheme")}
|
||||||
render={({ onChange, value }) => (
|
isOpen={loginThemeOpen}
|
||||||
<Select
|
placeholderText="Select a theme"
|
||||||
toggleId="kc-login-theme"
|
data-testid="select-login-theme"
|
||||||
onToggle={() => setLoginThemeOpen(!loginThemeOpen)}
|
|
||||||
onSelect={(_, value) => {
|
|
||||||
onChange(value as string);
|
|
||||||
setLoginThemeOpen(false);
|
|
||||||
}}
|
|
||||||
selections={value}
|
|
||||||
variant={SelectVariant.single}
|
|
||||||
aria-label={t("loginTheme")}
|
|
||||||
isOpen={loginThemeOpen}
|
|
||||||
placeholderText="Select a theme"
|
|
||||||
data-testid="select-login-theme"
|
|
||||||
>
|
|
||||||
{themeTypes.login.map((theme, idx) => (
|
|
||||||
<SelectOption
|
|
||||||
selected={theme.name === value}
|
|
||||||
key={`login-theme-${idx}`}
|
|
||||||
value={theme.name}
|
|
||||||
>
|
|
||||||
{t(`${theme.name}`)}
|
|
||||||
</SelectOption>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("accountTheme")}
|
|
||||||
fieldId="kc-account-theme"
|
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="realm-settings-help:accountTheme"
|
|
||||||
forLabel={t("accountTheme")}
|
|
||||||
forID="kc-account-theme"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="accountTheme"
|
|
||||||
control={control}
|
|
||||||
defaultValue=""
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Select
|
|
||||||
toggleId="kc-account-theme"
|
|
||||||
onToggle={() => setAccountThemeOpen(!accountThemeOpen)}
|
|
||||||
onSelect={(_, value) => {
|
|
||||||
onChange(value as string);
|
|
||||||
setAccountThemeOpen(false);
|
|
||||||
}}
|
|
||||||
selections={value}
|
|
||||||
variant={SelectVariant.single}
|
|
||||||
aria-label={t("accountTheme")}
|
|
||||||
isOpen={accountThemeOpen}
|
|
||||||
placeholderText="Select a theme"
|
|
||||||
data-testid="select-account-theme"
|
|
||||||
>
|
|
||||||
{themeTypes.account.map((theme, idx) => (
|
|
||||||
<SelectOption
|
|
||||||
selected={theme.name === value}
|
|
||||||
key={`account-theme-${idx}`}
|
|
||||||
value={theme.name}
|
|
||||||
>
|
|
||||||
{t(`${theme.name}`)}
|
|
||||||
</SelectOption>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("adminTheme")}
|
|
||||||
fieldId="kc-admin-console-theme"
|
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="realm-settings-help:adminConsoleTheme"
|
|
||||||
forLabel={t("adminTheme")}
|
|
||||||
forID="kc-admin-console-theme"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="adminTheme"
|
|
||||||
control={control}
|
|
||||||
defaultValue=""
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Select
|
|
||||||
toggleId="kc-admin-console-theme"
|
|
||||||
onToggle={() =>
|
|
||||||
setAdminConsoleThemeOpen(!adminConsoleThemeOpen)
|
|
||||||
}
|
|
||||||
onSelect={(_, value) => {
|
|
||||||
onChange(value as string);
|
|
||||||
setAdminConsoleThemeOpen(false);
|
|
||||||
}}
|
|
||||||
selections={value}
|
|
||||||
variant={SelectVariant.single}
|
|
||||||
aria-label={t("adminConsoleTheme")}
|
|
||||||
isOpen={adminConsoleThemeOpen}
|
|
||||||
placeholderText="Select a theme"
|
|
||||||
data-testid="select-admin-theme"
|
|
||||||
>
|
|
||||||
{themeTypes.admin.map((theme, idx) => (
|
|
||||||
<SelectOption
|
|
||||||
selected={theme.name === value}
|
|
||||||
key={`admin-theme-${idx}`}
|
|
||||||
value={theme.name}
|
|
||||||
>
|
|
||||||
{t(`${theme.name}`)}
|
|
||||||
</SelectOption>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("emailTheme")}
|
|
||||||
fieldId="kc-email-theme"
|
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="realm-settings-help:emailTheme"
|
|
||||||
forLabel={t("emailTheme")}
|
|
||||||
forID="kc-email-theme"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="emailTheme"
|
|
||||||
control={control}
|
|
||||||
defaultValue=""
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Select
|
|
||||||
toggleId="kc-email-theme"
|
|
||||||
onToggle={() => setEmailThemeOpen(!emailThemeOpen)}
|
|
||||||
onSelect={(_, value) => {
|
|
||||||
onChange(value as string);
|
|
||||||
setEmailThemeOpen(false);
|
|
||||||
}}
|
|
||||||
selections={value}
|
|
||||||
variant={SelectVariant.single}
|
|
||||||
aria-label={t("emailTheme")}
|
|
||||||
isOpen={emailThemeOpen}
|
|
||||||
placeholderText="Select a theme"
|
|
||||||
data-testid="select-email-theme"
|
|
||||||
>
|
|
||||||
{themeTypes.email.map((theme, idx) => (
|
|
||||||
<SelectOption
|
|
||||||
selected={theme.name === value}
|
|
||||||
key={`email-theme-${idx}`}
|
|
||||||
value={theme.name}
|
|
||||||
>
|
|
||||||
{t(`${theme.name}`)}
|
|
||||||
</SelectOption>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("internationalization")}
|
|
||||||
fieldId="kc-internationalization"
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="internationalizationEnabled"
|
|
||||||
control={control}
|
|
||||||
defaultValue={false}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Switch
|
|
||||||
id="kc-t-internationalization"
|
|
||||||
label={t("common:enabled")}
|
|
||||||
labelOff={t("common:disabled")}
|
|
||||||
isChecked={value}
|
|
||||||
data-testid={
|
|
||||||
value
|
|
||||||
? "internationalization-enabled"
|
|
||||||
: "internationalization-disabled"
|
|
||||||
}
|
|
||||||
onChange={onChange}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
{internationalizationEnabled && (
|
|
||||||
<>
|
|
||||||
<FormGroup
|
|
||||||
label={t("supportedLocales")}
|
|
||||||
fieldId="kc-t-supported-locales"
|
|
||||||
>
|
>
|
||||||
<Controller
|
{themeTypes.login.map((theme, idx) => (
|
||||||
name="supportedLocales"
|
<SelectOption
|
||||||
control={control}
|
selected={theme.name === value}
|
||||||
defaultValue={themeTypes?.account![0].locales}
|
key={`login-theme-${idx}`}
|
||||||
render={({ value, onChange }) => (
|
value={theme.name}
|
||||||
<Select
|
>
|
||||||
toggleId="kc-t-supported-locales"
|
{t(`${theme.name}`)}
|
||||||
onToggle={() => {
|
</SelectOption>
|
||||||
setSupportedLocalesOpen(!supportedLocalesOpen);
|
))}
|
||||||
}}
|
</Select>
|
||||||
onSelect={(_, v) => {
|
)}
|
||||||
const option = v as string;
|
/>
|
||||||
if (!value) {
|
</FormGroup>
|
||||||
onChange([option]);
|
<FormGroup
|
||||||
} else if (value!.includes(option)) {
|
label={t("accountTheme")}
|
||||||
onChange(
|
fieldId="kc-account-theme"
|
||||||
value.filter((item: string) => item !== option)
|
labelIcon={
|
||||||
);
|
<HelpItem
|
||||||
} else {
|
helpText="realm-settings-help:accountTheme"
|
||||||
onChange([...value, option]);
|
forLabel={t("accountTheme")}
|
||||||
}
|
forID="kc-account-theme"
|
||||||
}}
|
/>
|
||||||
onClear={() => {
|
}
|
||||||
onChange([]);
|
>
|
||||||
}}
|
<Controller
|
||||||
selections={value}
|
name="accountTheme"
|
||||||
variant={SelectVariant.typeaheadMulti}
|
control={control}
|
||||||
aria-label={t("supportedLocales")}
|
defaultValue=""
|
||||||
isOpen={supportedLocalesOpen}
|
render={({ onChange, value }) => (
|
||||||
placeholderText={"Select locales"}
|
<Select
|
||||||
>
|
toggleId="kc-account-theme"
|
||||||
{themeTypes?.login![0].locales.map(
|
onToggle={() => setAccountThemeOpen(!accountThemeOpen)}
|
||||||
(locale: string, idx: number) => (
|
onSelect={(_, value) => {
|
||||||
<SelectOption
|
onChange(value as string);
|
||||||
selected={true}
|
setAccountThemeOpen(false);
|
||||||
key={`locale-${idx}`}
|
}}
|
||||||
value={locale}
|
selections={value}
|
||||||
>
|
variant={SelectVariant.single}
|
||||||
{t(`allSupportedLocales.${locale}`)}
|
aria-label={t("accountTheme")}
|
||||||
</SelectOption>
|
isOpen={accountThemeOpen}
|
||||||
)
|
placeholderText="Select a theme"
|
||||||
)}
|
data-testid="select-account-theme"
|
||||||
</Select>
|
>
|
||||||
)}
|
{themeTypes.account.map((theme, idx) => (
|
||||||
/>
|
<SelectOption
|
||||||
</FormGroup>
|
selected={theme.name === value}
|
||||||
<FormGroup label={t("defaultLocale")} fieldId="kc-default-locale">
|
key={`account-theme-${idx}`}
|
||||||
<Controller
|
value={theme.name}
|
||||||
name="defaultLocale"
|
>
|
||||||
control={control}
|
{t(`${theme.name}`)}
|
||||||
defaultValue=""
|
</SelectOption>
|
||||||
render={({ onChange, value }) => (
|
))}
|
||||||
<Select
|
</Select>
|
||||||
toggleId="kc-t-default-locale"
|
)}
|
||||||
onToggle={() => setDefaultLocaleOpen(!defaultLocaleOpen)}
|
/>
|
||||||
onSelect={(_, value) => {
|
</FormGroup>
|
||||||
onChange(value as string);
|
<FormGroup
|
||||||
setDefaultLocaleOpen(false);
|
label={t("adminTheme")}
|
||||||
}}
|
fieldId="kc-admin-console-theme"
|
||||||
selections={value && t(`allSupportedLocales.${value}`)}
|
labelIcon={
|
||||||
variant={SelectVariant.single}
|
<HelpItem
|
||||||
aria-label={t("defaultLocale")}
|
helpText="realm-settings-help:adminConsoleTheme"
|
||||||
isOpen={defaultLocaleOpen}
|
forLabel={t("adminTheme")}
|
||||||
placeholderText="Select one"
|
forID="kc-admin-console-theme"
|
||||||
data-testid="select-default-locale"
|
/>
|
||||||
>
|
}
|
||||||
{watchSupportedLocales.map(
|
>
|
||||||
(locale: string, idx: number) => (
|
<Controller
|
||||||
<SelectOption
|
name="adminTheme"
|
||||||
key={`default-locale-${idx}`}
|
control={control}
|
||||||
value={locale}
|
defaultValue=""
|
||||||
>
|
render={({ onChange, value }) => (
|
||||||
{t(`allSupportedLocales.${locale}`)}
|
<Select
|
||||||
</SelectOption>
|
toggleId="kc-admin-console-theme"
|
||||||
)
|
onToggle={() =>
|
||||||
)}
|
setAdminConsoleThemeOpen(!adminConsoleThemeOpen)
|
||||||
</Select>
|
}
|
||||||
)}
|
onSelect={(_, value) => {
|
||||||
/>
|
onChange(value as string);
|
||||||
</FormGroup>
|
setAdminConsoleThemeOpen(false);
|
||||||
</>
|
}}
|
||||||
)}
|
selections={value}
|
||||||
<ActionGroup>
|
variant={SelectVariant.single}
|
||||||
<Button
|
aria-label={t("adminConsoleTheme")}
|
||||||
variant="primary"
|
isOpen={adminConsoleThemeOpen}
|
||||||
type="submit"
|
placeholderText="Select a theme"
|
||||||
data-testid="themes-tab-save"
|
data-testid="select-admin-theme"
|
||||||
|
>
|
||||||
|
{themeTypes.admin.map((theme, idx) => (
|
||||||
|
<SelectOption
|
||||||
|
selected={theme.name === value}
|
||||||
|
key={`admin-theme-${idx}`}
|
||||||
|
value={theme.name}
|
||||||
|
>
|
||||||
|
{t(`${theme.name}`)}
|
||||||
|
</SelectOption>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("emailTheme")}
|
||||||
|
fieldId="kc-email-theme"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="realm-settings-help:emailTheme"
|
||||||
|
forLabel={t("emailTheme")}
|
||||||
|
forID="kc-email-theme"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="emailTheme"
|
||||||
|
control={control}
|
||||||
|
defaultValue=""
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Select
|
||||||
|
toggleId="kc-email-theme"
|
||||||
|
onToggle={() => setEmailThemeOpen(!emailThemeOpen)}
|
||||||
|
onSelect={(_, value) => {
|
||||||
|
onChange(value as string);
|
||||||
|
setEmailThemeOpen(false);
|
||||||
|
}}
|
||||||
|
selections={value}
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
aria-label={t("emailTheme")}
|
||||||
|
isOpen={emailThemeOpen}
|
||||||
|
placeholderText="Select a theme"
|
||||||
|
data-testid="select-email-theme"
|
||||||
|
>
|
||||||
|
{themeTypes.email.map((theme, idx) => (
|
||||||
|
<SelectOption
|
||||||
|
selected={theme.name === value}
|
||||||
|
key={`email-theme-${idx}`}
|
||||||
|
value={theme.name}
|
||||||
|
>
|
||||||
|
{t(`${theme.name}`)}
|
||||||
|
</SelectOption>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("internationalization")}
|
||||||
|
fieldId="kc-internationalization"
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="internationalizationEnabled"
|
||||||
|
control={control}
|
||||||
|
defaultValue={false}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id="kc-t-internationalization"
|
||||||
|
label={t("common:enabled")}
|
||||||
|
labelOff={t("common:disabled")}
|
||||||
|
isChecked={value}
|
||||||
|
data-testid={
|
||||||
|
value
|
||||||
|
? "internationalization-enabled"
|
||||||
|
: "internationalization-disabled"
|
||||||
|
}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
{internationalizationEnabled && (
|
||||||
|
<>
|
||||||
|
<FormGroup
|
||||||
|
label={t("supportedLocales")}
|
||||||
|
fieldId="kc-t-supported-locales"
|
||||||
>
|
>
|
||||||
{t("common:save")}
|
<Controller
|
||||||
</Button>
|
name="supportedLocales"
|
||||||
<Button variant="link" onClick={reset}>
|
control={control}
|
||||||
{t("common:revert")}
|
defaultValue={themeTypes?.account![0].locales}
|
||||||
</Button>
|
render={({ value, onChange }) => (
|
||||||
</ActionGroup>
|
<Select
|
||||||
</FormAccess>
|
toggleId="kc-t-supported-locales"
|
||||||
</PageSection>
|
onToggle={() => {
|
||||||
</>
|
setSupportedLocalesOpen(!supportedLocalesOpen);
|
||||||
|
}}
|
||||||
|
onSelect={(_, v) => {
|
||||||
|
const option = v as string;
|
||||||
|
if (!value) {
|
||||||
|
onChange([option]);
|
||||||
|
} else if (value!.includes(option)) {
|
||||||
|
onChange(
|
||||||
|
value.filter((item: string) => item !== option)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
onChange([...value, option]);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onClear={() => {
|
||||||
|
onChange([]);
|
||||||
|
}}
|
||||||
|
selections={value}
|
||||||
|
variant={SelectVariant.typeaheadMulti}
|
||||||
|
aria-label={t("supportedLocales")}
|
||||||
|
isOpen={supportedLocalesOpen}
|
||||||
|
placeholderText={"Select locales"}
|
||||||
|
>
|
||||||
|
{themeTypes?.login![0].locales.map(
|
||||||
|
(locale: string, idx: number) => (
|
||||||
|
<SelectOption
|
||||||
|
selected={true}
|
||||||
|
key={`locale-${idx}`}
|
||||||
|
value={locale}
|
||||||
|
>
|
||||||
|
{t(`allSupportedLocales.${locale}`)}
|
||||||
|
</SelectOption>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup label={t("defaultLocale")} fieldId="kc-default-locale">
|
||||||
|
<Controller
|
||||||
|
name="defaultLocale"
|
||||||
|
control={control}
|
||||||
|
defaultValue=""
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Select
|
||||||
|
toggleId="kc-t-default-locale"
|
||||||
|
onToggle={() => setDefaultLocaleOpen(!defaultLocaleOpen)}
|
||||||
|
onSelect={(_, value) => {
|
||||||
|
onChange(value as string);
|
||||||
|
setDefaultLocaleOpen(false);
|
||||||
|
}}
|
||||||
|
selections={value && t(`allSupportedLocales.${value}`)}
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
aria-label={t("defaultLocale")}
|
||||||
|
isOpen={defaultLocaleOpen}
|
||||||
|
placeholderText="Select one"
|
||||||
|
data-testid="select-default-locale"
|
||||||
|
>
|
||||||
|
{watchSupportedLocales.map(
|
||||||
|
(locale: string, idx: number) => (
|
||||||
|
<SelectOption
|
||||||
|
key={`default-locale-${idx}`}
|
||||||
|
value={locale}
|
||||||
|
>
|
||||||
|
{t(`allSupportedLocales.${locale}`)}
|
||||||
|
</SelectOption>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<ActionGroup>
|
||||||
|
<Button variant="primary" type="submit" data-testid="themes-tab-save">
|
||||||
|
{t("common:save")}
|
||||||
|
</Button>
|
||||||
|
<Button variant="link" onClick={reset}>
|
||||||
|
{t("common:revert")}
|
||||||
|
</Button>
|
||||||
|
</ActionGroup>
|
||||||
|
</FormAccess>
|
||||||
|
</PageSection>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -101,302 +101,259 @@ export const RealmSettingsTokensTab = ({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<PageSection variant="light">
|
||||||
<PageSection variant="light">
|
<FormPanel
|
||||||
<FormPanel
|
title={t("realm-settings:general")}
|
||||||
title={t("realm-settings:general")}
|
className="kc-sso-session-template"
|
||||||
className="kc-sso-session-template"
|
>
|
||||||
|
<FormAccess
|
||||||
|
isHorizontal
|
||||||
|
role="manage-realm"
|
||||||
|
onSubmit={form.handleSubmit(save)}
|
||||||
>
|
>
|
||||||
<FormAccess
|
<FormGroup
|
||||||
isHorizontal
|
label={t("defaultSigAlg")}
|
||||||
role="manage-realm"
|
fieldId="kc-default-signature-algorithm"
|
||||||
onSubmit={form.handleSubmit(save)}
|
labelIcon={
|
||||||
>
|
<HelpItem
|
||||||
<FormGroup
|
helpText="realm-settings-help:defaultSigAlg"
|
||||||
label={t("defaultSigAlg")}
|
forLabel={t("defaultSigAlg")}
|
||||||
fieldId="kc-default-signature-algorithm"
|
forID={t("common:helpLabel", { label: t("algorithm") })}
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="realm-settings-help:defaultSigAlg"
|
|
||||||
forLabel={t("defaultSigAlg")}
|
|
||||||
forID={t("common:helpLabel", { label: t("algorithm") })}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="defaultSignatureAlgorithm"
|
|
||||||
defaultValue={"RS256"}
|
|
||||||
control={form.control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Select
|
|
||||||
toggleId="kc-default-sig-alg"
|
|
||||||
onToggle={() =>
|
|
||||||
setDefaultSigAlgDrpdwnOpen(!defaultSigAlgDrpdwnIsOpen)
|
|
||||||
}
|
|
||||||
onSelect={(_, value) => {
|
|
||||||
onChange(value.toString());
|
|
||||||
setDefaultSigAlgDrpdwnOpen(false);
|
|
||||||
}}
|
|
||||||
selections={[value.toString()]}
|
|
||||||
variant={SelectVariant.single}
|
|
||||||
aria-label={t("defaultSigAlg")}
|
|
||||||
isOpen={defaultSigAlgDrpdwnIsOpen}
|
|
||||||
data-testid="select-default-sig-alg"
|
|
||||||
>
|
|
||||||
{defaultSigAlgOptions!.map((p, idx) => (
|
|
||||||
<SelectOption
|
|
||||||
selected={p === value}
|
|
||||||
key={`default-sig-alg-${idx}`}
|
|
||||||
value={p}
|
|
||||||
></SelectOption>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
</FormAccess>
|
>
|
||||||
</FormPanel>
|
<Controller
|
||||||
<FormPanel
|
name="defaultSignatureAlgorithm"
|
||||||
title={t("realm-settings:refreshTokens")}
|
defaultValue={"RS256"}
|
||||||
className="kc-client-session-template"
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Select
|
||||||
|
toggleId="kc-default-sig-alg"
|
||||||
|
onToggle={() =>
|
||||||
|
setDefaultSigAlgDrpdwnOpen(!defaultSigAlgDrpdwnIsOpen)
|
||||||
|
}
|
||||||
|
onSelect={(_, value) => {
|
||||||
|
onChange(value.toString());
|
||||||
|
setDefaultSigAlgDrpdwnOpen(false);
|
||||||
|
}}
|
||||||
|
selections={[value.toString()]}
|
||||||
|
variant={SelectVariant.single}
|
||||||
|
aria-label={t("defaultSigAlg")}
|
||||||
|
isOpen={defaultSigAlgDrpdwnIsOpen}
|
||||||
|
data-testid="select-default-sig-alg"
|
||||||
|
>
|
||||||
|
{defaultSigAlgOptions!.map((p, idx) => (
|
||||||
|
<SelectOption
|
||||||
|
selected={p === value}
|
||||||
|
key={`default-sig-alg-${idx}`}
|
||||||
|
value={p}
|
||||||
|
></SelectOption>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</FormAccess>
|
||||||
|
</FormPanel>
|
||||||
|
<FormPanel
|
||||||
|
title={t("realm-settings:refreshTokens")}
|
||||||
|
className="kc-client-session-template"
|
||||||
|
>
|
||||||
|
<FormAccess
|
||||||
|
isHorizontal
|
||||||
|
role="manage-realm"
|
||||||
|
className="pf-u-mt-lg"
|
||||||
|
onSubmit={form.handleSubmit(save)}
|
||||||
>
|
>
|
||||||
<FormAccess
|
<FormGroup
|
||||||
isHorizontal
|
hasNoPaddingTop
|
||||||
role="manage-realm"
|
label={t("revokeRefreshToken")}
|
||||||
className="pf-u-mt-lg"
|
fieldId="kc-revoke-refresh-token"
|
||||||
onSubmit={form.handleSubmit(save)}
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="realm-settings-help:revokeRefreshToken"
|
||||||
|
forLabel={t("revokeRefreshToken")}
|
||||||
|
forID="revokeRefreshToken"
|
||||||
|
id="revokeRefreshToken"
|
||||||
|
/>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<FormGroup
|
<Controller
|
||||||
hasNoPaddingTop
|
name="revokeRefreshToken"
|
||||||
label={t("revokeRefreshToken")}
|
control={form.control}
|
||||||
fieldId="kc-revoke-refresh-token"
|
defaultValue={false}
|
||||||
labelIcon={
|
render={({ onChange, value }) => (
|
||||||
<HelpItem
|
<Switch
|
||||||
helpText="realm-settings-help:revokeRefreshToken"
|
id="kc-revoke-refresh-token"
|
||||||
forLabel={t("revokeRefreshToken")}
|
data-testid="revoke-refresh-token-switch"
|
||||||
forID="revokeRefreshToken"
|
aria-label="revoke-refresh-token-switch"
|
||||||
id="revokeRefreshToken"
|
label={t("common:enabled")}
|
||||||
|
labelOff={t("common:disabled")}
|
||||||
|
isChecked={value}
|
||||||
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
>
|
/>
|
||||||
<Controller
|
</FormGroup>
|
||||||
name="revokeRefreshToken"
|
<FormGroup
|
||||||
control={form.control}
|
label={t("refreshTokenMaxReuse")}
|
||||||
defaultValue={false}
|
labelIcon={
|
||||||
render={({ onChange, value }) => (
|
<HelpItem
|
||||||
<Switch
|
helpText="realm-settings-help:refreshTokenMaxReuse"
|
||||||
id="kc-revoke-refresh-token"
|
forLabel={t("refreshTokenMaxReuse")}
|
||||||
data-testid="revoke-refresh-token-switch"
|
forID="refreshTokenMaxReuse"
|
||||||
aria-label="revoke-refresh-token-switch"
|
|
||||||
label={t("common:enabled")}
|
|
||||||
labelOff={t("common:disabled")}
|
|
||||||
isChecked={value}
|
|
||||||
onChange={onChange}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
<FormGroup
|
fieldId="refreshTokenMaxReuse"
|
||||||
label={t("refreshTokenMaxReuse")}
|
>
|
||||||
labelIcon={
|
<Controller
|
||||||
<HelpItem
|
name="refreshTokenMaxReuse"
|
||||||
helpText="realm-settings-help:refreshTokenMaxReuse"
|
defaultValue={0}
|
||||||
forLabel={t("refreshTokenMaxReuse")}
|
control={form.control}
|
||||||
forID="refreshTokenMaxReuse"
|
render={({ onChange, value }) => (
|
||||||
|
<NumberInput
|
||||||
|
type="text"
|
||||||
|
id="refreshTokenMaxReuseMs"
|
||||||
|
value={value}
|
||||||
|
onPlus={() => onChange(value + 1)}
|
||||||
|
onMinus={() => onChange(value - 1)}
|
||||||
|
onChange={(event) =>
|
||||||
|
onChange(Number((event.target as HTMLInputElement).value))
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
fieldId="refreshTokenMaxReuse"
|
/>
|
||||||
>
|
</FormGroup>
|
||||||
<Controller
|
</FormAccess>
|
||||||
name="refreshTokenMaxReuse"
|
</FormPanel>
|
||||||
defaultValue={0}
|
<FormPanel
|
||||||
control={form.control}
|
title={t("realm-settings:accessTokens")}
|
||||||
render={({ onChange, value }) => (
|
className="kc-offline-session-template"
|
||||||
<NumberInput
|
>
|
||||||
type="text"
|
<FormAccess
|
||||||
id="refreshTokenMaxReuseMs"
|
isHorizontal
|
||||||
value={value}
|
role="manage-realm"
|
||||||
onPlus={() => onChange(value + 1)}
|
className="pf-u-mt-lg"
|
||||||
onMinus={() => onChange(value - 1)}
|
onSubmit={form.handleSubmit(save)}
|
||||||
onChange={(event) =>
|
|
||||||
onChange(Number((event.target as HTMLInputElement).value))
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
</FormAccess>
|
|
||||||
</FormPanel>
|
|
||||||
<FormPanel
|
|
||||||
title={t("realm-settings:accessTokens")}
|
|
||||||
className="kc-offline-session-template"
|
|
||||||
>
|
>
|
||||||
<FormAccess
|
<FormGroup
|
||||||
isHorizontal
|
label={t("accessTokenLifespan")}
|
||||||
role="manage-realm"
|
fieldId="accessTokenLifespan"
|
||||||
className="pf-u-mt-lg"
|
helperText={`It is recommended for this value to be shorter than the SSO session idle timeout: ${interpolateTimespan(
|
||||||
onSubmit={form.handleSubmit(save)}
|
forHumans(realm?.ssoSessionIdleTimeout!)
|
||||||
>
|
)}`}
|
||||||
<FormGroup
|
labelIcon={
|
||||||
label={t("accessTokenLifespan")}
|
<HelpItem
|
||||||
fieldId="accessTokenLifespan"
|
helpText="realm-settings-help:accessTokenLifespan"
|
||||||
helperText={`It is recommended for this value to be shorter than the SSO session idle timeout: ${interpolateTimespan(
|
forLabel={t("accessTokenLifespan")}
|
||||||
forHumans(realm?.ssoSessionIdleTimeout!)
|
forID="accessTokenLifespan"
|
||||||
)}`}
|
id="accessTokenLifespan"
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="realm-settings-help:accessTokenLifespan"
|
|
||||||
forLabel={t("accessTokenLifespan")}
|
|
||||||
forID="accessTokenLifespan"
|
|
||||||
id="accessTokenLifespan"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="accessTokenLifespan"
|
|
||||||
defaultValue=""
|
|
||||||
helperTextInvalid={t("common:required")}
|
|
||||||
control={form.control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<TimeSelector
|
|
||||||
validated={
|
|
||||||
value > realm?.ssoSessionIdleTimeout!
|
|
||||||
? "warning"
|
|
||||||
: "default"
|
|
||||||
}
|
|
||||||
className="kc-access-token-lifespan"
|
|
||||||
data-testid="access-token-lifespan-input"
|
|
||||||
aria-label="access-token-lifespan"
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="accessTokenLifespan"
|
||||||
|
defaultValue=""
|
||||||
|
helperTextInvalid={t("common:required")}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<TimeSelector
|
||||||
|
validated={
|
||||||
|
value > realm?.ssoSessionIdleTimeout!
|
||||||
|
? "warning"
|
||||||
|
: "default"
|
||||||
|
}
|
||||||
|
className="kc-access-token-lifespan"
|
||||||
|
data-testid="access-token-lifespan-input"
|
||||||
|
aria-label="access-token-lifespan"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={t("accessTokenLifespanImplicitFlow")}
|
label={t("accessTokenLifespanImplicitFlow")}
|
||||||
fieldId="accessTokenLifespanImplicitFlow"
|
fieldId="accessTokenLifespanImplicitFlow"
|
||||||
labelIcon={
|
labelIcon={
|
||||||
<HelpItem
|
<HelpItem
|
||||||
helpText="realm-settings-help:accessTokenLifespanImplicitFlow"
|
helpText="realm-settings-help:accessTokenLifespanImplicitFlow"
|
||||||
forLabel={t("accessTokenLifespanImplicitFlow")}
|
forLabel={t("accessTokenLifespanImplicitFlow")}
|
||||||
forID="accessTokenLifespanImplicitFlow"
|
forID="accessTokenLifespanImplicitFlow"
|
||||||
id="accessTokenLifespanImplicitFlow"
|
id="accessTokenLifespanImplicitFlow"
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="accessTokenLifespanForImplicitFlow"
|
|
||||||
defaultValue=""
|
|
||||||
control={form.control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<TimeSelector
|
|
||||||
className="kc-access-token-lifespan-implicit"
|
|
||||||
data-testid="access-token-lifespan-implicit-input"
|
|
||||||
aria-label="access-token-lifespan-implicit"
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
<FormGroup
|
|
||||||
label={t("clientLoginTimeout")}
|
|
||||||
fieldId="clientLoginTimeout"
|
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="realm-settings-help:clientLoginTimeout"
|
|
||||||
forLabel={t("clientLoginTimeout")}
|
|
||||||
forID="clientLoginTimeout"
|
|
||||||
id="clientLoginTimeout"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="accessCodeLifespan"
|
|
||||||
defaultValue=""
|
|
||||||
control={form.control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<TimeSelector
|
|
||||||
className="kc-client-login-timeout"
|
|
||||||
data-testid="client-login-timeout-input"
|
|
||||||
aria-label="client-login-timeout"
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
|
|
||||||
{offlineSessionMaxEnabled && (
|
|
||||||
<FormGroup
|
|
||||||
label={t("offlineSessionMax")}
|
|
||||||
fieldId="offlineSessionMax"
|
|
||||||
id="offline-session-max-label"
|
|
||||||
labelIcon={
|
|
||||||
<HelpItem
|
|
||||||
helpText="realm-settings-help:offlineSessionMax"
|
|
||||||
forLabel={t("offlineSessionMax")}
|
|
||||||
forID="offlineSessionMax"
|
|
||||||
id="offlineSessionMax"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="offlineSessionMaxLifespan"
|
|
||||||
defaultValue=""
|
|
||||||
control={form.control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<TimeSelector
|
|
||||||
className="kc-offline-session-max"
|
|
||||||
data-testid="offline-session-max-input"
|
|
||||||
aria-label="offline-session-max-input"
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
)}
|
|
||||||
</FormAccess>
|
|
||||||
</FormPanel>
|
|
||||||
<FormPanel
|
|
||||||
className="kc-login-settings-template"
|
|
||||||
title={t("actionTokens")}
|
|
||||||
>
|
|
||||||
<FormAccess
|
|
||||||
isHorizontal
|
|
||||||
role="manage-realm"
|
|
||||||
className="pf-u-mt-lg"
|
|
||||||
onSubmit={form.handleSubmit(save)}
|
|
||||||
>
|
>
|
||||||
|
<Controller
|
||||||
|
name="accessTokenLifespanForImplicitFlow"
|
||||||
|
defaultValue=""
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<TimeSelector
|
||||||
|
className="kc-access-token-lifespan-implicit"
|
||||||
|
data-testid="access-token-lifespan-implicit-input"
|
||||||
|
aria-label="access-token-lifespan-implicit"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("clientLoginTimeout")}
|
||||||
|
fieldId="clientLoginTimeout"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="realm-settings-help:clientLoginTimeout"
|
||||||
|
forLabel={t("clientLoginTimeout")}
|
||||||
|
forID="clientLoginTimeout"
|
||||||
|
id="clientLoginTimeout"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="accessCodeLifespan"
|
||||||
|
defaultValue=""
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<TimeSelector
|
||||||
|
className="kc-client-login-timeout"
|
||||||
|
data-testid="client-login-timeout-input"
|
||||||
|
aria-label="client-login-timeout"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
|
||||||
|
{offlineSessionMaxEnabled && (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={t("userInitiatedActionLifespan")}
|
label={t("offlineSessionMax")}
|
||||||
id="kc-user-initiated-action-lifespan"
|
fieldId="offlineSessionMax"
|
||||||
fieldId="userInitiatedActionLifespan"
|
id="offline-session-max-label"
|
||||||
labelIcon={
|
labelIcon={
|
||||||
<HelpItem
|
<HelpItem
|
||||||
helpText="realm-settings-help:userInitiatedActionLifespan"
|
helpText="realm-settings-help:offlineSessionMax"
|
||||||
forLabel={t("userInitiatedActionLifespan")}
|
forLabel={t("offlineSessionMax")}
|
||||||
forID="userInitiatedActionLifespan"
|
forID="offlineSessionMax"
|
||||||
id="userInitiatedActionLifespan"
|
id="offlineSessionMax"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Controller
|
<Controller
|
||||||
name="actionTokenGeneratedByUserLifespan"
|
name="offlineSessionMaxLifespan"
|
||||||
defaultValue={""}
|
defaultValue=""
|
||||||
control={form.control}
|
control={form.control}
|
||||||
render={({ onChange, value }) => (
|
render={({ onChange, value }) => (
|
||||||
<TimeSelector
|
<TimeSelector
|
||||||
className="kc-user-initiated-action-lifespan"
|
className="kc-offline-session-max"
|
||||||
data-testid="user-initiated-action-lifespan"
|
data-testid="offline-session-max-input"
|
||||||
aria-label="user-initiated-action-lifespan"
|
aria-label="offline-session-max-input"
|
||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
units={["minutes", "hours", "days"]}
|
units={["minutes", "hours", "days"]}
|
||||||
|
@ -404,141 +361,182 @@ export const RealmSettingsTokensTab = ({
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup
|
)}
|
||||||
label={t("defaultAdminInitiated")}
|
</FormAccess>
|
||||||
fieldId="defaultAdminInitiated"
|
</FormPanel>
|
||||||
id="default-admin-initiated-label"
|
<FormPanel
|
||||||
labelIcon={
|
className="kc-login-settings-template"
|
||||||
<HelpItem
|
title={t("actionTokens")}
|
||||||
helpText="realm-settings-help:defaultAdminInitiatedActionLifespan"
|
>
|
||||||
forLabel={t("defaultAdminInitiated")}
|
<FormAccess
|
||||||
forID="defaultAdminInitiated"
|
isHorizontal
|
||||||
id="defaultAdminInitiated"
|
role="manage-realm"
|
||||||
|
className="pf-u-mt-lg"
|
||||||
|
onSubmit={form.handleSubmit(save)}
|
||||||
|
>
|
||||||
|
<FormGroup
|
||||||
|
label={t("userInitiatedActionLifespan")}
|
||||||
|
id="kc-user-initiated-action-lifespan"
|
||||||
|
fieldId="userInitiatedActionLifespan"
|
||||||
|
labelIcon={
|
||||||
|
<HelpItem
|
||||||
|
helpText="realm-settings-help:userInitiatedActionLifespan"
|
||||||
|
forLabel={t("userInitiatedActionLifespan")}
|
||||||
|
forID="userInitiatedActionLifespan"
|
||||||
|
id="userInitiatedActionLifespan"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="actionTokenGeneratedByUserLifespan"
|
||||||
|
defaultValue={""}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<TimeSelector
|
||||||
|
className="kc-user-initiated-action-lifespan"
|
||||||
|
data-testid="user-initiated-action-lifespan"
|
||||||
|
aria-label="user-initiated-action-lifespan"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
>
|
/>
|
||||||
<Controller
|
</FormGroup>
|
||||||
name="actionTokenGeneratedByAdminLifespan"
|
<FormGroup
|
||||||
defaultValue={""}
|
label={t("defaultAdminInitiated")}
|
||||||
control={form.control}
|
fieldId="defaultAdminInitiated"
|
||||||
render={({ onChange, value }) => (
|
id="default-admin-initiated-label"
|
||||||
<TimeSelector
|
labelIcon={
|
||||||
className="kc-default-admin-initiated"
|
<HelpItem
|
||||||
data-testid="default-admin-initated-input"
|
helpText="realm-settings-help:defaultAdminInitiatedActionLifespan"
|
||||||
aria-label="default-admin-initated-input"
|
forLabel={t("defaultAdminInitiated")}
|
||||||
value={value}
|
forID="defaultAdminInitiated"
|
||||||
onChange={onChange}
|
id="defaultAdminInitiated"
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
<Text
|
>
|
||||||
className="kc-override-action-tokens-subtitle"
|
<Controller
|
||||||
component={TextVariants.h1}
|
name="actionTokenGeneratedByAdminLifespan"
|
||||||
|
defaultValue={""}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<TimeSelector
|
||||||
|
className="kc-default-admin-initiated"
|
||||||
|
data-testid="default-admin-initated-input"
|
||||||
|
aria-label="default-admin-initated-input"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<Text
|
||||||
|
className="kc-override-action-tokens-subtitle"
|
||||||
|
component={TextVariants.h1}
|
||||||
|
>
|
||||||
|
{t("overrideActionTokens")}
|
||||||
|
</Text>
|
||||||
|
<FormGroup
|
||||||
|
label={t("emailVerification")}
|
||||||
|
fieldId="emailVerification"
|
||||||
|
id="email-verification"
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="attributes.actionTokenGeneratedByUserLifespan-verify-email"
|
||||||
|
defaultValue={""}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<TimeSelector
|
||||||
|
className="kc-email-verification"
|
||||||
|
data-testid="email-verification-input"
|
||||||
|
aria-label="email-verification-input"
|
||||||
|
value={value}
|
||||||
|
onChange={(value: any) => onChange(value.toString())}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("idpAccountEmailVerification")}
|
||||||
|
fieldId="idpAccountEmailVerification"
|
||||||
|
id="idp-acct-label"
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="attributes.actionTokenGeneratedByUserLifespan-idp-verify-account-via-email"
|
||||||
|
defaultValue={""}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<TimeSelector
|
||||||
|
className="kc-idp-email-verification"
|
||||||
|
data-testid="idp-email-verification-input"
|
||||||
|
aria-label="idp-email-verification"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("forgotPassword")}
|
||||||
|
fieldId="forgotPassword"
|
||||||
|
id="forgot-password-label"
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="attributes.actionTokenGeneratedByUserLifespan-reset-credentials"
|
||||||
|
defaultValue={""}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<TimeSelector
|
||||||
|
className="kc-forgot-pw"
|
||||||
|
data-testid="forgot-pw-input"
|
||||||
|
aria-label="forgot-pw-input"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
label={t("executeActions")}
|
||||||
|
fieldId="executeActions"
|
||||||
|
id="execute-actions"
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="attributes.actionTokenGeneratedByUserLifespan-execute-actions"
|
||||||
|
defaultValue={""}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<TimeSelector
|
||||||
|
className="kc-execute-actions"
|
||||||
|
data-testid="execute-actions-input"
|
||||||
|
aria-label="execute-actions-input"
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
units={["minutes", "hours", "days"]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<ActionGroup>
|
||||||
|
<Button
|
||||||
|
variant="primary"
|
||||||
|
type="submit"
|
||||||
|
data-testid="tokens-tab-save"
|
||||||
|
isDisabled={!form.formState.isDirty}
|
||||||
>
|
>
|
||||||
{t("overrideActionTokens")}
|
{t("common:save")}
|
||||||
</Text>
|
</Button>
|
||||||
<FormGroup
|
<Button variant="link" onClick={reset}>
|
||||||
label={t("emailVerification")}
|
{t("common:revert")}
|
||||||
fieldId="emailVerification"
|
</Button>
|
||||||
id="email-verification"
|
</ActionGroup>
|
||||||
>
|
</FormAccess>
|
||||||
<Controller
|
</FormPanel>
|
||||||
name="attributes.actionTokenGeneratedByUserLifespan-verify-email"
|
</PageSection>
|
||||||
defaultValue={""}
|
|
||||||
control={form.control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<TimeSelector
|
|
||||||
className="kc-email-verification"
|
|
||||||
data-testid="email-verification-input"
|
|
||||||
aria-label="email-verification-input"
|
|
||||||
value={value}
|
|
||||||
onChange={(value: any) => onChange(value.toString())}
|
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("idpAccountEmailVerification")}
|
|
||||||
fieldId="idpAccountEmailVerification"
|
|
||||||
id="idp-acct-label"
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="attributes.actionTokenGeneratedByUserLifespan-idp-verify-account-via-email"
|
|
||||||
defaultValue={""}
|
|
||||||
control={form.control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<TimeSelector
|
|
||||||
className="kc-idp-email-verification"
|
|
||||||
data-testid="idp-email-verification-input"
|
|
||||||
aria-label="idp-email-verification"
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("forgotPassword")}
|
|
||||||
fieldId="forgotPassword"
|
|
||||||
id="forgot-password-label"
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="attributes.actionTokenGeneratedByUserLifespan-reset-credentials"
|
|
||||||
defaultValue={""}
|
|
||||||
control={form.control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<TimeSelector
|
|
||||||
className="kc-forgot-pw"
|
|
||||||
data-testid="forgot-pw-input"
|
|
||||||
aria-label="forgot-pw-input"
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<FormGroup
|
|
||||||
label={t("executeActions")}
|
|
||||||
fieldId="executeActions"
|
|
||||||
id="execute-actions"
|
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="attributes.actionTokenGeneratedByUserLifespan-execute-actions"
|
|
||||||
defaultValue={""}
|
|
||||||
control={form.control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<TimeSelector
|
|
||||||
className="kc-execute-actions"
|
|
||||||
data-testid="execute-actions-input"
|
|
||||||
aria-label="execute-actions-input"
|
|
||||||
value={value}
|
|
||||||
onChange={onChange}
|
|
||||||
units={["minutes", "hours", "days"]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<ActionGroup>
|
|
||||||
<Button
|
|
||||||
variant="primary"
|
|
||||||
type="submit"
|
|
||||||
data-testid="tokens-tab-save"
|
|
||||||
isDisabled={!form.formState.isDirty}
|
|
||||||
>
|
|
||||||
{t("common:save")}
|
|
||||||
</Button>
|
|
||||||
<Button variant="link" onClick={reset}>
|
|
||||||
{t("common:revert")}
|
|
||||||
</Button>
|
|
||||||
</ActionGroup>
|
|
||||||
</FormAccess>
|
|
||||||
</FormPanel>
|
|
||||||
</PageSection>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,15 +39,13 @@ export function EventsTypeTable({
|
||||||
onSelect={onSelect ? onSelect : undefined}
|
onSelect={onSelect ? onSelect : undefined}
|
||||||
canSelectAll={!!onSelect}
|
canSelectAll={!!onSelect}
|
||||||
toolbarItem={
|
toolbarItem={
|
||||||
<>
|
addTypes && (
|
||||||
{addTypes && (
|
<ToolbarItem>
|
||||||
<ToolbarItem>
|
<Button id="addTypes" onClick={addTypes} data-testid="addTypes">
|
||||||
<Button id="addTypes" onClick={addTypes} data-testid="addTypes">
|
{t("addSavedTypes")}
|
||||||
{t("addSavedTypes")}
|
</Button>
|
||||||
</Button>
|
</ToolbarItem>
|
||||||
</ToolbarItem>
|
)
|
||||||
)}
|
|
||||||
</>
|
|
||||||
}
|
}
|
||||||
actions={
|
actions={
|
||||||
!onDelete
|
!onDelete
|
||||||
|
|
|
@ -195,20 +195,18 @@ export const AESGeneratedForm = ({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{editMode && (
|
{editMode && (
|
||||||
<>
|
<TextInput
|
||||||
<TextInput
|
ref={form.register()}
|
||||||
ref={form.register()}
|
type="text"
|
||||||
type="text"
|
id="name"
|
||||||
id="name"
|
name="name"
|
||||||
name="name"
|
defaultValue={providerId}
|
||||||
defaultValue={providerId}
|
validated={
|
||||||
validated={
|
form.errors.name
|
||||||
form.errors.name
|
? ValidatedOptions.error
|
||||||
? ValidatedOptions.error
|
: ValidatedOptions.default
|
||||||
: ValidatedOptions.default
|
}
|
||||||
}
|
/>
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
|
|
|
@ -194,20 +194,18 @@ export const ECDSAGeneratedForm = ({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{editMode && (
|
{editMode && (
|
||||||
<>
|
<TextInput
|
||||||
<TextInput
|
ref={form.register()}
|
||||||
ref={form.register()}
|
type="text"
|
||||||
type="text"
|
id="name"
|
||||||
id="name"
|
name="name"
|
||||||
name="name"
|
defaultValue={providerId}
|
||||||
defaultValue={providerId}
|
validated={
|
||||||
validated={
|
form.errors.name
|
||||||
form.errors.name
|
? ValidatedOptions.error
|
||||||
? ValidatedOptions.error
|
: ValidatedOptions.default
|
||||||
: ValidatedOptions.default
|
}
|
||||||
}
|
/>
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
|
|
|
@ -202,20 +202,18 @@ export const HMACGeneratedForm = ({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{editMode && (
|
{editMode && (
|
||||||
<>
|
<TextInput
|
||||||
<TextInput
|
ref={form.register()}
|
||||||
ref={form.register()}
|
type="text"
|
||||||
type="text"
|
id="name"
|
||||||
id="name"
|
name="name"
|
||||||
name="name"
|
defaultValue={providerId}
|
||||||
defaultValue={providerId}
|
validated={
|
||||||
validated={
|
form.errors.name
|
||||||
form.errors.name
|
? ValidatedOptions.error
|
||||||
? ValidatedOptions.error
|
: ValidatedOptions.default
|
||||||
: ValidatedOptions.default
|
}
|
||||||
}
|
/>
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
|
|
|
@ -209,20 +209,18 @@ export const JavaKeystoreForm = ({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{editMode && (
|
{editMode && (
|
||||||
<>
|
<TextInput
|
||||||
<TextInput
|
ref={form.register()}
|
||||||
ref={form.register()}
|
type="text"
|
||||||
type="text"
|
id="name"
|
||||||
id="name"
|
name="name"
|
||||||
name="name"
|
defaultValue={providerId}
|
||||||
defaultValue={providerId}
|
validated={
|
||||||
validated={
|
form.errors.name
|
||||||
form.errors.name
|
? ValidatedOptions.error
|
||||||
? ValidatedOptions.error
|
: ValidatedOptions.default
|
||||||
: ValidatedOptions.default
|
}
|
||||||
}
|
/>
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
|
|
|
@ -203,20 +203,18 @@ export const RSAGeneratedForm = ({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{editMode && (
|
{editMode && (
|
||||||
<>
|
<TextInput
|
||||||
<TextInput
|
ref={form.register()}
|
||||||
ref={form.register()}
|
type="text"
|
||||||
type="text"
|
id="name"
|
||||||
id="name"
|
name="name"
|
||||||
name="name"
|
defaultValue={providerId}
|
||||||
defaultValue={providerId}
|
validated={
|
||||||
validated={
|
form.errors.name
|
||||||
form.errors.name
|
? ValidatedOptions.error
|
||||||
? ValidatedOptions.error
|
: ValidatedOptions.default
|
||||||
: ValidatedOptions.default
|
}
|
||||||
}
|
/>
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
|
|
|
@ -212,20 +212,18 @@ export const RSAForm = ({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{editMode && (
|
{editMode && (
|
||||||
<>
|
<TextInput
|
||||||
<TextInput
|
ref={form.register()}
|
||||||
ref={form.register()}
|
type="text"
|
||||||
type="text"
|
id="name"
|
||||||
id="name"
|
name="name"
|
||||||
name="name"
|
defaultValue={providerId}
|
||||||
defaultValue={providerId}
|
validated={
|
||||||
validated={
|
form.errors.name
|
||||||
form.errors.name
|
? ValidatedOptions.error
|
||||||
? ValidatedOptions.error
|
: ValidatedOptions.default
|
||||||
: ValidatedOptions.default
|
}
|
||||||
}
|
/>
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup
|
<FormGroup
|
||||||
|
|
|
@ -316,9 +316,7 @@ export const KerberosSettingsRequired = ({
|
||||||
)}
|
)}
|
||||||
></Controller>
|
></Controller>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
) : (
|
) : null}
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={t("updateFirstLogin")}
|
label={t("updateFirstLogin")}
|
||||||
|
|
|
@ -15,33 +15,31 @@ export const LdapMapperHardcodedLdapGroup = ({
|
||||||
const helpText = useTranslation("user-federation-help").t;
|
const helpText = useTranslation("user-federation-help").t;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<FormGroup
|
||||||
<FormGroup
|
label={t("group")}
|
||||||
label={t("group")}
|
labelIcon={
|
||||||
labelIcon={
|
<HelpItem
|
||||||
<HelpItem
|
helpText={helpText("groupHelp")}
|
||||||
helpText={helpText("groupHelp")}
|
forLabel={t("group")}
|
||||||
forLabel={t("group")}
|
forID="kc-group"
|
||||||
forID="kc-group"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
fieldId="kc-group"
|
|
||||||
isRequired
|
|
||||||
>
|
|
||||||
<TextInput
|
|
||||||
isRequired
|
|
||||||
type="text"
|
|
||||||
id="kc-group"
|
|
||||||
data-testid="mapper-group-fld"
|
|
||||||
name="config.group[0]"
|
|
||||||
ref={form.register({ required: true })}
|
|
||||||
validated={
|
|
||||||
form.errors.config?.group
|
|
||||||
? ValidatedOptions.error
|
|
||||||
: ValidatedOptions.default
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
}
|
||||||
</>
|
fieldId="kc-group"
|
||||||
|
isRequired
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
isRequired
|
||||||
|
type="text"
|
||||||
|
id="kc-group"
|
||||||
|
data-testid="mapper-group-fld"
|
||||||
|
name="config.group[0]"
|
||||||
|
ref={form.register({ required: true })}
|
||||||
|
validated={
|
||||||
|
form.errors.config?.group
|
||||||
|
? ValidatedOptions.error
|
||||||
|
: ValidatedOptions.default
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -76,9 +76,7 @@ export const LdapMapperList = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const MapperLink = (mapper: ComponentRepresentation) => (
|
const MapperLink = (mapper: ComponentRepresentation) => (
|
||||||
<>
|
<Link to={`${getUrl(url)}/${mapper.id}`}>{mapper.name}</Link>
|
||||||
<Link to={`${getUrl(url)}/${mapper.id}`}>{mapper.name}</Link>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -15,35 +15,33 @@ export const LdapMapperMsadUserAccount = ({
|
||||||
const helpText = useTranslation("user-federation-help").t;
|
const helpText = useTranslation("user-federation-help").t;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<FormGroup
|
||||||
<FormGroup
|
label={t("passwordPolicyHintsEnabled")}
|
||||||
label={t("passwordPolicyHintsEnabled")}
|
labelIcon={
|
||||||
labelIcon={
|
<HelpItem
|
||||||
<HelpItem
|
helpText={helpText("passwordPolicyHintsEnabledHelp")}
|
||||||
helpText={helpText("passwordPolicyHintsEnabledHelp")}
|
forLabel={t("passwordPolicyHintsEnabled")}
|
||||||
forLabel={t("passwordPolicyHintsEnabled")}
|
forID="kc-pw-policy-hints-enabled"
|
||||||
forID="kc-pw-policy-hints-enabled"
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-der-formatted"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.ldap-password-policy-hints-enabled"
|
||||||
|
defaultValue={["false"]}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id={"kc-pw-policy-hints-enabled"}
|
||||||
|
isDisabled={false}
|
||||||
|
onChange={(value) => onChange([`${value}`])}
|
||||||
|
isChecked={value[0] === "true"}
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
fieldId="kc-der-formatted"
|
></Controller>
|
||||||
hasNoPaddingTop
|
</FormGroup>
|
||||||
>
|
|
||||||
<Controller
|
|
||||||
name="config.ldap-password-policy-hints-enabled"
|
|
||||||
defaultValue={["false"]}
|
|
||||||
control={form.control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Switch
|
|
||||||
id={"kc-pw-policy-hints-enabled"}
|
|
||||||
isDisabled={false}
|
|
||||||
onChange={(value) => onChange([`${value}`])}
|
|
||||||
isChecked={value[0] === "true"}
|
|
||||||
label={t("common:on")}
|
|
||||||
labelOff={t("common:off")}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
></Controller>
|
|
||||||
</FormGroup>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -173,39 +173,35 @@ export const LdapMapperUserAttribute = ({
|
||||||
></Controller>
|
></Controller>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
{mapperType === "certificate-ldap-mapper" ? (
|
{mapperType === "certificate-ldap-mapper" ? (
|
||||||
<>
|
<FormGroup
|
||||||
<FormGroup
|
label={t("derFormatted")}
|
||||||
label={t("derFormatted")}
|
labelIcon={
|
||||||
labelIcon={
|
<HelpItem
|
||||||
<HelpItem
|
helpText={helpText("derFormattedHelp")}
|
||||||
helpText={helpText("derFormattedHelp")}
|
forLabel={t("derFormatted")}
|
||||||
forLabel={t("derFormatted")}
|
forID="kc-der-formatted"
|
||||||
forID="kc-der-formatted"
|
/>
|
||||||
|
}
|
||||||
|
fieldId="kc-der-formatted"
|
||||||
|
hasNoPaddingTop
|
||||||
|
>
|
||||||
|
<Controller
|
||||||
|
name="config.is-der-formatted"
|
||||||
|
defaultValue={["false"]}
|
||||||
|
control={form.control}
|
||||||
|
render={({ onChange, value }) => (
|
||||||
|
<Switch
|
||||||
|
id={"kc-der-formatted"}
|
||||||
|
isDisabled={false}
|
||||||
|
onChange={(value) => onChange([`${value}`])}
|
||||||
|
isChecked={value[0] === "true"}
|
||||||
|
label={t("common:on")}
|
||||||
|
labelOff={t("common:off")}
|
||||||
/>
|
/>
|
||||||
}
|
)}
|
||||||
fieldId="kc-der-formatted"
|
></Controller>
|
||||||
hasNoPaddingTop
|
</FormGroup>
|
||||||
>
|
) : null}
|
||||||
<Controller
|
|
||||||
name="config.is-der-formatted"
|
|
||||||
defaultValue={["false"]}
|
|
||||||
control={form.control}
|
|
||||||
render={({ onChange, value }) => (
|
|
||||||
<Switch
|
|
||||||
id={"kc-der-formatted"}
|
|
||||||
isDisabled={false}
|
|
||||||
onChange={(value) => onChange([`${value}`])}
|
|
||||||
isChecked={value[0] === "true"}
|
|
||||||
label={t("common:on")}
|
|
||||||
labelOff={t("common:off")}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
></Controller>
|
|
||||||
</FormGroup>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -190,9 +190,7 @@ export const SettingsCache = ({
|
||||||
)}
|
)}
|
||||||
></Controller>
|
></Controller>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
) : (
|
) : null}
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{_.isEqual(cachePolicyType, ["EVICT_DAILY"]) ||
|
{_.isEqual(cachePolicyType, ["EVICT_DAILY"]) ||
|
||||||
_.isEqual(cachePolicyType, ["EVICT_WEEKLY"]) ? (
|
_.isEqual(cachePolicyType, ["EVICT_WEEKLY"]) ? (
|
||||||
<>
|
<>
|
||||||
|
@ -269,9 +267,7 @@ export const SettingsCache = ({
|
||||||
></Controller>
|
></Controller>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : null}
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{_.isEqual(cachePolicyType, ["MAX_LIFESPAN"]) ? (
|
{_.isEqual(cachePolicyType, ["MAX_LIFESPAN"]) ? (
|
||||||
<FormGroup
|
<FormGroup
|
||||||
label={t("maxLifespan")}
|
label={t("maxLifespan")}
|
||||||
|
@ -292,9 +288,7 @@ export const SettingsCache = ({
|
||||||
data-testid="kerberos-cache-lifespan"
|
data-testid="kerberos-cache-lifespan"
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
) : (
|
) : null}
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</FormAccess>
|
</FormAccess>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -353,28 +353,26 @@ export const UserForm = ({
|
||||||
typeAheadAriaLabel="Select an action"
|
typeAheadAriaLabel="Select an action"
|
||||||
control={control}
|
control={control}
|
||||||
render={() => (
|
render={() => (
|
||||||
<>
|
<InputGroup>
|
||||||
<InputGroup>
|
<ChipGroup categoryName={" "}>
|
||||||
<ChipGroup categoryName={" "}>
|
{selectedGroups.map((currentChip) => (
|
||||||
{selectedGroups.map((currentChip) => (
|
<Chip
|
||||||
<Chip
|
key={currentChip.id}
|
||||||
key={currentChip.id}
|
onClick={() => deleteItem(currentChip.name!)}
|
||||||
onClick={() => deleteItem(currentChip.name!)}
|
>
|
||||||
>
|
{currentChip.path}
|
||||||
{currentChip.path}
|
</Chip>
|
||||||
</Chip>
|
))}
|
||||||
))}
|
</ChipGroup>
|
||||||
</ChipGroup>
|
<Button
|
||||||
<Button
|
id="kc-join-groups-button"
|
||||||
id="kc-join-groups-button"
|
onClick={toggleModal}
|
||||||
onClick={toggleModal}
|
variant="secondary"
|
||||||
variant="secondary"
|
data-testid="join-groups-button"
|
||||||
data-testid="join-groups-button"
|
>
|
||||||
>
|
{t("users:joinGroups")}
|
||||||
{t("users:joinGroups")}
|
</Button>
|
||||||
</Button>
|
</InputGroup>
|
||||||
</InputGroup>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
|
@ -189,9 +189,7 @@ export const UserGroups = () => {
|
||||||
refresh();
|
refresh();
|
||||||
}, [isDirectMembership]);
|
}, [isDirectMembership]);
|
||||||
|
|
||||||
const AliasRenderer = (group: GroupRepresentation) => {
|
const AliasRenderer = (group: GroupRepresentation) => group.name;
|
||||||
return <>{group.name}</>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleModal = () => {
|
const toggleModal = () => {
|
||||||
setOpen(!open);
|
setOpen(!open);
|
||||||
|
@ -232,17 +230,15 @@ export const UserGroups = () => {
|
||||||
directMembershipList.length === 0 ||
|
directMembershipList.length === 0 ||
|
||||||
isDirectMembership;
|
isDirectMembership;
|
||||||
return (
|
return (
|
||||||
<>
|
canLeaveGroup && (
|
||||||
{canLeaveGroup && (
|
<Button
|
||||||
<Button
|
data-testid={`leave-${group.name}`}
|
||||||
data-testid={`leave-${group.name}`}
|
onClick={() => leave(group)}
|
||||||
onClick={() => leave(group)}
|
variant="link"
|
||||||
variant="link"
|
>
|
||||||
>
|
{t("leave")}
|
||||||
{t("leave")}
|
</Button>
|
||||||
</Button>
|
)
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -63,14 +63,12 @@ export const UsersSection = () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const UserDetailLink = (user: UserRepresentation) => (
|
const UserDetailLink = (user: UserRepresentation) => (
|
||||||
<>
|
<Link
|
||||||
<Link
|
key={user.username}
|
||||||
key={user.username}
|
to={toUser({ realm: realmName, id: user.id!, tab: "settings" })}
|
||||||
to={toUser({ realm: realmName, id: user.id!, tab: "settings" })}
|
>
|
||||||
>
|
{user.username}
|
||||||
{user.username}
|
</Link>
|
||||||
</Link>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const loader = async (first?: number, max?: number, search?: string) => {
|
const loader = async (first?: number, max?: number, search?: string) => {
|
||||||
|
|
Loading…
Reference in a new issue