added acr loa map field to realm settings (#2736)
* added acr loa map field to realm settings fixes: #2668 * changed to use one form per tab, instead of shared * fixed test
This commit is contained in:
parent
f775fd6329
commit
afbbdaaf52
14 changed files with 620 additions and 617 deletions
|
@ -237,7 +237,6 @@ describe("Realm settings events tab tests", () => {
|
|||
sidebarPage.goToRealmSettings();
|
||||
|
||||
cy.findByTestId("rs-localization-tab").click();
|
||||
|
||||
cy.findByTestId("internationalization-disabled").click({ force: true });
|
||||
|
||||
cy.get(realmSettingsPage.supportedLocalesTypeahead)
|
||||
|
@ -245,10 +244,14 @@ describe("Realm settings events tab tests", () => {
|
|||
.get(".pf-c-select__menu-item")
|
||||
.contains("Dansk")
|
||||
.click();
|
||||
|
||||
cy.get("#kc-l-supported-locales").click();
|
||||
|
||||
cy.intercept("GET", `/admin/realms/${realmName}/localization/en*`).as(
|
||||
"load"
|
||||
);
|
||||
|
||||
cy.findByTestId("localization-tab-save").click();
|
||||
cy.wait("@load");
|
||||
|
||||
addBundle();
|
||||
|
||||
|
|
|
@ -99,25 +99,25 @@
|
|||
"noKeysDescription": "You haven't created any active keys",
|
||||
"certificate": "Certificate",
|
||||
"loginScreenCustomization": "Login screen customization",
|
||||
"userRegistration": "User registration",
|
||||
"registrationAllowed": "User registration",
|
||||
"userRegistrationHelpText": "Enable/disable the registration page. A link for registration will show on login page too.",
|
||||
"forgotPassword": "Forgot password",
|
||||
"resetPasswordAllowed": "Forgot password",
|
||||
"forgotPasswordHelpText": "Show a link on login page for user to click when they have forgotten their credentials.",
|
||||
"rememberMe": "Remember me",
|
||||
"rememberMeHelpText": "Show checkbox on login page to allow user to remain logged in between browser restarts until session expires.",
|
||||
"emailSettings": "Email settings",
|
||||
"emailAsUsername": "Email as username",
|
||||
"registrationEmailAsUsername": "Email as username",
|
||||
"emailAsUsernameHelpText": "Allow users to set email as username.",
|
||||
"loginWithEmail": "Login with email",
|
||||
"loginWithEmailAllowed": "Login with email",
|
||||
"loginWithEmailHelpText": "Allow users to log in with their email address.",
|
||||
"duplicateEmails": "Duplicate emails",
|
||||
"duplicateEmailsAllowed": "Duplicate emails",
|
||||
"duplicateEmailsHelpText": "Allow multiple users to have the same email address. Changing this setting will also clear the user's cache. It is recommended to manually update email constraints of existing users in the database after switching off support for duplicate email addresses.",
|
||||
"provideEmailTitle": "Provide your email address",
|
||||
"provideEmail": "To test connection, you should provide your email address first.",
|
||||
"verifyEmail": "Verify email",
|
||||
"verifyEmailHelpText": "Require user to verify their email address after initial login or after address changes are submitted.",
|
||||
"userInfoSettings": "User info settings",
|
||||
"editUsername": "Edit username",
|
||||
"editUsernameAllowed": "Edit username",
|
||||
"enableSwitchSuccess": "{{switch}} changed successfully",
|
||||
"enableSwitchError": "Could not enable / disable due to {{error}}",
|
||||
"testConnection": "Test connection",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
@import "@patternfly/patternfly/patternfly.min.css";
|
||||
@import "@patternfly/patternfly/patternfly-addons.css";
|
||||
|
||||
.keycloak__pageheader_brand {
|
||||
img.keycloak__pageheader_brand {
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, useFormContext } from "react-hook-form";
|
||||
import { Controller, FormProvider, useForm } from "react-hook-form";
|
||||
import {
|
||||
ActionGroup,
|
||||
Button,
|
||||
|
@ -16,7 +16,7 @@ import {
|
|||
} from "@patternfly/react-core";
|
||||
|
||||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import { getBaseUrl } from "../util";
|
||||
import { convertToFormValues, getBaseUrl } from "../util";
|
||||
import useIsFeatureEnabled, { Feature } from "../utils/useIsFeatureEnabled";
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
|
@ -24,25 +24,28 @@ import { FormAccess } from "../components/form-access/FormAccess";
|
|||
import { HelpItem } from "../components/help-enabler/HelpItem";
|
||||
import { FormattedLink } from "../components/external-link/FormattedLink";
|
||||
import { KeycloakTextInput } from "../components/keycloak-text-input/KeycloakTextInput";
|
||||
import { KeyValueInput } from "../components/key-value-form/KeyValueInput";
|
||||
|
||||
type RealmSettingsGeneralTabProps = {
|
||||
realm: RealmRepresentation;
|
||||
save: (realm: RealmRepresentation) => void;
|
||||
reset: () => void;
|
||||
};
|
||||
|
||||
export const RealmSettingsGeneralTab = ({
|
||||
realm,
|
||||
save,
|
||||
reset,
|
||||
}: RealmSettingsGeneralTabProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const adminClient = useAdminClient();
|
||||
const { realm: realmName } = useRealm();
|
||||
const form = useForm<RealmRepresentation>({ shouldUnregister: false });
|
||||
const {
|
||||
register,
|
||||
control,
|
||||
handleSubmit,
|
||||
setValue,
|
||||
formState: { isDirty },
|
||||
} = useFormContext();
|
||||
} = form;
|
||||
const isFeatureEnabled = useIsFeatureEnabled();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
|
@ -50,6 +53,19 @@ export const RealmSettingsGeneralTab = ({
|
|||
|
||||
const requireSslTypes = ["all", "external", "none"];
|
||||
|
||||
const setupForm = () => {
|
||||
convertToFormValues(realm, setValue);
|
||||
if (realm.attributes?.["acr.loa.map"]) {
|
||||
const result = Object.entries(
|
||||
JSON.parse(realm.attributes["acr.loa.map"])
|
||||
).flatMap(([key, value]) => ({ key, value }));
|
||||
result.concat({ key: "", value: "" });
|
||||
setValue("attributes.acr.loa.map", result);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(setupForm, []);
|
||||
|
||||
return (
|
||||
<PageSection variant="light">
|
||||
<FormAccess
|
||||
|
@ -143,6 +159,20 @@ export const RealmSettingsGeneralTab = ({
|
|||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("clients:acrToLoAMapping")}
|
||||
fieldId="acrToLoAMapping"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="clients-help:acrToLoAMapping"
|
||||
fieldLabelId="clients:acrToLoAMapping"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<FormProvider {...form}>
|
||||
<KeyValueInput name="attributes.acr.loa.map" />
|
||||
</FormProvider>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
hasNoPaddingTop
|
||||
label={t("userManagedAccess")}
|
||||
|
@ -237,7 +267,7 @@ export const RealmSettingsGeneralTab = ({
|
|||
<Button
|
||||
data-testid="general-tab-revert"
|
||||
variant="link"
|
||||
onClick={reset}
|
||||
onClick={setupForm}
|
||||
>
|
||||
{t("common:revert")}
|
||||
</Button>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { cloneDeep, isEqual, uniqWith } from "lodash-es";
|
||||
import { Controller, useForm, useFormContext, useWatch } from "react-hook-form";
|
||||
import { Controller, useForm, useWatch } from "react-hook-form";
|
||||
import {
|
||||
ActionGroup,
|
||||
AlertVariant,
|
||||
|
@ -49,10 +49,10 @@ import { PaginatingTableToolbar } from "../components/table-toolbar/PaginatingTa
|
|||
import { SearchIcon } from "@patternfly/react-icons";
|
||||
import { useWhoAmI } from "../context/whoami/WhoAmI";
|
||||
import type { KeyValueType } from "../components/key-value-form/key-value-convert";
|
||||
import { convertToFormValues } from "../util";
|
||||
|
||||
type LocalizationTabProps = {
|
||||
save: (realm: RealmRepresentation) => void;
|
||||
reset: () => void;
|
||||
refresh: () => void;
|
||||
realm: RealmRepresentation;
|
||||
};
|
||||
|
@ -67,11 +67,7 @@ export type BundleForm = {
|
|||
messageBundle: KeyValueType;
|
||||
};
|
||||
|
||||
export const LocalizationTab = ({
|
||||
save,
|
||||
reset,
|
||||
realm,
|
||||
}: LocalizationTabProps) => {
|
||||
export const LocalizationTab = ({ save, realm }: LocalizationTabProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const adminClient = useAdminClient();
|
||||
const [addMessageBundleModalOpen, setAddMessageBundleModalOpen] =
|
||||
|
@ -82,7 +78,9 @@ export const LocalizationTab = ({
|
|||
const [filterDropdownOpen, setFilterDropdownOpen] = useState(false);
|
||||
const [selectMenuLocale, setSelectMenuLocale] = useState(DEFAULT_LOCALE);
|
||||
|
||||
const { getValues, control, handleSubmit, formState } = useFormContext();
|
||||
const { setValue, getValues, control, handleSubmit, formState } = useForm({
|
||||
shouldUnregister: false,
|
||||
});
|
||||
const [selectMenuValueSelected, setSelectMenuValueSelected] = useState(false);
|
||||
const [messageBundles, setMessageBundles] = useState<[string, string][]>([]);
|
||||
const [tableRows, setTableRows] = useState<IRow[]>([]);
|
||||
|
@ -93,6 +91,15 @@ export const LocalizationTab = ({
|
|||
const { realm: currentRealm } = useRealm();
|
||||
const { whoAmI } = useWhoAmI();
|
||||
|
||||
const setupForm = () => {
|
||||
convertToFormValues(realm, setValue);
|
||||
if (realm.supportedLocales?.length === 0) {
|
||||
setValue("supportedLocales", [DEFAULT_LOCALE]);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(setupForm, []);
|
||||
|
||||
const watchSupportedLocales = useWatch<string[]>({
|
||||
control,
|
||||
name: "supportedLocales",
|
||||
|
@ -475,7 +482,7 @@ export const LocalizationTab = ({
|
|||
>
|
||||
{t("common:save")}
|
||||
</Button>
|
||||
<Button variant="link" onClick={reset}>
|
||||
<Button variant="link" onClick={setupForm}>
|
||||
{t("common:revert")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
|
|
|
@ -5,7 +5,6 @@ import { FormAccess } from "../components/form-access/FormAccess";
|
|||
import { HelpItem } from "../components/help-enabler/HelpItem";
|
||||
import { FormPanel } from "../components/scroll-form/FormPanel";
|
||||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { useAdminClient } from "../context/auth/AdminClient";
|
||||
import { useAlerts } from "../components/alert/Alerts";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
|
@ -15,26 +14,31 @@ type RealmSettingsLoginTabProps = {
|
|||
refresh: () => void;
|
||||
};
|
||||
|
||||
type SwitchType = { [K in keyof RealmRepresentation]: boolean };
|
||||
|
||||
export const RealmSettingsLoginTab = ({
|
||||
realm,
|
||||
refresh,
|
||||
}: RealmSettingsLoginTabProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
|
||||
const form = useForm<RealmRepresentation>({ mode: "onChange" });
|
||||
const { addAlert, addError } = useAlerts();
|
||||
const adminClient = useAdminClient();
|
||||
const { realm: realmName } = useRealm();
|
||||
|
||||
const updateSwitchValue = async (name: string) => {
|
||||
const switchValues = form.getValues();
|
||||
const updateSwitchValue = async (switches: SwitchType | SwitchType[]) => {
|
||||
const name = Array.isArray(switches)
|
||||
? Object.keys(switches[0])[0]
|
||||
: Object.keys(switches)[0];
|
||||
|
||||
try {
|
||||
await adminClient.realms.update(
|
||||
{
|
||||
realm: realmName,
|
||||
},
|
||||
switchValues
|
||||
Array.isArray(switches)
|
||||
? switches.reduce((realm, s) => Object.assign(realm, s), realm)
|
||||
: Object.assign(realm, switches)
|
||||
);
|
||||
addAlert(t("enableSwitchSuccess", { switch: t(name) }));
|
||||
refresh();
|
||||
|
@ -51,67 +55,51 @@ export const RealmSettingsLoginTab = ({
|
|||
>
|
||||
<FormAccess isHorizontal role="manage-realm">
|
||||
<FormGroup
|
||||
label={t("userRegistration")}
|
||||
label={t("registrationAllowed")}
|
||||
fieldId="kc-user-reg"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("userRegistrationHelpText")}
|
||||
fieldLabelId="realm-settings:userRegistration"
|
||||
fieldLabelId="realm-settings:registrationAllowed"
|
||||
/>
|
||||
}
|
||||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="registrationAllowed"
|
||||
defaultValue={realm.registrationAllowed}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-user-reg-switch"
|
||||
data-testid="user-reg-switch"
|
||||
value={value ? "on" : "off"}
|
||||
value={realm.registrationAllowed ? "on" : "off"}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value}
|
||||
isChecked={realm.registrationAllowed}
|
||||
onChange={(value) => {
|
||||
onChange(value);
|
||||
updateSwitchValue("userRegistration");
|
||||
updateSwitchValue({ registrationAllowed: value });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("forgotPassword")}
|
||||
label={t("resetPasswordAllowed")}
|
||||
fieldId="kc-forgot-pw"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings:forgotPasswordHelpText"
|
||||
fieldLabelId="realm-settings:forgotPassword"
|
||||
fieldLabelId="realm-settings:resetPasswordAllowed"
|
||||
/>
|
||||
}
|
||||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="resetPasswordAllowed"
|
||||
defaultValue={realm.resetPasswordAllowed}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-forgot-pw-switch"
|
||||
data-testid="forgot-pw-switch"
|
||||
name="resetPasswordAllowed"
|
||||
value={value ? "on" : "off"}
|
||||
value={realm.resetPasswordAllowed ? "on" : "off"}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value}
|
||||
isChecked={realm.resetPasswordAllowed}
|
||||
onChange={(value) => {
|
||||
onChange(value);
|
||||
updateSwitchValue("forgotPassword");
|
||||
updateSwitchValue({ resetPasswordAllowed: value });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("rememberMe")}
|
||||
|
@ -124,129 +112,110 @@ export const RealmSettingsLoginTab = ({
|
|||
}
|
||||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="rememberMe"
|
||||
defaultValue={realm.rememberMe}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-remember-me-switch"
|
||||
data-testid="remember-me-switch"
|
||||
value={value ? "on" : "off"}
|
||||
value={realm.rememberMe ? "on" : "off"}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value}
|
||||
isChecked={realm.rememberMe}
|
||||
onChange={(value) => {
|
||||
onChange(value);
|
||||
updateSwitchValue("rememberMe");
|
||||
updateSwitchValue({ rememberMe: value });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
</FormAccess>
|
||||
</FormPanel>
|
||||
<FormPanel className="kc-email-settings" title={t("emailSettings")}>
|
||||
<FormAccess isHorizontal role="manage-realm">
|
||||
<FormGroup
|
||||
label={t("emailAsUsername")}
|
||||
label={t("registrationEmailAsUsername")}
|
||||
fieldId="kc-email-as-username"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings:emailAsUsernameHelpText"
|
||||
fieldLabelId="realm-settings:emailAsUsername"
|
||||
fieldLabelId="realm-settings:registrationEmailAsUsername"
|
||||
/>
|
||||
}
|
||||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="registrationEmailAsUsername"
|
||||
defaultValue={realm.registrationEmailAsUsername}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-email-as-username-switch"
|
||||
data-testid="email-as-username-switch"
|
||||
value={value ? "on" : "off"}
|
||||
value={realm.registrationEmailAsUsername ? "on" : "off"}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value}
|
||||
isChecked={realm.registrationEmailAsUsername}
|
||||
onChange={(value) => {
|
||||
onChange(value);
|
||||
updateSwitchValue("emailAsUsername");
|
||||
updateSwitchValue([
|
||||
{
|
||||
registrationEmailAsUsername: value,
|
||||
},
|
||||
{
|
||||
duplicateEmailsAllowed: false,
|
||||
},
|
||||
]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("loginWithEmail")}
|
||||
label={t("loginWithEmailAllowed")}
|
||||
fieldId="kc-login-with-email"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings:loginWithEmailHelpText"
|
||||
fieldLabelId="realm-settings:loginWithEmail"
|
||||
fieldLabelId="realm-settings:loginWithEmailAllowed"
|
||||
/>
|
||||
}
|
||||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="loginWithEmailAllowed"
|
||||
defaultValue={realm.loginWithEmailAllowed}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-login-with-email-switch"
|
||||
data-testid="login-with-email-switch"
|
||||
value={value ? "on" : "off"}
|
||||
value={realm.loginWithEmailAllowed ? "on" : "off"}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value}
|
||||
isChecked={realm.loginWithEmailAllowed}
|
||||
onChange={(value) => {
|
||||
onChange(value);
|
||||
updateSwitchValue("loginWithEmail");
|
||||
updateSwitchValue([
|
||||
{
|
||||
loginWithEmailAllowed: value,
|
||||
},
|
||||
{ duplicateEmailsAllowed: false },
|
||||
]);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("duplicateEmails")}
|
||||
label={t("duplicateEmailsAllowed")}
|
||||
fieldId="kc-duplicate-emails"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings:duplicateEmailsHelpText"
|
||||
fieldLabelId="realm-settings:duplicateEmails"
|
||||
fieldLabelId="realm-settings:duplicateEmailsAllowed"
|
||||
/>
|
||||
}
|
||||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="duplicateEmailsAllowed"
|
||||
defaultValue={realm.duplicateEmailsAllowed}
|
||||
control={form.control}
|
||||
render={({ onChange }) => (
|
||||
<Switch
|
||||
id="kc-duplicate-emails-switch"
|
||||
data-testid="duplicate-emails-switch"
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={
|
||||
form.getValues().duplicateEmailsAllowed &&
|
||||
!form.getValues().loginWithEmailAllowed &&
|
||||
!form.getValues().registrationEmailAsUsername
|
||||
realm.duplicateEmailsAllowed ||
|
||||
realm.loginWithEmailAllowed ||
|
||||
realm.registrationEmailAsUsername
|
||||
}
|
||||
onChange={(value) => {
|
||||
onChange(value);
|
||||
updateSwitchValue("duplicateEmails");
|
||||
updateSwitchValue({
|
||||
duplicateEmailsAllowed: value,
|
||||
});
|
||||
}}
|
||||
isDisabled={
|
||||
form.getValues().loginWithEmailAllowed ||
|
||||
form.getValues().registrationEmailAsUsername
|
||||
realm.loginWithEmailAllowed || realm.registrationEmailAsUsername
|
||||
}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("verifyEmail")}
|
||||
|
@ -259,26 +228,18 @@ export const RealmSettingsLoginTab = ({
|
|||
}
|
||||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="verifyEmail"
|
||||
defaultValue={realm.verifyEmail}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-verify-email-switch"
|
||||
data-testid="verify-email-switch"
|
||||
name="verifyEmail"
|
||||
value={value ? "on" : "off"}
|
||||
value={realm.verifyEmail ? "on" : "off"}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value}
|
||||
isChecked={realm.verifyEmail}
|
||||
onChange={(value) => {
|
||||
onChange(value);
|
||||
updateSwitchValue("verifyEmail");
|
||||
updateSwitchValue({ verifyEmail: value });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
</FormAccess>
|
||||
</FormPanel>
|
||||
|
@ -288,35 +249,27 @@ export const RealmSettingsLoginTab = ({
|
|||
>
|
||||
<FormAccess isHorizontal role="manage-realm">
|
||||
<FormGroup
|
||||
label={t("editUsername")}
|
||||
label={t("editUsernameAllowed")}
|
||||
fieldId="kc-edit-username"
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:editUsername"
|
||||
fieldLabelId="realm-settings:editUsername"
|
||||
fieldLabelId="realm-settings:editUsernameAllowed"
|
||||
/>
|
||||
}
|
||||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="editUsernameAllowed"
|
||||
defaultValue={realm.editUsernameAllowed}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id="kc-edit-username-switch"
|
||||
data-testid="edit-username-switch"
|
||||
value={value ? "on" : "off"}
|
||||
value={realm.editUsernameAllowed ? "on" : "off"}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
isChecked={value}
|
||||
isChecked={realm.editUsernameAllowed}
|
||||
onChange={(value) => {
|
||||
onChange(value);
|
||||
updateSwitchValue("userInfoSettings");
|
||||
updateSwitchValue({ editUsernameAllowed: value });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
</FormAccess>
|
||||
</FormPanel>
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
import React, { useState } from "react";
|
||||
|
||||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import type { RealmSettingsParams } from "./routes/RealmSettings";
|
||||
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
|
||||
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
|
||||
import { useRealm } from "../context/realm-context/RealmContext";
|
||||
import { RealmSettingsTabs } from "./RealmSettingsTabs";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
export default function RealmSettingsSection() {
|
||||
const adminClient = useAdminClient();
|
||||
const { realm: realmName } = useRealm();
|
||||
const { realm: realmName } = useParams<RealmSettingsParams>();
|
||||
const [realm, setRealm] = useState<RealmRepresentation>();
|
||||
const [key, setKey] = useState(0);
|
||||
|
||||
const refresh = () => {
|
||||
setKey(key + 1);
|
||||
setRealm(undefined);
|
||||
};
|
||||
|
||||
useFetch(() => adminClient.realms.findOne({ realm: realmName }), setRealm, [
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { Controller, FormProvider, useForm, useWatch } from "react-hook-form";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
AlertVariant,
|
||||
|
@ -34,7 +34,7 @@ import { RealmSettingsEmailTab } from "./EmailTab";
|
|||
import { EventsTab } from "./event-config/EventsTab";
|
||||
import { RealmSettingsGeneralTab } from "./GeneralTab";
|
||||
import { RealmSettingsLoginTab } from "./LoginTab";
|
||||
import { SecurityDefences } from "./security-defences/SecurityDefences";
|
||||
import { SecurityDefenses } from "./security-defences/SecurityDefenses";
|
||||
import { RealmSettingsSessionsTab } from "./SessionsTab";
|
||||
import { RealmSettingsThemesTab } from "./ThemesTab";
|
||||
import { RealmSettingsTokensTab } from "./TokensTab";
|
||||
|
@ -53,7 +53,7 @@ import { UserProfileTab } from "./user-profile/UserProfileTab";
|
|||
import useIsFeatureEnabled, { Feature } from "../utils/useIsFeatureEnabled";
|
||||
import { ClientPoliciesTab, toClientPolicies } from "./routes/ClientPolicies";
|
||||
import { KeysTab } from "./keys/KeysTab";
|
||||
import { DEFAULT_LOCALE } from "../i18n";
|
||||
import type { KeyValueType } from "../components/key-value-form/key-value-convert";
|
||||
|
||||
type RealmSettingsHeaderProps = {
|
||||
onChange: (value: boolean) => void;
|
||||
|
@ -176,55 +176,59 @@ export const RealmSettingsTabs = ({
|
|||
const history = useHistory();
|
||||
const isFeatureEnabled = useIsFeatureEnabled();
|
||||
|
||||
const form = useForm({ mode: "onChange", shouldUnregister: false });
|
||||
const { control, getValues, setValue, reset: resetForm } = form;
|
||||
|
||||
const { control, setValue, getValues } = useForm({
|
||||
mode: "onChange",
|
||||
shouldUnregister: false,
|
||||
});
|
||||
const [key, setKey] = useState(0);
|
||||
|
||||
const refreshHeader = () => {
|
||||
setKey(new Date().getTime());
|
||||
setKey(key + 1);
|
||||
};
|
||||
|
||||
const setupForm = (r: RealmRepresentation = realm) => {
|
||||
convertToFormValues(r, setValue);
|
||||
if (r.supportedLocales?.length === 0) {
|
||||
setValue("supportedLocales", [DEFAULT_LOCALE]);
|
||||
}
|
||||
resetForm(getValues());
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setupForm();
|
||||
}, []);
|
||||
useEffect(setupForm, []);
|
||||
|
||||
const save = async (r: RealmRepresentation) => {
|
||||
r = convertFormValuesToObject(r);
|
||||
if (
|
||||
r.attributes?.["acr.loa.map"] &&
|
||||
typeof r.attributes["acr.loa.map"] !== "string"
|
||||
) {
|
||||
const map = JSON.stringify(
|
||||
Object.fromEntries(
|
||||
(r.attributes["acr.loa.map"] as KeyValueType[])
|
||||
.filter(({ key }) => key !== "")
|
||||
.map(({ key, value }) => [key, value])
|
||||
)
|
||||
);
|
||||
r.attributes["acr.loa.map"] = map !== "{}" ? map : "[]";
|
||||
}
|
||||
|
||||
const save = async (realm: RealmRepresentation) => {
|
||||
try {
|
||||
realm = convertFormValuesToObject(realm);
|
||||
|
||||
await adminClient.realms.update(
|
||||
{ realm: realmName },
|
||||
{
|
||||
...realm,
|
||||
id: realmName,
|
||||
...r,
|
||||
id: r.realm,
|
||||
}
|
||||
);
|
||||
setupForm(realm);
|
||||
const isRealmRenamed = realmName !== realm.realm;
|
||||
if (isRealmRenamed) {
|
||||
await refreshRealms();
|
||||
history.push(toRealmSettings({ realm: realm.realm!, tab: "general" }));
|
||||
}
|
||||
addAlert(t("saveSuccess"), AlertVariant.success);
|
||||
} catch (error) {
|
||||
addError("realm-settings:saveError", error);
|
||||
}
|
||||
};
|
||||
|
||||
const userProfileEnabled = useWatch({
|
||||
control,
|
||||
name: "attributes.userProfileEnabled",
|
||||
defaultValue: "false",
|
||||
});
|
||||
const isRealmRenamed = realmName !== (r.realm || realm.realm);
|
||||
if (isRealmRenamed) {
|
||||
await refreshRealms();
|
||||
history.push(toRealmSettings({ realm: r.realm!, tab: "general" }));
|
||||
}
|
||||
refresh();
|
||||
};
|
||||
|
||||
const route = (tab: RealmSettingsTab | undefined = "general") =>
|
||||
routableTab({
|
||||
|
@ -258,7 +262,6 @@ export const RealmSettingsTabs = ({
|
|||
)}
|
||||
/>
|
||||
<PageSection variant="light" className="pf-u-p-0">
|
||||
<FormProvider {...form}>
|
||||
<RoutableTabs
|
||||
isBox
|
||||
mountOnEnter
|
||||
|
@ -272,10 +275,7 @@ export const RealmSettingsTabs = ({
|
|||
data-testid="rs-general-tab"
|
||||
{...route()}
|
||||
>
|
||||
<RealmSettingsGeneralTab
|
||||
save={save}
|
||||
reset={() => resetForm(realm)}
|
||||
/>
|
||||
<RealmSettingsGeneralTab realm={realm} save={save} />
|
||||
</Tab>
|
||||
<Tab
|
||||
title={<TabTitleText>{t("login")}</TabTitleText>}
|
||||
|
@ -296,10 +296,7 @@ export const RealmSettingsTabs = ({
|
|||
data-testid="rs-themes-tab"
|
||||
{...route("themes")}
|
||||
>
|
||||
<RealmSettingsThemesTab
|
||||
save={save}
|
||||
reset={() => resetForm(realm)}
|
||||
/>
|
||||
<RealmSettingsThemesTab realm={realm} save={save} />
|
||||
</Tab>
|
||||
<Tab
|
||||
title={<TabTitleText>{t("realm-settings:keys")}</TabTitleText>}
|
||||
|
@ -324,7 +321,6 @@ export const RealmSettingsTabs = ({
|
|||
key={key}
|
||||
refresh={refresh}
|
||||
save={save}
|
||||
reset={() => resetForm(realm)}
|
||||
realm={realm}
|
||||
/>
|
||||
</Tab>
|
||||
|
@ -333,12 +329,10 @@ export const RealmSettingsTabs = ({
|
|||
data-testid="rs-security-defenses-tab"
|
||||
{...route("securityDefences")}
|
||||
>
|
||||
<SecurityDefences save={save} reset={() => resetForm(realm)} />
|
||||
<SecurityDefenses realm={realm} save={save} />
|
||||
</Tab>
|
||||
<Tab
|
||||
title={
|
||||
<TabTitleText>{t("realm-settings:sessions")}</TabTitleText>
|
||||
}
|
||||
title={<TabTitleText>{t("realm-settings:sessions")}</TabTitleText>}
|
||||
data-testid="rs-sessions-tab"
|
||||
{...route("sessions")}
|
||||
>
|
||||
|
@ -349,17 +343,11 @@ export const RealmSettingsTabs = ({
|
|||
data-testid="rs-tokens-tab"
|
||||
{...route("tokens")}
|
||||
>
|
||||
<RealmSettingsTokensTab
|
||||
save={save}
|
||||
realm={realm}
|
||||
reset={() => resetForm(realm)}
|
||||
/>
|
||||
<RealmSettingsTokensTab save={save} realm={realm} />
|
||||
</Tab>
|
||||
<Tab
|
||||
title={
|
||||
<TabTitleText>
|
||||
{t("realm-settings:clientPolicies")}
|
||||
</TabTitleText>
|
||||
<TabTitleText>{t("realm-settings:clientPolicies")}</TabTitleText>
|
||||
}
|
||||
data-testid="rs-clientPolicies-tab"
|
||||
{...route("clientPolicies")}
|
||||
|
@ -411,12 +399,10 @@ export const RealmSettingsTabs = ({
|
|||
</RoutableTabs>
|
||||
</Tab>
|
||||
{isFeatureEnabled(Feature.DeclarativeUserProfile) &&
|
||||
userProfileEnabled === "true" && (
|
||||
realm.attributes?.userProfileEnabled === "true" && (
|
||||
<Tab
|
||||
title={
|
||||
<TabTitleText>
|
||||
{t("realm-settings:userProfile")}
|
||||
</TabTitleText>
|
||||
<TabTitleText>{t("realm-settings:userProfile")}</TabTitleText>
|
||||
}
|
||||
data-testid="rs-user-profile-tab"
|
||||
{...route("userProfile")}
|
||||
|
@ -432,7 +418,6 @@ export const RealmSettingsTabs = ({
|
|||
<UserRegistration />
|
||||
</Tab>
|
||||
</RoutableTabs>
|
||||
</FormProvider>
|
||||
</PageSection>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, useFormContext, useWatch } from "react-hook-form";
|
||||
import { Controller, useForm, useWatch } from "react-hook-form";
|
||||
import {
|
||||
ActionGroup,
|
||||
Button,
|
||||
|
@ -14,6 +14,7 @@ import { FormAccess } from "../components/form-access/FormAccess";
|
|||
import { HelpItem } from "../components/help-enabler/HelpItem";
|
||||
import { FormPanel } from "../components/scroll-form/FormPanel";
|
||||
import { TimeSelector } from "../components/time-selector/TimeSelector";
|
||||
import { convertToFormValues } from "../util";
|
||||
|
||||
import "./realm-settings-section.css";
|
||||
|
||||
|
@ -28,24 +29,22 @@ export const RealmSettingsSessionsTab = ({
|
|||
}: RealmSettingsSessionsTabProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
reset: resetForm,
|
||||
formState,
|
||||
} = useFormContext<RealmRepresentation>();
|
||||
const { setValue, control, handleSubmit, formState } =
|
||||
useForm<RealmRepresentation>({
|
||||
shouldUnregister: false,
|
||||
});
|
||||
|
||||
const offlineSessionMaxEnabled = useWatch({
|
||||
control,
|
||||
name: "offlineSessionMaxLifespanEnabled",
|
||||
});
|
||||
|
||||
const reset = () => {
|
||||
if (realm) {
|
||||
resetForm(realm);
|
||||
}
|
||||
const setupForm = () => {
|
||||
convertToFormValues(realm, setValue);
|
||||
};
|
||||
|
||||
useEffect(setupForm, []);
|
||||
|
||||
return (
|
||||
<PageSection variant="light">
|
||||
<FormPanel
|
||||
|
@ -399,7 +398,7 @@ export const RealmSettingsSessionsTab = ({
|
|||
>
|
||||
{t("common:save")}
|
||||
</Button>
|
||||
<Button variant="link" onClick={reset}>
|
||||
<Button variant="link" onClick={setupForm}>
|
||||
{t("common:revert")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, useFormContext } from "react-hook-form";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import {
|
||||
ActionGroup,
|
||||
Button,
|
||||
|
@ -15,15 +15,16 @@ import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/r
|
|||
import { FormAccess } from "../components/form-access/FormAccess";
|
||||
import { HelpItem } from "../components/help-enabler/HelpItem";
|
||||
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
||||
import { convertToFormValues } from "../util";
|
||||
|
||||
type RealmSettingsThemesTabProps = {
|
||||
realm: RealmRepresentation;
|
||||
save: (realm: RealmRepresentation) => void;
|
||||
reset: () => void;
|
||||
};
|
||||
|
||||
export const RealmSettingsThemesTab = ({
|
||||
realm,
|
||||
save,
|
||||
reset,
|
||||
}: RealmSettingsThemesTabProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
|
||||
|
@ -32,9 +33,14 @@ export const RealmSettingsThemesTab = ({
|
|||
const [adminConsoleThemeOpen, setAdminConsoleThemeOpen] = useState(false);
|
||||
const [emailThemeOpen, setEmailThemeOpen] = useState(false);
|
||||
|
||||
const { control, handleSubmit } = useFormContext();
|
||||
const { control, handleSubmit, setValue } = useForm<RealmRepresentation>();
|
||||
const themeTypes = useServerInfo().themes!;
|
||||
|
||||
const setupForm = () => {
|
||||
convertToFormValues(realm, setValue);
|
||||
};
|
||||
useEffect(setupForm, []);
|
||||
|
||||
return (
|
||||
<PageSection variant="light">
|
||||
<FormAccess
|
||||
|
@ -217,7 +223,7 @@ export const RealmSettingsThemesTab = ({
|
|||
<Button variant="primary" type="submit" data-testid="themes-tab-save">
|
||||
{t("common:save")}
|
||||
</Button>
|
||||
<Button variant="link" onClick={reset}>
|
||||
<Button variant="link" onClick={setupForm}>
|
||||
{t("common:revert")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, useFormContext, useWatch } from "react-hook-form";
|
||||
import { Controller, useForm, useWatch } from "react-hook-form";
|
||||
import {
|
||||
ActionGroup,
|
||||
Button,
|
||||
|
@ -27,6 +27,7 @@ import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
|||
|
||||
import "./realm-settings-section.css";
|
||||
import { useWhoAmI } from "../context/whoami/WhoAmI";
|
||||
import { convertToFormValues } from "../util";
|
||||
|
||||
type RealmSettingsSessionsTabProps = {
|
||||
realm: RealmRepresentation;
|
||||
|
@ -60,8 +61,8 @@ export const RealmSettingsTokensTab = ({
|
|||
javaKeystoreAlgOptions!
|
||||
);
|
||||
|
||||
const form = useFormContext<RealmRepresentation>();
|
||||
const { control } = form;
|
||||
const form = useForm<RealmRepresentation>({ shouldUnregister: false });
|
||||
const { setValue, control } = form;
|
||||
|
||||
const offlineSessionMaxEnabled = useWatch({
|
||||
control,
|
||||
|
@ -81,6 +82,10 @@ export const RealmSettingsTokensTab = ({
|
|||
defaultValue: false,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
convertToFormValues(realm, setValue);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<PageSection variant="light">
|
||||
<FormPanel
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Controller, useFormContext, useWatch } from "react-hook-form";
|
||||
import { Controller, FormProvider, useForm, useWatch } from "react-hook-form";
|
||||
import {
|
||||
ActionGroup,
|
||||
Button,
|
||||
|
@ -13,22 +13,25 @@ import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/r
|
|||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import { HelpItem } from "../../components/help-enabler/HelpItem";
|
||||
import { Time } from "./Time";
|
||||
import { convertToFormValues } from "../../util";
|
||||
|
||||
type BruteForceDetectionProps = {
|
||||
realm: RealmRepresentation;
|
||||
save: (realm: RealmRepresentation) => void;
|
||||
reset: () => void;
|
||||
};
|
||||
|
||||
export const BruteForceDetection = ({
|
||||
realm,
|
||||
save,
|
||||
reset,
|
||||
}: BruteForceDetectionProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const form = useForm({ shouldUnregister: false });
|
||||
const {
|
||||
setValue,
|
||||
handleSubmit,
|
||||
control,
|
||||
formState: { isDirty },
|
||||
} = useFormContext();
|
||||
} = form;
|
||||
|
||||
const enable = useWatch({
|
||||
control,
|
||||
|
@ -40,8 +43,16 @@ export const BruteForceDetection = ({
|
|||
name: "permanentLockout",
|
||||
});
|
||||
|
||||
const setupForm = () => convertToFormValues(realm, setValue);
|
||||
useEffect(setupForm, []);
|
||||
|
||||
return (
|
||||
<FormAccess role="manage-realm" isHorizontal onSubmit={handleSubmit(save)}>
|
||||
<FormProvider {...form}>
|
||||
<FormAccess
|
||||
role="manage-realm"
|
||||
isHorizontal
|
||||
onSubmit={handleSubmit(save)}
|
||||
>
|
||||
<FormGroup
|
||||
label={t("common:enabled")}
|
||||
fieldId="bruteForceProtected"
|
||||
|
@ -62,6 +73,8 @@ export const BruteForceDetection = ({
|
|||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
{enable && (
|
||||
<>
|
||||
<FormGroup
|
||||
label={t("failureFactor")}
|
||||
labelIcon={
|
||||
|
@ -71,7 +84,6 @@ export const BruteForceDetection = ({
|
|||
/>
|
||||
}
|
||||
fieldId="failureFactor"
|
||||
style={enable ? {} : { display: "none" }}
|
||||
>
|
||||
<Controller
|
||||
name="failureFactor"
|
||||
|
@ -96,7 +108,6 @@ export const BruteForceDetection = ({
|
|||
label={t("permanentLockout")}
|
||||
fieldId="permanentLockout"
|
||||
hasNoPaddingTop
|
||||
style={enable ? {} : { display: "none" }}
|
||||
>
|
||||
<Controller
|
||||
name="permanentLockout"
|
||||
|
@ -114,18 +125,13 @@ export const BruteForceDetection = ({
|
|||
/>
|
||||
</FormGroup>
|
||||
|
||||
<Time
|
||||
name="waitIncrementSeconds"
|
||||
style={enable && !permanentLockout ? {} : { display: "none" }}
|
||||
/>
|
||||
<Time
|
||||
name="maxFailureWaitSeconds"
|
||||
style={enable && !permanentLockout ? {} : { display: "none" }}
|
||||
/>
|
||||
<Time
|
||||
name="maxDeltaTimeSeconds"
|
||||
style={enable && !permanentLockout ? {} : { display: "none" }}
|
||||
/>
|
||||
{!permanentLockout && (
|
||||
<>
|
||||
<Time name="waitIncrementSeconds" />
|
||||
<Time name="maxFailureWaitSeconds" />
|
||||
<Time name="maxDeltaTimeSeconds" />
|
||||
</>
|
||||
)}
|
||||
|
||||
<FormGroup
|
||||
label={t("quickLoginCheckMilliSeconds")}
|
||||
|
@ -136,7 +142,6 @@ export const BruteForceDetection = ({
|
|||
/>
|
||||
}
|
||||
fieldId="quickLoginCheckMilliSeconds"
|
||||
style={enable ? {} : { display: "none" }}
|
||||
>
|
||||
<Controller
|
||||
name="quickLoginCheckMilliSeconds"
|
||||
|
@ -157,10 +162,9 @@ export const BruteForceDetection = ({
|
|||
/>
|
||||
</FormGroup>
|
||||
|
||||
<Time
|
||||
name="minimumQuickLoginWaitSeconds"
|
||||
style={enable ? {} : { display: "none" }}
|
||||
/>
|
||||
<Time name="minimumQuickLoginWaitSeconds" />
|
||||
</>
|
||||
)}
|
||||
|
||||
<ActionGroup>
|
||||
<Button
|
||||
|
@ -171,10 +175,11 @@ export const BruteForceDetection = ({
|
|||
>
|
||||
{t("common:save")}
|
||||
</Button>
|
||||
<Button variant="link" onClick={reset}>
|
||||
<Button variant="link" onClick={setupForm}>
|
||||
{t("common:revert")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
</FormAccess>
|
||||
</FormProvider>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,27 +1,34 @@
|
|||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useFormContext } from "react-hook-form";
|
||||
import { FormProvider, useForm } from "react-hook-form";
|
||||
import { ActionGroup, Button } from "@patternfly/react-core";
|
||||
|
||||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import { FormAccess } from "../../components/form-access/FormAccess";
|
||||
import { HelpLinkTextInput } from "./HelpLinkTextInput";
|
||||
import { convertToFormValues } from "../../util";
|
||||
|
||||
import "./security-defences.css";
|
||||
|
||||
type HeadersFormProps = {
|
||||
realm: RealmRepresentation;
|
||||
save: (realm: RealmRepresentation) => void;
|
||||
reset: () => void;
|
||||
};
|
||||
|
||||
export const HeadersForm = ({ save, reset }: HeadersFormProps) => {
|
||||
export const HeadersForm = ({ realm, save }: HeadersFormProps) => {
|
||||
const { t } = useTranslation();
|
||||
const form = useForm();
|
||||
const {
|
||||
setValue,
|
||||
formState: { isDirty },
|
||||
handleSubmit,
|
||||
} = useFormContext();
|
||||
} = form;
|
||||
|
||||
const setupForm = () => convertToFormValues(realm, setValue);
|
||||
useEffect(setupForm, []);
|
||||
|
||||
return (
|
||||
<FormProvider {...form}>
|
||||
<FormAccess
|
||||
isHorizontal
|
||||
role="manage-realm"
|
||||
|
@ -66,10 +73,11 @@ export const HeadersForm = ({ save, reset }: HeadersFormProps) => {
|
|||
>
|
||||
{t("common:save")}
|
||||
</Button>
|
||||
<Button variant="link" onClick={reset}>
|
||||
<Button variant="link" onClick={setupForm}>
|
||||
{t("common:revert")}
|
||||
</Button>
|
||||
</ActionGroup>
|
||||
</FormAccess>
|
||||
</FormProvider>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -6,12 +6,12 @@ import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/r
|
|||
import { HeadersForm } from "./HeadersForm";
|
||||
import { BruteForceDetection } from "./BruteForceDetection";
|
||||
|
||||
type SecurityDefencesProps = {
|
||||
type SecurityDefensesProps = {
|
||||
realm: RealmRepresentation;
|
||||
save: (realm: RealmRepresentation) => void;
|
||||
reset: () => void;
|
||||
};
|
||||
|
||||
export const SecurityDefences = ({ save, reset }: SecurityDefencesProps) => {
|
||||
export const SecurityDefenses = ({ realm, save }: SecurityDefensesProps) => {
|
||||
const { t } = useTranslation("realm-settings");
|
||||
const [activeTab, setActiveTab] = useState(10);
|
||||
return (
|
||||
|
@ -25,7 +25,7 @@ export const SecurityDefences = ({ save, reset }: SecurityDefencesProps) => {
|
|||
title={<TabTitleText>{t("headers")}</TabTitleText>}
|
||||
>
|
||||
<PageSection variant="light">
|
||||
<HeadersForm save={save} reset={reset} />
|
||||
<HeadersForm realm={realm} save={save} />
|
||||
</PageSection>
|
||||
</Tab>
|
||||
<Tab
|
||||
|
@ -34,7 +34,7 @@ export const SecurityDefences = ({ save, reset }: SecurityDefencesProps) => {
|
|||
title={<TabTitleText>{t("bruteForceDetection")}</TabTitleText>}
|
||||
>
|
||||
<PageSection variant="light">
|
||||
<BruteForceDetection save={save} reset={reset} />
|
||||
<BruteForceDetection realm={realm} save={save} />
|
||||
</PageSection>
|
||||
</Tab>
|
||||
</Tabs>
|
Loading…
Reference in a new issue