Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR for #1647 - add ui:props to all material-ui widgets #1672

Closed
wants to merge 7 commits into from

Conversation

dekelb
Copy link

@dekelb dekelb commented Mar 23, 2020

This PR is a fix for issue #1647

Following the comments in the issue - it seems like the best option was to use the "ui:props" inside the uiSchema (of each field), which being pushed into the "options" variable inside the widget (as part of the WidgetProps).

The reason I decided to use the "ui:props" and not just add properties directly to the "options" is that some of those properties are already being used, and this might cause issues there.

Also - those properties are relevant specifically to the Components that we take from the Theme. I noticed some requests to also support Fields/Components from other libs - using this standard we will be able to support other field-specific properties.

/>
}
label={label}
label={label || schema.title}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the "schema.title" to be aligned with the rest of the widgets

control={checkbox}
key={index}
label={option.label}
/>
) : (
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is duplicated with no reason

@@ -41,13 +42,14 @@ const RangeWidget = ({
//error={!!rawErrors}
required={required}
>
<FormLabel id={id}>{label}</FormLabel>
<FormLabel id={id}>{label || schema.title}</FormLabel>
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the "schema.title" to be aligned with the rest of the widgets

@@ -33,7 +36,7 @@ const UpDownWidget = ({
//error={!!rawErrors}
required={required}
>
<InputLabel>{label}</InputLabel>
<InputLabel>{label || schema.title}</InputLabel>
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the "schema.title" to be aligned with the rest of the widgets

return inline ? (
<FormControlLabel

return <FormControlLabel
control={checkbox}
key={index}
label={option.label}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this missing the || schema.title that was added in all the other places on purpose?

Copy link
Author

@dekelb dekelb Mar 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, you can find this in line 62 - it's part of the FormLabel, not as part of the FormControlLabel

@epicfaace epicfaace self-requested a review March 25, 2020 19:27
@dekelb
Copy link
Author

dekelb commented Apr 4, 2020

@epicfaace any update on this one? I'm not so sure why it didn't get into v2-alpha5

Copy link
Member

@epicfaace epicfaace left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry it took some time to get to this.

  • Can you add some tests that verify this functionality (both the ui:props and schema.title overrides)? You could just extend the snapshot tests that are already in the material-ui folder.
  • I'm worried that people may use ui:props to override fields that we don't want the user to override, such as, for example, required, id, or onChange (to override these ones, it really might be best to make a custom widget). Perhaps we should define a list of overridable props for each widget using ui:props and only override those. What do you think?

@heath-freenome
Copy link
Member

One suggestion is to pull out the required, id or onChange props using something like the Lodash omit() function. Make a helper, like the rangeSpec() utility function, called maybe uiProps(), which extracts all. of the non-override-able variables and returns just the other stuff?

@Fedorov113
Copy link

Hello, any update on this?

@epicfaace
Copy link
Member

epicfaace commented May 17, 2020

@dekelb just thought of another thing -- what if someone inputs dangerouslySetInnerHTML into ui:props? This is essentially a security vulnerability if someone allows users to edit uiSchemas.

I'm thinking it would be best if, for each widget, we could define a whitelist of props that could be overridden using ui:props -- this would be best for security. Do you know how such a list could be assembled? Perhaps from the type definitions for material ui widgets?

@kedano
Copy link

kedano commented May 20, 2020

Hi, I'm trying to figure out how I could use the variant prop and other adjustments to my schema with material-ui.

Could it be an idea like @epicfaace mention to whitelist at least the props that has something to do with the design in the material-ui doc? https://material-ui.com/api/text-field/

@epicfaace epicfaace added this to In progress in PRs May 23, 2020
@epicfaace epicfaace moved this from In progress to Review in progress in PRs May 23, 2020
@howientc
Copy link

Any progress on this PR?

@epicfaace
Copy link
Member

We need to add a whitelist for allowed props. See how it was done with the fluent ui theme.

@ronny-rentner
Copy link

We need to add a whitelist for allowed props. See how it was done with the fluent ui theme.

Why do you need an allowlist?

Just let all props through, if they do something or not, it doesn't hurt and it will work when upstream adds new props automatically.

@ronny-rentner
Copy link

@dekelb just thought of another thing -- what if someone inputs dangerouslySetInnerHTML into ui:props? This is essentially a security vulnerability if someone allows users to edit uiSchemas.

Why would that someone not validate and escape user input correctly as you would always do it with any kind of user input?

I'm thinking it would be best if, for each widget, we could define a whitelist of props that could be overridden using ui:props -- this would be best for security. Do you know how such a list could be assembled? Perhaps from the type definitions for material ui widgets?

The list will change constantly. It should just let extra props through that it doesn't know. It's a common scheme to let pass all other props down in the hierarchy.

@ronny-rentner
Copy link

PS: Check out upstream: https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/TextField/TextField.js
They also have "...other" and pass through all props.

@epicfaace
Copy link
Member

Why would that someone not validate and escape user input correctly as you would always do it with any kind of user input?

One use case of react-jsonschema-form is allowing users to specify and save their own JSON Schemas (which I use myself in a form builder). It doesn't seem trivial to validate that input; at least, there don't exist libraries that could do that automatically (something like XSS sanitizers) and it would require you to perform the validation yourself.

The current behavior of react-jsonschema-form is that no possible JSON Schema / uiSchema can have a security impact, because there's no way to set the dangerouslyInnerHTML prop. With this change, this guarantee changes, because suddenly uiSchemas become untrusted user input and can cause XSS vulnerabilities. At the very least, this would be a backwards incompatible change.

@kedano
Copy link

kedano commented Nov 26, 2020

Hi, any update on this? Still waiting on the whitelisting?

@wight554
Copy link

wight554 commented Apr 10, 2022

While this one is seems to be dead, can you pass rest props to all components like you do here https://github.com/rjsf-team/react-jsonschema-form/blob/master/packages/material-ui/src/TextWidget/TextWidget.tsx#L53
It should be safe enough in this case
I'd like to create own minimal wrappers for components with own props whitelist, but currently I need to rewrite all non-textwidget widgets to achieve that
cc @epicfaace

@wight554
Copy link

Currently I can do something like this with TextWidget and I'd like to be able to do this for other widgets as well:

export const TextWidget = ({ options, ...props }: WidgetProps) => {
  const allProps: object & WhitelistedProps =
    typeof options?.props === 'object' && options?.props !== null ? options?.props : {};

  const pickedProps = pick(allProps, PROPS_WHITELIST);

  return <Widgets.TextWidget {...props} options={options} {...pickedProps} />;
};

@epicfaace
Copy link
Member

While this one is seems to be dead, can you pass rest props to all components like you do here https://github.com/rjsf-team/react-jsonschema-form/blob/master/packages/material-ui/src/TextWidget/TextWidget.tsx#L53 It should be safe enough in this case I'd like to create own minimal wrappers for components with own props whitelist, but currently I need to rewrite all non-textwidget widgets to achieve that cc @epicfaace

@wight554 sorry I don't understand what you are proposing, could you provide more details?

@wight554
Copy link

While this one is seems to be dead, can you pass rest props to all components like you do here https://github.com/rjsf-team/react-jsonschema-form/blob/master/packages/material-ui/src/TextWidget/TextWidget.tsx#L53 It should be safe enough in this case I'd like to create own minimal wrappers for components with own props whitelist, but currently I need to rewrite all non-textwidget widgets to achieve that cc @epicfaace

@wight554 sorry I don't understand what you are proposing, could you provide more details?

The idea was to add props spreading to all widget components
E.g. there's no ... props in select widget https://github.com/rjsf-team/react-jsonschema-form/blob/master/packages/material-ui/src/SelectWidget/SelectWidget.tsx#L68 like in link I've shared before

@epicfaace
Copy link
Member

Ok. Why do you think it would be safe enough in this case?

@wight554
Copy link

Ok. Why do you think it would be safe enough in this case?

There's no way to pass these, unless you wrap component with some hoc
Doing this for all will allow creating generic hoc for all components that'll check ui:props and pass it per widget

Copy link

stale bot commented Dec 12, 2023

This issue has been automatically marked as possibly close because it has not had recent activity. It will be closed if no further activity occurs. Please leave a comment if this is still an issue for you. Thank you.

@stale stale bot added the possibly close To confirm if this issue can be closed label Dec 12, 2023
Copy link

stale bot commented Jan 11, 2024

This issue was closed because of lack of recent activity. Reopen if you still need assistance.

@stale stale bot closed this Jan 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting changes possibly close To confirm if this issue can be closed
Projects
No open projects
PRs
  
Review in progress
Development

Successfully merging this pull request may close these issues.

None yet

8 participants