@page "/apikeys" @attribute [Authorize(Policy = AdminUiPolicies.FleetAdmin)] @rendermode RenderMode.InteractiveServer @using ZB.MOM.WW.OtOpcUa.Configuration.Entities @using ZB.MOM.WW.OtOpcUa.Core.Authorization @inject IApiKeyAdminService Keys

OPC UA API keys

@if (_created is not null) { } @if (!string.IsNullOrWhiteSpace(_error)) { }
Create a key
Keys
@if (_keys is null) {
Loading…
} else if (_keys.Count == 0) {
No keys yet. Until one exists, only anonymous sessions can connect.
} else { @foreach (var k in _keys) { }
Name Principal Key id Status Created (UTC) Expires (UTC)
@k.Name @k.Principal @k.ApiKeyId @if (!k.Enabled) { revoked } else if (k.ExpiresUtc is { } e && e <= DateTime.UtcNow) { expired } else { active } @k.CreatedUtc.ToString("yyyy-MM-dd HH:mm") @(k.ExpiresUtc?.ToString("yyyy-MM-dd") ?? "—")
}
@code { private IReadOnlyList? _keys; private string _newName = ""; private string _newPrincipal = ""; private DateTime? _newExpires; private string? _created; private string? _error; private bool _busy; protected override async Task OnInitializedAsync() => await ReloadAsync(); private async Task ReloadAsync() { try { _keys = await Keys.ListAsync(default); } catch (Exception ex) { _error = ex.Message; _keys = []; } } private async Task CreateAsync() { _busy = true; _error = null; _created = null; try { // Shown once, held only in this component's state. There is no way to recover it afterwards // — the server stores a hash — so it is deliberately not written anywhere else. _created = await Keys.CreateAsync( _newName, _newPrincipal, // A date-only input means midnight; treat it as UTC rather than local so an operator // near a timezone boundary does not get a key that expired before it was issued. _newExpires is { } d ? DateTime.SpecifyKind(d, DateTimeKind.Utc) : null, notes: null, default); _newName = ""; _newPrincipal = ""; _newExpires = null; await ReloadAsync(); } catch (Exception ex) { _error = ex.Message; } finally { _busy = false; } } private async Task SetEnabledAsync(string apiKeyId, bool enabled) { _busy = true; _error = null; try { await Keys.SetEnabledAsync(apiKeyId, enabled, default); await ReloadAsync(); } catch (Exception ex) { _error = ex.Message; } finally { _busy = false; } } private async Task DeleteAsync(string apiKeyId) { _busy = true; _error = null; try { await Keys.DeleteAsync(apiKeyId, default); await ReloadAsync(); } catch (Exception ex) { _error = ex.Message; } finally { _busy = false; } } }