Skip to content

Conversation

@tanujdargan
Copy link
Contributor

Fixes: #51299 - Impossible to load UI if user does not have read permissions on plugins

Summary

This PR ensures the Airflow UI loads gracefully for authenticated users who do not have read permissions on plugins.

Details

  • Refactored routes/ui/config.py to safely handle cases where plugins_manager.flask_appbuilder_menu_links is None, preventing 403 errors from blocking the UI.
  • Adjusted import order for clarity and maintainability.
  • The UI now loads extra plugin menu items from a new plugins_extra_menu_items attribute in the UI config endpoint, so all authenticated users can see them, regardless of direct plugin permissions.
  • The UI no longer calls the public/providers endpoint for these menu items.
  • Fixes failing CI pipeline and other tests.

Context

Previously, users without read permissions on plugins would receive a 403 Forbidden error, causing the entire UI to fail rendering. With this fix, the UI continues to render and display default elements, and plugin menu items are provided in a way accessible to all authenticated users.


Closes #51299.

@boring-cyborg boring-cyborg bot added area:API Airflow's REST/HTTP API area:UI Related to UI/UX. For Frontend Developers. labels Jun 13, 2025
@tanujdargan
Copy link
Contributor Author

@pierrejeambrun I had to create a new PR as I rebased by mistake while shifting between dev environments but this one shouldn't require anything to be done hopefully.

@rawwar
Copy link
Contributor

rawwar commented Jun 14, 2025

@tanujdargan , I created a new user with the "Viewer" role, and when I log in, I still see 403 errors with your changes:

image

Refactored config.py for ui api routes.

Fixed 403 error still showing for plugin imports
@tanujdargan
Copy link
Contributor Author

@rawwar You were right about the 403 error still being there I've gone ahead and pushed an update for that, should be all good now!

@tanujdargan
Copy link
Contributor Author

@pierrejeambrun Could you review?

Copy link
Member

@pierrejeambrun pierrejeambrun left a comment

Choose a reason for hiding this comment

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

Thanks, looking good, just a few suggestions / questions.

Comment on lines 33 to 35
const { data, error, isLoading } = usePluginServiceImportErrors(undefined, {
retry: false,
});
Copy link
Member

Choose a reason for hiding this comment

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

Why is that necesssary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a deliberate optimization. It prevents the UI from making multiple, pointless API calls when a user gets a 403 (Forbidden) error, as their permissions are unlikely to change between retries.

Copy link
Member

Choose a reason for hiding this comment

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

I don't think we should do that. Request could fail for many different reason. (network error because of poor connection, in the subway for instance, or other status code) and should be retried.

This is consistent with the rest of the application. Indeed if someone does not have permission, request will be sent two times for no reason, but that's where we are at the moment.

That needs to be solved at the entire application level and not only in one particular API call.

I suggest to remove this and follow up with a dedicated PR if you have ideas on how to approach this.

pierrejeambrun
pierrejeambrun previously approved these changes Jun 20, 2025
Copy link
Member

@pierrejeambrun pierrejeambrun left a comment

Choose a reason for hiding this comment

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

1 small nit, working as expected, thanks for the PR.

Comment on lines 33 to 35
const { data, error, isLoading } = usePluginServiceImportErrors(undefined, {
retry: false,
});
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we should do that. Request could fail for many different reason. (network error because of poor connection, in the subway for instance, or other status code) and should be retried.

This is consistent with the rest of the application. Indeed if someone does not have permission, request will be sent two times for no reason, but that's where we are at the moment.

That needs to be solved at the entire application level and not only in one particular API call.

I suggest to remove this and follow up with a dedicated PR if you have ideas on how to approach this.

Copy link
Member

@pierrejeambrun pierrejeambrun left a comment

Choose a reason for hiding this comment

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

This need some small adjustments, following #51889 merge.

appbuilder_menu_items is deprecated and we should instead return external_views that target the None or "nav" destination. (both will endup being extra menu items). Or you can return all external_views and do the filtering in the UI if "destination==="nav" (None does not need to be checked there because the API fills None with "nav" when returning a response).

dashboard_alert: list[UIAlert]
show_external_log_redirect: bool
external_log_name: str | None = None
plugins_extra_menu_items: list[AppBuilderMenuItemResponse] = []
Copy link
Member

Choose a reason for hiding this comment

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

You don't need to provide a default. This can never be None and will be passed from the plugin manager.

@tanujdargan tanujdargan requested review from kaxil and potiuk as code owners June 26, 2025 10:15
@tanujdargan
Copy link
Contributor Author

It makes more sense to start this from scratch since most of the stuff would need to be redone and I would have a lot of unnecessary conflicts.

@pierrejeambrun
Copy link
Member

@tanujdargan Thanks for you message, I'm not sure starting over would be the fastest way, do you plan to open a new PR with the updates?

@tanujdargan
Copy link
Contributor Author

I partially started over, it was more efficient since I had a lot of merge conflicts some of which couldn't be resolved. I've raised a new PR here: #52408

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:API Airflow's REST/HTTP API area:UI Related to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug - Impossible to load UI if user does not have read permissions on plugins

3 participants