using HanaToolbox.Logging;
using HanaToolbox.Services.Interfaces;
namespace HanaToolbox.Services;
///
/// Wraps hdbuserstore operations using SuUserSwitcher to run as <sid>adm.
/// Keys stored in the OS user's home directory (~/.hdbusers/).
///
public sealed class KeyManagerService(
IUserSwitcher switcher,
IHdbClientLocator locator,
AppLogger logger) : IKeyManagerService
{
public async Task CreateKeyAsync(
string keyName, string connectionString,
string user, string password,
string sid, CancellationToken ct = default)
{
var hdbus = locator.LocateHdbuserstore(null, sid, "00");
var result = await switcher.RunAsAsync(sid,
$"\"{hdbus}\" SET \"{keyName}\" \"{connectionString}\" \"{user}\" \"{password}\"", ct);
if (!result.Success)
{
logger.Error($"Failed to create key '{keyName}': {result.StdErr}");
return false;
}
logger.Success($"Key '{keyName}' created.");
return true;
}
public async Task DeleteKeyAsync(string keyName, string sid, CancellationToken ct = default)
{
var hdbus = locator.LocateHdbuserstore(null, sid, "00");
var result = await switcher.RunAsAsync(sid,
$"\"{hdbus}\" DELETE \"{keyName}\"", ct);
if (!result.Success)
{
logger.Error($"Failed to delete key '{keyName}': {result.StdErr}");
return false;
}
logger.Success($"Key '{keyName}' deleted.");
return true;
}
public async Task> ListKeysAsync(string sid, CancellationToken ct = default)
{
var hdbus = locator.LocateHdbuserstore(null, sid, "00");
var result = await switcher.RunAsAsync(sid, $"\"{hdbus}\" LIST", ct);
if (!result.Success) return [];
// Parse lines like: "KEY mykey" from hdbuserstore LIST output
return result.StdOut
.Split('\n', StringSplitOptions.RemoveEmptyEntries)
.Where(l => l.TrimStart().StartsWith("KEY "))
.Select(l => l.Trim()[4..].Trim()) // strip "KEY "
.ToList();
}
public async Task TestKeyAsync(
string hdbsqlPath, string keyName, string sid, CancellationToken ct = default)
{
var result = await switcher.RunAsAsync(sid,
$"\"{hdbsqlPath}\" -U \"{keyName}\" \"SELECT 'Connection successful' FROM DUMMY\"", ct);
var ok = result.Success && result.StdOut.Contains("Connection successful");
if (ok) logger.Success($"Key '{keyName}' connection test passed.");
else logger.Error($"Key '{keyName}' connection test failed: {result.StdErr}");
return ok;
}
}