Files
123123/ZA.CoreService.ESBCertificateManager/Services/SonicSetupRepository.cs
T

599 lines
18 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].[Environment] AS environment
ON environment.[EnvironmentId] =
connection.[EnvironmentId]
LEFT JOIN [dbo].[SonicContainer] AS container
ON container.[SonicConnectionId] =
connection.[SonicConnectionId]
AND container.[IsActive] = 1
WHERE connection.[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))
{
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,
[ModifiedDateTime] = SYSUTCDATETIME(),
[ModifiedBy] = SUSER_SNAME()
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],
[CreationDateTime],
[CreatedBy],
[ModifiedDateTime],
[ModifiedBy]
)
OUTPUT INSERTED.[SonicCredentialId]
VALUES
(
@SonicConnectionId,
@CredentialName,
@CredentialUserName,
@CredentialSecret,
@IsDefault,
1,
SYSUTCDATETIME(),
SUSER_SNAME(),
NULL,
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;
}
public async Task<SonicCredentialProfile?> GetCredentialByIdAsync(
int sonicCredentialId,
CancellationToken cancellationToken = default)
{
if (sonicCredentialId <= 0)
{
throw new ArgumentOutOfRangeException(
nameof(sonicCredentialId));
}
const string sql = """
SELECT
[SonicCredentialId],
[SonicConnectionId],
[CredentialName],
[CredentialUserName],
[CredentialSecret],
[IsDefault],
[IsActive]
FROM [dbo].[SonicCredential]
WHERE [SonicCredentialId] = @SonicCredentialId
AND [IsActive] = 1;
""";
await using SqlConnection connection =
new(_connectionString);
await connection.OpenAsync(cancellationToken);
await using SqlCommand command =
new(sql, connection);
command.Parameters.Add(
new SqlParameter(
"@SonicCredentialId",
SqlDbType.Int)
{
Value = sonicCredentialId
});
await using SqlDataReader reader =
await command.ExecuteReaderAsync(cancellationToken);
if (!await reader.ReadAsync(cancellationToken))
{
return null;
}
int userNameOrdinal =
reader.GetOrdinal("CredentialUserName");
int secretOrdinal =
reader.GetOrdinal("CredentialSecret");
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))
{
return null;
}
return new SonicCredentialProfile
{
SonicCredentialId =
reader.GetInt32(
reader.GetOrdinal("SonicCredentialId")),
SonicConnectionId =
reader.GetInt32(
reader.GetOrdinal("SonicConnectionId")),
CredentialName =
reader.GetString(
reader.GetOrdinal("CredentialName")),
UserName = userName,
Secret = secret,
IsDefault =
reader.GetBoolean(
reader.GetOrdinal("IsDefault")),
IsActive =
reader.GetBoolean(
reader.GetOrdinal("IsActive"))
};
}
}