diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs index 77c895a57fe..e535df16879 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs @@ -214,7 +214,7 @@ public async Task CreateTenantSettingsAsync(TenantSetupOptions se shellSettings["ConnectionString"] = setupOptions.DatabaseConnectionString; shellSettings["TablePrefix"] = setupOptions.DatabaseTablePrefix; - shellSettings["DatabaseProvider"] = setupOptions.DatabaseProvider; + shellSettings["DatabaseProvider"] = setupOptions.DatabaseProvider.ToString(); shellSettings["Secret"] = Guid.NewGuid().ToString(); shellSettings["RecipeName"] = setupOptions.RecipeName; diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Options/TenantSetupOptions.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Options/TenantSetupOptions.cs index 23e2cfa9793..10b53b7897b 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Options/TenantSetupOptions.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Options/TenantSetupOptions.cs @@ -43,7 +43,7 @@ public class TenantSetupOptions /// /// Gets or sets the database provider. /// - public string DatabaseProvider { get; set; } + public DatabaseProviderName DatabaseProvider { get; set; } /// /// Gets or sets the database connection string. diff --git a/src/OrchardCore.Modules/OrchardCore.Setup/Controllers/SetupController.cs b/src/OrchardCore.Modules/OrchardCore.Setup/Controllers/SetupController.cs index 6004a691a2b..4be0f0f9451 100644 --- a/src/OrchardCore.Modules/OrchardCore.Setup/Controllers/SetupController.cs +++ b/src/OrchardCore.Modules/OrchardCore.Setup/Controllers/SetupController.cs @@ -26,7 +26,7 @@ public class SetupController : Controller private readonly ISetupService _setupService; private readonly ShellSettings _shellSettings; private readonly IShellHost _shellHost; - private IdentityOptions _identityOptions; + private readonly IdentityOptions _identityOptions; private readonly IEmailAddressValidator _emailAddressValidator; private readonly IEnumerable _databaseProviders; private readonly ILogger _logger; @@ -59,13 +59,9 @@ public async Task Index(string token) var recipes = await _setupService.GetSetupRecipesAsync(); var defaultRecipe = recipes.FirstOrDefault(x => x.Tags.Contains("default")) ?? recipes.FirstOrDefault(); - if (!string.IsNullOrWhiteSpace(_shellSettings["Secret"])) + if (!await ShouldProceedWithTokenAsync(token)) { - if (string.IsNullOrEmpty(token) || !await IsTokenValid(token)) - { - _logger.LogWarning("An attempt to access '{TenantName}' without providing a secret was made", _shellSettings.Name); - return StatusCode(404); - } + return StatusCode(404); } var model = new SetupViewModel @@ -90,28 +86,14 @@ public async Task Index(string token) [HttpPost, ActionName("Index")] public async Task IndexPOST(SetupViewModel model) { - if (!string.IsNullOrWhiteSpace(_shellSettings["Secret"])) + if (!await ShouldProceedWithTokenAsync(model.Secret)) { - if (string.IsNullOrEmpty(model.Secret) || !await IsTokenValid(model.Secret)) - { - _logger.LogWarning("An attempt to access '{TenantName}' without providing a valid secret was made", _shellSettings.Name); - return StatusCode(404); - } + return StatusCode(404); } model.DatabaseProviders = _databaseProviders; model.Recipes = await _setupService.GetSetupRecipesAsync(); - var selectedProvider = model.DatabaseProviders.FirstOrDefault(x => x.Value == model.DatabaseProvider); - - if (!model.DatabaseConfigurationPreset) - { - if (selectedProvider != null && selectedProvider.HasConnectionString && String.IsNullOrWhiteSpace(model.ConnectionString)) - { - ModelState.AddModelError(nameof(model.ConnectionString), S["The connection string is mandatory for this provider."]); - } - } - if (String.IsNullOrEmpty(model.Password)) { ModelState.AddModelError(nameof(model.Password), S["The password is required."]); @@ -123,7 +105,7 @@ public async Task IndexPOST(SetupViewModel model) } RecipeDescriptor selectedRecipe = null; - if (!string.IsNullOrEmpty(_shellSettings["RecipeName"])) + if (!String.IsNullOrEmpty(_shellSettings["RecipeName"])) { selectedRecipe = model.Recipes.FirstOrDefault(x => x.Name == _shellSettings["RecipeName"]); if (selectedRecipe == null) @@ -169,8 +151,9 @@ public async Task IndexPOST(SetupViewModel model) } }; - if (!string.IsNullOrEmpty(_shellSettings["ConnectionString"])) + if (!String.IsNullOrEmpty(_shellSettings["ConnectionString"])) { + model.DatabaseConfigurationPreset = true; setupContext.Properties[SetupConstants.DatabaseProvider] = _shellSettings["DatabaseProvider"]; setupContext.Properties[SetupConstants.DatabaseConnectionString] = _shellSettings["ConnectionString"]; setupContext.Properties[SetupConstants.DatabaseTablePrefix] = _shellSettings["TablePrefix"]; @@ -184,7 +167,7 @@ public async Task IndexPOST(SetupViewModel model) var executionId = await _setupService.SetupAsync(setupContext); - // Check if a component in the Setup failed + // Check if any Setup component failed (e.g., database connection validation) if (setupContext.Errors.Any()) { foreach (var error in setupContext.Errors) @@ -215,9 +198,13 @@ private void CopyShellSettingsValues(SetupViewModel model) if (!String.IsNullOrEmpty(_shellSettings["DatabaseProvider"])) { model.DatabaseConfigurationPreset = true; - model.DatabaseProvider = _shellSettings["DatabaseProvider"]; + if (Enum.TryParse(_shellSettings["DatabaseProvider"], out DatabaseProviderName providerName)) + { + model.DatabaseProvider = providerName; + } } - else + + if (!model.DatabaseProvider.HasValue) { model.DatabaseProvider = model.DatabaseProviders.FirstOrDefault(p => p.IsDefault)?.Value; } @@ -228,6 +215,21 @@ private void CopyShellSettingsValues(SetupViewModel model) } } + private async Task ShouldProceedWithTokenAsync(string token) + { + if (!String.IsNullOrWhiteSpace(_shellSettings["Secret"])) + { + if (String.IsNullOrEmpty(token) || !await IsTokenValid(token)) + { + _logger.LogWarning("An attempt to access '{TenantName}' without providing a secret was made", _shellSettings.Name); + + return false; + } + } + + return true; + } + private async Task IsTokenValid(string token) { try diff --git a/src/OrchardCore.Modules/OrchardCore.Setup/ViewModels/SetupViewModel.cs b/src/OrchardCore.Modules/OrchardCore.Setup/ViewModels/SetupViewModel.cs index efae2f92820..53b4b3b49d4 100644 --- a/src/OrchardCore.Modules/OrchardCore.Setup/ViewModels/SetupViewModel.cs +++ b/src/OrchardCore.Modules/OrchardCore.Setup/ViewModels/SetupViewModel.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; +using Microsoft.AspNetCore.Mvc.ModelBinding; using OrchardCore.Data; using OrchardCore.Recipes.Models; using OrchardCore.Setup.Annotations; @@ -15,7 +16,7 @@ public class SetupViewModel public string Description { get; set; } - public string DatabaseProvider { get; set; } + public DatabaseProviderName? DatabaseProvider { get; set; } public string ConnectionString { get; set; } @@ -24,6 +25,7 @@ public class SetupViewModel /// /// True if the database configuration is preset and can't be changed or displayed on the Setup screen. /// + [BindNever] public bool DatabaseConfigurationPreset { get; set; } [Required] @@ -38,8 +40,10 @@ public class SetupViewModel [DataType(DataType.Password)] public string PasswordConfirmation { get; set; } + [BindNever] public IEnumerable DatabaseProviders { get; set; } = Enumerable.Empty(); + [BindNever] public IEnumerable Recipes { get; set; } public bool RecipeNamePreset { get; set; } diff --git a/src/OrchardCore.Modules/OrchardCore.Setup/Views/Setup/Index.cshtml b/src/OrchardCore.Modules/OrchardCore.Setup/Views/Setup/Index.cshtml index 8d8272d2e13..3450338a417 100644 --- a/src/OrchardCore.Modules/OrchardCore.Setup/Views/Setup/Index.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.Setup/Views/Setup/Index.cshtml @@ -66,6 +66,7 @@ var passwordTooltip = T["Password must have at least {0}.", passwordOptions]; }
+
@if (LocOptions.Value.SupportedUICultures.Count() > 1) { @@ -92,6 +93,9 @@

@T["Setup"]

@T["Please answer a few questions to configure your site."]

+ +
+ @if (defaultRecipe == null) {