From 5c0cfbe7f17ea8673b430db6cc4e720c0f1f2e21 Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 4 Oct 2024 11:42:33 -0400 Subject: [PATCH 01/28] In Auto setup, when IsUninitialized, response http status code 409 --- .../AutoSetupMiddleware.cs | 117 +------------- .../Services/AutoSetupService.cs | 146 ++++++++++++++++++ .../Services/IAutoSetupService.cs | 11 ++ .../OrchardCore.AutoSetup/Startup.cs | 3 + 4 files changed, 165 insertions(+), 112 deletions(-) create mode 100644 src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs create mode 100644 src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs index 19411e2f406..6e44e618df7 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs @@ -1,14 +1,12 @@ -using System.Text; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using OrchardCore.Abstractions.Setup; using OrchardCore.AutoSetup.Extensions; using OrchardCore.AutoSetup.Options; +using OrchardCore.AutoSetup.Services; using OrchardCore.Environment.Shell; using OrchardCore.Locking.Distributed; -using OrchardCore.Setup.Services; namespace OrchardCore.AutoSetup; @@ -131,13 +129,13 @@ public async Task InvokeAsync(HttpContext httpContext) if (!settings.IsUninitialized()) { await _shellHost.ReloadShellContextAsync(_shellSettings, eventSource: false); - httpContext.Response.Redirect(pathBase); + httpContext.Response.StatusCode = 409; return; } - var setupService = httpContext.RequestServices.GetRequiredService(); - if (await SetupTenantAsync(setupService, _setupOptions, _shellSettings)) + var autoSetupService = httpContext.RequestServices.GetRequiredService(); + if (await autoSetupService.SetupTenantAsync(_setupOptions, _shellSettings)) { if (_setupOptions.IsDefault) { @@ -146,7 +144,7 @@ public async Task InvokeAsync(HttpContext httpContext) { if (_setupOptions != setupOptions) { - await CreateTenantSettingsAsync(setupOptions); + await autoSetupService.CreateTenantSettingsAsync(setupOptions); } } } @@ -160,109 +158,4 @@ public async Task InvokeAsync(HttpContext httpContext) await _next.Invoke(httpContext); } - - /// - /// Sets up a tenant. - /// - /// The setup service. - /// The tenant setup options. - /// The tenant shell settings. - /// - /// Returns true if successfully setup. - /// - public async Task SetupTenantAsync(ISetupService setupService, TenantSetupOptions setupOptions, ShellSettings shellSettings) - { - var setupContext = await GetSetupContextAsync(setupOptions, setupService, shellSettings); - - _logger.LogInformation("AutoSetup is initializing the site"); - - await setupService.SetupAsync(setupContext); - - if (setupContext.Errors.Count == 0) - { - _logger.LogInformation("AutoSetup successfully provisioned the site '{SiteName}'.", setupOptions.SiteName); - - return true; - } - - var stringBuilder = new StringBuilder(); - foreach (var error in setupContext.Errors) - { - stringBuilder.AppendLine($"{error.Key} : '{error.Value}'"); - } - - _logger.LogError("AutoSetup failed installing the site '{SiteName}' with errors: {Errors}", setupOptions.SiteName, stringBuilder); - - return false; - } - - /// - /// Creates a tenant shell settings. - /// - /// The setup options. - /// The . - public async Task CreateTenantSettingsAsync(TenantSetupOptions setupOptions) - { - using var shellSettings = _shellSettingsManager - .CreateDefaultSettings() - .AsUninitialized() - .AsDisposable(); - - shellSettings.Name = setupOptions.ShellName; - shellSettings.RequestUrlHost = setupOptions.RequestUrlHost; - shellSettings.RequestUrlPrefix = setupOptions.RequestUrlPrefix; - - shellSettings["ConnectionString"] = setupOptions.DatabaseConnectionString; - shellSettings["TablePrefix"] = setupOptions.DatabaseTablePrefix; - shellSettings["Schema"] = setupOptions.DatabaseSchema; - shellSettings["DatabaseProvider"] = setupOptions.DatabaseProvider; - shellSettings["Secret"] = Guid.NewGuid().ToString(); - shellSettings["RecipeName"] = setupOptions.RecipeName; - shellSettings["FeatureProfile"] = setupOptions.FeatureProfile; - - await _shellHost.UpdateShellSettingsAsync(shellSettings); - - return shellSettings; - } - - /// - /// Gets a setup context from the configuration. - /// - /// The tenant setup options. - /// The setup service. - /// The tenant shell settings. - /// The used to setup the site. - private static async Task GetSetupContextAsync(TenantSetupOptions options, ISetupService setupService, ShellSettings shellSettings) - { - var recipes = await setupService.GetSetupRecipesAsync(); - - var recipe = recipes.SingleOrDefault(r => r.Name == options.RecipeName); - - var setupContext = new SetupContext - { - Recipe = recipe, - ShellSettings = shellSettings, - Errors = new Dictionary() - }; - - if (shellSettings.IsDefaultShell()) - { - // The 'Default' shell is first created by the infrastructure, - // so the following 'Autosetup' options need to be passed. - shellSettings.RequestUrlHost = options.RequestUrlHost; - shellSettings.RequestUrlPrefix = options.RequestUrlPrefix; - } - - setupContext.Properties[SetupConstants.AdminEmail] = options.AdminEmail; - setupContext.Properties[SetupConstants.AdminPassword] = options.AdminPassword; - setupContext.Properties[SetupConstants.AdminUsername] = options.AdminUsername; - setupContext.Properties[SetupConstants.DatabaseConnectionString] = options.DatabaseConnectionString; - setupContext.Properties[SetupConstants.DatabaseProvider] = options.DatabaseProvider; - setupContext.Properties[SetupConstants.DatabaseTablePrefix] = options.DatabaseTablePrefix; - setupContext.Properties[SetupConstants.DatabaseSchema] = options.DatabaseSchema; - setupContext.Properties[SetupConstants.SiteName] = options.SiteName; - setupContext.Properties[SetupConstants.SiteTimeZone] = options.SiteTimeZone; - - return setupContext; - } } diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs new file mode 100644 index 00000000000..992f5e5ea54 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs @@ -0,0 +1,146 @@ +using System.Text; +using Microsoft.Extensions.Logging; +using OrchardCore.Abstractions.Setup; +using OrchardCore.AutoSetup.Options; +using OrchardCore.Environment.Shell; +using OrchardCore.Setup.Services; + +namespace OrchardCore.AutoSetup.Services; +public class AutoSetupService : IAutoSetupService +{ + /// + /// The shell host. + /// + private readonly IShellHost _shellHost; + + /// + /// The shell settings manager. + /// + private readonly IShellSettingsManager _shellSettingsManager; + + /// + /// The setup service. + /// + private readonly ISetupService _setupService; + + /// + /// The logger. + /// + private readonly ILogger _logger; + + public AutoSetupService( + IShellHost shellHost, + IShellSettingsManager shellSettingsManager, + ISetupService setupService, + ILogger logger + ) + { + _shellHost = shellHost; + _shellSettingsManager = shellSettingsManager; + _setupService = setupService; + _logger = logger; + } + + /// + /// Sets up a tenant. + /// + /// The tenant setup options. + /// The tenant shell settings. + /// + /// Returns true if successfully setup. + /// + public async Task SetupTenantAsync(TenantSetupOptions setupOptions, ShellSettings shellSettings) + { + var setupContext = await GetSetupContextAsync(setupOptions, shellSettings); + + _logger.LogInformation("AutoSetup is initializing the site"); + + await _setupService.SetupAsync(setupContext); + + if (setupContext.Errors.Count == 0) + { + _logger.LogInformation("AutoSetup successfully provisioned the site '{SiteName}'.", setupOptions.SiteName); + + return true; + } + + var stringBuilder = new StringBuilder(); + foreach (var error in setupContext.Errors) + { + stringBuilder.AppendLine($"{error.Key} : '{error.Value}'"); + } + + _logger.LogError("AutoSetup failed installing the site '{SiteName}' with errors: {Errors}", setupOptions.SiteName, stringBuilder); + + return false; + } + + /// + /// Creates a tenant shell settings. + /// + /// The setup options. + /// The . + public async Task CreateTenantSettingsAsync(TenantSetupOptions setupOptions) + { + using var shellSettings = _shellSettingsManager + .CreateDefaultSettings() + .AsUninitialized() + .AsDisposable(); + + shellSettings.Name = setupOptions.ShellName; + shellSettings.RequestUrlHost = setupOptions.RequestUrlHost; + shellSettings.RequestUrlPrefix = setupOptions.RequestUrlPrefix; + + shellSettings["ConnectionString"] = setupOptions.DatabaseConnectionString; + shellSettings["TablePrefix"] = setupOptions.DatabaseTablePrefix; + shellSettings["Schema"] = setupOptions.DatabaseSchema; + shellSettings["DatabaseProvider"] = setupOptions.DatabaseProvider; + shellSettings["Secret"] = Guid.NewGuid().ToString(); + shellSettings["RecipeName"] = setupOptions.RecipeName; + shellSettings["FeatureProfile"] = setupOptions.FeatureProfile; + + await _shellHost.UpdateShellSettingsAsync(shellSettings); + + return shellSettings; + } + + /// + /// Gets a setup context from the configuration. + /// + /// The tenant setup options. + /// The tenant shell settings. + /// The used to setup the site. + public async Task GetSetupContextAsync(TenantSetupOptions options, ShellSettings shellSettings) + { + var recipes = await _setupService.GetSetupRecipesAsync(); + + var recipe = recipes.SingleOrDefault(r => r.Name == options.RecipeName); + + var setupContext = new SetupContext + { + Recipe = recipe, + ShellSettings = shellSettings, + Errors = new Dictionary() + }; + + if (shellSettings.IsDefaultShell()) + { + // The 'Default' shell is first created by the infrastructure, + // so the following 'Autosetup' options need to be passed. + shellSettings.RequestUrlHost = options.RequestUrlHost; + shellSettings.RequestUrlPrefix = options.RequestUrlPrefix; + } + + setupContext.Properties[SetupConstants.AdminEmail] = options.AdminEmail; + setupContext.Properties[SetupConstants.AdminPassword] = options.AdminPassword; + setupContext.Properties[SetupConstants.AdminUsername] = options.AdminUsername; + setupContext.Properties[SetupConstants.DatabaseConnectionString] = options.DatabaseConnectionString; + setupContext.Properties[SetupConstants.DatabaseProvider] = options.DatabaseProvider; + setupContext.Properties[SetupConstants.DatabaseTablePrefix] = options.DatabaseTablePrefix; + setupContext.Properties[SetupConstants.DatabaseSchema] = options.DatabaseSchema; + setupContext.Properties[SetupConstants.SiteName] = options.SiteName; + setupContext.Properties[SetupConstants.SiteTimeZone] = options.SiteTimeZone; + + return setupContext; + } +} diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs new file mode 100644 index 00000000000..4f6fe5200ff --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs @@ -0,0 +1,11 @@ +using OrchardCore.AutoSetup.Options; +using OrchardCore.Environment.Shell; +using OrchardCore.Setup.Services; + +namespace OrchardCore.AutoSetup.Services; +public interface IAutoSetupService +{ + Task CreateTenantSettingsAsync(TenantSetupOptions setupOptions); + Task GetSetupContextAsync(TenantSetupOptions options, ShellSettings shellSettings); + Task SetupTenantAsync(TenantSetupOptions setupOptions, ShellSettings shellSettings); +} \ No newline at end of file diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Startup.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Startup.cs index fe2567d190e..8198afb7e3c 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Startup.cs @@ -7,6 +7,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using OrchardCore.AutoSetup.Options; +using OrchardCore.AutoSetup.Services; using OrchardCore.Environment.Shell; using OrchardCore.Environment.Shell.Configuration; using OrchardCore.Modules; @@ -67,6 +68,8 @@ public override void ConfigureServices(IServiceCollection services) { services.Configure(o => o.ConfigurationExists = true); } + + services.AddScoped(); } /// From cbb43d264bea75ec1993d8529de57a972c4771ac Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 4 Oct 2024 12:04:57 -0400 Subject: [PATCH 02/28] Remove ILogger --- .../OrchardCore.AutoSetup/AutoSetupMiddleware.cs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs index 6e44e618df7..3f46e6bd115 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs @@ -1,6 +1,5 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using OrchardCore.AutoSetup.Extensions; using OrchardCore.AutoSetup.Options; @@ -45,11 +44,6 @@ public class AutoSetupMiddleware /// private readonly AutoSetupOptions _options; - /// - /// The logger. - /// - private readonly ILogger _logger; - /// /// The auto setup lock options. /// @@ -68,16 +62,14 @@ public class AutoSetupMiddleware /// The shell settings. /// The shell settings manager. /// The distributed lock. - /// The auto setup options. - /// The logger. + /// The auto setup options. public AutoSetupMiddleware( RequestDelegate next, IShellHost shellHost, ShellSettings shellSettings, IShellSettingsManager shellSettingsManager, IDistributedLock distributedLock, - IOptions options, - ILogger logger) + IOptions options) { _next = next; _shellHost = shellHost; @@ -85,8 +77,6 @@ public AutoSetupMiddleware( _shellSettingsManager = shellSettingsManager; _distributedLock = distributedLock; _options = options.Value; - _logger = logger; - _lockOptions = _options.LockOptions; _setupOptions = _options.Tenants.FirstOrDefault(options => _shellSettings.Name == options.ShellName); } From 1573e53359ba6486bf5053cdb5a88bbcf5a50a9c Mon Sep 17 00:00:00 2001 From: andy Date: Fri, 4 Oct 2024 12:17:14 -0400 Subject: [PATCH 03/28] Update src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs Co-authored-by: Hisham Bin Ateya --- .../OrchardCore.AutoSetup/Services/IAutoSetupService.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs index 4f6fe5200ff..c2b2730e540 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs @@ -3,9 +3,12 @@ using OrchardCore.Setup.Services; namespace OrchardCore.AutoSetup.Services; + public interface IAutoSetupService { Task CreateTenantSettingsAsync(TenantSetupOptions setupOptions); + Task GetSetupContextAsync(TenantSetupOptions options, ShellSettings shellSettings); + Task SetupTenantAsync(TenantSetupOptions setupOptions, ShellSettings shellSettings); } \ No newline at end of file From ff715ae5c491b0ac50db2e0638443ec7ab5a2a30 Mon Sep 17 00:00:00 2001 From: andy Date: Fri, 4 Oct 2024 12:17:38 -0400 Subject: [PATCH 04/28] Update src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs Co-authored-by: Hisham Bin Ateya --- .../Services/AutoSetupService.cs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs index 992f5e5ea54..b718d800fc6 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs @@ -8,24 +8,9 @@ namespace OrchardCore.AutoSetup.Services; public class AutoSetupService : IAutoSetupService { - /// - /// The shell host. - /// private readonly IShellHost _shellHost; - - /// - /// The shell settings manager. - /// private readonly IShellSettingsManager _shellSettingsManager; - - /// - /// The setup service. - /// private readonly ISetupService _setupService; - - /// - /// The logger. - /// private readonly ILogger _logger; public AutoSetupService( From 5ffc4aa00fb69a38a750c23aea26f1e3c5e3d223 Mon Sep 17 00:00:00 2001 From: andy Date: Fri, 4 Oct 2024 12:18:02 -0400 Subject: [PATCH 05/28] Update src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs Co-authored-by: Hisham Bin Ateya --- .../OrchardCore.AutoSetup/Services/AutoSetupService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs index b718d800fc6..46e637037dc 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs @@ -55,7 +55,7 @@ public async Task SetupTenantAsync(TenantSetupOptions setupOptions, ShellS stringBuilder.AppendLine($"{error.Key} : '{error.Value}'"); } - _logger.LogError("AutoSetup failed installing the site '{SiteName}' with errors: {Errors}", setupOptions.SiteName, stringBuilder); + _logger.LogError("The AutoSetup failed installing the site '{SiteName}' with errors: {Errors}.", setupOptions.SiteName, stringBuilder); return false; } From c02123c17771e3bbe524e411baf3639fce9b2b52 Mon Sep 17 00:00:00 2001 From: andy Date: Fri, 4 Oct 2024 12:18:13 -0400 Subject: [PATCH 06/28] Update src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs Co-authored-by: Hisham Bin Ateya --- .../OrchardCore.AutoSetup/Services/AutoSetupService.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs index 46e637037dc..cd8573eaed2 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs @@ -75,7 +75,6 @@ public async Task CreateTenantSettingsAsync(TenantSetupOptions se shellSettings.Name = setupOptions.ShellName; shellSettings.RequestUrlHost = setupOptions.RequestUrlHost; shellSettings.RequestUrlPrefix = setupOptions.RequestUrlPrefix; - shellSettings["ConnectionString"] = setupOptions.DatabaseConnectionString; shellSettings["TablePrefix"] = setupOptions.DatabaseTablePrefix; shellSettings["Schema"] = setupOptions.DatabaseSchema; From 281daa4e8fe4574b511e7d93d700495d3c2f99fc Mon Sep 17 00:00:00 2001 From: andy Date: Fri, 4 Oct 2024 12:18:37 -0400 Subject: [PATCH 07/28] Update src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs Co-authored-by: Hisham Bin Ateya --- .../OrchardCore.AutoSetup/Services/AutoSetupService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs index cd8573eaed2..9fbe29b8fc1 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs @@ -44,7 +44,7 @@ public async Task SetupTenantAsync(TenantSetupOptions setupOptions, ShellS if (setupContext.Errors.Count == 0) { - _logger.LogInformation("AutoSetup successfully provisioned the site '{SiteName}'.", setupOptions.SiteName); + _logger.LogInformation("The AutoSetup successfully provisioned the site '{SiteName}'.", setupOptions.SiteName); return true; } From 511dc12d14b1ab46ec5bdd6be4ff71f431fcdb09 Mon Sep 17 00:00:00 2001 From: andy Date: Fri, 4 Oct 2024 12:18:52 -0400 Subject: [PATCH 08/28] Update src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs Co-authored-by: Hisham Bin Ateya --- .../OrchardCore.AutoSetup/Services/AutoSetupService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs index 9fbe29b8fc1..ee6fea89739 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs @@ -38,7 +38,7 @@ public async Task SetupTenantAsync(TenantSetupOptions setupOptions, ShellS { var setupContext = await GetSetupContextAsync(setupOptions, shellSettings); - _logger.LogInformation("AutoSetup is initializing the site"); + _logger.LogInformation("The AutoSetup is initializing the site."); await _setupService.SetupAsync(setupContext); From 7a51f4483a3bce418fb586b7b1f7bfdc2215e42d Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 4 Oct 2024 12:22:40 -0400 Subject: [PATCH 09/28] Move the docs to the interface --- .../Services/AutoSetupService.cs | 25 +++---------------- .../Services/IAutoSetupService.cs | 23 +++++++++++++++-- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs index ee6fea89739..64f941237b8 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs @@ -25,15 +25,7 @@ ILogger logger _setupService = setupService; _logger = logger; } - - /// - /// Sets up a tenant. - /// - /// The tenant setup options. - /// The tenant shell settings. - /// - /// Returns true if successfully setup. - /// + public async Task SetupTenantAsync(TenantSetupOptions setupOptions, ShellSettings shellSettings) { var setupContext = await GetSetupContextAsync(setupOptions, shellSettings); @@ -59,12 +51,7 @@ public async Task SetupTenantAsync(TenantSetupOptions setupOptions, ShellS return false; } - - /// - /// Creates a tenant shell settings. - /// - /// The setup options. - /// The . + public async Task CreateTenantSettingsAsync(TenantSetupOptions setupOptions) { using var shellSettings = _shellSettingsManager @@ -87,13 +74,7 @@ public async Task CreateTenantSettingsAsync(TenantSetupOptions se return shellSettings; } - - /// - /// Gets a setup context from the configuration. - /// - /// The tenant setup options. - /// The tenant shell settings. - /// The used to setup the site. + public async Task GetSetupContextAsync(TenantSetupOptions options, ShellSettings shellSettings) { var recipes = await _setupService.GetSetupRecipesAsync(); diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs index c2b2730e540..556c85e6b41 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs @@ -1,4 +1,4 @@ -using OrchardCore.AutoSetup.Options; +using OrchardCore.AutoSetup.Options; using OrchardCore.Environment.Shell; using OrchardCore.Setup.Services; @@ -6,9 +6,28 @@ namespace OrchardCore.AutoSetup.Services; public interface IAutoSetupService { + /// + /// Creates a tenant shell settings. + /// + /// The setup options. + /// The . Task CreateTenantSettingsAsync(TenantSetupOptions setupOptions); + /// + /// Gets a setup context from the configuration. + /// + /// The tenant setup options. + /// The tenant shell settings. + /// The used to setup the site. Task GetSetupContextAsync(TenantSetupOptions options, ShellSettings shellSettings); + /// + /// Sets up a tenant. + /// + /// The tenant setup options. + /// The tenant shell settings. + /// + /// Returns true if successfully setup. + /// Task SetupTenantAsync(TenantSetupOptions setupOptions, ShellSettings shellSettings); -} \ No newline at end of file +} From 1fbc8c6933f01c9323486cf680c4672d24cb81b8 Mon Sep 17 00:00:00 2001 From: andy Date: Fri, 4 Oct 2024 13:00:58 -0400 Subject: [PATCH 10/28] Update src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Zoltán Lehóczky --- .../OrchardCore.AutoSetup/Services/IAutoSetupService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs index 556c85e6b41..d662153ba50 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs @@ -27,7 +27,7 @@ public interface IAutoSetupService /// The tenant setup options. /// The tenant shell settings. /// - /// Returns true if successfully setup. + /// Returns if successfully setup. /// Task SetupTenantAsync(TenantSetupOptions setupOptions, ShellSettings shellSettings); } From 6f99df3ebdf8c5779c327666886853bab6c4b981 Mon Sep 17 00:00:00 2001 From: andy Date: Fri, 4 Oct 2024 13:01:09 -0400 Subject: [PATCH 11/28] Update src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Zoltán Lehóczky --- .../OrchardCore.AutoSetup/Services/AutoSetupService.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs index 64f941237b8..bc2b9781702 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs @@ -6,6 +6,7 @@ using OrchardCore.Setup.Services; namespace OrchardCore.AutoSetup.Services; + public class AutoSetupService : IAutoSetupService { private readonly IShellHost _shellHost; From 9c25005f32b2b277711e8e2cfe753d5c895c666a Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 4 Oct 2024 13:02:20 -0400 Subject: [PATCH 12/28] change to 503 --- .../OrchardCore.AutoSetup/AutoSetupMiddleware.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs index 3f46e6bd115..dc69af85a88 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs @@ -119,7 +119,7 @@ public async Task InvokeAsync(HttpContext httpContext) if (!settings.IsUninitialized()) { await _shellHost.ReloadShellContextAsync(_shellSettings, eventSource: false); - httpContext.Response.StatusCode = 409; + httpContext.Response.StatusCode = 503; return; } From 2d52d80d6bfc3fde841ca1747e356fcbc611b4e4 Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 4 Oct 2024 22:41:55 -0400 Subject: [PATCH 13/28] Consider the failure situation --- .../OrchardCore.AutoSetup/AutoSetupMiddleware.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs index dc69af85a88..b73f3d8eb48 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs @@ -141,6 +141,12 @@ public async Task InvokeAsync(HttpContext httpContext) httpContext.Response.Redirect(pathBase); + return; + } + else + { + httpContext.Response.StatusCode = 503; + return; } } From 1cf54b3548eec911587bc892b56cb45cf7f9bc7d Mon Sep 17 00:00:00 2001 From: Andy Date: Thu, 10 Oct 2024 20:37:55 -0400 Subject: [PATCH 14/28] Show the error message to the user --- .../OrchardCore.AutoSetup/AutoSetupMiddleware.cs | 16 ++++++++++++---- .../Services/AutoSetupService.cs | 6 +++--- .../Services/IAutoSetupService.cs | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs index b73f3d8eb48..0dbcdd2e98c 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs @@ -1,3 +1,4 @@ +using System.Text; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -119,13 +120,14 @@ public async Task InvokeAsync(HttpContext httpContext) if (!settings.IsUninitialized()) { await _shellHost.ReloadShellContextAsync(_shellSettings, eventSource: false); - httpContext.Response.StatusCode = 503; - + httpContext.Response.StatusCode = StatusCodes.Status503ServiceUnavailable; + await httpContext.Response.WriteAsync("The requested tenant is not initialized."); return; } var autoSetupService = httpContext.RequestServices.GetRequiredService(); - if (await autoSetupService.SetupTenantAsync(_setupOptions, _shellSettings)) + (var setupContext, var isSuccess) = await autoSetupService.SetupTenantAsync(_setupOptions, _shellSettings); + if (isSuccess) { if (_setupOptions.IsDefault) { @@ -145,8 +147,14 @@ public async Task InvokeAsync(HttpContext httpContext) } else { - httpContext.Response.StatusCode = 503; + httpContext.Response.StatusCode = StatusCodes.Status503ServiceUnavailable; + var stringBuilder = new StringBuilder(); + foreach (var error in setupContext.Errors) + { + stringBuilder.AppendLine($"{error.Key} : '{error.Value}'"); + } + await httpContext.Response.WriteAsync($"The AutoSetup failed installing the site '{_setupOptions.SiteName}' with errors: {stringBuilder}."); return; } } diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs index bc2b9781702..cdc66022aa6 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs @@ -27,7 +27,7 @@ ILogger logger _logger = logger; } - public async Task SetupTenantAsync(TenantSetupOptions setupOptions, ShellSettings shellSettings) + public async Task<(SetupContext, bool)> SetupTenantAsync(TenantSetupOptions setupOptions, ShellSettings shellSettings) { var setupContext = await GetSetupContextAsync(setupOptions, shellSettings); @@ -39,7 +39,7 @@ public async Task SetupTenantAsync(TenantSetupOptions setupOptions, ShellS { _logger.LogInformation("The AutoSetup successfully provisioned the site '{SiteName}'.", setupOptions.SiteName); - return true; + return (setupContext,true); } var stringBuilder = new StringBuilder(); @@ -50,7 +50,7 @@ public async Task SetupTenantAsync(TenantSetupOptions setupOptions, ShellS _logger.LogError("The AutoSetup failed installing the site '{SiteName}' with errors: {Errors}.", setupOptions.SiteName, stringBuilder); - return false; + return (setupContext, false); } public async Task CreateTenantSettingsAsync(TenantSetupOptions setupOptions) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs index d662153ba50..93f46b1288d 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/IAutoSetupService.cs @@ -29,5 +29,5 @@ public interface IAutoSetupService /// /// Returns if successfully setup. /// - Task SetupTenantAsync(TenantSetupOptions setupOptions, ShellSettings shellSettings); + Task<(SetupContext, bool)> SetupTenantAsync(TenantSetupOptions setupOptions, ShellSettings shellSettings); } From 23333d7e07af60ebb0c741ab6f8a5fbc7742f58b Mon Sep 17 00:00:00 2001 From: Andy Date: Sat, 12 Oct 2024 13:14:20 -0400 Subject: [PATCH 15/28] Test -- InvokeAsync_InitializedShell_SkipsSetup --- .../AutoSetupMiddlewareTests.cs | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs diff --git a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs new file mode 100644 index 00000000000..50f97c68648 --- /dev/null +++ b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Options; +using Moq; +using OrchardCore.AutoSetup.Options; +using OrchardCore.AutoSetup.Services; +using OrchardCore.Environment.Shell; +using OrchardCore.Locking; +using OrchardCore.Locking.Distributed; +using OrchardCore.Setup.Services; +using Xunit; +using OrchardCore.AutoSetup; +using OrchardCore.AutoSetup.Extensions; +using OrchardCore.Environment.Shell.Models; + +namespace OrchardCore.Tests.Modules.OrchardCore.AutoSetup; + +public class AutoSetupMiddlewareTests +{ + private readonly Mock _mockShellHost; + private readonly ShellSettings _shellSettings; + private readonly Mock _mockShellSettingsManager; + private readonly Mock _mockDistributedLock; + private readonly Mock> _mockOptions; + private readonly Mock _mockAutoSetupService; + + public AutoSetupMiddlewareTests() + { + _mockShellHost = new Mock(); + _shellSettings = new ShellSettings(); + _mockShellSettingsManager = new Mock(); + _mockDistributedLock = new Mock(); + _mockOptions = new Mock>(); + _mockAutoSetupService = new Mock(); + + _mockOptions.Setup(o => o.Value).Returns(new AutoSetupOptions + { + LockOptions = new LockOptions(), + Tenants = new List + { + new TenantSetupOptions { ShellName = ShellSettings.DefaultShellName } + } + }); + } + + [Fact] + public async Task InvokeAsync_InitializedShell_SkipsSetup() + { + // Arrange + _shellSettings.State = TenantState.Running; + + var httpContext = new DefaultHttpContext(); + var nextCalled = false; + + var middleware = new AutoSetupMiddleware( + next: (innerHttpContext) => { nextCalled = true; return Task.CompletedTask; }, + _mockShellHost.Object, + _shellSettings, + _mockShellSettingsManager.Object, + _mockDistributedLock.Object, + _mockOptions.Object); + + // Act + await middleware.InvokeAsync(httpContext); + + // Assert + Assert.True(nextCalled); + _mockAutoSetupService.Verify(s => s.SetupTenantAsync(It.IsAny(), It.IsAny()), Times.Never); + } +} + From 4f665cecc04ac2a46ef52349e89db898aa6b4a32 Mon Sep 17 00:00:00 2001 From: Andy Date: Sat, 12 Oct 2024 14:26:59 -0400 Subject: [PATCH 16/28] InvokeAsync_FailedSetup_ReturnsServiceUnavailable --- .../AutoSetupMiddleware.cs | 20 ++++---- .../OrchardCore.AutoSetup/Startup.cs | 2 +- .../AutoSetupMiddlewareTests.cs | 47 +++++++++++++++++-- 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs index 0dbcdd2e98c..7342a3b91a4 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs @@ -113,20 +113,22 @@ public async Task InvokeAsync(HttpContext httpContext) } // Check if the tenant was installed by another instance. - using var settings = (await _shellSettingsManager - .LoadSettingsAsync(_shellSettings.Name)) - .AsDisposable(); + using var settings = await _shellSettingsManager.LoadSettingsAsync(_shellSettings.Name); - if (!settings.IsUninitialized()) + if (settings != null) { - await _shellHost.ReloadShellContextAsync(_shellSettings, eventSource: false); - httpContext.Response.StatusCode = StatusCodes.Status503ServiceUnavailable; - await httpContext.Response.WriteAsync("The requested tenant is not initialized."); - return; + settings.AsDisposable(); + if (!settings.IsUninitialized()) + { + await _shellHost.ReloadShellContextAsync(_shellSettings, eventSource: false); + httpContext.Response.StatusCode = StatusCodes.Status503ServiceUnavailable; + await httpContext.Response.WriteAsync("The requested tenant is not initialized."); + return; + } } var autoSetupService = httpContext.RequestServices.GetRequiredService(); - (var setupContext, var isSuccess) = await autoSetupService.SetupTenantAsync(_setupOptions, _shellSettings); + (var setupContext, var isSuccess) = await autoSetupService.SetupTenantAsync(_setupOptions, _shellSettings); if (isSuccess) { if (_setupOptions.IsDefault) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Startup.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Startup.cs index 8198afb7e3c..5cc96d2d794 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Startup.cs @@ -69,7 +69,7 @@ public override void ConfigureServices(IServiceCollection services) services.Configure(o => o.ConfigurationExists = true); } - services.AddScoped(); + services.AddSingleton(); } /// diff --git a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs index 50f97c68648..c467c2c79bc 100644 --- a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs +++ b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs @@ -28,8 +28,9 @@ public class AutoSetupMiddlewareTests public AutoSetupMiddlewareTests() { - _mockShellHost = new Mock(); _shellSettings = new ShellSettings(); + _shellSettings.AsDefaultShell(); + _mockShellHost = new Mock(); _mockShellSettingsManager = new Mock(); _mockDistributedLock = new Mock(); _mockOptions = new Mock>(); @@ -42,7 +43,7 @@ public AutoSetupMiddlewareTests() { new TenantSetupOptions { ShellName = ShellSettings.DefaultShellName } } - }); + }); } [Fact] @@ -68,6 +69,46 @@ public async Task InvokeAsync_InitializedShell_SkipsSetup() // Assert Assert.True(nextCalled); _mockAutoSetupService.Verify(s => s.SetupTenantAsync(It.IsAny(), It.IsAny()), Times.Never); - } + } + + [Fact] + public async Task InvokeAsync_FailedSetup_ReturnsServiceUnavailable() + { + // Arrange + _shellSettings.State = TenantState.Uninitialized; + + SetupDistributedLockMock(true); + + var setupContext = new SetupContext { Errors = new Dictionary { { "Error", "Test error" } } }; + _mockAutoSetupService.Setup(s => s.SetupTenantAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync((setupContext, false)); + + var httpContext = new DefaultHttpContext(); + httpContext.RequestServices = new ServiceCollection() + .AddSingleton(_mockAutoSetupService.Object) + .BuildServiceProvider(); + + var middleware = new AutoSetupMiddleware( + next: (innerHttpContext) => Task.CompletedTask, + _mockShellHost.Object, + _shellSettings, + _mockShellSettingsManager.Object, + _mockDistributedLock.Object, + _mockOptions.Object); + + // Act + await middleware.InvokeAsync(httpContext); + + // Assert + Assert.Equal(StatusCodes.Status503ServiceUnavailable, httpContext.Response.StatusCode); + } + + private void SetupDistributedLockMock(bool acquireLock) + { + var mockLocker = new Mock(); + _mockDistributedLock + .Setup(d => d.TryAcquireLockAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync((mockLocker.Object, acquireLock)); + } } From 42558653c5af4550673d47a2678140b469bc578d Mon Sep 17 00:00:00 2001 From: Andy Date: Sat, 12 Oct 2024 14:29:22 -0400 Subject: [PATCH 17/28] InvokeAsync_FailedLockAcquisition_ThrowsTimeoutException --- .../AutoSetupMiddlewareTests.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs index c467c2c79bc..98bf0976404 100644 --- a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs +++ b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs @@ -103,6 +103,28 @@ public async Task InvokeAsync_FailedSetup_ReturnsServiceUnavailable() Assert.Equal(StatusCodes.Status503ServiceUnavailable, httpContext.Response.StatusCode); } + [Fact] + public async Task InvokeAsync_FailedLockAcquisition_ThrowsTimeoutException() + { + // Arrange + _shellSettings.State = TenantState.Uninitialized; + + SetupDistributedLockMock(false); + + var httpContext = new DefaultHttpContext(); + + var middleware = new AutoSetupMiddleware( + next: (innerHttpContext) => Task.CompletedTask, + _mockShellHost.Object, + _shellSettings, + _mockShellSettingsManager.Object, + _mockDistributedLock.Object, + _mockOptions.Object); + + // Act & Assert + await Assert.ThrowsAsync(() => middleware.InvokeAsync(httpContext)); + } + private void SetupDistributedLockMock(bool acquireLock) { var mockLocker = new Mock(); From ed75f46054290292a3fc2e5943522a0048d1771e Mon Sep 17 00:00:00 2001 From: Andy Date: Sat, 12 Oct 2024 14:34:23 -0400 Subject: [PATCH 18/28] InvokeAsync_UnInitializedShell_PerformsSetup --- .../AutoSetupMiddlewareTests.cs | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs index 98bf0976404..50d5b5b3f07 100644 --- a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs +++ b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs @@ -103,6 +103,39 @@ public async Task InvokeAsync_FailedSetup_ReturnsServiceUnavailable() Assert.Equal(StatusCodes.Status503ServiceUnavailable, httpContext.Response.StatusCode); } + [Fact] + public async Task InvokeAsync_UnInitializedShell_PerformsSetup() + { + // Arrange + _shellSettings.State = TenantState.Uninitialized; + + SetupDistributedLockMock(true); + + var setupContext = new SetupContext(); + _mockAutoSetupService.Setup(s => s.SetupTenantAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync((setupContext, true)); + + var httpContext = new DefaultHttpContext(); + httpContext.RequestServices = new ServiceCollection() + .AddSingleton(_mockAutoSetupService.Object) + .BuildServiceProvider(); + + var middleware = new AutoSetupMiddleware( + next: (innerHttpContext) => Task.CompletedTask, + _mockShellHost.Object, + _shellSettings, + _mockShellSettingsManager.Object, + _mockDistributedLock.Object, + _mockOptions.Object); + + // Act + await middleware.InvokeAsync(httpContext); + + // Assert + Assert.Equal(StatusCodes.Status302Found, httpContext.Response.StatusCode); // Redirect + _mockAutoSetupService.Verify(s => s.SetupTenantAsync(It.IsAny(), It.IsAny()), Times.Once); + } + [Fact] public async Task InvokeAsync_FailedLockAcquisition_ThrowsTimeoutException() { From 889565e2f20a37d476d24a5a2370c73169fba2db Mon Sep 17 00:00:00 2001 From: Andy Date: Sat, 12 Oct 2024 14:37:40 -0400 Subject: [PATCH 19/28] Clean --- .../AutoSetupMiddlewareTests.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs index 50d5b5b3f07..716d71e3db7 100644 --- a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs +++ b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs @@ -1,19 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Options; -using Moq; +using OrchardCore.AutoSetup; using OrchardCore.AutoSetup.Options; using OrchardCore.AutoSetup.Services; using OrchardCore.Environment.Shell; +using OrchardCore.Environment.Shell.Models; using OrchardCore.Locking; using OrchardCore.Locking.Distributed; using OrchardCore.Setup.Services; -using Xunit; -using OrchardCore.AutoSetup; -using OrchardCore.AutoSetup.Extensions; -using OrchardCore.Environment.Shell.Models; namespace OrchardCore.Tests.Modules.OrchardCore.AutoSetup; From b039be0b13e846901ae3b3698a73804a49b61180 Mon Sep 17 00:00:00 2001 From: Andy Date: Sat, 12 Oct 2024 14:38:19 -0400 Subject: [PATCH 20/28] Clean --- .../OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs index 716d71e3db7..0d758937654 100644 --- a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs +++ b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs @@ -22,7 +22,7 @@ public AutoSetupMiddlewareTests() { _shellSettings = new ShellSettings(); _shellSettings.AsDefaultShell(); - _mockShellHost = new Mock(); + _mockShellHost = new Mock(); _mockShellSettingsManager = new Mock(); _mockDistributedLock = new Mock(); _mockOptions = new Mock>(); @@ -35,8 +35,8 @@ public AutoSetupMiddlewareTests() { new TenantSetupOptions { ShellName = ShellSettings.DefaultShellName } } - }); - } + }); + } [Fact] public async Task InvokeAsync_InitializedShell_SkipsSetup() From 13ba5744f421d2074dc78b787017d3715b055a6c Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 29 Oct 2024 11:25:35 -0400 Subject: [PATCH 21/28] Correct DI scope for IAutoSetupService --- src/OrchardCore.Modules/OrchardCore.AutoSetup/Startup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Startup.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Startup.cs index 5cc96d2d794..8198afb7e3c 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Startup.cs @@ -69,7 +69,7 @@ public override void ConfigureServices(IServiceCollection services) services.Configure(o => o.ConfigurationExists = true); } - services.AddSingleton(); + services.AddScoped(); } /// From debdf12e1c4c640f1d83d979739a3b84cece0328 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 29 Oct 2024 11:52:04 -0400 Subject: [PATCH 22/28] Won't stop other Middlewares after success --- .../OrchardCore.AutoSetup/AutoSetupMiddleware.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs index 7342a3b91a4..fb0404f96b1 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs @@ -144,8 +144,6 @@ public async Task InvokeAsync(HttpContext httpContext) } httpContext.Response.Redirect(pathBase); - - return; } else { From 9d0902ff6206b7507cb1731b103e3cce31dd2024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Leh=C3=B3czky?= Date: Tue, 29 Oct 2024 23:17:07 +0100 Subject: [PATCH 23/28] Code styling --- .../OrchardCore.AutoSetup/Services/AutoSetupService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs index cdc66022aa6..24be1e9e737 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs @@ -39,7 +39,7 @@ ILogger logger { _logger.LogInformation("The AutoSetup successfully provisioned the site '{SiteName}'.", setupOptions.SiteName); - return (setupContext,true); + return (setupContext, true); } var stringBuilder = new StringBuilder(); From 29a8a107699a1caa3e7e60b6f0e273b293f2aa7a Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 29 Oct 2024 20:27:45 -0400 Subject: [PATCH 24/28] Shouldn't write error messages to the response directly --- .../OrchardCore.AutoSetup/AutoSetupMiddleware.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs index fb0404f96b1..cdb8a7e4b3d 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/AutoSetupMiddleware.cs @@ -1,4 +1,3 @@ -using System.Text; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -148,13 +147,7 @@ public async Task InvokeAsync(HttpContext httpContext) else { httpContext.Response.StatusCode = StatusCodes.Status503ServiceUnavailable; - var stringBuilder = new StringBuilder(); - foreach (var error in setupContext.Errors) - { - stringBuilder.AppendLine($"{error.Key} : '{error.Value}'"); - } - - await httpContext.Response.WriteAsync($"The AutoSetup failed installing the site '{_setupOptions.SiteName}' with errors: {stringBuilder}."); + await httpContext.Response.WriteAsync($"The AutoSetup failed installing the site."); return; } } From 3c806ab2974a2677677f60e23c7a66802c9fa039 Mon Sep 17 00:00:00 2001 From: andy Date: Sat, 2 Nov 2024 12:19:32 -0500 Subject: [PATCH 25/28] Update test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs Co-authored-by: Hisham Bin Ateya --- .../OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs index 0d758937654..656edd17999 100644 --- a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs +++ b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs @@ -32,9 +32,9 @@ public AutoSetupMiddlewareTests() { LockOptions = new LockOptions(), Tenants = new List - { - new TenantSetupOptions { ShellName = ShellSettings.DefaultShellName } - } + { + new TenantSetupOptions { ShellName = ShellSettings.DefaultShellName } + } }); } From 30cf024bb41706c7cf2ce8be2de3f00983a571a1 Mon Sep 17 00:00:00 2001 From: andy Date: Sat, 2 Nov 2024 12:19:55 -0500 Subject: [PATCH 26/28] Update test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs Co-authored-by: Hisham Bin Ateya --- .../Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs index 656edd17999..cab7fb5acf8 100644 --- a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs +++ b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs @@ -46,7 +46,6 @@ public async Task InvokeAsync_InitializedShell_SkipsSetup() var httpContext = new DefaultHttpContext(); var nextCalled = false; - var middleware = new AutoSetupMiddleware( next: (innerHttpContext) => { nextCalled = true; return Task.CompletedTask; }, _mockShellHost.Object, From d02b9e11cbe19e533cf67900d650778be97d40c7 Mon Sep 17 00:00:00 2001 From: andy Date: Sat, 2 Nov 2024 12:20:07 -0500 Subject: [PATCH 27/28] Update test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs Co-authored-by: Hisham Bin Ateya --- .../OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs index cab7fb5acf8..b430da19fa0 100644 --- a/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs +++ b/test/OrchardCore.Tests/Modules/OrchardCore.AutoSetup/AutoSetupMiddlewareTests.cs @@ -47,7 +47,12 @@ public async Task InvokeAsync_InitializedShell_SkipsSetup() var httpContext = new DefaultHttpContext(); var nextCalled = false; var middleware = new AutoSetupMiddleware( - next: (innerHttpContext) => { nextCalled = true; return Task.CompletedTask; }, + next: (innerHttpContext) => + { + nextCalled = true; + + return Task.CompletedTask; + }, _mockShellHost.Object, _shellSettings, _mockShellSettingsManager.Object, From 703a62292139590e4c31162575f54328aaa6f681 Mon Sep 17 00:00:00 2001 From: andy Date: Sat, 2 Nov 2024 12:20:22 -0500 Subject: [PATCH 28/28] Update src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs Co-authored-by: Hisham Bin Ateya --- .../OrchardCore.AutoSetup/Services/AutoSetupService.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs index 24be1e9e737..fa16bb59dfc 100644 --- a/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs +++ b/src/OrchardCore.Modules/OrchardCore.AutoSetup/Services/AutoSetupService.cs @@ -78,9 +78,8 @@ public async Task CreateTenantSettingsAsync(TenantSetupOptions se public async Task GetSetupContextAsync(TenantSetupOptions options, ShellSettings shellSettings) { - var recipes = await _setupService.GetSetupRecipesAsync(); - - var recipe = recipes.SingleOrDefault(r => r.Name == options.RecipeName); + var recipe = (await _setupService.GetSetupRecipesAsync()) + .SingleOrDefault(r => r.Name == options.RecipeName); var setupContext = new SetupContext {