fix(central-ui): resolve CentralUI-002/003/004 — site-scope enforcement, per-circuit console capture, cached auth state
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
@using ScadaLink.Commons.Messages.RemoteQuery
|
||||
@using ScadaLink.Communication
|
||||
@inject ISiteRepository SiteRepository
|
||||
@inject ScadaLink.CentralUI.Auth.SiteScopeService SiteScope
|
||||
@inject CommunicationService CommunicationService
|
||||
|
||||
<div class="container-fluid mt-3">
|
||||
@@ -212,9 +213,16 @@
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_sites = (await SiteRepository.GetAllSitesAsync()).ToList();
|
||||
// Site scoping (CentralUI-002): a scoped Deployment user may only query
|
||||
// event logs for the sites they are permitted on.
|
||||
_sites = await SiteScope.FilterSitesAsync(await SiteRepository.GetAllSitesAsync());
|
||||
}
|
||||
|
||||
// _sites is already filtered, so membership IS the scope check.
|
||||
private bool SelectedSiteIsPermitted =>
|
||||
!string.IsNullOrEmpty(_selectedSiteId)
|
||||
&& _sites.Any(s => s.SiteIdentifier == _selectedSiteId);
|
||||
|
||||
private async Task Search()
|
||||
{
|
||||
_entries = new();
|
||||
@@ -237,6 +245,14 @@
|
||||
{
|
||||
_searching = true;
|
||||
_errorMessage = null;
|
||||
// Site scoping (CentralUI-002): re-check before querying — the dropdown is
|
||||
// filtered, but the selection must not be trusted on its own.
|
||||
if (!SelectedSiteIsPermitted)
|
||||
{
|
||||
_errorMessage = "You are not permitted to view event logs for that site.";
|
||||
_searching = false;
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
var request = new EventLogQueryRequest(
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
@using ScadaLink.Commons.Types.Enums
|
||||
@using ScadaLink.Communication
|
||||
@inject ISiteRepository SiteRepository
|
||||
@inject ScadaLink.CentralUI.Auth.SiteScopeService SiteScope
|
||||
@inject CommunicationService CommunicationService
|
||||
@inject IJSRuntime JS
|
||||
@inject IDialogService Dialog
|
||||
@@ -360,9 +361,17 @@
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_sites = (await SiteRepository.GetAllSitesAsync()).ToList();
|
||||
// Site scoping (CentralUI-002): a scoped Deployment user may only inspect
|
||||
// and act on parked messages for the sites they are permitted on.
|
||||
_sites = await SiteScope.FilterSitesAsync(await SiteRepository.GetAllSitesAsync());
|
||||
}
|
||||
|
||||
// True only when the currently selected SiteIdentifier is one this user is
|
||||
// permitted on. _sites is already filtered, so membership IS the scope check.
|
||||
private bool SelectedSiteIsPermitted =>
|
||||
!string.IsNullOrEmpty(_selectedSiteId)
|
||||
&& _sites.Any(s => s.SiteIdentifier == _selectedSiteId);
|
||||
|
||||
private async Task OnSiteChanged(ChangeEventArgs e)
|
||||
{
|
||||
_selectedSiteId = e.Value?.ToString() ?? string.Empty;
|
||||
@@ -393,6 +402,15 @@
|
||||
{
|
||||
_searching = true;
|
||||
_errorMessage = null;
|
||||
// Site scoping (CentralUI-002): re-check before querying — the dropdown is
|
||||
// filtered, but the selection must not be trusted on its own.
|
||||
if (!SelectedSiteIsPermitted)
|
||||
{
|
||||
_errorMessage = "You are not permitted to view parked messages for that site.";
|
||||
_messages = null;
|
||||
_searching = false;
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
var request = new ParkedMessageQueryRequest(
|
||||
@@ -557,6 +575,7 @@
|
||||
{
|
||||
var ids = _selectedIds.ToList();
|
||||
if (ids.Count == 0) return;
|
||||
if (!SelectedSiteIsPermitted) { _toast.ShowError("Not permitted for this site."); return; }
|
||||
|
||||
var confirmed = await Dialog.ConfirmAsync(
|
||||
"Retry parked messages",
|
||||
@@ -587,6 +606,7 @@
|
||||
{
|
||||
var ids = _selectedIds.ToList();
|
||||
if (ids.Count == 0) return;
|
||||
if (!SelectedSiteIsPermitted) { _toast.ShowError("Not permitted for this site."); return; }
|
||||
|
||||
var confirmed = await Dialog.ConfirmAsync(
|
||||
"Discard parked messages",
|
||||
@@ -618,6 +638,7 @@
|
||||
|
||||
private async Task RetrySingle(ParkedMessageEntry msg)
|
||||
{
|
||||
if (!SelectedSiteIsPermitted) { _toast.ShowError("Not permitted for this site."); return; }
|
||||
_actionInProgress = true;
|
||||
_activeAction = "Retry";
|
||||
try
|
||||
@@ -638,6 +659,7 @@
|
||||
|
||||
private async Task<bool> DiscardSingle(ParkedMessageEntry msg)
|
||||
{
|
||||
if (!SelectedSiteIsPermitted) { _toast.ShowError("Not permitted for this site."); return false; }
|
||||
var confirmed = await Dialog.ConfirmAsync(
|
||||
"Discard parked message",
|
||||
$"Permanently discard message {ShortId(msg.MessageId)}? This cannot be undone.",
|
||||
|
||||
Reference in New Issue
Block a user