eb8ead58d2
Add SiteReplicationActor (runs on every site node) to replicate deployed configs and store-and-forward buffer operations to the standby peer via cluster member discovery and fire-and-forget Tell. Wire ReplicationService handler and pass replication actor to DeploymentManagerActor singleton. Fix 5 pre-existing ConfigurationDatabase test failures: RowVersion NOT NULL on SQLite, stale migration name assertion, and seed data count mismatch.
1187 lines
54 KiB
C#
1187 lines
54 KiB
C#
using System.Security.Cryptography;
|
|
using Akka.Actor;
|
|
using Newtonsoft.Json;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging;
|
|
using ScadaLink.Commons.Entities.ExternalSystems;
|
|
using ScadaLink.Commons.Entities.InboundApi;
|
|
using ScadaLink.Commons.Entities.Instances;
|
|
using ScadaLink.Commons.Entities.Scripts;
|
|
using ScadaLink.Commons.Entities.Templates;
|
|
using ScadaLink.Commons.Entities.Notifications;
|
|
using ScadaLink.Commons.Entities.Security;
|
|
using ScadaLink.Commons.Entities.Sites;
|
|
using ScadaLink.Commons.Interfaces.Repositories;
|
|
using ScadaLink.Commons.Messages.DebugView;
|
|
using ScadaLink.Commons.Messages.Management;
|
|
using ScadaLink.Commons.Messages.RemoteQuery;
|
|
using ScadaLink.DeploymentManager;
|
|
using ScadaLink.HealthMonitoring;
|
|
using ScadaLink.Communication;
|
|
using ScadaLink.TemplateEngine;
|
|
using ScadaLink.TemplateEngine.Services;
|
|
|
|
namespace ScadaLink.ManagementService;
|
|
|
|
/// <summary>
|
|
/// Central actor that handles all management commands from the CLI (via ClusterClient).
|
|
/// Receives ManagementEnvelope messages, authorizes based on roles, then delegates to
|
|
/// the appropriate service or repository using scoped DI.
|
|
/// </summary>
|
|
public class ManagementActor : ReceiveActor
|
|
{
|
|
private readonly IServiceProvider _serviceProvider;
|
|
private readonly ILogger<ManagementActor> _logger;
|
|
|
|
public ManagementActor(IServiceProvider serviceProvider, ILogger<ManagementActor> logger)
|
|
{
|
|
_serviceProvider = serviceProvider;
|
|
_logger = logger;
|
|
Receive<ManagementEnvelope>(HandleEnvelope);
|
|
}
|
|
|
|
private void HandleEnvelope(ManagementEnvelope envelope)
|
|
{
|
|
var sender = Sender;
|
|
var correlationId = envelope.CorrelationId;
|
|
var user = envelope.User;
|
|
|
|
// Check authorization
|
|
var requiredRole = GetRequiredRole(envelope.Command);
|
|
if (requiredRole != null && !user.Roles.Contains(requiredRole, StringComparer.OrdinalIgnoreCase))
|
|
{
|
|
sender.Tell(new ManagementUnauthorized(correlationId,
|
|
$"Role '{requiredRole}' required for {envelope.Command.GetType().Name}"));
|
|
return;
|
|
}
|
|
|
|
// Process command asynchronously with scoped DI
|
|
Task.Run(async () =>
|
|
{
|
|
using var scope = _serviceProvider.CreateScope();
|
|
try
|
|
{
|
|
var result = await DispatchCommand(scope.ServiceProvider, envelope.Command, user.Username);
|
|
var json = JsonConvert.SerializeObject(result, Formatting.None);
|
|
sender.Tell(new ManagementSuccess(correlationId, json));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Management command {Command} failed (CorrelationId={CorrelationId})",
|
|
envelope.Command.GetType().Name, correlationId);
|
|
sender.Tell(new ManagementError(correlationId, ex.Message, "COMMAND_FAILED"));
|
|
}
|
|
});
|
|
}
|
|
|
|
private static string? GetRequiredRole(object command) => command switch
|
|
{
|
|
// Admin operations
|
|
CreateSiteCommand or UpdateSiteCommand or DeleteSiteCommand
|
|
or ListRoleMappingsCommand or CreateRoleMappingCommand
|
|
or UpdateRoleMappingCommand or DeleteRoleMappingCommand
|
|
or ListApiKeysCommand or CreateApiKeyCommand or DeleteApiKeyCommand
|
|
or UpdateApiKeyCommand
|
|
or ListScopeRulesCommand or AddScopeRuleCommand or DeleteScopeRuleCommand => "Admin",
|
|
|
|
// Design operations
|
|
CreateAreaCommand or DeleteAreaCommand
|
|
or CreateTemplateCommand or UpdateTemplateCommand or DeleteTemplateCommand
|
|
or ValidateTemplateCommand
|
|
or CreateExternalSystemCommand or UpdateExternalSystemCommand
|
|
or DeleteExternalSystemCommand
|
|
or CreateExternalSystemMethodCommand or UpdateExternalSystemMethodCommand
|
|
or DeleteExternalSystemMethodCommand
|
|
or CreateNotificationListCommand or UpdateNotificationListCommand
|
|
or DeleteNotificationListCommand
|
|
or UpdateSmtpConfigCommand
|
|
or CreateDataConnectionCommand or UpdateDataConnectionCommand
|
|
or DeleteDataConnectionCommand
|
|
or AssignDataConnectionToSiteCommand
|
|
or UnassignDataConnectionFromSiteCommand
|
|
or AddTemplateAttributeCommand or UpdateTemplateAttributeCommand or DeleteTemplateAttributeCommand
|
|
or AddTemplateAlarmCommand or UpdateTemplateAlarmCommand or DeleteTemplateAlarmCommand
|
|
or AddTemplateScriptCommand or UpdateTemplateScriptCommand or DeleteTemplateScriptCommand
|
|
or AddTemplateCompositionCommand or DeleteTemplateCompositionCommand
|
|
or CreateSharedScriptCommand or UpdateSharedScriptCommand or DeleteSharedScriptCommand
|
|
or CreateDatabaseConnectionDefCommand or UpdateDatabaseConnectionDefCommand or DeleteDatabaseConnectionDefCommand
|
|
or CreateApiMethodCommand or UpdateApiMethodCommand or DeleteApiMethodCommand
|
|
or UpdateAreaCommand => "Design",
|
|
|
|
// Deployment operations
|
|
CreateInstanceCommand or MgmtDeployInstanceCommand or MgmtEnableInstanceCommand
|
|
or MgmtDisableInstanceCommand or MgmtDeleteInstanceCommand
|
|
or SetConnectionBindingsCommand
|
|
or MgmtDeployArtifactsCommand
|
|
or DebugSnapshotCommand => "Deployment",
|
|
|
|
// Read-only queries -- any authenticated user
|
|
_ => null
|
|
};
|
|
|
|
private async Task<object?> DispatchCommand(IServiceProvider sp, object command, string user)
|
|
{
|
|
return command switch
|
|
{
|
|
// Templates
|
|
ListTemplatesCommand => await HandleListTemplates(sp),
|
|
GetTemplateCommand cmd => await HandleGetTemplate(sp, cmd),
|
|
CreateTemplateCommand cmd => await HandleCreateTemplate(sp, cmd, user),
|
|
UpdateTemplateCommand cmd => await HandleUpdateTemplate(sp, cmd, user),
|
|
DeleteTemplateCommand cmd => await HandleDeleteTemplate(sp, cmd, user),
|
|
ValidateTemplateCommand cmd => await HandleValidateTemplate(sp, cmd),
|
|
|
|
// Template members
|
|
AddTemplateAttributeCommand cmd => await HandleAddAttribute(sp, cmd, user),
|
|
UpdateTemplateAttributeCommand cmd => await HandleUpdateAttribute(sp, cmd, user),
|
|
DeleteTemplateAttributeCommand cmd => await HandleDeleteAttribute(sp, cmd, user),
|
|
AddTemplateAlarmCommand cmd => await HandleAddAlarm(sp, cmd, user),
|
|
UpdateTemplateAlarmCommand cmd => await HandleUpdateAlarm(sp, cmd, user),
|
|
DeleteTemplateAlarmCommand cmd => await HandleDeleteAlarm(sp, cmd, user),
|
|
AddTemplateScriptCommand cmd => await HandleAddScript(sp, cmd, user),
|
|
UpdateTemplateScriptCommand cmd => await HandleUpdateScript(sp, cmd, user),
|
|
DeleteTemplateScriptCommand cmd => await HandleDeleteScript(sp, cmd, user),
|
|
AddTemplateCompositionCommand cmd => await HandleAddComposition(sp, cmd, user),
|
|
DeleteTemplateCompositionCommand cmd => await HandleDeleteComposition(sp, cmd, user),
|
|
|
|
// Instances
|
|
ListInstancesCommand cmd => await HandleListInstances(sp, cmd),
|
|
GetInstanceCommand cmd => await HandleGetInstance(sp, cmd),
|
|
CreateInstanceCommand cmd => await HandleCreateInstance(sp, cmd, user),
|
|
MgmtDeployInstanceCommand cmd => await HandleDeployInstance(sp, cmd, user),
|
|
MgmtEnableInstanceCommand cmd => await HandleEnableInstance(sp, cmd, user),
|
|
MgmtDisableInstanceCommand cmd => await HandleDisableInstance(sp, cmd, user),
|
|
MgmtDeleteInstanceCommand cmd => await HandleDeleteInstance(sp, cmd, user),
|
|
SetConnectionBindingsCommand cmd => await HandleSetConnectionBindings(sp, cmd, user),
|
|
|
|
// Sites
|
|
ListSitesCommand => await HandleListSites(sp),
|
|
GetSiteCommand cmd => await HandleGetSite(sp, cmd),
|
|
CreateSiteCommand cmd => await HandleCreateSite(sp, cmd),
|
|
UpdateSiteCommand cmd => await HandleUpdateSite(sp, cmd),
|
|
DeleteSiteCommand cmd => await HandleDeleteSite(sp, cmd),
|
|
ListAreasCommand cmd => await HandleListAreas(sp, cmd),
|
|
CreateAreaCommand cmd => await HandleCreateArea(sp, cmd),
|
|
DeleteAreaCommand cmd => await HandleDeleteArea(sp, cmd),
|
|
UpdateAreaCommand cmd => await HandleUpdateArea(sp, cmd),
|
|
|
|
// Data Connections
|
|
ListDataConnectionsCommand => await HandleListDataConnections(sp),
|
|
GetDataConnectionCommand cmd => await HandleGetDataConnection(sp, cmd),
|
|
CreateDataConnectionCommand cmd => await HandleCreateDataConnection(sp, cmd),
|
|
UpdateDataConnectionCommand cmd => await HandleUpdateDataConnection(sp, cmd),
|
|
DeleteDataConnectionCommand cmd => await HandleDeleteDataConnection(sp, cmd),
|
|
AssignDataConnectionToSiteCommand cmd => await HandleAssignDataConnectionToSite(sp, cmd),
|
|
UnassignDataConnectionFromSiteCommand cmd => await HandleUnassignDataConnectionFromSite(sp, cmd),
|
|
|
|
// External Systems
|
|
ListExternalSystemsCommand => await HandleListExternalSystems(sp),
|
|
GetExternalSystemCommand cmd => await HandleGetExternalSystem(sp, cmd),
|
|
CreateExternalSystemCommand cmd => await HandleCreateExternalSystem(sp, cmd),
|
|
UpdateExternalSystemCommand cmd => await HandleUpdateExternalSystem(sp, cmd),
|
|
DeleteExternalSystemCommand cmd => await HandleDeleteExternalSystem(sp, cmd),
|
|
ListExternalSystemMethodsCommand cmd => await HandleListExternalSystemMethods(sp, cmd),
|
|
GetExternalSystemMethodCommand cmd => await HandleGetExternalSystemMethod(sp, cmd),
|
|
CreateExternalSystemMethodCommand cmd => await HandleCreateExternalSystemMethod(sp, cmd),
|
|
UpdateExternalSystemMethodCommand cmd => await HandleUpdateExternalSystemMethod(sp, cmd),
|
|
DeleteExternalSystemMethodCommand cmd => await HandleDeleteExternalSystemMethod(sp, cmd),
|
|
|
|
// Notification Lists
|
|
ListNotificationListsCommand => await HandleListNotificationLists(sp),
|
|
GetNotificationListCommand cmd => await HandleGetNotificationList(sp, cmd),
|
|
CreateNotificationListCommand cmd => await HandleCreateNotificationList(sp, cmd),
|
|
UpdateNotificationListCommand cmd => await HandleUpdateNotificationList(sp, cmd),
|
|
DeleteNotificationListCommand cmd => await HandleDeleteNotificationList(sp, cmd),
|
|
ListSmtpConfigsCommand => await HandleListSmtpConfigs(sp),
|
|
UpdateSmtpConfigCommand cmd => await HandleUpdateSmtpConfig(sp, cmd),
|
|
|
|
// Shared Scripts
|
|
ListSharedScriptsCommand => await HandleListSharedScripts(sp),
|
|
GetSharedScriptCommand cmd => await HandleGetSharedScript(sp, cmd),
|
|
CreateSharedScriptCommand cmd => await HandleCreateSharedScript(sp, cmd, user),
|
|
UpdateSharedScriptCommand cmd => await HandleUpdateSharedScript(sp, cmd, user),
|
|
DeleteSharedScriptCommand cmd => await HandleDeleteSharedScript(sp, cmd, user),
|
|
|
|
// Database Connections (External System)
|
|
ListDatabaseConnectionsCommand => await HandleListDatabaseConnections(sp),
|
|
GetDatabaseConnectionCommand cmd => await HandleGetDatabaseConnection(sp, cmd),
|
|
CreateDatabaseConnectionDefCommand cmd => await HandleCreateDatabaseConnection(sp, cmd),
|
|
UpdateDatabaseConnectionDefCommand cmd => await HandleUpdateDatabaseConnection(sp, cmd),
|
|
DeleteDatabaseConnectionDefCommand cmd => await HandleDeleteDatabaseConnection(sp, cmd),
|
|
|
|
// Inbound API Methods
|
|
ListApiMethodsCommand => await HandleListApiMethods(sp),
|
|
GetApiMethodCommand cmd => await HandleGetApiMethod(sp, cmd),
|
|
CreateApiMethodCommand cmd => await HandleCreateApiMethod(sp, cmd),
|
|
UpdateApiMethodCommand cmd => await HandleUpdateApiMethod(sp, cmd),
|
|
DeleteApiMethodCommand cmd => await HandleDeleteApiMethod(sp, cmd),
|
|
|
|
// Security
|
|
ListRoleMappingsCommand => await HandleListRoleMappings(sp),
|
|
CreateRoleMappingCommand cmd => await HandleCreateRoleMapping(sp, cmd),
|
|
UpdateRoleMappingCommand cmd => await HandleUpdateRoleMapping(sp, cmd),
|
|
DeleteRoleMappingCommand cmd => await HandleDeleteRoleMapping(sp, cmd),
|
|
ListApiKeysCommand => await HandleListApiKeys(sp),
|
|
CreateApiKeyCommand cmd => await HandleCreateApiKey(sp, cmd),
|
|
DeleteApiKeyCommand cmd => await HandleDeleteApiKey(sp, cmd),
|
|
UpdateApiKeyCommand cmd => await HandleUpdateApiKey(sp, cmd),
|
|
ListScopeRulesCommand cmd => await HandleListScopeRules(sp, cmd),
|
|
AddScopeRuleCommand cmd => await HandleAddScopeRule(sp, cmd),
|
|
DeleteScopeRuleCommand cmd => await HandleDeleteScopeRule(sp, cmd),
|
|
|
|
// Deployments
|
|
MgmtDeployArtifactsCommand cmd => await HandleDeployArtifacts(sp, cmd, user),
|
|
QueryDeploymentsCommand cmd => await HandleQueryDeployments(sp, cmd),
|
|
|
|
// Audit Log
|
|
QueryAuditLogCommand cmd => await HandleQueryAuditLog(sp, cmd),
|
|
|
|
// Health
|
|
GetHealthSummaryCommand => HandleGetHealthSummary(sp),
|
|
GetSiteHealthCommand cmd => HandleGetSiteHealth(sp, cmd),
|
|
|
|
// Remote Queries
|
|
QueryEventLogsCommand cmd => await HandleQueryEventLogs(sp, cmd),
|
|
QueryParkedMessagesCommand cmd => await HandleQueryParkedMessages(sp, cmd),
|
|
DebugSnapshotCommand cmd => await HandleDebugSnapshot(sp, cmd),
|
|
|
|
_ => throw new NotSupportedException($"Unknown command type: {command.GetType().Name}")
|
|
};
|
|
}
|
|
|
|
// ========================================================================
|
|
// Template handlers
|
|
// ========================================================================
|
|
|
|
private static async Task<object?> HandleListTemplates(IServiceProvider sp)
|
|
{
|
|
var repo = sp.GetRequiredService<ITemplateEngineRepository>();
|
|
return await repo.GetAllTemplatesAsync();
|
|
}
|
|
|
|
private static async Task<object?> HandleGetTemplate(IServiceProvider sp, GetTemplateCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ITemplateEngineRepository>();
|
|
return await repo.GetTemplateWithChildrenAsync(cmd.TemplateId);
|
|
}
|
|
|
|
private static async Task<object?> HandleCreateTemplate(IServiceProvider sp, CreateTemplateCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<TemplateService>();
|
|
var result = await svc.CreateTemplateAsync(cmd.Name, cmd.Description, cmd.ParentTemplateId, user);
|
|
return result.IsSuccess
|
|
? result.Value
|
|
: throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleUpdateTemplate(IServiceProvider sp, UpdateTemplateCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<TemplateService>();
|
|
var result = await svc.UpdateTemplateAsync(cmd.TemplateId, cmd.Name, cmd.Description, cmd.ParentTemplateId, user);
|
|
return result.IsSuccess
|
|
? result.Value
|
|
: throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteTemplate(IServiceProvider sp, DeleteTemplateCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<TemplateService>();
|
|
var result = await svc.DeleteTemplateAsync(cmd.TemplateId, user);
|
|
return result.IsSuccess
|
|
? result.Value
|
|
: throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleValidateTemplate(IServiceProvider sp, ValidateTemplateCommand cmd)
|
|
{
|
|
var svc = sp.GetRequiredService<TemplateService>();
|
|
return await svc.DetectCollisionsAsync(cmd.TemplateId);
|
|
}
|
|
|
|
// ========================================================================
|
|
// Instance handlers
|
|
// ========================================================================
|
|
|
|
private static async Task<object?> HandleListInstances(IServiceProvider sp, ListInstancesCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ICentralUiRepository>();
|
|
return await repo.GetInstancesFilteredAsync(cmd.SiteId, cmd.TemplateId, cmd.SearchTerm);
|
|
}
|
|
|
|
private static async Task<object?> HandleGetInstance(IServiceProvider sp, GetInstanceCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ITemplateEngineRepository>();
|
|
return await repo.GetInstanceByIdAsync(cmd.InstanceId);
|
|
}
|
|
|
|
private static async Task<object?> HandleCreateInstance(IServiceProvider sp, CreateInstanceCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<InstanceService>();
|
|
var result = await svc.CreateInstanceAsync(cmd.UniqueName, cmd.TemplateId, cmd.SiteId, cmd.AreaId, user);
|
|
return result.IsSuccess
|
|
? result.Value
|
|
: throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleDeployInstance(IServiceProvider sp, MgmtDeployInstanceCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<DeploymentService>();
|
|
var result = await svc.DeployInstanceAsync(cmd.InstanceId, user);
|
|
return result.IsSuccess
|
|
? result.Value
|
|
: throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleEnableInstance(IServiceProvider sp, MgmtEnableInstanceCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<DeploymentService>();
|
|
var result = await svc.EnableInstanceAsync(cmd.InstanceId, user);
|
|
return result.IsSuccess
|
|
? result.Value
|
|
: throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleDisableInstance(IServiceProvider sp, MgmtDisableInstanceCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<DeploymentService>();
|
|
var result = await svc.DisableInstanceAsync(cmd.InstanceId, user);
|
|
return result.IsSuccess
|
|
? result.Value
|
|
: throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteInstance(IServiceProvider sp, MgmtDeleteInstanceCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<DeploymentService>();
|
|
var result = await svc.DeleteInstanceAsync(cmd.InstanceId, user);
|
|
return result.IsSuccess
|
|
? result.Value
|
|
: throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleSetConnectionBindings(IServiceProvider sp, SetConnectionBindingsCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<InstanceService>();
|
|
var result = await svc.SetConnectionBindingsAsync(cmd.InstanceId, cmd.Bindings, user);
|
|
return result.IsSuccess
|
|
? result.Value
|
|
: throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
// ========================================================================
|
|
// Site handlers
|
|
// ========================================================================
|
|
|
|
private static async Task<object?> HandleListSites(IServiceProvider sp)
|
|
{
|
|
var repo = sp.GetRequiredService<ISiteRepository>();
|
|
return await repo.GetAllSitesAsync();
|
|
}
|
|
|
|
private static async Task<object?> HandleGetSite(IServiceProvider sp, GetSiteCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ISiteRepository>();
|
|
return await repo.GetSiteByIdAsync(cmd.SiteId);
|
|
}
|
|
|
|
private static async Task<object?> HandleCreateSite(IServiceProvider sp, CreateSiteCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ISiteRepository>();
|
|
var site = new Site(cmd.Name, cmd.SiteIdentifier)
|
|
{
|
|
Description = cmd.Description,
|
|
NodeAAddress = cmd.NodeAAddress,
|
|
NodeBAddress = cmd.NodeBAddress
|
|
};
|
|
await repo.AddSiteAsync(site);
|
|
await repo.SaveChangesAsync();
|
|
var commService = sp.GetService<CommunicationService>();
|
|
commService?.RefreshSiteAddresses();
|
|
return site;
|
|
}
|
|
|
|
private static async Task<object?> HandleUpdateSite(IServiceProvider sp, UpdateSiteCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ISiteRepository>();
|
|
var site = await repo.GetSiteByIdAsync(cmd.SiteId)
|
|
?? throw new InvalidOperationException($"Site with ID {cmd.SiteId} not found.");
|
|
site.Name = cmd.Name;
|
|
site.Description = cmd.Description;
|
|
site.NodeAAddress = cmd.NodeAAddress;
|
|
site.NodeBAddress = cmd.NodeBAddress;
|
|
await repo.UpdateSiteAsync(site);
|
|
await repo.SaveChangesAsync();
|
|
var commService = sp.GetService<CommunicationService>();
|
|
commService?.RefreshSiteAddresses();
|
|
return site;
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteSite(IServiceProvider sp, DeleteSiteCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ISiteRepository>();
|
|
// Check for instances referencing this site
|
|
var instances = await repo.GetInstancesBySiteIdAsync(cmd.SiteId);
|
|
if (instances.Count > 0)
|
|
throw new InvalidOperationException(
|
|
$"Cannot delete site {cmd.SiteId}: it has {instances.Count} instance(s).");
|
|
await repo.DeleteSiteAsync(cmd.SiteId);
|
|
await repo.SaveChangesAsync();
|
|
var commService = sp.GetService<CommunicationService>();
|
|
commService?.RefreshSiteAddresses();
|
|
return true;
|
|
}
|
|
|
|
private static async Task<object?> HandleListAreas(IServiceProvider sp, ListAreasCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ICentralUiRepository>();
|
|
return await repo.GetAreaTreeBySiteIdAsync(cmd.SiteId);
|
|
}
|
|
|
|
private static async Task<object?> HandleCreateArea(IServiceProvider sp, CreateAreaCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ITemplateEngineRepository>();
|
|
var area = new Area(cmd.Name)
|
|
{
|
|
SiteId = cmd.SiteId,
|
|
ParentAreaId = cmd.ParentAreaId
|
|
};
|
|
await repo.AddAreaAsync(area);
|
|
await repo.SaveChangesAsync();
|
|
return area;
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteArea(IServiceProvider sp, DeleteAreaCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ITemplateEngineRepository>();
|
|
await repo.DeleteAreaAsync(cmd.AreaId);
|
|
await repo.SaveChangesAsync();
|
|
return true;
|
|
}
|
|
|
|
// ========================================================================
|
|
// Data Connection handlers
|
|
// ========================================================================
|
|
|
|
private static async Task<object?> HandleListDataConnections(IServiceProvider sp)
|
|
{
|
|
var repo = sp.GetRequiredService<ISiteRepository>();
|
|
return await repo.GetAllDataConnectionsAsync();
|
|
}
|
|
|
|
private static async Task<object?> HandleGetDataConnection(IServiceProvider sp, GetDataConnectionCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ISiteRepository>();
|
|
return await repo.GetDataConnectionByIdAsync(cmd.DataConnectionId);
|
|
}
|
|
|
|
private static async Task<object?> HandleCreateDataConnection(IServiceProvider sp, CreateDataConnectionCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ISiteRepository>();
|
|
var conn = new DataConnection(cmd.Name, cmd.Protocol) { Configuration = cmd.Configuration };
|
|
await repo.AddDataConnectionAsync(conn);
|
|
await repo.SaveChangesAsync();
|
|
return conn;
|
|
}
|
|
|
|
private static async Task<object?> HandleUpdateDataConnection(IServiceProvider sp, UpdateDataConnectionCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ISiteRepository>();
|
|
var conn = await repo.GetDataConnectionByIdAsync(cmd.DataConnectionId)
|
|
?? throw new InvalidOperationException($"DataConnection with ID {cmd.DataConnectionId} not found.");
|
|
conn.Name = cmd.Name;
|
|
conn.Protocol = cmd.Protocol;
|
|
conn.Configuration = cmd.Configuration;
|
|
await repo.UpdateDataConnectionAsync(conn);
|
|
await repo.SaveChangesAsync();
|
|
return conn;
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteDataConnection(IServiceProvider sp, DeleteDataConnectionCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ISiteRepository>();
|
|
await repo.DeleteDataConnectionAsync(cmd.DataConnectionId);
|
|
await repo.SaveChangesAsync();
|
|
return true;
|
|
}
|
|
|
|
private static async Task<object?> HandleAssignDataConnectionToSite(IServiceProvider sp, AssignDataConnectionToSiteCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ISiteRepository>();
|
|
var assignment = new SiteDataConnectionAssignment
|
|
{
|
|
SiteId = cmd.SiteId,
|
|
DataConnectionId = cmd.DataConnectionId
|
|
};
|
|
await repo.AddSiteDataConnectionAssignmentAsync(assignment);
|
|
await repo.SaveChangesAsync();
|
|
return assignment;
|
|
}
|
|
|
|
private static async Task<object?> HandleUnassignDataConnectionFromSite(IServiceProvider sp, UnassignDataConnectionFromSiteCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ISiteRepository>();
|
|
await repo.DeleteSiteDataConnectionAssignmentAsync(cmd.AssignmentId);
|
|
await repo.SaveChangesAsync();
|
|
return true;
|
|
}
|
|
|
|
// ========================================================================
|
|
// External System handlers
|
|
// ========================================================================
|
|
|
|
private static async Task<object?> HandleListExternalSystems(IServiceProvider sp)
|
|
{
|
|
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
|
return await repo.GetAllExternalSystemsAsync();
|
|
}
|
|
|
|
private static async Task<object?> HandleGetExternalSystem(IServiceProvider sp, GetExternalSystemCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
|
return await repo.GetExternalSystemByIdAsync(cmd.ExternalSystemId);
|
|
}
|
|
|
|
private static async Task<object?> HandleCreateExternalSystem(IServiceProvider sp, CreateExternalSystemCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
|
var def = new ExternalSystemDefinition(cmd.Name, cmd.EndpointUrl, cmd.AuthType)
|
|
{
|
|
AuthConfiguration = cmd.AuthConfiguration
|
|
};
|
|
await repo.AddExternalSystemAsync(def);
|
|
await repo.SaveChangesAsync();
|
|
return def;
|
|
}
|
|
|
|
private static async Task<object?> HandleUpdateExternalSystem(IServiceProvider sp, UpdateExternalSystemCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
|
var def = await repo.GetExternalSystemByIdAsync(cmd.ExternalSystemId)
|
|
?? throw new InvalidOperationException($"ExternalSystem with ID {cmd.ExternalSystemId} not found.");
|
|
def.Name = cmd.Name;
|
|
def.EndpointUrl = cmd.EndpointUrl;
|
|
def.AuthType = cmd.AuthType;
|
|
def.AuthConfiguration = cmd.AuthConfiguration;
|
|
await repo.UpdateExternalSystemAsync(def);
|
|
await repo.SaveChangesAsync();
|
|
return def;
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteExternalSystem(IServiceProvider sp, DeleteExternalSystemCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
|
await repo.DeleteExternalSystemAsync(cmd.ExternalSystemId);
|
|
await repo.SaveChangesAsync();
|
|
return true;
|
|
}
|
|
|
|
private static async Task<object?> HandleListExternalSystemMethods(IServiceProvider sp, ListExternalSystemMethodsCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
|
return await repo.GetMethodsByExternalSystemIdAsync(cmd.ExternalSystemId);
|
|
}
|
|
|
|
private static async Task<object?> HandleGetExternalSystemMethod(IServiceProvider sp, GetExternalSystemMethodCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
|
return await repo.GetExternalSystemMethodByIdAsync(cmd.MethodId);
|
|
}
|
|
|
|
private static async Task<object?> HandleCreateExternalSystemMethod(IServiceProvider sp, CreateExternalSystemMethodCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
|
var method = new ExternalSystemMethod(cmd.Name, cmd.HttpMethod, cmd.Path)
|
|
{
|
|
ExternalSystemDefinitionId = cmd.ExternalSystemId,
|
|
ParameterDefinitions = cmd.ParameterDefinitions,
|
|
ReturnDefinition = cmd.ReturnDefinition
|
|
};
|
|
await repo.AddExternalSystemMethodAsync(method);
|
|
await repo.SaveChangesAsync();
|
|
return method;
|
|
}
|
|
|
|
private static async Task<object?> HandleUpdateExternalSystemMethod(IServiceProvider sp, UpdateExternalSystemMethodCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
|
var method = await repo.GetExternalSystemMethodByIdAsync(cmd.MethodId)
|
|
?? throw new InvalidOperationException($"ExternalSystemMethod with ID {cmd.MethodId} not found.");
|
|
if (cmd.Name != null) method.Name = cmd.Name;
|
|
if (cmd.HttpMethod != null) method.HttpMethod = cmd.HttpMethod;
|
|
if (cmd.Path != null) method.Path = cmd.Path;
|
|
if (cmd.ParameterDefinitions != null) method.ParameterDefinitions = cmd.ParameterDefinitions;
|
|
if (cmd.ReturnDefinition != null) method.ReturnDefinition = cmd.ReturnDefinition;
|
|
await repo.UpdateExternalSystemMethodAsync(method);
|
|
await repo.SaveChangesAsync();
|
|
return method;
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteExternalSystemMethod(IServiceProvider sp, DeleteExternalSystemMethodCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
|
await repo.DeleteExternalSystemMethodAsync(cmd.MethodId);
|
|
await repo.SaveChangesAsync();
|
|
return true;
|
|
}
|
|
|
|
// ========================================================================
|
|
// Notification handlers
|
|
// ========================================================================
|
|
|
|
private static async Task<object?> HandleListNotificationLists(IServiceProvider sp)
|
|
{
|
|
var repo = sp.GetRequiredService<INotificationRepository>();
|
|
return await repo.GetAllNotificationListsAsync();
|
|
}
|
|
|
|
private static async Task<object?> HandleGetNotificationList(IServiceProvider sp, GetNotificationListCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<INotificationRepository>();
|
|
return await repo.GetNotificationListByIdAsync(cmd.NotificationListId);
|
|
}
|
|
|
|
private static async Task<object?> HandleCreateNotificationList(IServiceProvider sp, CreateNotificationListCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<INotificationRepository>();
|
|
var list = new NotificationList(cmd.Name);
|
|
foreach (var email in cmd.RecipientEmails)
|
|
{
|
|
list.Recipients.Add(new NotificationRecipient(email, email));
|
|
}
|
|
await repo.AddNotificationListAsync(list);
|
|
await repo.SaveChangesAsync();
|
|
return list;
|
|
}
|
|
|
|
private static async Task<object?> HandleUpdateNotificationList(IServiceProvider sp, UpdateNotificationListCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<INotificationRepository>();
|
|
var list = await repo.GetNotificationListByIdAsync(cmd.NotificationListId)
|
|
?? throw new InvalidOperationException($"NotificationList with ID {cmd.NotificationListId} not found.");
|
|
list.Name = cmd.Name;
|
|
|
|
// Remove existing recipients and re-add
|
|
var existingRecipients = await repo.GetRecipientsByListIdAsync(cmd.NotificationListId);
|
|
foreach (var r in existingRecipients)
|
|
{
|
|
await repo.DeleteRecipientAsync(r.Id);
|
|
}
|
|
|
|
foreach (var email in cmd.RecipientEmails)
|
|
{
|
|
await repo.AddRecipientAsync(new NotificationRecipient(email, email)
|
|
{
|
|
NotificationListId = cmd.NotificationListId
|
|
});
|
|
}
|
|
|
|
await repo.UpdateNotificationListAsync(list);
|
|
await repo.SaveChangesAsync();
|
|
return list;
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteNotificationList(IServiceProvider sp, DeleteNotificationListCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<INotificationRepository>();
|
|
await repo.DeleteNotificationListAsync(cmd.NotificationListId);
|
|
await repo.SaveChangesAsync();
|
|
return true;
|
|
}
|
|
|
|
private static async Task<object?> HandleListSmtpConfigs(IServiceProvider sp)
|
|
{
|
|
var repo = sp.GetRequiredService<INotificationRepository>();
|
|
return await repo.GetAllSmtpConfigurationsAsync();
|
|
}
|
|
|
|
private static async Task<object?> HandleUpdateSmtpConfig(IServiceProvider sp, UpdateSmtpConfigCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<INotificationRepository>();
|
|
var config = await repo.GetSmtpConfigurationByIdAsync(cmd.SmtpConfigId)
|
|
?? throw new InvalidOperationException($"SmtpConfiguration with ID {cmd.SmtpConfigId} not found.");
|
|
config.Host = cmd.Server;
|
|
config.Port = cmd.Port;
|
|
config.AuthType = cmd.AuthMode;
|
|
config.FromAddress = cmd.FromAddress;
|
|
await repo.UpdateSmtpConfigurationAsync(config);
|
|
await repo.SaveChangesAsync();
|
|
return config;
|
|
}
|
|
|
|
// ========================================================================
|
|
// Security handlers
|
|
// ========================================================================
|
|
|
|
private static async Task<object?> HandleListRoleMappings(IServiceProvider sp)
|
|
{
|
|
var repo = sp.GetRequiredService<ISecurityRepository>();
|
|
return await repo.GetAllMappingsAsync();
|
|
}
|
|
|
|
private static async Task<object?> HandleCreateRoleMapping(IServiceProvider sp, CreateRoleMappingCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ISecurityRepository>();
|
|
var mapping = new LdapGroupMapping(cmd.LdapGroupName, cmd.Role);
|
|
await repo.AddMappingAsync(mapping);
|
|
await repo.SaveChangesAsync();
|
|
return mapping;
|
|
}
|
|
|
|
private static async Task<object?> HandleUpdateRoleMapping(IServiceProvider sp, UpdateRoleMappingCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ISecurityRepository>();
|
|
var mapping = await repo.GetMappingByIdAsync(cmd.MappingId)
|
|
?? throw new InvalidOperationException($"RoleMapping with ID {cmd.MappingId} not found.");
|
|
mapping.LdapGroupName = cmd.LdapGroupName;
|
|
mapping.Role = cmd.Role;
|
|
await repo.UpdateMappingAsync(mapping);
|
|
await repo.SaveChangesAsync();
|
|
return mapping;
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteRoleMapping(IServiceProvider sp, DeleteRoleMappingCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ISecurityRepository>();
|
|
await repo.DeleteMappingAsync(cmd.MappingId);
|
|
await repo.SaveChangesAsync();
|
|
return true;
|
|
}
|
|
|
|
private static async Task<object?> HandleListApiKeys(IServiceProvider sp)
|
|
{
|
|
var repo = sp.GetRequiredService<IInboundApiRepository>();
|
|
return await repo.GetAllApiKeysAsync();
|
|
}
|
|
|
|
private static async Task<object?> HandleCreateApiKey(IServiceProvider sp, CreateApiKeyCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IInboundApiRepository>();
|
|
var keyValue = Convert.ToBase64String(RandomNumberGenerator.GetBytes(32));
|
|
var apiKey = new ApiKey(cmd.Name, keyValue) { IsEnabled = true };
|
|
await repo.AddApiKeyAsync(apiKey);
|
|
await repo.SaveChangesAsync();
|
|
return apiKey;
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteApiKey(IServiceProvider sp, DeleteApiKeyCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IInboundApiRepository>();
|
|
await repo.DeleteApiKeyAsync(cmd.ApiKeyId);
|
|
await repo.SaveChangesAsync();
|
|
return true;
|
|
}
|
|
|
|
// ========================================================================
|
|
// Deployment handlers
|
|
// ========================================================================
|
|
|
|
private static async Task<object?> HandleDeployArtifacts(IServiceProvider sp, MgmtDeployArtifactsCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<ArtifactDeploymentService>();
|
|
var command = await svc.BuildDeployArtifactsCommandAsync();
|
|
var result = await svc.DeployToAllSitesAsync(command, user);
|
|
return result.IsSuccess
|
|
? result.Value
|
|
: throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleQueryDeployments(IServiceProvider sp, QueryDeploymentsCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IDeploymentManagerRepository>();
|
|
if (cmd.InstanceId.HasValue)
|
|
return await repo.GetDeploymentsByInstanceIdAsync(cmd.InstanceId.Value);
|
|
return await repo.GetAllDeploymentRecordsAsync();
|
|
}
|
|
|
|
// ========================================================================
|
|
// Audit Log handler
|
|
// ========================================================================
|
|
|
|
private static async Task<object?> HandleQueryAuditLog(IServiceProvider sp, QueryAuditLogCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ICentralUiRepository>();
|
|
return await repo.GetAuditLogEntriesAsync(
|
|
cmd.User, cmd.EntityType, cmd.Action, cmd.From, cmd.To,
|
|
page: cmd.Page, pageSize: cmd.PageSize);
|
|
}
|
|
|
|
// ========================================================================
|
|
// Health handlers
|
|
// ========================================================================
|
|
|
|
private static object? HandleGetHealthSummary(IServiceProvider sp)
|
|
{
|
|
var aggregator = sp.GetRequiredService<ICentralHealthAggregator>();
|
|
return aggregator.GetAllSiteStates();
|
|
}
|
|
|
|
private static object? HandleGetSiteHealth(IServiceProvider sp, GetSiteHealthCommand cmd)
|
|
{
|
|
var aggregator = sp.GetRequiredService<ICentralHealthAggregator>();
|
|
return aggregator.GetSiteState(cmd.SiteIdentifier);
|
|
}
|
|
|
|
// ========================================================================
|
|
// Template member handlers
|
|
// ========================================================================
|
|
|
|
private static async Task<object?> HandleAddAttribute(IServiceProvider sp, AddTemplateAttributeCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<TemplateService>();
|
|
var attr = new TemplateAttribute(cmd.Name)
|
|
{
|
|
DataType = Enum.Parse<ScadaLink.Commons.Types.Enums.DataType>(cmd.DataType, ignoreCase: true),
|
|
Value = cmd.Value,
|
|
Description = cmd.Description,
|
|
DataSourceReference = cmd.DataSourceReference,
|
|
IsLocked = cmd.IsLocked
|
|
};
|
|
var result = await svc.AddAttributeAsync(cmd.TemplateId, attr, user);
|
|
return result.IsSuccess ? result.Value : throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleUpdateAttribute(IServiceProvider sp, UpdateTemplateAttributeCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<TemplateService>();
|
|
var attr = new TemplateAttribute(cmd.Name)
|
|
{
|
|
DataType = Enum.Parse<ScadaLink.Commons.Types.Enums.DataType>(cmd.DataType, ignoreCase: true),
|
|
Value = cmd.Value,
|
|
Description = cmd.Description,
|
|
DataSourceReference = cmd.DataSourceReference,
|
|
IsLocked = cmd.IsLocked
|
|
};
|
|
var result = await svc.UpdateAttributeAsync(cmd.AttributeId, attr, user);
|
|
return result.IsSuccess ? result.Value : throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteAttribute(IServiceProvider sp, DeleteTemplateAttributeCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<TemplateService>();
|
|
var result = await svc.DeleteAttributeAsync(cmd.AttributeId, user);
|
|
return result.IsSuccess ? result.Value : throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleAddAlarm(IServiceProvider sp, AddTemplateAlarmCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<TemplateService>();
|
|
var alarm = new TemplateAlarm(cmd.Name)
|
|
{
|
|
TriggerType = Enum.Parse<ScadaLink.Commons.Types.Enums.AlarmTriggerType>(cmd.TriggerType, ignoreCase: true),
|
|
PriorityLevel = cmd.PriorityLevel,
|
|
Description = cmd.Description,
|
|
TriggerConfiguration = cmd.TriggerConfiguration,
|
|
IsLocked = cmd.IsLocked
|
|
};
|
|
var result = await svc.AddAlarmAsync(cmd.TemplateId, alarm, user);
|
|
return result.IsSuccess ? result.Value : throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleUpdateAlarm(IServiceProvider sp, UpdateTemplateAlarmCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<TemplateService>();
|
|
var alarm = new TemplateAlarm(cmd.Name)
|
|
{
|
|
TriggerType = Enum.Parse<ScadaLink.Commons.Types.Enums.AlarmTriggerType>(cmd.TriggerType, ignoreCase: true),
|
|
PriorityLevel = cmd.PriorityLevel,
|
|
Description = cmd.Description,
|
|
TriggerConfiguration = cmd.TriggerConfiguration,
|
|
IsLocked = cmd.IsLocked
|
|
};
|
|
var result = await svc.UpdateAlarmAsync(cmd.AlarmId, alarm, user);
|
|
return result.IsSuccess ? result.Value : throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteAlarm(IServiceProvider sp, DeleteTemplateAlarmCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<TemplateService>();
|
|
var result = await svc.DeleteAlarmAsync(cmd.AlarmId, user);
|
|
return result.IsSuccess ? result.Value : throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleAddScript(IServiceProvider sp, AddTemplateScriptCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<TemplateService>();
|
|
var script = new TemplateScript(cmd.Name, cmd.Code)
|
|
{
|
|
TriggerType = cmd.TriggerType,
|
|
TriggerConfiguration = cmd.TriggerConfiguration,
|
|
IsLocked = cmd.IsLocked,
|
|
ParameterDefinitions = cmd.ParameterDefinitions,
|
|
ReturnDefinition = cmd.ReturnDefinition
|
|
};
|
|
var result = await svc.AddScriptAsync(cmd.TemplateId, script, user);
|
|
return result.IsSuccess ? result.Value : throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleUpdateScript(IServiceProvider sp, UpdateTemplateScriptCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<TemplateService>();
|
|
var script = new TemplateScript(cmd.Name, cmd.Code)
|
|
{
|
|
TriggerType = cmd.TriggerType,
|
|
TriggerConfiguration = cmd.TriggerConfiguration,
|
|
IsLocked = cmd.IsLocked,
|
|
ParameterDefinitions = cmd.ParameterDefinitions,
|
|
ReturnDefinition = cmd.ReturnDefinition
|
|
};
|
|
var result = await svc.UpdateScriptAsync(cmd.ScriptId, script, user);
|
|
return result.IsSuccess ? result.Value : throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteScript(IServiceProvider sp, DeleteTemplateScriptCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<TemplateService>();
|
|
var result = await svc.DeleteScriptAsync(cmd.ScriptId, user);
|
|
return result.IsSuccess ? result.Value : throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleAddComposition(IServiceProvider sp, AddTemplateCompositionCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<TemplateService>();
|
|
var result = await svc.AddCompositionAsync(cmd.TemplateId, cmd.ComposedTemplateId, cmd.InstanceName, user);
|
|
return result.IsSuccess ? result.Value : throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteComposition(IServiceProvider sp, DeleteTemplateCompositionCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<TemplateService>();
|
|
var result = await svc.DeleteCompositionAsync(cmd.CompositionId, user);
|
|
return result.IsSuccess ? result.Value : throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
// ========================================================================
|
|
// Shared Script handlers
|
|
// ========================================================================
|
|
|
|
private static async Task<object?> HandleListSharedScripts(IServiceProvider sp)
|
|
{
|
|
var svc = sp.GetRequiredService<SharedScriptService>();
|
|
return await svc.GetAllSharedScriptsAsync();
|
|
}
|
|
|
|
private static async Task<object?> HandleGetSharedScript(IServiceProvider sp, GetSharedScriptCommand cmd)
|
|
{
|
|
var svc = sp.GetRequiredService<SharedScriptService>();
|
|
return await svc.GetSharedScriptByIdAsync(cmd.SharedScriptId);
|
|
}
|
|
|
|
private static async Task<object?> HandleCreateSharedScript(IServiceProvider sp, CreateSharedScriptCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<SharedScriptService>();
|
|
var result = await svc.CreateSharedScriptAsync(cmd.Name, cmd.Code, cmd.ParameterDefinitions, cmd.ReturnDefinition, user);
|
|
return result.IsSuccess ? result.Value : throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleUpdateSharedScript(IServiceProvider sp, UpdateSharedScriptCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<SharedScriptService>();
|
|
var result = await svc.UpdateSharedScriptAsync(cmd.SharedScriptId, cmd.Code, cmd.ParameterDefinitions, cmd.ReturnDefinition, user);
|
|
return result.IsSuccess ? result.Value : throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteSharedScript(IServiceProvider sp, DeleteSharedScriptCommand cmd, string user)
|
|
{
|
|
var svc = sp.GetRequiredService<SharedScriptService>();
|
|
var result = await svc.DeleteSharedScriptAsync(cmd.SharedScriptId, user);
|
|
return result.IsSuccess ? result.Value : throw new InvalidOperationException(result.Error);
|
|
}
|
|
|
|
// ========================================================================
|
|
// Database Connection Definition handlers
|
|
// ========================================================================
|
|
|
|
private static async Task<object?> HandleListDatabaseConnections(IServiceProvider sp)
|
|
{
|
|
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
|
return await repo.GetAllDatabaseConnectionsAsync();
|
|
}
|
|
|
|
private static async Task<object?> HandleGetDatabaseConnection(IServiceProvider sp, GetDatabaseConnectionCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
|
return await repo.GetDatabaseConnectionByIdAsync(cmd.DatabaseConnectionId);
|
|
}
|
|
|
|
private static async Task<object?> HandleCreateDatabaseConnection(IServiceProvider sp, CreateDatabaseConnectionDefCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
|
var def = new DatabaseConnectionDefinition(cmd.Name, cmd.ConnectionString);
|
|
await repo.AddDatabaseConnectionAsync(def);
|
|
await repo.SaveChangesAsync();
|
|
return def;
|
|
}
|
|
|
|
private static async Task<object?> HandleUpdateDatabaseConnection(IServiceProvider sp, UpdateDatabaseConnectionDefCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
|
var def = await repo.GetDatabaseConnectionByIdAsync(cmd.DatabaseConnectionId)
|
|
?? throw new InvalidOperationException($"DatabaseConnection with ID {cmd.DatabaseConnectionId} not found.");
|
|
def.Name = cmd.Name;
|
|
def.ConnectionString = cmd.ConnectionString;
|
|
await repo.UpdateDatabaseConnectionAsync(def);
|
|
await repo.SaveChangesAsync();
|
|
return def;
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteDatabaseConnection(IServiceProvider sp, DeleteDatabaseConnectionDefCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IExternalSystemRepository>();
|
|
await repo.DeleteDatabaseConnectionAsync(cmd.DatabaseConnectionId);
|
|
await repo.SaveChangesAsync();
|
|
return true;
|
|
}
|
|
|
|
// ========================================================================
|
|
// Inbound API Method handlers
|
|
// ========================================================================
|
|
|
|
private static async Task<object?> HandleListApiMethods(IServiceProvider sp)
|
|
{
|
|
var repo = sp.GetRequiredService<IInboundApiRepository>();
|
|
return await repo.GetAllApiMethodsAsync();
|
|
}
|
|
|
|
private static async Task<object?> HandleGetApiMethod(IServiceProvider sp, GetApiMethodCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IInboundApiRepository>();
|
|
return await repo.GetApiMethodByIdAsync(cmd.ApiMethodId);
|
|
}
|
|
|
|
private static async Task<object?> HandleCreateApiMethod(IServiceProvider sp, CreateApiMethodCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IInboundApiRepository>();
|
|
var method = new ApiMethod(cmd.Name, cmd.Script)
|
|
{
|
|
TimeoutSeconds = cmd.TimeoutSeconds,
|
|
ParameterDefinitions = cmd.ParameterDefinitions,
|
|
ReturnDefinition = cmd.ReturnDefinition
|
|
};
|
|
await repo.AddApiMethodAsync(method);
|
|
await repo.SaveChangesAsync();
|
|
return method;
|
|
}
|
|
|
|
private static async Task<object?> HandleUpdateApiMethod(IServiceProvider sp, UpdateApiMethodCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IInboundApiRepository>();
|
|
var method = await repo.GetApiMethodByIdAsync(cmd.ApiMethodId)
|
|
?? throw new InvalidOperationException($"ApiMethod with ID {cmd.ApiMethodId} not found.");
|
|
method.Script = cmd.Script;
|
|
method.TimeoutSeconds = cmd.TimeoutSeconds;
|
|
method.ParameterDefinitions = cmd.ParameterDefinitions;
|
|
method.ReturnDefinition = cmd.ReturnDefinition;
|
|
await repo.UpdateApiMethodAsync(method);
|
|
await repo.SaveChangesAsync();
|
|
return method;
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteApiMethod(IServiceProvider sp, DeleteApiMethodCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IInboundApiRepository>();
|
|
await repo.DeleteApiMethodAsync(cmd.ApiMethodId);
|
|
await repo.SaveChangesAsync();
|
|
return true;
|
|
}
|
|
|
|
// ========================================================================
|
|
// Additional Security handlers (API key update, scope rules)
|
|
// ========================================================================
|
|
|
|
private static async Task<object?> HandleUpdateApiKey(IServiceProvider sp, UpdateApiKeyCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<IInboundApiRepository>();
|
|
var key = await repo.GetApiKeyByIdAsync(cmd.ApiKeyId)
|
|
?? throw new InvalidOperationException($"ApiKey with ID {cmd.ApiKeyId} not found.");
|
|
key.IsEnabled = cmd.IsEnabled;
|
|
await repo.UpdateApiKeyAsync(key);
|
|
await repo.SaveChangesAsync();
|
|
return key;
|
|
}
|
|
|
|
private static async Task<object?> HandleListScopeRules(IServiceProvider sp, ListScopeRulesCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ISecurityRepository>();
|
|
return await repo.GetScopeRulesForMappingAsync(cmd.MappingId);
|
|
}
|
|
|
|
private static async Task<object?> HandleAddScopeRule(IServiceProvider sp, AddScopeRuleCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ISecurityRepository>();
|
|
var rule = new SiteScopeRule { LdapGroupMappingId = cmd.MappingId, SiteId = cmd.SiteId };
|
|
await repo.AddScopeRuleAsync(rule);
|
|
await repo.SaveChangesAsync();
|
|
return rule;
|
|
}
|
|
|
|
private static async Task<object?> HandleDeleteScopeRule(IServiceProvider sp, DeleteScopeRuleCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ISecurityRepository>();
|
|
await repo.DeleteScopeRuleAsync(cmd.ScopeRuleId);
|
|
await repo.SaveChangesAsync();
|
|
return true;
|
|
}
|
|
|
|
// ========================================================================
|
|
// Area update handler
|
|
// ========================================================================
|
|
|
|
private static async Task<object?> HandleUpdateArea(IServiceProvider sp, UpdateAreaCommand cmd)
|
|
{
|
|
var repo = sp.GetRequiredService<ITemplateEngineRepository>();
|
|
var area = await repo.GetAreaByIdAsync(cmd.AreaId)
|
|
?? throw new InvalidOperationException($"Area with ID {cmd.AreaId} not found.");
|
|
area.Name = cmd.Name;
|
|
await repo.UpdateAreaAsync(area);
|
|
await repo.SaveChangesAsync();
|
|
return area;
|
|
}
|
|
|
|
// ========================================================================
|
|
// Remote Query handlers
|
|
// ========================================================================
|
|
|
|
private static async Task<object?> HandleQueryEventLogs(IServiceProvider sp, QueryEventLogsCommand cmd)
|
|
{
|
|
var commService = sp.GetRequiredService<CommunicationService>();
|
|
var request = new EventLogQueryRequest(
|
|
Guid.NewGuid().ToString("N"),
|
|
cmd.SiteIdentifier,
|
|
cmd.From, cmd.To,
|
|
cmd.EventType, cmd.Severity,
|
|
null, // InstanceId
|
|
cmd.Keyword,
|
|
null, // ContinuationToken
|
|
cmd.PageSize,
|
|
DateTimeOffset.UtcNow);
|
|
return await commService.QueryEventLogsAsync(cmd.SiteIdentifier, request);
|
|
}
|
|
|
|
private static async Task<object?> HandleQueryParkedMessages(IServiceProvider sp, QueryParkedMessagesCommand cmd)
|
|
{
|
|
var commService = sp.GetRequiredService<CommunicationService>();
|
|
var request = new ParkedMessageQueryRequest(
|
|
Guid.NewGuid().ToString("N"),
|
|
cmd.SiteIdentifier,
|
|
cmd.Page,
|
|
cmd.PageSize,
|
|
DateTimeOffset.UtcNow);
|
|
return await commService.QueryParkedMessagesAsync(cmd.SiteIdentifier, request);
|
|
}
|
|
|
|
private static async Task<object?> HandleDebugSnapshot(IServiceProvider sp, DebugSnapshotCommand cmd)
|
|
{
|
|
var instanceRepo = sp.GetRequiredService<ITemplateEngineRepository>();
|
|
var instance = await instanceRepo.GetInstanceByIdAsync(cmd.InstanceId)
|
|
?? throw new InvalidOperationException($"Instance {cmd.InstanceId} not found.");
|
|
|
|
var siteRepo = sp.GetRequiredService<ISiteRepository>();
|
|
var site = await siteRepo.GetSiteByIdAsync(instance.SiteId)
|
|
?? throw new InvalidOperationException($"Site {instance.SiteId} not found.");
|
|
|
|
var commService = sp.GetRequiredService<CommunicationService>();
|
|
var request = new DebugSnapshotRequest(instance.UniqueName, Guid.NewGuid().ToString("N"));
|
|
return await commService.RequestDebugSnapshotAsync(site.SiteIdentifier, request);
|
|
}
|
|
}
|