diff --git a/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/Services/SiteService.cs b/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/Services/SiteService.cs index 52bf3c05..8ed913bf 100644 --- a/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/Services/SiteService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.TemplateEngine/Services/SiteService.cs @@ -124,73 +124,10 @@ public class SiteService // --- Data Connection CRUD --- - /// Creates a new data connection owned by the specified site. - /// Primary key of the owning site. - /// Display name of the data connection. - /// Protocol identifier (e.g., "OpcUa"). - /// JSON configuration for the primary endpoint; may be null. - /// JSON configuration for the backup endpoint; may be null. - /// Number of retries before switching to the backup endpoint. - /// Authenticated username for audit logging. - /// Cancellation token. - /// A successful result containing the new , or a failure result. - public async Task> CreateDataConnectionAsync( - int siteId, string name, string protocol, string? primaryConfiguration, - string? backupConfiguration, int failoverRetryCount, string user, - CancellationToken cancellationToken = default) - { - if (string.IsNullOrWhiteSpace(name)) - return Result.Failure("Data connection name is required."); - if (string.IsNullOrWhiteSpace(protocol)) - return Result.Failure("Protocol is required."); - - var connection = new DataConnection(name, protocol, siteId) - { - PrimaryConfiguration = primaryConfiguration, - BackupConfiguration = backupConfiguration, - FailoverRetryCount = failoverRetryCount - }; - await _repository.AddDataConnectionAsync(connection, cancellationToken); - await _repository.SaveChangesAsync(cancellationToken); - - await _auditService.LogAsync(user, "Create", "DataConnection", - connection.Id.ToString(), name, connection, cancellationToken); - - return Result.Success(connection); - } - - /// Updates an existing data connection's configuration. - /// Primary key of the data connection to update. - /// New display name. - /// New protocol identifier. - /// New primary endpoint JSON configuration; may be null. - /// New backup endpoint JSON configuration; may be null. - /// New failover retry count. - /// Authenticated username for audit logging. - /// Cancellation token. - /// A successful result containing the updated , or a failure result if not found. - public async Task> UpdateDataConnectionAsync( - int connectionId, string name, string protocol, string? primaryConfiguration, - string? backupConfiguration, int failoverRetryCount, string user, - CancellationToken cancellationToken = default) - { - var connection = await _repository.GetDataConnectionByIdAsync(connectionId, cancellationToken); - if (connection == null) - return Result.Failure($"Data connection with ID {connectionId} not found."); - - connection.Name = name; - connection.Protocol = protocol; - connection.PrimaryConfiguration = primaryConfiguration; - connection.BackupConfiguration = backupConfiguration; - connection.FailoverRetryCount = failoverRetryCount; - await _repository.UpdateDataConnectionAsync(connection, cancellationToken); - await _repository.SaveChangesAsync(cancellationToken); - - await _auditService.LogAsync(user, "Update", "DataConnection", - connection.Id.ToString(), name, connection, cancellationToken); - - return Result.Success(connection); - } + // Create/update of data connections deliberately live only in the Management + // Service, which audits the secret-scrubbed public shape. The SiteService versions + // (no production callers) audited the raw entity — Primary/BackupConfiguration can + // embed protocol credentials — and were removed (review 2026-10-21 08/C1). /// Deletes a data connection by its primary key. /// Primary key of the data connection to delete. diff --git a/tests/ZB.MOM.WW.ScadaBridge.TemplateEngine.Tests/Services/SiteServiceTests.cs b/tests/ZB.MOM.WW.ScadaBridge.TemplateEngine.Tests/Services/SiteServiceTests.cs index 9aba6af7..a023a545 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.TemplateEngine.Tests/Services/SiteServiceTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.TemplateEngine.Tests/Services/SiteServiceTests.cs @@ -98,20 +98,19 @@ public class SiteServiceTests Assert.True(result.IsSuccess); } - /// Verifies that creating a data connection with valid input succeeds. - /// A task that represents the asynchronous operation. - [Fact] - public async Task CreateDataConnection_ValidInput_Success() + /// + /// Review 2026-10-21 08/C1: SiteService must not offer a data-connection create/update + /// that audits the raw DataConnection entity — its Primary/BackupConfiguration + /// can embed protocol credentials, which would land in plaintext in the indefinitely + /// retained config audit. The Management Service path (which audits the scrubbed + /// public shape) is the only writer. + /// + [Theory] + [InlineData("CreateDataConnectionAsync")] + [InlineData("UpdateDataConnectionAsync")] + public void SiteService_HasNoRawDataConnectionWriter(string method) { - _repoMock.Setup(r => r.SaveChangesAsync(It.IsAny())) - .ReturnsAsync(1); - - var result = await _sut.CreateDataConnectionAsync(1, "OPC-Server1", "OpcUa", "{\"url\":\"opc.tcp://localhost\"}", null, 3, "admin"); - - Assert.True(result.IsSuccess); - Assert.Equal("OPC-Server1", result.Value.Name); - Assert.Equal("OpcUa", result.Value.Protocol); - Assert.Equal(1, result.Value.SiteId); + Assert.Null(typeof(SiteService).GetMethod(method)); } /// Verifies that updating a site with valid input succeeds.