Files
scadalink-design/src/ScadaLink.CentralUI/Components/Layout/NavMenu.razor
Joseph Doherty d38356efdb Phase 1 WP-11–22: Host infrastructure, Blazor Server UI, and integration tests
Host infrastructure (WP-11–17):
- StartupValidator with 19 validation rules
- /health/ready endpoint with DB + Akka health checks
- Akka.NET bootstrap via AkkaHostedService (HOCON config, cluster, remoting, SBR)
- Serilog with SiteId/NodeHostname/NodeRole enrichment
- DeadLetterMonitorActor with count tracking
- CoordinatedShutdown wiring (no Environment.Exit)
- Windows Service support (UseWindowsService)

Central UI (WP-18–21):
- Blazor Server shell with Bootstrap 5, role-aware NavMenu
- Login/logout flow (LDAP auth → JWT → HTTP-only cookie)
- CookieAuthenticationStateProvider with idle timeout
- LDAP group mapping CRUD page (Admin role)
- Route guards with Authorize attributes per role
- SignalR reconnection overlay for failover

Integration tests (WP-22):
- Startup validation, auth flow, audit transactions, readiness gating
186 tests pass (1 skipped: LDAP integration), zero warnings.
2026-03-16 19:50:59 -04:00

81 lines
3.7 KiB
Plaintext

@using ScadaLink.Security
<nav class="sidebar d-flex flex-column">
<div class="brand">ScadaLink</div>
<ul class="nav flex-column flex-grow-1">
<li class="nav-item">
<NavLink class="nav-link" href="/" Match="NavLinkMatch.All">Dashboard</NavLink>
</li>
<AuthorizeView>
<Authorized>
@* Admin section — Admin role only *@
<AuthorizeView Policy="@AuthorizationPolicies.RequireAdmin">
<Authorized Context="adminContext">
<li class="nav-section-header">Admin</li>
<li class="nav-item">
<NavLink class="nav-link" href="admin/ldap-mappings">LDAP Mappings</NavLink>
</li>
<li class="nav-item">
<NavLink class="nav-link" href="admin/sites">Sites</NavLink>
</li>
<li class="nav-item">
<NavLink class="nav-link" href="admin/areas">Areas</NavLink>
</li>
</Authorized>
</AuthorizeView>
@* Design section — Design role *@
<AuthorizeView Policy="@AuthorizationPolicies.RequireDesign">
<Authorized Context="designContext">
<li class="nav-section-header">Design</li>
<li class="nav-item">
<NavLink class="nav-link" href="design/templates">Templates</NavLink>
</li>
<li class="nav-item">
<NavLink class="nav-link" href="design/shared-scripts">Shared Scripts</NavLink>
</li>
<li class="nav-item">
<NavLink class="nav-link" href="design/external-systems">External Systems</NavLink>
</li>
</Authorized>
</AuthorizeView>
@* Deployment section — Deployment role *@
<AuthorizeView Policy="@AuthorizationPolicies.RequireDeployment">
<Authorized Context="deploymentContext">
<li class="nav-section-header">Deployment</li>
<li class="nav-item">
<NavLink class="nav-link" href="deployment/instances">Instances</NavLink>
</li>
<li class="nav-item">
<NavLink class="nav-link" href="deployment/deployments">Deployments</NavLink>
</li>
<li class="nav-item">
<NavLink class="nav-link" href="deployment/debug-view">Debug View</NavLink>
</li>
</Authorized>
</AuthorizeView>
@* Health — visible to all authenticated users *@
<li class="nav-section-header">Monitoring</li>
<li class="nav-item">
<NavLink class="nav-link" href="monitoring/health">Health Dashboard</NavLink>
</li>
</Authorized>
</AuthorizeView>
</ul>
<AuthorizeView>
<Authorized>
<div class="border-top border-secondary p-2">
<span class="d-block text-light small px-2">@context.User.FindFirst("DisplayName")?.Value</span>
<form method="post" action="/auth/logout">
<button type="submit" class="btn btn-link btn-sm text-muted text-decoration-none px-2">Sign Out</button>
</form>
</div>
</Authorized>
</AuthorizeView>
</nav>