feat(adminui): gate the Secrets rail link on the page's own policy
The /admin/secrets link was already in the side rail, but ungated — every authenticated user saw it, and a Designer/Operator clicking it was bounced by the page's own [Authorize(Policy = SecretsAuthorization.ManagePolicy)]. Hide the advertised dead end. Gated on that same policy constant rather than Roles="Administrator". The two are equivalent today (the RCL's AdminRole is "Administrator", read off the same ClaimTypes.Role claim FleetAdmin uses), so this is not about reach — it is that the rail cannot drift if the RCL ever changes its policy. Live-gated on docker-dev, both directions, because the positive half alone proves nothing here: the link rendered for an admin BEFORE this change too, so "admin still sees it" is satisfied equally by a working gate and by an inert one. Negative control — gate swapped to Roles="NoSuchRoleFalsifyProbe", rebuilt, item went to 0 while /role-grants and /apikeys stayed at 1 (the item is hidden, not the rail broken). Restored build hashed to the same image ID as the pre-falsification one, proving the restore was byte-exact. This also rules out AuthorizeView being inert inside ThemeShell's <Nav> slot under this host's static router, which would have silently hidden the link from everyone. SecretsNavLinkTests covers it in the AdminUI's actual idiom — source scan + metadata cross-check, NOT bUnit (the bunit PackageVersion pin has zero PackageReferences repo-wide). The load-bearing assertion is index ordering (AuthorizeView open < NavRailItem < close): a scan that merely finds both tags in the file passes when they are not nested, which is the ungated state. Scope: Secrets only. /role-grants and /apikeys are FleetAdmin (Administrator- only) too and stay visible to everyone, so the rail is now inconsistent — deliberate, as hiding those is a UX call for the whole rail rather than something to smuggle into this change. Noted in the markup. Family-wide task from the scadaproj index session (ScadaBridge ee193cd2, ignitionoee 3627bb8, HistorianGateway 58b6418, mxgw 87d575d).
This commit is contained in:
@@ -25,7 +25,19 @@
|
||||
<NavRailItem Href="/certificates" Text="Certificates" />
|
||||
<NavRailItem Href="/role-grants" Text="Role grants" />
|
||||
<NavRailItem Href="/apikeys" Text="API keys" />
|
||||
<NavRailItem Href="/admin/secrets" Text="Secrets" />
|
||||
@* Gated on the page's OWN policy constant, not Roles="Administrator", so the rail
|
||||
can never drift from what the page actually admits (pinned by SecretsNavLinkTests).
|
||||
ManagePolicy resolves to AdminRole "Administrator" over the same ClaimTypes.Role
|
||||
claim FleetAdmin reads.
|
||||
|
||||
NOTE this is currently the ONLY gated item, and the rail is therefore inconsistent:
|
||||
/role-grants and /apikeys are FleetAdmin (Administrator-only) too and stay visible
|
||||
to everyone, i.e. still advertised dead ends for a Designer/Operator. That is a
|
||||
deliberate scope boundary, not an oversight — hiding them is a UX call for the
|
||||
whole rail, filed as a follow-up rather than smuggled in here. *@
|
||||
<AuthorizeView Policy="@ZB.MOM.WW.Secrets.Ui.SecretsAuthorization.ManagePolicy">
|
||||
<NavRailItem Href="/admin/secrets" Text="Secrets" />
|
||||
</AuthorizeView>
|
||||
</NavRailSection>
|
||||
<NavRailSection Title="Scripting" Key="scripting">
|
||||
<NavRailItem Href="/scripts" Text="Scripts" />
|
||||
|
||||
Reference in New Issue
Block a user