Read Only Access of a realm clients' Authz is broken for Admin Console

Fixes #24586

Signed-off-by: Hynek Mlnarik <hmlnarik@redhat.com>
This commit is contained in:
Hynek Mlnarik 2024-02-28 16:42:48 +01:00 committed by Hynek Mlnařík
parent 49bbed13b9
commit 486c21cf77
6 changed files with 74 additions and 13 deletions

View file

@ -163,6 +163,20 @@ describe("User creation", () => {
masthead.checkNotificationMessage("The user has been saved");
attributesTab
.addAttribute("LDAP_ID", "value_test")
.addAttribute("LDAP_ID", "another_value_test")
.addAttribute("c", "d")
.save();
masthead.checkNotificationMessage("The user has not been saved: ");
cy.get(".pf-c-helper-text__item-text")
.filter(':contains("Update of read-only attribute rejected")')
.should("have.length", 2);
cy.reload();
userDetailsPage.goToDetailsTab();
attributesTab
.goToAttributesTab()

View file

@ -44,7 +44,7 @@ export default class AttributesTab {
cy.findByTestId(this.#keyInput).should((exist ? "" : "not.") + "exist");
if (exist) {
cy.findAllByTestId(this.#keyInput).invoke("val").should("eq", "key_test");
cy.findAllByTestId(this.#keyInput).invoke("val").should("eq", key);
}
return this;

View file

@ -73,9 +73,10 @@ export const KeyValueInput = ({
<span className="pf-c-form__label-text">{t("value")}</span>
</GridItem>
{fields.map((attribute, index) => {
const keyError = !!(errors as any)[name]?.[index]?.key;
const valueError = !!(errors as any)[name]?.[index]?.value;
const error = (errors as any)[name]?.[index];
const keyError = !!error?.key;
const valueErrorPresent = !!error?.value || !!error?.message;
const valueError = error?.message || t("valueError");
return (
<Fragment key={attribute.id}>
<GridItem span={5}>
@ -118,15 +119,15 @@ export const KeyValueInput = ({
aria-label={t("value")}
data-testid={`${name}-value`}
{...register(`${name}.${index}.value`, { required: true })}
validated={valueError ? "error" : "default"}
validated={valueErrorPresent ? "error" : "default"}
isRequired
isDisabled={isDisabled}
/>
)}
{valueError && (
{valueErrorPresent && (
<HelperText>
<HelperTextItem variant="error">
{t("valueError")}
{valueError}
</HelperTextItem>
</HelperText>
)}

View file

@ -55,6 +55,7 @@ import { toUsers } from "./routes/Users";
import { isLightweightUser } from "./utils";
import { getUnmanagedAttributes } from "../components/users/resource";
import "./user-section.css";
import { KeyValueType } from "../components/key-value-form/key-value-convert";
export default function EditUser() {
const { t } = useTranslation();
@ -63,7 +64,15 @@ export default function EditUser() {
const { hasAccess } = useAccess();
const { id } = useParams<UserParams>();
const { realm: realmName } = useRealm();
const form = useForm<UserFormFields>({ mode: "onChange" });
// Validation of form fields is performed on server, thus we need to clear all errors before submit
const clearAllErrorsBeforeSubmit = async (values: UserFormFields) => ({
values,
errors: {},
});
const form = useForm<UserFormFields>({
mode: "onChange",
resolver: clearAllErrorsBeforeSubmit,
});
const [realm, setRealm] = useState<RealmRepresentation>();
const [user, setUser] = useState<UIUserRepresentation>();
const [bruteForced, setBruteForced] = useState<BruteForced>();
@ -147,9 +156,46 @@ export default function EditUser() {
refresh();
} catch (error) {
if (isUserProfileError(error)) {
setUserProfileServerError(error, form.setError, ((key, param) =>
t(key as string, param as any)) as TFunction);
addError("userNotSaved", error);
if (
isUnmanagedAttributesEnabled &&
Array.isArray(data.unmanagedAttributes)
) {
const unmanagedAttributeErrors: object[] = new Array(
data.unmanagedAttributes.length,
);
let someUnmanagedAttributeError = false;
setUserProfileServerError<UserFormFields>(
error,
(field, params) => {
if (field.startsWith("attributes.")) {
const attributeName = field.substring("attributes.".length);
(data.unmanagedAttributes as KeyValueType[]).forEach(
(attr, index) => {
if (attr.key === attributeName) {
unmanagedAttributeErrors[index] = params;
someUnmanagedAttributeError = true;
}
},
);
} else {
form.setError(field, params);
}
},
((key, param) => t(key as string, param as any)) as TFunction,
);
if (someUnmanagedAttributeError) {
form.setError(
"unmanagedAttributes",
unmanagedAttributeErrors as any,
);
}
} else {
setUserProfileServerError<UserFormFields>(error, form.setError, ((
key,
param,
) => t(key as string, param as any)) as TFunction);
}
addError("userNotSaved", "");
} else {
addError("userCreateError", error);
}

View file

@ -8,7 +8,7 @@ import { beerify, debeerify } from "../util";
export type UserFormFields = Omit<
UIUserRepresentation,
"attributes" | "userProfileMetadata | unmanagedAttributes"
"attributes" | "userProfileMetadata" | "unmanagedAttributes"
> & {
attributes?: KeyValueType[] | Record<string, string | string[]>;
unmanagedAttributes?: KeyValueType[] | Record<string, string | string[]>;

View file

@ -69,7 +69,7 @@ export function setUserProfileServerError<T>(
setError(fieldName(e.field) as keyof T, {
message: t(e.errorMessage, {
...params,
defaultValue: e.field,
defaultValue: e.errorMessage || e.field,
}),
type: "server",
});