using System.CommandLine; using System.CommandLine.Parsing; namespace ZB.MOM.WW.ScadaBridge.CLI.Commands; /// /// Resolved Management API connection details for an audit subcommand, or an /// error describing why resolution failed. /// public sealed class AuditConnection { /// /// The management URL, or null if resolution failed. /// public string? Url { get; init; } /// /// The username for authentication, or null if resolution failed. /// public string? Username { get; init; } /// /// The password for authentication, or null if resolution failed. /// public string? Password { get; init; } /// /// Error message if resolution failed, or null. /// public string? Error { get; init; } /// /// Error code if resolution failed, or null. /// public string? ErrorCode { get; init; } /// /// Creates a failed connection with an error message and code. /// /// The error message. /// The error code. /// A failed AuditConnection. public static AuditConnection Fail(string error, string code) => new() { Error = error, ErrorCode = code }; } /// /// Connection/format resolution shared by the audit subcommands. Mirrors the URL /// and credential precedence used by (command line → config /// file / environment), but produces a raw target /// because the audit endpoints are plain REST resources rather than POST /management /// command-envelope calls. /// public static class AuditCommandHelpers { /// /// Resolves management API connection details from command line arguments, config file, or environment variables. /// /// The parsed command line arguments. /// The URL option. /// The username option. /// The password option. /// The resolved connection details, or a failure result. public static AuditConnection ResolveConnection( ParseResult result, Option urlOption, Option usernameOption, Option passwordOption) { var config = CliConfig.Load(); var url = result.GetValue(urlOption); if (string.IsNullOrWhiteSpace(url)) url = config.ManagementUrl; if (string.IsNullOrWhiteSpace(url)) { return AuditConnection.Fail( "No management URL specified. Use --url, set SCADALINK_MANAGEMENT_URL, or add 'managementUrl' to ~/.scadabridge/config.json.", "NO_URL"); } if (!CommandHelpers.IsValidManagementUrl(url)) { return AuditConnection.Fail( $"Invalid management URL '{url}'. Expected an absolute http/https URL (e.g. http://localhost:9001).", "INVALID_URL"); } var username = CommandHelpers.ResolveCredential(result.GetValue(usernameOption), config.Username); var password = CommandHelpers.ResolveCredential(result.GetValue(passwordOption), config.Password); if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password)) { return AuditConnection.Fail( "Credentials required. Use --username/--password or set SCADALINK_USERNAME/SCADALINK_PASSWORD.", "NO_CREDENTIALS"); } return new AuditConnection { Url = url, Username = username, Password = password }; } /// /// Resolves the output format from command line arguments, config file, or defaults to "table". /// /// The parsed command line arguments. /// The format option. /// The resolved format string. public static string ResolveFormat(ParseResult result, Option formatOption) => CommandHelpers.ResolveFormat(result, formatOption, CliConfig.Load()); }