Resolve all 46 low-severity architecture review findings
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using ZB.MOM.WW.ScadaBridge.CentralUI.Auth;
|
||||
using ZB.MOM.WW.ScadaBridge.Security;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Services;
|
||||
|
||||
/// <summary>Scoped application boundary that checks current circuit authority before host failover.</summary>
|
||||
public sealed class AuthorizedManualFailoverService(AuthenticationStateProvider auth, IManualFailoverService backend)
|
||||
{
|
||||
/// <summary>Fails over central only for a currently authorized administrator.</summary>
|
||||
public async Task<string?> FailOverCentralAsync()
|
||||
=> await backend.FailOverCentralAsync(await auth.RequireRoleAsync(Roles.Administrator));
|
||||
|
||||
/// <summary>Fails over a site only for a currently authorized administrator.</summary>
|
||||
public async Task<SiteFailoverOutcome> FailOverSiteAsync(string siteId)
|
||||
=> await backend.FailOverSiteAsync(siteId, await auth.RequireRoleAsync(Roles.Administrator));
|
||||
}
|
||||
@@ -84,6 +84,7 @@ public sealed class FlowDebugService : IFlowDebugService
|
||||
private readonly ManagementActorHolder _holder;
|
||||
private readonly AuthenticationStateProvider _auth;
|
||||
private readonly IInboundApiRepository _inboundApi;
|
||||
private readonly ISiteRepository _sites;
|
||||
private readonly ITemplateEngineRepository _templates;
|
||||
private readonly IFlatteningPipeline _pipeline;
|
||||
private readonly CommunicationService _comms;
|
||||
@@ -116,8 +117,10 @@ public sealed class FlowDebugService : IFlowDebugService
|
||||
ITemplateEngineRepository templates,
|
||||
IFlatteningPipeline pipeline,
|
||||
CommunicationService comms,
|
||||
ILogger<FlowDebugService> logger)
|
||||
ILogger<FlowDebugService> logger,
|
||||
ISiteRepository sites)
|
||||
{
|
||||
_sites = sites ?? throw new ArgumentNullException(nameof(sites));
|
||||
_holder = holder ?? throw new ArgumentNullException(nameof(holder));
|
||||
_auth = auth ?? throw new ArgumentNullException(nameof(auth));
|
||||
_inboundApi = inboundApi ?? throw new ArgumentNullException(nameof(inboundApi));
|
||||
@@ -322,6 +325,13 @@ public sealed class FlowDebugService : IFlowDebugService
|
||||
}
|
||||
|
||||
var site = step.SiteId!;
|
||||
var scope = new SiteScopeService(_auth);
|
||||
if (!await scope.IsSystemWideAsync())
|
||||
{
|
||||
var owner = (await _sites.GetAllSitesAsync(ct)).FirstOrDefault(s => s.SiteIdentifier == site);
|
||||
if (owner is null || !await scope.IsSiteAllowedAsync(owner.Id))
|
||||
return new(false, "You are not permitted to act on cached calls for this site.");
|
||||
}
|
||||
SiteCallRelayOutcome outcome;
|
||||
bool siteReachable;
|
||||
string? errorMessage;
|
||||
|
||||
@@ -12,6 +12,15 @@ public sealed class PollGate
|
||||
/// may proceed; <see langword="false"/> if a previous refresh is still running.</returns>
|
||||
public bool TryEnter() => Interlocked.CompareExchange(ref _inFlight, 1, 0) == 0;
|
||||
|
||||
/// <summary>Runs and observes a posted refresh, releasing the gate even if dispatch is rejected.</summary>
|
||||
public async Task RunAsync(Func<Task> dispatch, Action<Exception> onError)
|
||||
{
|
||||
if (!TryEnter()) return;
|
||||
try { await dispatch().ConfigureAwait(false); }
|
||||
catch (Exception error) { onError(error); }
|
||||
finally { Exit(); }
|
||||
}
|
||||
|
||||
/// <summary>Releases the gate after a poll tick's refresh has completed.</summary>
|
||||
public void Exit() => Volatile.Write(ref _inFlight, 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user