diff --git a/src/Tgstation.Server.Host/Setup/SetupWizard.cs b/src/Tgstation.Server.Host/Setup/SetupWizard.cs index 15f2b82e48..775cbe98e0 100644 --- a/src/Tgstation.Server.Host/Setup/SetupWizard.cs +++ b/src/Tgstation.Server.Host/Setup/SetupWizard.cs @@ -5,6 +5,7 @@ using System.Data.SqlClient; using System.Globalization; using System.IO; using System.Linq; +using System.Net; using System.Text; using System.Text.RegularExpressions; using System.Threading; @@ -141,19 +142,29 @@ namespace Tgstation.Server.Host.Setup /// A prompt for a yes or no value. /// /// The question . + /// The optional default response if the user doesn't enter anything. /// The for the operation. /// A resulting in if the user replied yes, otherwise. - async Task PromptYesNo(string question, CancellationToken cancellationToken) + async Task PromptYesNo(string question, bool? defaultResponse, CancellationToken cancellationToken) { do { - await console.WriteAsync(question, false, cancellationToken); + await console.WriteAsync($"{question} ({(defaultResponse == true ? 'Y' : 'y')}/{(defaultResponse == false ? 'N' : 'n')}): ", false, cancellationToken); var responseString = await console.ReadLineAsync(false, cancellationToken); - var upperResponse = responseString.ToUpperInvariant(); - if (upperResponse == "Y" || upperResponse == "YES") - return true; - else if (upperResponse == "N" || upperResponse == "NO") - return false; + if (responseString.Length == 0) + { + if (defaultResponse.HasValue) + return defaultResponse.Value; + } + else + { + var upperResponse = responseString.ToUpperInvariant(); + if (upperResponse == "Y" || upperResponse == "YES") + return true; + else if (upperResponse == "N" || upperResponse == "NO") + return false; + } + await console.WriteAsync("Invalid response!", true, cancellationToken); } while (true); @@ -316,7 +327,8 @@ namespace Tgstation.Server.Host.Setup await console.WriteAsync("Note, this relative path (currently) resolves to the following:", true, cancellationToken); await console.WriteAsync(resolvedPath, true, cancellationToken); bool writeResolved = await PromptYesNo( - "Would you like to save the relative path in the configuration? If not, the full path will be saved. (y/n): ", + "Would you like to save the relative path in the configuration? If not, the full path will be saved.", + null, cancellationToken); if (writeResolved) @@ -405,6 +417,7 @@ namespace Tgstation.Server.Host.Setup ushort? serverPort = null; bool isSqliteDB = databaseConfiguration.DatabaseType == DatabaseType.Sqlite; + IPHostEntry serverAddressEntry = null; if (!isSqliteDB) do { @@ -430,7 +443,20 @@ namespace Tgstation.Server.Host.Setup } } - break; + try + { + if (serverAddress != null) + { + await console.WriteAsync("Attempting to resolve address...", true, cancellationToken); + serverAddressEntry = await Dns.GetHostEntryAsync(serverAddress, cancellationToken); + } + + break; + } + catch (Exception ex) + { + await console.WriteAsync($"Unable to resolve address: {ex.Message}", true, cancellationToken); + } } while (true); @@ -451,7 +477,10 @@ namespace Tgstation.Server.Host.Setup databaseName = await ValidateNonExistantSqliteDBName(databaseName, cancellationToken); } else - dbExists = await PromptYesNo("Does this database already exist? If not, we will attempt to CREATE it. (y/n): ", cancellationToken); + dbExists = await PromptYesNo( + "Does this database already exist? If not, we will attempt to CREATE it.", + null, + cancellationToken); } if (String.IsNullOrWhiteSpace(databaseName)) @@ -463,7 +492,12 @@ namespace Tgstation.Server.Host.Setup bool useWinAuth; if (databaseConfiguration.DatabaseType == DatabaseType.SqlServer && platformIdentifier.IsWindows) - useWinAuth = await PromptYesNo("Use Windows Authentication? (y/n): ", cancellationToken); + { + var defaultResponse = serverAddressEntry.AddressList.Any(IPAddress.IsLoopback) + ? (bool?)true + : null; + useWinAuth = await PromptYesNo("Use Windows Authentication?", defaultResponse, cancellationToken); + } else useWinAuth = false; @@ -648,7 +682,7 @@ namespace Tgstation.Server.Host.Setup if (String.IsNullOrWhiteSpace(newGeneralConfiguration.GitHubAccessToken)) newGeneralConfiguration.GitHubAccessToken = null; - newGeneralConfiguration.HostApiDocumentation = await PromptYesNo("Host API Documentation? (y/n): ", cancellationToken); + newGeneralConfiguration.HostApiDocumentation = await PromptYesNo("Host API Documentation?", false, cancellationToken); return newGeneralConfiguration; } @@ -662,7 +696,7 @@ namespace Tgstation.Server.Host.Setup { var fileLoggingConfiguration = new FileLoggingConfiguration(); await console.WriteAsync(null, true, cancellationToken); - fileLoggingConfiguration.Disable = !await PromptYesNo("Enable file logging? (y/n): ", cancellationToken); + fileLoggingConfiguration.Disable = !await PromptYesNo("Enable file logging?", true, cancellationToken); if (!fileLoggingConfiguration.Disable) { @@ -747,7 +781,7 @@ namespace Tgstation.Server.Host.Setup { var elasticsearchConfiguration = new ElasticsearchConfiguration(); await console.WriteAsync(null, true, cancellationToken); - elasticsearchConfiguration.Enable = await PromptYesNo("Enable logging to an external ElasticSearch server? (y/n): ", cancellationToken); + elasticsearchConfiguration.Enable = await PromptYesNo("Enable logging to an external ElasticSearch server?", false, cancellationToken); if (elasticsearchConfiguration.Enable) { @@ -797,8 +831,11 @@ namespace Tgstation.Server.Host.Setup { var config = new ControlPanelConfiguration { - Enable = await PromptYesNo("Enable the web control panel? (y/n): ", cancellationToken), - AllowAnyOrigin = await PromptYesNo("Allow web control panels hosted elsewhere to access the server? (Access-Control-Allow-Origin: *) (y/n): ", cancellationToken), + Enable = await PromptYesNo("Enable the web control panel?", true, cancellationToken), + AllowAnyOrigin = await PromptYesNo( + "Allow web control panels hosted elsewhere to access the server? (Access-Control-Allow-Origin: *)", + true, + cancellationToken), }; if (!config.AllowAnyOrigin) @@ -822,7 +859,7 @@ namespace Tgstation.Server.Host.Setup /// A resulting in the new . async Task ConfigureSwarm(CancellationToken cancellationToken) { - var enable = await PromptYesNo("Enable swarm mode? (y/n): ", cancellationToken); + var enable = await PromptYesNo("Enable swarm mode?", false, cancellationToken); if (!enable) return null; @@ -860,7 +897,7 @@ namespace Tgstation.Server.Host.Setup } while (String.IsNullOrWhiteSpace(privateKey)); - var controller = await PromptYesNo("Is this server the swarm's controller? (y/n): ", cancellationToken); + var controller = await PromptYesNo("Is this server the swarm's controller? (y/n): ", null, cancellationToken); Uri controllerAddress = null; if (!controller) controllerAddress = await ParseAddress("Enter the swarm controller's HTTP(S) address: "); @@ -1065,7 +1102,7 @@ namespace Tgstation.Server.Host.Setup { await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "The configuration settings are requesting the setup wizard be run, but you already appear to have a configuration file ({0})!", userConfigFileName), true, cancellationToken); - forceRun = await PromptYesNo("Continue running setup wizard? (y/n): ", cancellationToken); + forceRun = await PromptYesNo("Continue running setup wizard?", false, cancellationToken); } if (!forceRun) diff --git a/tests/Tgstation.Server.Host.Tests/Setup/TestSetupWizard.cs b/tests/Tgstation.Server.Host.Tests/Setup/TestSetupWizard.cs index 841f97bfd1..8edbf59c70 100644 --- a/tests/Tgstation.Server.Host.Tests/Setup/TestSetupWizard.cs +++ b/tests/Tgstation.Server.Host.Tests/Setup/TestSetupWizard.cs @@ -152,14 +152,14 @@ namespace Tgstation.Server.Host.Setup.Tests "666", "FakeDBType", nameof(DatabaseType.SqlServer), - "this isn't validated", + "localhost", "nor is this", "no", //test winauth "yes", //sql server will always fail so reconfigure with maria nameof(DatabaseType.MariaDB), - "bleh", + "127.0.0.1", "blah", "NO", "user", @@ -187,7 +187,7 @@ namespace Tgstation.Server.Host.Setup.Tests String.Empty, //test MySQL errors nameof(DatabaseType.MySql), - String.Empty, + "::1", String.Empty, "DbName", "n",