Files
123123/ZA.CoreService.ESBCertificateManager/Services/SonicSetupRepository.cs
T
2026-07-28 08:03:12 +02:00

505 lines
15 KiB
C#

using System.Data;
using Microsoft.Data.SqlClient;
using ZA.CoreService.ESBCertificateManager.Models;
namespace ZA.CoreService.ESBCertificateManager.Services;
public sealed class SonicSetupRepository
{
private readonly string _connectionString;
public SonicSetupRepository(string connectionString)
{
if (string.IsNullOrWhiteSpace(connectionString))
{
throw new ArgumentException(
"Der SQL-Connection-String fehlt.",
nameof(connectionString));
}
_connectionString = connectionString;
}
public async Task<IReadOnlyList<SonicSystemOption>> GetSystemsAsync(
string environmentCode,
CancellationToken cancellationToken = default)
{
if (string.IsNullOrWhiteSpace(environmentCode))
{
throw new ArgumentException(
"Der EnvironmentCode fehlt.",
nameof(environmentCode));
}
const string sql = """
SELECT
connection.SonicConnectionId,
connection.ConnectionName,
environment.EnvironmentCode,
connection.DomainName,
connection.ManagementHost,
connection.ManagementPort,
connection.ConnectionProtocol,
MIN(container.ContainerName)
AS ValidationContainerName
FROM dbo.SonicConnection AS connection
INNER JOIN dbo.SonicContainer AS container
ON container.SonicConnectionId =
connection.SonicConnectionId
INNER JOIN dbo.EsbService AS service
ON service.EsbServiceId =
container.EsbServiceId
INNER JOIN dbo.Environment AS environment
ON environment.EnvironmentId =
service.EnvironmentId
WHERE connection.IsActive = 1
AND container.IsActive = 1
AND service.IsActive = 1
AND environment.IsActive = 1
AND environment.EnvironmentCode =
@EnvironmentCode
GROUP BY
connection.SonicConnectionId,
connection.ConnectionName,
environment.EnvironmentCode,
connection.DomainName,
connection.ManagementHost,
connection.ManagementPort,
connection.ConnectionProtocol
ORDER BY connection.ConnectionName;
""";
List<SonicSystemOption> systems = [];
await using SqlConnection connection =
new(_connectionString);
await connection.OpenAsync(cancellationToken);
await using SqlCommand command =
new(sql, connection);
command.Parameters.Add(
new SqlParameter(
"@EnvironmentCode",
SqlDbType.NVarChar,
30)
{
Value = environmentCode
.Trim()
.ToUpperInvariant()
});
await using SqlDataReader reader =
await command.ExecuteReaderAsync(cancellationToken);
int sonicConnectionIdOrdinal =
reader.GetOrdinal("SonicConnectionId");
int connectionNameOrdinal =
reader.GetOrdinal("ConnectionName");
int environmentCodeOrdinal =
reader.GetOrdinal("EnvironmentCode");
int domainNameOrdinal =
reader.GetOrdinal("DomainName");
int managementHostOrdinal =
reader.GetOrdinal("ManagementHost");
int managementPortOrdinal =
reader.GetOrdinal("ManagementPort");
int connectionProtocolOrdinal =
reader.GetOrdinal("ConnectionProtocol");
int validationContainerNameOrdinal =
reader.GetOrdinal("ValidationContainerName");
while (await reader.ReadAsync(cancellationToken))
{
if (reader.IsDBNull(managementPortOrdinal))
{
continue;
}
systems.Add(
new SonicSystemOption
{
SonicConnectionId =
reader.GetInt32(
sonicConnectionIdOrdinal),
ConnectionName =
reader.GetString(
connectionNameOrdinal),
EnvironmentCode =
reader.GetString(
environmentCodeOrdinal),
DomainName =
reader.IsDBNull(domainNameOrdinal)
? string.Empty
: reader.GetString(
domainNameOrdinal),
ManagementHost =
reader.GetString(
managementHostOrdinal),
ManagementPort =
reader.GetInt32(
managementPortOrdinal),
ConnectionProtocol =
reader.IsDBNull(connectionProtocolOrdinal)
? "tcp"
: reader.GetString(
connectionProtocolOrdinal),
ValidationContainerName =
reader.IsDBNull(
validationContainerNameOrdinal)
? string.Empty
: reader.GetString(
validationContainerNameOrdinal)
});
}
return systems;
}
public async Task<int> AddCredentialAsync(
int sonicConnectionId,
string credentialName,
string userName,
string secret,
bool isDefault,
CancellationToken cancellationToken = default)
{
if (sonicConnectionId <= 0)
{
throw new ArgumentOutOfRangeException(
nameof(sonicConnectionId));
}
if (string.IsNullOrWhiteSpace(credentialName))
{
throw new ArgumentException(
"Der Profilname fehlt.",
nameof(credentialName));
}
if (string.IsNullOrWhiteSpace(userName))
{
throw new ArgumentException(
"Der Sonic-Benutzername fehlt.",
nameof(userName));
}
if (string.IsNullOrEmpty(secret))
{
throw new ArgumentException(
"Das Sonic-Kennwort fehlt.",
nameof(secret));
}
string normalizedCredentialName =
credentialName.Trim();
string normalizedUserName =
userName.Trim();
if (normalizedCredentialName.Length > 150)
{
throw new ArgumentException(
"Der Profilname darf maximal 150 Zeichen enthalten.",
nameof(credentialName));
}
if (normalizedUserName.Length > 256)
{
throw new ArgumentException(
"Der Benutzername darf maximal 256 Zeichen enthalten.",
nameof(userName));
}
if (secret.Length > 512)
{
throw new ArgumentException(
"Das Kennwort darf maximal 512 Zeichen enthalten.",
nameof(secret));
}
await using SqlConnection connection =
new(_connectionString);
await connection.OpenAsync(cancellationToken);
await using SqlTransaction transaction =
(SqlTransaction)
await connection.BeginTransactionAsync(
cancellationToken);
try
{
if (isDefault)
{
const string clearDefaultSql = """
UPDATE dbo.SonicCredential
SET
IsDefault = 0,
UpdatedAtUtc = SYSUTCDATETIME()
WHERE SonicConnectionId =
@SonicConnectionId
AND IsDefault = 1;
""";
await using SqlCommand clearDefaultCommand =
new(
clearDefaultSql,
connection,
transaction);
clearDefaultCommand.Parameters.Add(
new SqlParameter(
"@SonicConnectionId",
SqlDbType.Int)
{
Value = sonicConnectionId
});
await clearDefaultCommand.ExecuteNonQueryAsync(
cancellationToken);
}
const string insertSql = """
INSERT INTO dbo.SonicCredential
(
SonicConnectionId,
CredentialName,
CredentialUserName,
CredentialSecret,
IsDefault,
IsActive,
CreatedAtUtc,
UpdatedAtUtc
)
OUTPUT INSERTED.SonicCredentialId
VALUES
(
@SonicConnectionId,
@CredentialName,
@CredentialUserName,
@CredentialSecret,
@IsDefault,
1,
SYSUTCDATETIME(),
NULL
);
""";
await using SqlCommand insertCommand =
new(
insertSql,
connection,
transaction);
insertCommand.Parameters.Add(
new SqlParameter(
"@SonicConnectionId",
SqlDbType.Int)
{
Value = sonicConnectionId
});
insertCommand.Parameters.Add(
new SqlParameter(
"@CredentialName",
SqlDbType.NVarChar,
150)
{
Value = normalizedCredentialName
});
insertCommand.Parameters.Add(
new SqlParameter(
"@CredentialUserName",
SqlDbType.NVarChar,
256)
{
Value = normalizedUserName
});
insertCommand.Parameters.Add(
new SqlParameter(
"@CredentialSecret",
SqlDbType.NVarChar,
512)
{
Value = secret
});
insertCommand.Parameters.Add(
new SqlParameter(
"@IsDefault",
SqlDbType.Bit)
{
Value = isDefault
});
object? result =
await insertCommand.ExecuteScalarAsync(
cancellationToken);
if (result is null || result is DBNull)
{
throw new InvalidOperationException(
"Das Benutzerprofil konnte nicht angelegt werden.");
}
int credentialId =
Convert.ToInt32(result);
await transaction.CommitAsync(
cancellationToken);
return credentialId;
}
catch
{
try
{
await transaction.RollbackAsync(
CancellationToken.None);
}
catch
{
// Die ursprüngliche Exception soll erhalten bleiben.
}
throw;
}
}
public async Task<IReadOnlyList<SonicCredentialProfile>>
GetCredentialsAsync(
int sonicConnectionId,
CancellationToken cancellationToken = default)
{
if (sonicConnectionId <= 0)
{
throw new ArgumentOutOfRangeException(
nameof(sonicConnectionId));
}
const string sql = """
SELECT
SonicCredentialId,
SonicConnectionId,
CredentialName,
CredentialUserName,
CredentialSecret,
IsDefault,
IsActive
FROM dbo.SonicCredential
WHERE SonicConnectionId = @SonicConnectionId
AND IsActive = 1
ORDER BY
IsDefault DESC,
CredentialName;
""";
List<SonicCredentialProfile> profiles = [];
await using SqlConnection connection =
new(_connectionString);
await connection.OpenAsync(cancellationToken);
await using SqlCommand command =
new(sql, connection);
command.Parameters.Add(
new SqlParameter(
"@SonicConnectionId",
SqlDbType.Int)
{
Value = sonicConnectionId
});
await using SqlDataReader reader =
await command.ExecuteReaderAsync(cancellationToken);
int credentialIdOrdinal =
reader.GetOrdinal("SonicCredentialId");
int connectionIdOrdinal =
reader.GetOrdinal("SonicConnectionId");
int credentialNameOrdinal =
reader.GetOrdinal("CredentialName");
int userNameOrdinal =
reader.GetOrdinal("CredentialUserName");
int secretOrdinal =
reader.GetOrdinal("CredentialSecret");
int isDefaultOrdinal =
reader.GetOrdinal("IsDefault");
int isActiveOrdinal =
reader.GetOrdinal("IsActive");
while (await reader.ReadAsync(cancellationToken))
{
string? userName =
reader.IsDBNull(userNameOrdinal)
? null
: reader.GetString(userNameOrdinal);
string? secret =
reader.IsDBNull(secretOrdinal)
? null
: reader.GetString(secretOrdinal);
if (string.IsNullOrWhiteSpace(userName)
|| string.IsNullOrEmpty(secret))
{
continue;
}
profiles.Add(
new SonicCredentialProfile
{
SonicCredentialId =
reader.GetInt32(
credentialIdOrdinal),
SonicConnectionId =
reader.GetInt32(
connectionIdOrdinal),
CredentialName =
reader.GetString(
credentialNameOrdinal),
UserName = userName,
Secret = secret,
IsDefault =
reader.GetBoolean(
isDefaultOrdinal),
IsActive =
reader.GetBoolean(
isActiveOrdinal)
});
}
return profiles;
}
}