Simplify DB to six tables and load credentials via Always Encrypted SonicCredential.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-29 08:23:55 +02:00
co-authored by Cursor
parent 4d19873776
commit dcfcb5289d
15 changed files with 1356 additions and 461 deletions
@@ -23,26 +23,31 @@ public sealed class SonicConnectionRepository
public async Task<IReadOnlyList<DatabaseSonicConnection>>
GetActiveAsync(
string? environmentCode = null,
CancellationToken cancellationToken = default)
{
const string sql = """
SELECT
SonicConnectionId,
ConnectionName,
ManagementHost,
ManagementPort,
ConnectionProtocol,
DomainName,
CredentialUserName,
CredentialReference,
CredentialSecret,
JavaHomePath,
SonicHomePath,
Notes,
IsActive
FROM dbo.SonicConnection
WHERE IsActive = 1
ORDER BY ConnectionName;
connection.[SonicConnectionId],
connection.[ConnectionName],
connection.[ManagementHost],
connection.[ManagementPort],
connection.[ConnectionProtocol],
connection.[DomainName],
environment.[EnvironmentCode],
connection.[IsActive]
FROM [dbo].[SonicConnection] AS connection
INNER JOIN [dbo].[Environment] AS environment
ON environment.[EnvironmentId] =
connection.[EnvironmentId]
WHERE connection.[IsActive] = 1
AND environment.[IsActive] = 1
AND
(
@EnvironmentCode IS NULL
OR environment.[EnvironmentCode] = @EnvironmentCode
)
ORDER BY connection.[ConnectionName];
""";
List<DatabaseSonicConnection> connections = [];
@@ -55,6 +60,22 @@ public sealed class SonicConnectionRepository
await using SqlCommand command =
new(sql, connection);
string? normalizedEnvironmentCode =
string.IsNullOrWhiteSpace(environmentCode)
? null
: environmentCode.Trim().ToUpperInvariant();
command.Parameters.Add(
new SqlParameter(
"@EnvironmentCode",
SqlDbType.NVarChar,
30)
{
Value = normalizedEnvironmentCode is null
? DBNull.Value
: normalizedEnvironmentCode
});
await using SqlDataReader reader =
await command.ExecuteReaderAsync(
cancellationToken);
@@ -77,23 +98,8 @@ public sealed class SonicConnectionRepository
int domainOrdinal =
reader.GetOrdinal("DomainName");
int userNameOrdinal =
reader.GetOrdinal("CredentialUserName");
int credentialReferenceOrdinal =
reader.GetOrdinal("CredentialReference");
int credentialSecretOrdinal =
reader.GetOrdinal("CredentialSecret");
int javaHomeOrdinal =
reader.GetOrdinal("JavaHomePath");
int sonicHomeOrdinal =
reader.GetOrdinal("SonicHomePath");
int notesOrdinal =
reader.GetOrdinal("Notes");
int environmentCodeOrdinal =
reader.GetOrdinal("EnvironmentCode");
int isActiveOrdinal =
reader.GetOrdinal("IsActive");
@@ -112,9 +118,7 @@ public sealed class SonicConnectionRepository
reader.GetString(hostOrdinal),
ManagementPort =
ReadNullableInt32(
reader,
portOrdinal),
reader.GetInt32(portOrdinal),
ConnectionProtocol =
ReadNullableString(
@@ -126,35 +130,10 @@ public sealed class SonicConnectionRepository
reader,
domainOrdinal),
CredentialUserName =
EnvironmentCode =
ReadNullableString(
reader,
userNameOrdinal),
CredentialReference =
ReadNullableString(
reader,
credentialReferenceOrdinal),
CredentialSecret =
ReadNullableString(
reader,
credentialSecretOrdinal),
JavaHomePath =
ReadNullableString(
reader,
javaHomeOrdinal),
SonicHomePath =
ReadNullableString(
reader,
sonicHomeOrdinal),
Notes =
ReadNullableString(
reader,
notesOrdinal),
environmentCodeOrdinal),
IsActive =
reader.GetBoolean(
@@ -165,154 +144,6 @@ public sealed class SonicConnectionRepository
return connections;
}
public async Task SaveCredentialsAsync(
int sonicConnectionId,
string credentialUserName,
string credentialSecret,
CancellationToken cancellationToken = default)
{
if (sonicConnectionId <= 0)
{
throw new ArgumentOutOfRangeException(
nameof(sonicConnectionId),
"Die SonicConnectionId ist ungültig.");
}
if (string.IsNullOrWhiteSpace(
credentialUserName))
{
throw new ArgumentException(
"Der Sonic-Benutzername fehlt.",
nameof(credentialUserName));
}
if (string.IsNullOrEmpty(
credentialSecret))
{
throw new ArgumentException(
"Das Sonic-Kennwort fehlt.",
nameof(credentialSecret));
}
string normalizedUserName =
credentialUserName.Trim();
if (normalizedUserName.Length > 256)
{
throw new ArgumentException(
"Der Sonic-Benutzername darf maximal 256 Zeichen enthalten.",
nameof(credentialUserName));
}
if (credentialSecret.Length > 512)
{
throw new ArgumentException(
"Das Sonic-Kennwort darf maximal 512 Zeichen enthalten.",
nameof(credentialSecret));
}
const string sql = """
UPDATE dbo.SonicConnection
SET
CredentialUserName = @CredentialUserName,
CredentialSecret = @CredentialSecret,
UpdatedAtUtc = SYSUTCDATETIME()
WHERE SonicConnectionId = @SonicConnectionId
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(
"@CredentialUserName",
SqlDbType.NVarChar,
256)
{
Value = normalizedUserName
});
command.Parameters.Add(
new SqlParameter(
"@CredentialSecret",
SqlDbType.NVarChar,
512)
{
Value = credentialSecret
});
command.Parameters.Add(
new SqlParameter(
"@SonicConnectionId",
SqlDbType.Int)
{
Value = sonicConnectionId
});
int affectedRows =
await command.ExecuteNonQueryAsync(
cancellationToken);
if (affectedRows != 1)
{
throw new InvalidOperationException(
"Die aktive Sonic-Verbindung wurde nicht eindeutig gefunden.");
}
}
public async Task ClearCredentialsAsync(
int sonicConnectionId,
CancellationToken cancellationToken = default)
{
if (sonicConnectionId <= 0)
{
throw new ArgumentOutOfRangeException(
nameof(sonicConnectionId),
"Die SonicConnectionId ist ungültig.");
}
const string sql = """
UPDATE dbo.SonicConnection
SET
CredentialUserName = NULL,
CredentialSecret = NULL,
UpdatedAtUtc = SYSUTCDATETIME()
WHERE SonicConnectionId = @SonicConnectionId;
""";
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
});
int affectedRows =
await command.ExecuteNonQueryAsync(
cancellationToken);
if (affectedRows != 1)
{
throw new InvalidOperationException(
"Die Sonic-Verbindung wurde nicht eindeutig gefunden.");
}
}
private static string? ReadNullableString(
SqlDataReader reader,
int ordinal)
@@ -321,13 +152,4 @@ public sealed class SonicConnectionRepository
? null
: reader.GetString(ordinal);
}
private static int? ReadNullableInt32(
SqlDataReader reader,
int ordinal)
{
return reader.IsDBNull(ordinal)
? null
: reader.GetInt32(ordinal);
}
}
}