Hide tabs based on user authorization levels#3035
Open
WilliamBZA wants to merge 6 commits into
Open
Conversation
ramonsmits
reviewed
Jun 19, 2026
ramonsmits
left a comment
Member
There was a problem hiding this comment.
Added some improvement on:
dvdstelt
added a commit
that referenced
this pull request
Jun 22, 2026
Review fixes for user authorization tab hiding (#3035)
Map each gated UI capability to the ServiceControl HTTP route it represents (apiRoutes.ts), and normalize a (method, path) pair into a comparison key with route parameters collapsed to {} (routeMatching.ts). Matching couples only to method and path structure, so it survives server-side route parameter renames.
Co-Authored-By: Dennis van der Stelt <dvdstelt@gmail.com>
Co-Authored-By: williambza <william.brander@gmail.com>
Add AllowedRoutesStore, which fetches the my/routes manifest from the Primary and Monitoring instances, merges them, and dedupes concurrent fetches. Add the useAllowedRoutes composable (canCall / canAnyCall) that resource-owning view models build on, plus the startup fetch in App.vue. Gating is fail-open until the user is authenticated and the manifest has loaded, but a malformed manifest entry is skipped rather than aborting the load, so a single bad entry can never leave the store unloaded and silently fail every gate open. Co-Authored-By: Dennis van der Stelt <dvdstelt@gmail.com> Co-Authored-By: williambza <william.brander@gmail.com>
Hide navigation items (PageHeader.vue) and Configuration sub-tabs (ConfigurationView.vue) whose backing ServiceControl route the current user is not allowed to call. Co-Authored-By: Ramon Smits <ramon.smits@gmail.com> Co-Authored-By: Dennis van der Stelt <dvdstelt@gmail.com>
Add PermissionGate, a wrapper that disables a slotted action and shows a tooltip with the reason when the user lacks the backing route, instead of hiding the control. Apply it to failed-message, deleted-message and message-group actions, custom-check dismiss, heartbeat endpoint instances, redirects, health-check notifications, edit and retry, and monitored endpoint deletion. Resource-owning stores expose the capability getters these controls bind to. The edit/config fetch is skipped for users without edit permission and treats a 403 as unavailable rather than logging an error. Co-Authored-By: Ramon Smits <ramon.smits@gmail.com> Co-Authored-By: williambza <william.brander@gmail.com>
Render a Configuration page that lists the capabilities derived from the current user's allowed routes, with the supporting route and router-link entries. Co-Authored-By: Ramon Smits <ramon.smits@gmail.com> Co-Authored-By: williambza <william.brander@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Gates the ServicePulse UI on the set of ServiceControl API routes the signed-in user is actually allowed to call (the
my/routesmanifest). Navigation items and Configuration sub-tabs the user cannot reach are hidden; action buttons they cannot use are disabled with an explanatory tooltip (not hidden), so the UI stays discoverable.Gating is fail-open: it only applies once authorization is enabled, the user is authenticated, and the manifest has loaded. In every other state the full UI is shown, so an unreachable or slow ServiceControl never locks a user out.
This PR consolidates the work previously split across #3041 and #3044. It supersedes the earlier permission-string gating model, which was introduced and then removed on this branch in favour of the route-based approach.
How it works
composables/apiRoutes.ts): maps each gated UI capability to the ServiceControl HTTP route it represents. This is the single point of coupling to ServiceControl's route surface; the UI gates on routes it already calls, never on internal permission names.composables/routeMatching.ts): normalizes a (method, path) pair into a comparison key with route parameters collapsed to{}, so matching couples to method plus path structure and survives server-side parameter renames.stores/AllowedRoutesStore.ts): fetchesmy/routesfrom the Primary and Monitoring instances, merges them, and keeps a per-store in-flight guard so concurrent callers share one request. Per-instance fail-open: a failed or non-array response is ignored rather than fataled.composables/useAllowedRoutes.ts): exposescanCallandcanAnyCall. Resource-owning stores call these and surface capability getters; templates bind to those getters.components/PermissionGate.vue): reusable component that disables a slotted action and shows a tooltip with the reason when the user lacks the route, instead of removing the control.What is gated
PageHeader.vue) and Configuration sub-tabs(
ConfigurationView.vue): hidden when no backing route is allowed.HealthChecksStore,HeartbeatInstancesStore,MessageStore,MonitoringEndpointDetailsStore,RedirectsStore,ThroughputStore.UserPermissions.vue) renders the capabilities derived from the user's allowed routes.Design decisions
Backend dependency
Requires ServiceControl to serve the
my/routesallowed-route manifest on thePrimary instance, and the equivalent on the Monitoring instance.
Reviewer Checklist