Only show activated required actions in credentials reset dialog (#19048)
This commit is contained in:
parent
e40fa5fcb4
commit
fc0a9be79f
4 changed files with 34 additions and 83 deletions
|
@ -45,6 +45,7 @@
|
|||
"emailInvalid": "You must enter a valid email.",
|
||||
"notVerified": "Not verified",
|
||||
"requiredUserActions": "Required user actions",
|
||||
"requiredActionPlaceholder": "Select action",
|
||||
"federationLink": "Federation link",
|
||||
"addUser": "Add user",
|
||||
"impersonate": "Impersonate",
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/groupRepresentation";
|
||||
import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
|
||||
import type RequiredActionProviderRepresentation from "@keycloak/keycloak-admin-client/lib/defs/requiredActionProviderRepresentation";
|
||||
import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
|
||||
import {
|
||||
ActionGroup,
|
||||
|
@ -10,8 +9,6 @@ import {
|
|||
ChipGroup,
|
||||
FormGroup,
|
||||
InputGroup,
|
||||
Select,
|
||||
SelectOption,
|
||||
Switch,
|
||||
} from "@patternfly/react-core";
|
||||
import { useState } from "react";
|
||||
|
@ -32,6 +29,7 @@ import useFormatDate from "../utils/useFormatDate";
|
|||
import useIsFeatureEnabled, { Feature } from "../utils/useIsFeatureEnabled";
|
||||
import { FederatedUserLink } from "./FederatedUserLink";
|
||||
import { UserProfileFields } from "./UserProfileFields";
|
||||
import { RequiredActionMultiSelect } from "./user-credentials/RequiredActionMultiSelect";
|
||||
|
||||
export type BruteForced = {
|
||||
isBruteForceProtected?: boolean;
|
||||
|
@ -93,10 +91,6 @@ export const UserForm = ({
|
|||
const formatDate = useFormatDate();
|
||||
const isFeatureEnabled = useIsFeatureEnabled();
|
||||
|
||||
const [
|
||||
isRequiredUserActionsDropdownOpen,
|
||||
setRequiredUserActionsDropdownOpen,
|
||||
] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
const { adminClient } = useAdminClient();
|
||||
const { addAlert, addError } = useAlerts();
|
||||
|
@ -118,22 +112,14 @@ export const UserForm = ({
|
|||
const [open, setOpen] = useState(false);
|
||||
const [locked, setLocked] = useState(isLocked);
|
||||
const [realm, setRealm] = useState<RealmRepresentation>();
|
||||
const [requiredActions, setRequiredActions] = useState<
|
||||
RequiredActionProviderRepresentation[]
|
||||
>([]);
|
||||
|
||||
useFetch(
|
||||
() =>
|
||||
Promise.all([
|
||||
adminClient.realms.findOne({ realm: realmName }),
|
||||
adminClient.authenticationManagement.getRequiredActions(),
|
||||
]),
|
||||
([realm, actions]) => {
|
||||
() => adminClient.realms.findOne({ realm: realmName }),
|
||||
(realm) => {
|
||||
if (!realm) {
|
||||
throw new Error(t("common:notFound"));
|
||||
}
|
||||
setRealm(realm);
|
||||
setRequiredActions(actions);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
@ -147,10 +133,6 @@ export const UserForm = ({
|
|||
}
|
||||
};
|
||||
|
||||
const clearSelection = () => {
|
||||
setRequiredUserActionsDropdownOpen(false);
|
||||
};
|
||||
|
||||
const deleteItem = (id: string) => {
|
||||
setSelectedGroups(selectedGroups.filter((item) => item.name !== id));
|
||||
onGroupsUpdate?.(selectedGroups);
|
||||
|
@ -233,56 +215,11 @@ export const UserForm = ({
|
|||
</FormGroup>
|
||||
</>
|
||||
)}
|
||||
<FormGroup
|
||||
label={t("requiredUserActions")}
|
||||
fieldId="kc-required-user-actions"
|
||||
validated={errors.requiredActions ? "error" : "default"}
|
||||
helperTextInvalid={t("common:required")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("users-help:requiredUserActions")}
|
||||
fieldLabelId="users:requiredUserActions"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Controller
|
||||
name="requiredActions"
|
||||
defaultValue={[]}
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<Select
|
||||
data-testid="required-actions-select"
|
||||
placeholderText="Select action"
|
||||
toggleId="kc-required-user-actions"
|
||||
onToggle={() =>
|
||||
setRequiredUserActionsDropdownOpen(
|
||||
!isRequiredUserActionsDropdownOpen
|
||||
)
|
||||
}
|
||||
isOpen={isRequiredUserActionsDropdownOpen}
|
||||
selections={field.value}
|
||||
onSelect={(_, v) => {
|
||||
const option = v as string;
|
||||
if (field.value.includes(option)) {
|
||||
field.onChange(
|
||||
field.value.filter((item: string) => item !== option)
|
||||
);
|
||||
} else {
|
||||
field.onChange([...field.value, option]);
|
||||
}
|
||||
}}
|
||||
onClear={clearSelection}
|
||||
variant="typeaheadmulti"
|
||||
>
|
||||
{requiredActions.map(({ alias, name }) => (
|
||||
<SelectOption key={alias} value={alias}>
|
||||
{name}
|
||||
</SelectOption>
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<RequiredActionMultiSelect
|
||||
name="requiredActions"
|
||||
label="requiredUserActions"
|
||||
help="users-help:requiredUserActions"
|
||||
/>
|
||||
{(user?.federationLink || user?.origin) && (
|
||||
<FormGroup
|
||||
label={t("federationLink")}
|
||||
|
|
|
@ -12,7 +12,17 @@ import { useTranslation } from "react-i18next";
|
|||
import { HelpItem } from "ui-shared";
|
||||
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
|
||||
|
||||
export const CredentialsResetActionMultiSelect = () => {
|
||||
type RequiredActionMultiSelectProps = {
|
||||
name: string;
|
||||
label: string;
|
||||
help: string;
|
||||
};
|
||||
|
||||
export const RequiredActionMultiSelect = ({
|
||||
name,
|
||||
label,
|
||||
help,
|
||||
}: RequiredActionMultiSelectProps) => {
|
||||
const { t } = useTranslation("users");
|
||||
const { adminClient } = useAdminClient();
|
||||
const { control } = useFormContext();
|
||||
|
@ -24,24 +34,22 @@ export const CredentialsResetActionMultiSelect = () => {
|
|||
useFetch(
|
||||
() => adminClient.authenticationManagement.getRequiredActions(),
|
||||
(actions) => {
|
||||
setRequiredActions(actions);
|
||||
const enabledUserActions = actions.filter((action) => {
|
||||
return action.enabled;
|
||||
});
|
||||
setRequiredActions(enabledUserActions);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<FormGroup
|
||||
label={t("resetActions")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("clients-help:resetActions")}
|
||||
fieldLabelId="resetActions"
|
||||
/>
|
||||
}
|
||||
label={t(label)}
|
||||
labelIcon={<HelpItem helpText={t(help)} fieldLabelId="resetActions" />}
|
||||
fieldId="actions"
|
||||
>
|
||||
<Controller
|
||||
name="actions"
|
||||
name={name}
|
||||
defaultValue={[]}
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
|
@ -52,6 +60,7 @@ export const CredentialsResetActionMultiSelect = () => {
|
|||
chipGroupProps={{
|
||||
numChips: 3,
|
||||
}}
|
||||
placeholderText={t("requiredActionPlaceholder")}
|
||||
menuAppendTo="parent"
|
||||
onToggle={(open) => setOpen(open)}
|
||||
isOpen={open}
|
|
@ -3,7 +3,7 @@ import { FormProvider, useForm, useWatch } from "react-hook-form";
|
|||
import { ModalVariant, Form, AlertVariant } from "@patternfly/react-core";
|
||||
|
||||
import type { RequiredActionAlias } from "@keycloak/keycloak-admin-client/lib/defs/requiredActionProviderRepresentation";
|
||||
import { CredentialsResetActionMultiSelect } from "./CredentialsResetActionMultiSelect";
|
||||
import { RequiredActionMultiSelect } from "./RequiredActionMultiSelect";
|
||||
import { ConfirmDialogModal } from "../../components/confirm-dialog/ConfirmDialog";
|
||||
import { useAdminClient } from "../../context/auth/AdminClient";
|
||||
import { useAlerts } from "../../components/alert/Alerts";
|
||||
|
@ -84,7 +84,11 @@ export const ResetCredentialDialog = ({
|
|||
data-testid="credential-reset-modal"
|
||||
>
|
||||
<FormProvider {...form}>
|
||||
<CredentialsResetActionMultiSelect />
|
||||
<RequiredActionMultiSelect
|
||||
name="actions"
|
||||
label="resetActions"
|
||||
help="clients-help:resetActions"
|
||||
/>
|
||||
<LifespanField />
|
||||
</FormProvider>
|
||||
</Form>
|
||||
|
|
Loading…
Reference in a new issue