diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/RoleGrants.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/RoleGrants.razor index caed4c75..7afc3d69 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/RoleGrants.razor +++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/RoleGrants.razor @@ -1,33 +1,21 @@ @page "/role-grants" -@* Per Q4 of the AdminUI rebuild plan, v2 replaced v1's per-cluster RoleGrants table with a - fleet-wide LDAP-group → role map. This page surfaces the mapping read-only; the source of - truth is Authentication:Ldap:GroupToRole in appsettings (editable on the host filesystem, not - from the UI yet). *@ -@attribute [Microsoft.AspNetCore.Authorization.Authorize] +@attribute [Microsoft.AspNetCore.Authorization.Authorize(Policy = "FleetAdmin")] @rendermode RenderMode.InteractiveServer @using Microsoft.Extensions.Options +@using ZB.MOM.WW.OtOpcUa.Configuration.Entities +@using ZB.MOM.WW.OtOpcUa.Configuration.Enums +@using ZB.MOM.WW.OtOpcUa.Configuration.Services @using ZB.MOM.WW.OtOpcUa.Security.Ldap @inject IOptionsSnapshot Ldap +@inject ILdapGroupRoleMappingService RoleMappings

Role grants

-
- LDAP group membership determines fleet roles. Edit the mapping in - appsettings.json under Authentication:Ldap:GroupToRole - and restart the admin node (or sign out + back in for cached claims to refresh). UI-driven - editing of the mapping is deferred — it implies a config-reload mechanism that doesn't exist - yet. -
- -@if (_options is null) +@if (_options is not null) { -

Loading…

-} -else -{ -
+
LDAP binding
Enabled@(_options.Enabled ? "yes" : "no")
@@ -40,16 +28,61 @@ else }
+} +
+
Group → role (database)
+
+
+ + + +
+ @if (_error is not null) + { +
@_error
+ } +
+
+ + + + @if (_rows.Count == 0) + { + + } + else + { + @foreach (var r in _rows) + { + + + + + + } + } + +
LDAP groupRole
No database role grants. Authentication falls back to the appsettings map below.
@r.LdapGroup@r.Role
+
+
+ +@if (_options is not null) +{
-
Group → role mapping (@(_options.GroupToRole?.Count ?? 0))
+
Fallback (appsettings) (@(_options.GroupToRole?.Count ?? 0))
+
+ These Authentication:Ldap:GroupToRole entries apply when a group has no database row above. +
@if (_options.GroupToRole is null || _options.GroupToRole.Count == 0) { -
- No mapping configured. Every authenticated user lands with zero roles — - the fallback authorization policy will refuse every request. Add a - GroupToRole entry before deploying. -
+
No appsettings fallback mapping configured.
} else { @@ -73,9 +106,45 @@ else @code { private LdapOptions? _options; + private IReadOnlyList _rows = []; + private string _newGroup = ""; + private AdminRole _newRole = AdminRole.ConfigViewer; + private string? _error; + private bool _busy; - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { _options = Ldap.Value; + await ReloadAsync(); + } + + private async Task ReloadAsync() + => _rows = (await RoleMappings.ListAllAsync(default)).Where(r => r.IsSystemWide).ToList(); + + private async Task AddAsync() + { + _error = null; + if (string.IsNullOrWhiteSpace(_newGroup)) { _error = "LDAP group is required."; return; } + _busy = true; + try + { + await RoleMappings.CreateAsync(new LdapGroupRoleMapping + { + LdapGroup = _newGroup.Trim(), Role = _newRole, IsSystemWide = true, ClusterId = null, + }, default); + _newGroup = ""; + _newRole = AdminRole.ConfigViewer; + await ReloadAsync(); + } + catch (Exception ex) { _error = ex.Message; } + finally { _busy = false; } + } + + private async Task DeleteAsync(Guid id) + { + _error = null; _busy = true; + try { await RoleMappings.DeleteAsync(id, default); await ReloadAsync(); } + catch (Exception ex) { _error = ex.Message; } + finally { _busy = false; } } }