feat(centralui): Verify-endpoint button + result/cert panel (T17)
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
@namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Forms
|
||||
@using ZB.MOM.WW.ScadaBridge.CentralUI.Services
|
||||
@using ZB.MOM.WW.ScadaBridge.Commons.Messages.Management
|
||||
@using ZB.MOM.WW.ScadaBridge.Commons.Types.DataConnections
|
||||
@using ZB.MOM.WW.ScadaBridge.Commons.Types.Flattening
|
||||
@inject IEndpointVerificationService VerificationService
|
||||
|
||||
<div class="opcua-endpoint-editor">
|
||||
<h6 class="text-muted border-bottom pb-1">@Title</h6>
|
||||
@@ -40,6 +43,62 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
<button type="button" class="btn btn-outline-primary btn-sm"
|
||||
data-test="verify-endpoint-btn"
|
||||
disabled="@_verifying"
|
||||
@onclick="VerifyEndpoint">
|
||||
@if (_verifying)
|
||||
{
|
||||
<span class="spinner-border spinner-border-sm me-1" role="status" aria-hidden="true"></span>
|
||||
<span>Verifying…</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>Verify endpoint</span>
|
||||
}
|
||||
</button>
|
||||
|
||||
@if (_verifyResult is { } result)
|
||||
{
|
||||
@if (result.Success)
|
||||
{
|
||||
<span class="text-success small ms-2" data-test="verify-success">
|
||||
✓ Endpoint reachable
|
||||
</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="text-danger small ms-2" data-test="verify-failure">
|
||||
@result.FailureKind: @result.Error
|
||||
</span>
|
||||
}
|
||||
|
||||
@if (result.FailureKind == VerifyFailureKind.UntrustedCertificate
|
||||
&& result.Cert is { } cert)
|
||||
{
|
||||
<div class="border rounded bg-light p-2 mt-2 small" data-test="verify-cert-panel">
|
||||
<div class="text-muted mb-1">Untrusted server certificate</div>
|
||||
<dl class="row mb-1 small">
|
||||
<dt class="col-sm-3">Subject</dt>
|
||||
<dd class="col-sm-9"><code>@cert.Subject</code></dd>
|
||||
<dt class="col-sm-3">Issuer</dt>
|
||||
<dd class="col-sm-9"><code>@cert.Issuer</code></dd>
|
||||
<dt class="col-sm-3">Thumbprint</dt>
|
||||
<dd class="col-sm-9"><code>@cert.Thumbprint</code></dd>
|
||||
<dt class="col-sm-3">Not before</dt>
|
||||
<dd class="col-sm-9">@cert.NotBeforeUtc.ToString("u")</dd>
|
||||
<dt class="col-sm-3">Not after</dt>
|
||||
<dd class="col-sm-9">@cert.NotAfterUtc.ToString("u")</dd>
|
||||
</dl>
|
||||
<div class="text-muted fst-italic">
|
||||
Use cert management to trust this certificate.
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="text-muted small mt-2 mb-1">Authentication</div>
|
||||
@if (Config.UserIdentity is null)
|
||||
{
|
||||
@@ -253,6 +312,37 @@
|
||||
[Parameter] public bool IsLegacy { get; set; }
|
||||
[Parameter] public ValidationResult? Errors { get; set; }
|
||||
|
||||
// Verify-endpoint context (M7 T17): the site + connection identity the verify
|
||||
// probe targets. Supplied by DataConnectionForm (_formSiteId → SiteIdentifier,
|
||||
// _formName, _protocol). When SiteIdentifier is blank the connection has not been
|
||||
// assigned a site yet, so verification is unavailable.
|
||||
[Parameter] public string SiteIdentifier { get; set; } = string.Empty;
|
||||
[Parameter] public string ConnectionName { get; set; } = string.Empty;
|
||||
[Parameter] public string Protocol { get; set; } = "OpcUa";
|
||||
|
||||
private bool _verifying;
|
||||
private VerifyEndpointResult? _verifyResult;
|
||||
|
||||
private async Task VerifyEndpoint()
|
||||
{
|
||||
_verifying = true;
|
||||
_verifyResult = null;
|
||||
try
|
||||
{
|
||||
_verifyResult = await VerificationService.VerifyAsync(
|
||||
SiteIdentifier, ConnectionName, Protocol, Config);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_verifyResult = new VerifyEndpointResult(
|
||||
false, VerifyFailureKind.ServerError, ex.Message, null);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_verifying = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnableHeartbeat() =>
|
||||
Config.Heartbeat = new OpcUaHeartbeatConfig();
|
||||
|
||||
|
||||
@@ -86,6 +86,9 @@
|
||||
IdPrefix="primary"
|
||||
Config="_primaryConfig"
|
||||
IsLegacy="_primaryIsLegacy"
|
||||
SiteIdentifier="@_formSiteIdentifier"
|
||||
ConnectionName="@_formName"
|
||||
Protocol="@_protocol"
|
||||
Errors="_primaryErrors" />
|
||||
}
|
||||
|
||||
@@ -118,6 +121,9 @@
|
||||
IdPrefix="backup"
|
||||
Config="_backupConfig"
|
||||
IsLegacy="_backupIsLegacy"
|
||||
SiteIdentifier="@_formSiteIdentifier"
|
||||
ConnectionName="@_formName"
|
||||
Protocol="@_protocol"
|
||||
Errors="_backupErrors" />
|
||||
}
|
||||
<div class="mb-2">
|
||||
@@ -170,6 +176,13 @@
|
||||
private ValidationResult? _backupErrors;
|
||||
private string? _formError;
|
||||
|
||||
// The machine-readable site identifier (used in Akka addresses) for the currently
|
||||
// selected site — resolved from _formSiteId (the numeric primary key) so the
|
||||
// endpoint editor's Verify probe can target the owning site. Blank until a site is
|
||||
// chosen, which disables verification in the editor.
|
||||
private string _formSiteIdentifier =>
|
||||
_sites.FirstOrDefault(s => s.Id == _formSiteId)?.SiteIdentifier ?? string.Empty;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
|
||||
Reference in New Issue
Block a user