fix(adminui): capture audit username at click time, not at panel init
v2-ci / build (push) Failing after 48s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
v2-ci / build (push) Failing after 48s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
DriverStatusPanel previously cached the username in a field at OnInitializedAsync and forwarded the cached value into RestartDriver / ReconnectDriver messages. A token refresh or claim change mid- circuit would land the stale name in the audit ConfigEdit row. Re-reads AuthenticationStateProvider at button-click time so the audit entry reflects the current principal.
This commit is contained in:
+20
-4
@@ -149,7 +149,6 @@
|
|||||||
|
|
||||||
// Authorization
|
// Authorization
|
||||||
private bool _canOperate;
|
private bool _canOperate;
|
||||||
private string? _currentUserName;
|
|
||||||
|
|
||||||
// Action state
|
// Action state
|
||||||
private bool _busyReconnect;
|
private bool _busyReconnect;
|
||||||
@@ -162,8 +161,9 @@
|
|||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
// Check DriverOperator authorization so buttons only render for permitted users.
|
// Check DriverOperator authorization so buttons only render for permitted users.
|
||||||
|
// The username for audit logging is re-read at button-click time (not captured here)
|
||||||
|
// so token-refreshes mid-session land in audit entries accurately.
|
||||||
var auth = await AuthState.GetAuthenticationStateAsync();
|
var auth = await AuthState.GetAuthenticationStateAsync();
|
||||||
_currentUserName = auth.User.Identity?.Name ?? auth.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value ?? "unknown";
|
|
||||||
var authResult = await AuthorizationService.AuthorizeAsync(auth.User, null, "DriverOperator");
|
var authResult = await AuthorizationService.AuthorizeAsync(auth.User, null, "DriverOperator");
|
||||||
_canOperate = authResult.Succeeded;
|
_canOperate = authResult.Succeeded;
|
||||||
|
|
||||||
@@ -213,8 +213,9 @@
|
|||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var userName = await GetCurrentUserNameAsync();
|
||||||
var result = await AdminOps.AskAsync<ReconnectDriverResult>(
|
var result = await AdminOps.AskAsync<ReconnectDriverResult>(
|
||||||
new ReconnectDriver(ClusterId, DriverInstanceId, _currentUserName ?? "unknown", Guid.NewGuid()),
|
new ReconnectDriver(ClusterId, DriverInstanceId, userName, Guid.NewGuid()),
|
||||||
new System.Threading.CancellationTokenSource(TimeSpan.FromSeconds(15)).Token);
|
new System.Threading.CancellationTokenSource(TimeSpan.FromSeconds(15)).Token);
|
||||||
ShowOpResult(result.Ok, result.Ok ? "Reconnect dispatched" : (result.Message ?? "Failed"));
|
ShowOpResult(result.Ok, result.Ok ? "Reconnect dispatched" : (result.Message ?? "Failed"));
|
||||||
}
|
}
|
||||||
@@ -237,8 +238,9 @@
|
|||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var userName = await GetCurrentUserNameAsync();
|
||||||
var result = await AdminOps.AskAsync<RestartDriverResult>(
|
var result = await AdminOps.AskAsync<RestartDriverResult>(
|
||||||
new RestartDriver(ClusterId, DriverInstanceId, _currentUserName ?? "unknown", Guid.NewGuid()),
|
new RestartDriver(ClusterId, DriverInstanceId, userName, Guid.NewGuid()),
|
||||||
new System.Threading.CancellationTokenSource(TimeSpan.FromSeconds(15)).Token);
|
new System.Threading.CancellationTokenSource(TimeSpan.FromSeconds(15)).Token);
|
||||||
ShowOpResult(result.Ok, result.Ok ? "Restart dispatched" : (result.Message ?? "Failed"));
|
ShowOpResult(result.Ok, result.Ok ? "Restart dispatched" : (result.Message ?? "Failed"));
|
||||||
}
|
}
|
||||||
@@ -253,6 +255,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Re-reads the AuthenticationState at call time so the username forwarded to the
|
||||||
|
/// audit log reflects the current claims-principal — survives token refresh / role
|
||||||
|
/// change during a long-lived Blazor circuit. Returns "unknown" if no Name claim is
|
||||||
|
/// present (auth requirements upstream should normally prevent this).
|
||||||
|
/// </summary>
|
||||||
|
private async Task<string> GetCurrentUserNameAsync()
|
||||||
|
{
|
||||||
|
var auth = await AuthState.GetAuthenticationStateAsync();
|
||||||
|
return auth.User.Identity?.Name
|
||||||
|
?? auth.User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value
|
||||||
|
?? "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
private void ShowOpResult(bool ok, string message)
|
private void ShowOpResult(bool ok, string message)
|
||||||
{
|
{
|
||||||
_opResultOk = ok;
|
_opResultOk = ok;
|
||||||
|
|||||||
Reference in New Issue
Block a user