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

Support dynamic UI Capabilities #59377

Open
legrego opened this issue Mar 4, 2020 · 8 comments
Open

Support dynamic UI Capabilities #59377

legrego opened this issue Mar 4, 2020 · 8 comments
Labels
enhancement New value added to drive a business result Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc

Comments

@legrego
Copy link
Member

legrego commented Mar 4, 2020

Currently, UI Capabilities are retrieved during Core's setup phase, and are cached for the lifetime of the current page.

This model served the legacy platform well, because switching between applications required a full page reload, so users were able to get updated capabilities often enough.

The new platform allows users to navigate between applications without requiring a full page reload. This is great! As it stands today, static capabilities will continue to work.

Static capabilities start to break down when we transition from anonymous pages to authenticated pages, or when switching between spaces.

We would like users to enter Kibana after authenticating, without requiring a full page reload. To do this, we need a way of signaling to the core platform that capabilities should be refreshed. Once the UI has the updated set of capabilities, we need a way to propagate those changes to all initialized plugins and services, so that they can respond accordingly.

@legrego legrego added Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc enhancement New value added to drive a business result labels Mar 4, 2020
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-platform (Team:Platform)

@joshdover
Copy link
Contributor

I think we could use a similar mechanism that licensing uses where we include a hash of the current capabilities in a response header. Then the platform can register an interceptor that reads that header and anytime it changes, it can refetch the capabilities. This has the benefit of being able to get updates quickly without having to introduce yet another polling request.

Of course this can introduce overhead on each response from the server, so this only works if fetching the capabilities for a user is fast.

This mechanism has the side-benefit of being able to update other tabs / windows when the capabilities change for other reasons (Admin changes your permissions for example).

@legrego
Copy link
Member Author

legrego commented Mar 4, 2020

I think we could use a similar mechanism that licensing uses where we include a hash of the current capabilities in a response header.

Of course this can introduce overhead on each response from the server, so this only works if fetching the capabilities for a user is fast.

I like this idea, but share your concern as well. Both Security and Spaces register capability "switchers" which each make at least one round-trip to Elasticsearch in order to compute the next set of capabilities. We'd need to see what kind of overhead this introduces.

Maybe we could do this check on just a subset of requests, if there's some logical way to do so (e.g., system vs user requests, or something else)

@joshdover
Copy link
Contributor

If that's the case, then yes we shouldn't do this on every request.

What if we use some sort of user queue that these should be reloaded. For example, if we re-fetched the capabilities each time a user switches applications, we would get a very similar UX to what we have today.

@legrego
Copy link
Member Author

legrego commented Mar 6, 2020

If that's the case, then yes we shouldn't do this on every request.

What if we use some sort of user queue that these should be reloaded. For example, if we re-fetched the capabilities each time a user switches applications, we would get a very similar UX to what we have today.

That sounds like a good compromise to me!

@pgayvallet
Copy link
Contributor

Once the UI has the updated set of capabilities, we need a way to propagate those changes to all initialized plugins and services, so that they can respond accordingly.

I think we could use a similar mechanism that licensing uses where we include a hash of the current capabilities in a response header. Then the platform can register an interceptor that reads that header and anytime it changes, it can refetch the capabilities.

Overall, +1, this is really something we should have.

However, the whole codebase is currently performing it's capabilities check with the postulate that these are immutable and accessible in a synchronous way, making me wonder about the size of this enhancement.

  1. We will need to wait for full codebase migration to TS before doing something that impactful
  2. Even with TS backup, these sounds like very heavy change in a lot of places.

Maybe having the interceptor or another mechanism detecting when an action requires the capabilities to be refreshed, and performing a real page reload instead of just directing to the new page is more realistic in short/mid term?

@legrego
Copy link
Member Author

legrego commented Mar 9, 2020

However, the whole codebase is currently performing it's capabilities check with the postulate that these are immutable and accessible in a synchronous way, making me wonder about the size of this enhancement.

You're absolutely right, this is a sizable enhancement that we wouldn't be able to tackle in the short term. I don't know if it's still the case, but when we did the initial feature controls work, the actual usage of UI Capabilities was rather limited (show/hide a button, enable/disable a form, etc). There will of course be exceptions to this, and logic that was previously static will inherently become more complex.

Maybe having the interceptor or another mechanism detecting when an action requires the capabilities to be refreshed, and performing a real page reload instead of just directing to the new page is more realistic in short/mid term?

The places where we require new capabilities are already setup to do this today, but it's something we're trying to get away from:

img

In an ideal world, we would get this down to a single page load for the login screen. We are going to try to eliminate the second reload (for the space selector) without dynamic capabilities (#59555), but the real problem for us is the switch between unauthenticated and authenticated pages (or in core speak, "anonymous" and "not anonymous" routes).

Another idea (which is arguably more work, and an even larger enhancement) is to introduce a teardown phase, which would allow plugins to re-setup and re-start themselves without requiring a full page reload. That would allow capabilities to be consumed in a static manner, without needing to fully reload the page.

@joshdover
Copy link
Contributor

Some notes from backlog grooming:

  • Updating capabilities while an app is on the page may lead to confusing UX
  • One option would be to provide a "snapshot" of the current capabilities when an application is mounted so that they are stable during the lifecycle of a single app
  • Background services should consume an Observable of changing capabilities so they are always up to date

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New value added to drive a business result Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc
Projects
None yet
Development

No branches or pull requests

4 participants