feat: move Areas to Design role, fix logout, add Sign Out button

Areas management is a design concern, not admin. Moved Areas page
authorization from RequireAdmin to RequireDesign, moved nav link from
Admin to Design section, updated ManagementActor role check. Added
GET /logout endpoint (was 404, now redirects to login). Improved Sign
Out button visibility in sidebar next to username.
This commit is contained in:
Joseph Doherty
2026-03-18 00:28:35 -04:00
parent 75a6636a2c
commit 68115e7e38
5 changed files with 22 additions and 13 deletions

View File

@@ -177,7 +177,7 @@ At any level, an override is only permitted if the attribute has **not been lock
- Areas support **parent-child relationships** (e.g., Plant → Building → Production Line → Cell).
- Each instance is assigned to an area within its site.
- Areas are used for **filtering and finding instances** in the central UI.
- Area definitions are managed by users with the **Admin** role.
- Area definitions are managed by users with the **Design** role.
### 3.11 Pre-Deployment Validation
@@ -394,7 +394,7 @@ The central cluster hosts a **configuration and management UI** (no live machine
### 9.3 Roles
- **Admin**: System-wide permission to manage sites, data connections, LDAP group-to-role mappings, API keys, and system-level configuration.
- **Design**: System-wide permission to author and edit templates, scripts, shared scripts, external system definitions, notification lists, and inbound API method definitions.
- **Design**: System-wide permission to author and edit templates, scripts, shared scripts, external system definitions, notification lists, inbound API method definitions, and area definitions.
- **Deployment**: Permission to manage instances (create, set overrides, bind connections, disable, delete) and deploy configurations to sites. Also triggers system-wide artifact deployment. Can be scoped **per site**.
### 9.4 Role Scoping

View File

@@ -86,6 +86,13 @@ public static class AuthEndpoints
context.Response.Redirect("/login");
}).DisableAntiforgery();
// GET /logout — allows direct navigation to logout (redirects to login after sign-out)
endpoints.MapGet("/logout", async (HttpContext context) =>
{
await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return Results.Redirect("/login");
});
return endpoints;
}
}

View File

@@ -23,9 +23,6 @@
<li class="nav-item">
<NavLink class="nav-link" href="/admin/data-connections">Data Connections</NavLink>
</li>
<li class="nav-item">
<NavLink class="nav-link" href="/admin/areas">Areas</NavLink>
</li>
<li class="nav-item">
<NavLink class="nav-link" href="/admin/api-keys">API Keys</NavLink>
</li>
@@ -45,6 +42,9 @@
<li class="nav-item">
<NavLink class="nav-link" href="/design/external-systems">External Systems</NavLink>
</li>
<li class="nav-item">
<NavLink class="nav-link" href="/admin/areas">Areas</NavLink>
</li>
</Authorized>
</AuthorizeView>
@@ -90,11 +90,13 @@
<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" data-enhance="false">
<button type="submit" class="btn btn-link btn-sm text-muted text-decoration-none px-2">Sign Out</button>
</form>
<div class="border-top border-secondary px-3 py-2">
<div class="d-flex justify-content-between align-items-center">
<span class="text-light small">@context.User.FindFirst("DisplayName")?.Value</span>
<form method="post" action="/auth/logout" data-enhance="false">
<button type="submit" class="btn btn-outline-light btn-sm py-0 px-2">Sign Out</button>
</form>
</div>
</div>
</Authorized>
</AuthorizeView>

View File

@@ -3,7 +3,7 @@
@using ScadaLink.Commons.Entities.Instances
@using ScadaLink.Commons.Entities.Sites
@using ScadaLink.Commons.Interfaces.Repositories
@attribute [Authorize(Policy = AuthorizationPolicies.RequireAdmin)]
@attribute [Authorize(Policy = AuthorizationPolicies.RequireDesign)]
@inject ISiteRepository SiteRepository
@inject ITemplateEngineRepository TemplateEngineRepository

View File

@@ -74,13 +74,13 @@ public class ManagementActor : ReceiveActor
{
// Admin operations
CreateSiteCommand or UpdateSiteCommand or DeleteSiteCommand
or CreateAreaCommand or DeleteAreaCommand
or ListRoleMappingsCommand or CreateRoleMappingCommand
or UpdateRoleMappingCommand or DeleteRoleMappingCommand
or ListApiKeysCommand or CreateApiKeyCommand or DeleteApiKeyCommand => "Admin",
// Design operations
CreateTemplateCommand or UpdateTemplateCommand or DeleteTemplateCommand
CreateAreaCommand or DeleteAreaCommand
or CreateTemplateCommand or UpdateTemplateCommand or DeleteTemplateCommand
or ValidateTemplateCommand
or CreateExternalSystemCommand or UpdateExternalSystemCommand
or DeleteExternalSystemCommand