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:
parent
49bbed13b9
commit
486c21cf77
6 changed files with 74 additions and 13 deletions
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
)}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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[]>;
|
||||
|
|
|
@ -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",
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue