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; } }