-
Notifications
You must be signed in to change notification settings - Fork 8.2k
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
Migrate capabilities mixin to New Platform service #45393
Comments
My questions / remarks after inspecting atm the
|
const defaultCapabilities = mergeCapabilities( | |
...(await Promise.all( | |
kbnServer.pluginSpecs | |
.map(spec => spec.getUiCapabilitiesProvider()) | |
.filter(provider => !!provider) | |
.map(provider => provider(server)) | |
)) | |
); |
kibana/src/legacy/core_plugins/kibana/index.js
Lines 260 to 268 in 62d0353
uiCapabilities: async function () { | |
return { | |
discover: { | |
show: true, | |
createShortUrl: true, | |
save: true, | |
saveQuery: true, | |
}, | |
visualize: { |
The accessor (uiCapabilities: async function () {
) is an async function, however I could not find any usage where a static object wouldn't have worked. So I guess we could add a similar mecanism in each plugin's kibana.json
{
"id": "data",
"version": "kibana",
"server": true,
"ui": true,
"capabilities": {
"navlinks": {
"myapp": true
},
"data": {
"aFeature": true
}
}
}
- Do we want that?
- If we do, do we want to also add a programmatic way to register capabilities to manage edge cases?
LP server knows about client navlinks. NP does not
navlinks are a special things in capabilities, as they are not declared in the plugin descriptors but instead generated from kbnServer.uiExports
.
kibana/src/legacy/server/capabilities/capabilities_mixin.ts
Lines 52 to 63 in d9c34ca
server.decorate('request', 'getCapabilities', function() { | |
// Get legacy nav links | |
const navLinks = server.getUiNavLinks().reduce( | |
(acc, spec) => ({ | |
...acc, | |
[spec._id]: true, | |
}), | |
{} as Record<string, boolean> | |
); | |
return resolveCapabilities(this, modifiers, defaultCapabilities, { navLinks }); | |
}); |
kibana/src/legacy/ui/ui_nav_links/ui_nav_links_mixin.js
Lines 22 to 41 in 049814d
export function uiNavLinksMixin(kbnServer, server) { | |
const uiApps = server.getAllUiApps(); | |
const { navLinkSpecs = [] } = kbnServer.uiExports; | |
const fromSpecs = navLinkSpecs | |
.map(navLinkSpec => new UiNavLink(navLinkSpec)); | |
const fromApps = uiApps | |
.map(app => app.getNavLink()) | |
.filter(Boolean); | |
const uiNavLinks = fromSpecs | |
.concat(fromApps) | |
.sort((a, b) => a.getOrder() - b.getOrder()); | |
server.decorate('server', 'getUiNavLinks', () => ( | |
uiNavLinks.slice(0) | |
)); | |
} |
NP have no way to access the NP plugins application list from server side (and we really don't want to find a way). So I guess the NP plugins will register their app/navlinks
the same way they do with other capabilities. Do we all agree on that, or do we want to find some way to do 'auto-discovery' on applications?
current CapabilitiesModifier needs Request access
export type CapabilitiesModifier = (
request: Request,
uiCapabilities: Capabilities
) => Capabilities | Promise<Capabilities>;
This is mostly used by spaces/security to access session/space from the request:
kibana/x-pack/plugins/spaces/server/plugin.ts
Lines 183 to 191 in e46f977
legacyAPI.capabilities.registerCapabilitiesModifier(async (request, uiCapabilities) => { | |
try { | |
const activeSpace = await spacesService.getActiveSpace(KibanaRequest.from(request)); | |
const features = featuresSetup.getFeatures(); | |
return toggleUICapabilities(features, uiCapabilities, activeSpace); | |
} catch (e) { | |
return uiCapabilities; | |
} | |
}); |
kibana/x-pack/plugins/spaces/server/spaces_service/spaces_service.ts
Lines 58 to 69 in ad356f5
const getSpaceId = (request: RequestFacade) => { | |
// Currently utilized by reporting | |
const isFakeRequest = typeof (request as any).getBasePath === 'function'; | |
const basePath = isFakeRequest | |
? (request as Record<string, any>).getBasePath() | |
: http.basePath.get(request); | |
const spaceId = getSpaceIdFromPath(basePath, http.basePath.serverBasePath); | |
return spaceId; | |
}; |
Accessing the current context makes sense for that kind of feature, as capabilities modifiers/togglers will need to know about context to toggle the capabilities.
- Should we keep this interface parameters, or do we can/want to provide a more specialised object that the raw request?
Client-side capabilities service
We already have a client-side service for this in src/core/public/application/capabilities/capabilities_service.tsx
. It currently access the capabilities from the injectedMetadata
.
- Does this issue moves the service as first-class, therefor moving up from the
ApplicationService
? - One of the ticket requirements is
Provide an API endpoint for the client-side to retrieve the current user's capabilities based on the registered applications.
Is the current approach acceptable or do we want to change it for a proper http endpoint and call from frontend?
👍
It would be nice to at least move the custom capabilities under a
See comment below about navLinks.
Before this change, we needed uiCapabilities to be able to do dynamic things. I agree that we probably don't need this anymore and a static spec would be fine.
Agreed that navLinks are strange in here, this was really just necessary for LP usage. It's important to note that this part of capabilities is not read anywhere in the server-side code, only toggled by the capabilities modifiers. Given that, the server doesn't actually need to know about all the possible navLinks in the system. One flow that could work (and was the original intent) is that the client-side could send a list of all the registered applications to a backend endpoint and receive a list back of which apps should be available. I believe this pattern would work with both legacy and NP apps. It actually worked like this for a bit until we found some issues with missing security request interceptors. That has since been resolved. See #36319 for more details.
A more specific interface probably makes sense, you'll probably need to look at these two modifiers that are registered and see what they actually need access to.
As mentioned above, the current approach probably isn't what we want. We should make an HTTP request with the list of registered applications so that the backend can manage toggling access to those. In terms of where this lives in Core, I think being part of ApplicationService is debatable. The capabilities data is not exactly coupled to applications, but we need the list of capabilities in order to make the request to the backend and filter the applications. Regardless, it may make sense to move it to a first-class service from an API consumer standpoint. |
@joshdover I got a feeling the I see conflicting direction regarding how we want to manage them between this issue and #45291:
I don't think implementing both makes much sense? IMHO we either
I've got two mains reasons that would make me choose the second option:
WDYT? |
The legacy capabilities mixin needs to be migrated to the New Platform as a Core service.
This service should handle:
The text was updated successfully, but these errors were encountered: