-
Notifications
You must be signed in to change notification settings - Fork 14k
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
fix: Native filter dashboard RBAC aware dataset permission #25029
fix: Native filter dashboard RBAC aware dataset permission #25029
Conversation
superset/security/manager.py
Outdated
slc := self.get_session.query(Slice) | ||
.filter(Slice.id == slice_id) | ||
.one_or_none() | ||
form_data.get("type") == "NATIVE_FILTER" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this needs a few extra validations here in order to grant access:
- We still need to check that the user has access to the dashboard (I'd suggest moving the
self.can_access_dashboard(dashboard_)
check to be right afterand dashboard_.roles
since we want to check dashboard access whether it's via a chart or native filter - That the datasource is actually used as a native filter on the dashboard. We can probably borrow logic from @Vitor-Avila's PR here; performance shouldn't be a concern here since we only need to check one dashboard
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch, @jfrag1! I agree it's a valid check and with this improved version that we know the dashboardId
shouldn't be too expensive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Oops. Yeah I missed moving
self.can_access_dashboard(dashboard_)
outside of theor
block. I've placed it at the end of the logic checks as it's likely the most expensive check. - That is an option. Note in theory we should be including the filter ID in the query-context to check for the specific filter rather than seeing if any filter matches.
thank you so much for working on this PR @john-bodley! 🙏 |
f15ee5d
to
10a7bc1
Compare
@@ -94,6 +95,7 @@ export const getFormData = ({ | |||
viz_type: filterType, | |||
type, | |||
dashboardId, | |||
native_filter_id: id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling this id
seemed a tad terse. I'm not sure if this should be snake or camel case.
10a7bc1
to
ef763bf
Compare
slc := self.get_session.query(Slice) | ||
.filter(Slice.id == slice_id) | ||
.one_or_none() | ||
( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
( | |
( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe @Vitor-Avila or @jfrag1 can help add if there's anything else we need to do for embedded with the below logic? Check for a guest user?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I will add logic for embedded in a separate PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@eschutho Black formats the code how it sees fit.
[], | ||
) | ||
for target in fltr.get("targets", []) | ||
if native_filter_id == fltr.get("id") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
ef763bf
to
30a2d35
Compare
# Native filter. | ||
form_data.get("type") == "NATIVE_FILTER" | ||
and (native_filter_id := form_data.get("native_filter_id")) | ||
and dashboard_.json_metadata |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hey @john-bodley I just tested this branch locally and I still see the permission error -- it seems that dashboardId
is still not included in the filter's payload data (despite #25025). Curious to know if you are facing a different behavior on your end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Vitor-Avila just to confirm have you rebuilt the frontend assets? If the problem still persists would you mind sharing a URL—leveraging the example dataset—so I can further debug this issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@john-bodley ohh that's true! I didn't have rebuilt the frontend assets 🤦 thanks for the heads up and I just confirmed it works properly after doing so. Filter box are showing an error, but I can take a look to implement a similar approach to fix it. Again apologies for the false alarm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Phew! I'm glad to hear that this was a false alarm. Thanks again for testing the change.
30a2d35
to
b843dc1
Compare
mock_g.user = security_manager.find_user("gamma") | ||
mock_is_owner.return_value = False | ||
mock_can_access.return_value = False | ||
mock_can_access_schema.return_value = False | ||
|
||
for kwarg in ["query_context", "viz"]: | ||
births.roles = [] | ||
db.session.flush() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to flush these updates to the database transaction given the logic in the test is confined to the same Flask-SQLAlchemy session.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thank you for the fix @john-bodley.
(cherry picked from commit 60889d2)
SUMMARY
Somewhat related to #25008, this PR ensures that access is granted to a datasource (in the context of a dashboard native filter) when dashboard RBAC is enabled. Thanks to @michael-s-molina for #25025 which exposed the
dashboardId
in the client form data.BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
BEFORE
AFTER
TESTING INSTRUCTIONS
Added unit tests.
ADDITIONAL INFORMATION
cc: @jfrag1