using HanaToolbox.Config; using HanaToolbox.Logging; using HanaToolbox.Services; using HanaToolbox.Services.Interfaces; using Spectre.Console; namespace HanaToolbox.Tui; /// /// Full guided onboarding wizard. /// Walks through every setting, creates hdbuserstore keys, and writes hanatoolbox.json. /// public sealed class OnboardTui( KeyManagerTui keyManagerTui, CronSetupTui cronSetupTui, FirewallTui firewallTui, AppLogger _logger) { public async Task RunAsync(CancellationToken ct = default) { AnsiConsole.Clear(); AnsiConsole.Write(new FigletText("HanaToolbox").Color(Color.Cyan1)); AnsiConsole.Write(new Rule("[cyan]Initial Setup Wizard[/]").RuleStyle("cyan")); AnsiConsole.MarkupLine("[grey]This wizard will configure HanaToolbox for this system.[/]\n"); // Root check if (Environment.UserName != "root") { AnsiConsole.MarkupLine("[red]Warning: Not running as root. Some operations may fail.[/]"); if (!AnsiConsole.Confirm("Continue anyway?", defaultValue: false)) return; } var config = ConfigService.Exists() ? ConfigService.Load() : new AppConfig(); // Step 1: HANA global settings AnsiConsole.Write(new Rule("[blue]Step 1 of 7 — HANA Settings[/]").RuleStyle("blue")); config.Hana.Sid = AnsiConsole.Prompt(new TextPrompt("HANA SID:").DefaultValue(config.Hana.Sid)); config.Hana.InstanceNumber = AnsiConsole.Prompt(new TextPrompt("Instance number:").DefaultValue(config.Hana.InstanceNumber)); AnsiConsole.WriteLine(); // Step 2: hdbuserstore keys AnsiConsole.Write(new Rule("[blue]Step 2 of 7 — Key Manager[/]").RuleStyle("blue")); AnsiConsole.MarkupLine("[grey]Set up hdbuserstore keys needed for automated operations.[/]"); if (AnsiConsole.Confirm("Open Key Manager now?", defaultValue: true)) await keyManagerTui.RunAsync(config.Hana, config.Hana.Sid, ct); AnsiConsole.WriteLine(); // Step 3: Cron tasks AnsiConsole.Write(new Rule("[blue]Step 3 of 7 — Cron Task Settings[/]").RuleStyle("blue")); config = cronSetupTui.Run(config); // Step 4: Firewall AnsiConsole.Write(new Rule("[blue]Step 4 of 7 — Firewall[/]").RuleStyle("blue")); if (AnsiConsole.Confirm("Configure firewall rules now?", defaultValue: true)) { var updated = await firewallTui.RunAsync(config.Firewall, ct); if (updated != null) config.Firewall = updated; } AnsiConsole.WriteLine(); // Step 5: Binary paths (optional overrides) AnsiConsole.Write(new Rule("[blue]Step 5 of 7 — Binary Paths (optional)[/]").RuleStyle("blue")); AnsiConsole.MarkupLine("[grey]Leave empty to use auto-detection (which, /usr/sap/hdbclient, etc.)[/]"); var hdbsqlOverride = AnsiConsole.Prompt( new TextPrompt("hdbsql path override (empty = auto):").AllowEmpty().DefaultValue("")); var hdbusOverride = AnsiConsole.Prompt( new TextPrompt("hdbuserstore path override (empty = auto):").AllowEmpty().DefaultValue("")); if (!string.IsNullOrWhiteSpace(hdbsqlOverride)) config.Hana.HdbsqlPath = hdbsqlOverride; if (!string.IsNullOrWhiteSpace(hdbusOverride)) config.Hana.HdbuserstorePath = hdbusOverride; AnsiConsole.WriteLine(); // Step 6: ntfy notifications AnsiConsole.Write(new Rule("[blue]Step 6 of 7 — Notifications (ntfy)[/]").RuleStyle("blue")); AnsiConsole.MarkupLine("[grey]HanaToolbox sends alerts via ntfy.sh (or a self-hosted ntfy server).[/]"); AnsiConsole.MarkupLine("[grey]Leave the token empty to disable notifications.[/]"); AnsiConsole.WriteLine(); config.Ntfy.Url = AnsiConsole.Prompt( new TextPrompt("ntfy server URL (topic included):") .DefaultValue(config.Ntfy.Url)); config.Ntfy.Token = AnsiConsole.Prompt( new TextPrompt("ntfy access token (empty = no auth):") .Secret() .AllowEmpty() .DefaultValue(string.IsNullOrWhiteSpace(config.Ntfy.Token) ? string.Empty : "(existing)")); // If user accepted "(existing)" prompt without typing, keep the real token if (config.Ntfy.Token == "(existing)") config.Ntfy.Token = ConfigService.Exists() ? ConfigService.Load().Ntfy.Token : string.Empty; AnsiConsole.WriteLine(); // Step 7: Save AnsiConsole.Write(new Rule("[blue]Step 7 of 7 — Finalize[/]").RuleStyle("blue")); var crontabLine = $"* * * * * root /usr/local/bin/hanatoolbox cron"; AnsiConsole.MarkupLine("[grey]Add the following line to your system crontab ([cyan]/etc/crontab[/] or [cyan]/etc/cron.d/hanatoolbox[/]):[/]"); AnsiConsole.MarkupLine($"[cyan]{crontabLine}[/]"); AnsiConsole.WriteLine(); if (!AnsiConsole.Confirm("Save configuration to /etc/hanatoolbox/hanatoolbox.json?", defaultValue: true)) { AnsiConsole.MarkupLine("[yellow]Aborted. No changes saved.[/]"); return; } ConfigService.Save(config); AnsiConsole.MarkupLine("[green]✅ Configuration saved successfully![/]"); AnsiConsole.MarkupLine($"[grey]Config file: /etc/hanatoolbox/hanatoolbox.json[/]"); } }