From 88faa82759a1cc13beacea1acc6e4dd259fb5072 Mon Sep 17 00:00:00 2001 From: Antoine Griffard Date: Thu, 19 Mar 2020 20:09:15 +0100 Subject: [PATCH] Tenant Workflows: Disable and Enable Tasks (#4765) --- .../Workflows/Activities/CreateTenantTask.cs | 92 ++++++++++------ .../Workflows/Activities/DisableTenantTask.cs | 46 ++++++-- .../Workflows/Activities/EnableTenantTask.cs | 35 +++++- .../Workflows/Activities/SetupTenantTask.cs | 101 +++++++++++------- .../Workflows/Activities/TenantActivity.cs | 6 +- .../Workflows/Activities/TenantTask.cs | 4 +- .../Http/Activities/HttpRequestTask.cs | 3 - 7 files changed, 197 insertions(+), 90 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/CreateTenantTask.cs b/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/CreateTenantTask.cs index b7b160fd7fb..498795c5ffa 100644 --- a/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/CreateTenantTask.cs +++ b/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/CreateTenantTask.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.Localization; using OrchardCore.Environment.Shell; using OrchardCore.Environment.Shell.Models; +using OrchardCore.Environment.Shell.Scope; using OrchardCore.Workflows.Abstractions.Models; using OrchardCore.Workflows.Activities; using OrchardCore.Workflows.Models; @@ -13,12 +14,9 @@ namespace OrchardCore.Tenants.Workflows.Activities { public class CreateTenantTask : TenantTask { - private readonly IWorkflowExpressionEvaluator _expressionEvaluator; - public CreateTenantTask(IShellSettingsManager shellSettingsManager, IShellHost shellHost, IWorkflowExpressionEvaluator expressionEvaluator, IWorkflowScriptEvaluator scriptEvaluator, IStringLocalizer localizer) - : base(shellSettingsManager, shellHost, scriptEvaluator, localizer) + : base(shellSettingsManager, shellHost, expressionEvaluator, scriptEvaluator, localizer) { - _expressionEvaluator = expressionEvaluator; } public override string Name => nameof(CreateTenantTask); @@ -77,43 +75,75 @@ public WorkflowExpression RecipeName public override IEnumerable GetPossibleOutcomes(WorkflowExecutionContext workflowContext, ActivityContext activityContext) { - return Outcomes(S["Done"]); + return Outcomes(S["Done"], S["Failed"]); } public async override Task ExecuteAsync(WorkflowExecutionContext workflowContext, ActivityContext activityContext) { - var tenantNameTask = _expressionEvaluator.EvaluateAsync(TenantName, workflowContext); - var tenantDescriptionTask = _expressionEvaluator.EvaluateAsync(Description, workflowContext); - var requestUrlPrefixTask = _expressionEvaluator.EvaluateAsync(RequestUrlPrefix, workflowContext); - var requestUrlHostTask = _expressionEvaluator.EvaluateAsync(RequestUrlHost, workflowContext); - var databaseProviderTask = _expressionEvaluator.EvaluateAsync(DatabaseProvider, workflowContext); - var connectionStringTask = _expressionEvaluator.EvaluateAsync(ConnectionString, workflowContext); - var tablePrefixTask = _expressionEvaluator.EvaluateAsync(TablePrefix, workflowContext); - var recipeNameTask = _expressionEvaluator.EvaluateAsync(RecipeName, workflowContext); + if (ShellScope.Context.Settings.Name != ShellHelper.DefaultShellName) + { + return Outcomes("Failed"); + } + + var tenantName = (await ExpressionEvaluator.EvaluateAsync(TenantName, workflowContext))?.Trim(); + + if (string.IsNullOrEmpty(tenantName)) + { + return Outcomes("Failed"); + } + + if (ShellHost.TryGetSettings(tenantName, out var shellSettings)) + { + return Outcomes("Failed"); + } + + var requestUrlPrefix = (await ExpressionEvaluator.EvaluateAsync(RequestUrlPrefix, workflowContext))?.Trim(); + var requestUrlHost = (await ExpressionEvaluator.EvaluateAsync(RequestUrlHost, workflowContext))?.Trim(); + var databaseProvider = (await ExpressionEvaluator.EvaluateAsync(DatabaseProvider, workflowContext))?.Trim(); + var connectionString = (await ExpressionEvaluator.EvaluateAsync(ConnectionString, workflowContext))?.Trim(); + var tablePrefix = (await ExpressionEvaluator.EvaluateAsync(TablePrefix, workflowContext))?.Trim(); + var recipeName = (await ExpressionEvaluator.EvaluateAsync(RecipeName, workflowContext))?.Trim(); + + // Creates a default shell settings based on the configuration. + shellSettings = ShellSettingsManager.CreateDefaultSettings(); + + shellSettings.Name = tenantName; + + if (!string.IsNullOrEmpty(requestUrlHost)) + { + shellSettings.RequestUrlHost = requestUrlHost; + } + + if (!string.IsNullOrEmpty(requestUrlPrefix)) + { + shellSettings.RequestUrlPrefix = requestUrlPrefix; + } + + shellSettings.State = TenantState.Uninitialized; + + if (!string.IsNullOrEmpty(connectionString)) + { + shellSettings["ConnectionString"] = connectionString; + } - await Task.WhenAll(tenantNameTask, tenantDescriptionTask, requestUrlPrefixTask, requestUrlHostTask, databaseProviderTask, connectionStringTask, tablePrefixTask, recipeNameTask); + if (!string.IsNullOrEmpty(tablePrefix)) + { + shellSettings["TablePrefix"] = tablePrefix; + } - var shellSettings = new ShellSettings(); + if (!string.IsNullOrEmpty(databaseProvider)) + { + shellSettings["DatabaseProvider"] = databaseProvider; + } - if (!string.IsNullOrWhiteSpace(tenantNameTask.Result)) + if (!string.IsNullOrEmpty(recipeName)) { - shellSettings = new ShellSettings - { - Name = tenantNameTask.Result?.Trim(), - RequestUrlPrefix = requestUrlPrefixTask.Result?.Trim(), - RequestUrlHost = requestUrlHostTask.Result?.Trim(), - State = TenantState.Uninitialized - }; - shellSettings["Description"] = tenantDescriptionTask.Result?.Trim(); - shellSettings["ConnectionString"] = connectionStringTask.Result?.Trim(); - shellSettings["TablePrefix"] = tablePrefixTask.Result?.Trim(); - shellSettings["DatabaseProvider"] = databaseProviderTask.Result?.Trim(); - shellSettings["Secret"] = Guid.NewGuid().ToString(); - shellSettings["RecipeName"] = recipeNameTask.Result.Trim(); + shellSettings["RecipeName"] = recipeName; } - await ShellSettingsManager.SaveSettingsAsync(shellSettings); - var shellContext = await ShellHost.GetOrCreateShellContextAsync(shellSettings); + shellSettings["Secret"] = Guid.NewGuid().ToString(); + + await ShellHost.UpdateShellSettingsAsync(shellSettings); workflowContext.LastResult = shellSettings; workflowContext.CorrelationId = shellSettings.Name; diff --git a/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/DisableTenantTask.cs b/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/DisableTenantTask.cs index 780c6a728f8..8808c334bc4 100644 --- a/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/DisableTenantTask.cs +++ b/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/DisableTenantTask.cs @@ -1,7 +1,11 @@ using System.Collections.Generic; +using System.Threading.Tasks; using Microsoft.Extensions.Localization; using OrchardCore.Environment.Shell; +using OrchardCore.Environment.Shell.Models; +using OrchardCore.Environment.Shell.Scope; using OrchardCore.Workflows.Abstractions.Models; +using OrchardCore.Workflows.Activities; using OrchardCore.Workflows.Models; using OrchardCore.Workflows.Services; @@ -9,11 +13,10 @@ namespace OrchardCore.Tenants.Workflows.Activities { public class DisableTenantTask : TenantTask { - public DisableTenantTask(IShellSettingsManager shellSettingsManager, IShellHost shellHost, IWorkflowScriptEvaluator scriptEvaluator, IStringLocalizer localizer) - : base(shellSettingsManager, shellHost, scriptEvaluator, localizer) + public DisableTenantTask(IShellSettingsManager shellSettingsManager, IShellHost shellHost, IWorkflowExpressionEvaluator expressionEvaluator, IWorkflowScriptEvaluator scriptEvaluator, IStringLocalizer localizer) + : base(shellSettingsManager, shellHost, expressionEvaluator, scriptEvaluator, localizer) { } - public override string Name => nameof(DisableTenantTask); public override LocalizedString Category => S["Tenant"]; @@ -22,16 +25,37 @@ public DisableTenantTask(IShellSettingsManager shellSettingsManager, IShellHost public override IEnumerable GetPossibleOutcomes(WorkflowExecutionContext workflowContext, ActivityContext activityContext) { - return Outcomes(S["Disabled"]); + return Outcomes(S["Disabled"], S["Failed"]); } - //public override async Task ExecuteAsync(WorkflowExecutionContext workflowContext, ActivityContext activityContext) - //{ - // //var shellSettings = await GetTenantAsync(workflowContext); - // //shellSettings.State = TenantState.Disabled; - // //await ShellHost.UpdateShellSettingsAsync(shellSettings); + public override async Task ExecuteAsync(WorkflowExecutionContext workflowContext, ActivityContext activityContext) + { + if (ShellScope.Context.Settings.Name != ShellHelper.DefaultShellName) + { + return Outcomes("Failed"); + } + + var tenantName = (await ExpressionEvaluator.EvaluateAsync(TenantName, workflowContext))?.Trim(); + + if (tenantName == ShellHelper.DefaultShellName) + { + return Outcomes("Failed"); + } - // return Outcomes("Disable"); - //} + if (!ShellHost.TryGetSettings(tenantName?.Trim(), out var shellSettings)) + { + return Outcomes("Failed"); + } + + if (shellSettings.State != TenantState.Running) + { + return Outcomes("Failed"); + } + + shellSettings.State = TenantState.Disabled; + await ShellHost.UpdateShellSettingsAsync(shellSettings); + + return Outcomes("Disabled"); + } } } diff --git a/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/EnableTenantTask.cs b/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/EnableTenantTask.cs index 19abd3e73de..91380d7db40 100644 --- a/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/EnableTenantTask.cs +++ b/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/EnableTenantTask.cs @@ -1,7 +1,11 @@ using System.Collections.Generic; +using System.Threading.Tasks; using Microsoft.Extensions.Localization; using OrchardCore.Environment.Shell; +using OrchardCore.Environment.Shell.Models; +using OrchardCore.Environment.Shell.Scope; using OrchardCore.Workflows.Abstractions.Models; +using OrchardCore.Workflows.Activities; using OrchardCore.Workflows.Models; using OrchardCore.Workflows.Services; @@ -9,8 +13,8 @@ namespace OrchardCore.Tenants.Workflows.Activities { public class EnableTenantTask : TenantTask { - public EnableTenantTask(IShellSettingsManager shellSettingsManager, IShellHost shellHost, IWorkflowScriptEvaluator scriptEvaluator, IStringLocalizer localizer) - : base(shellSettingsManager, shellHost, scriptEvaluator, localizer) + public EnableTenantTask(IShellSettingsManager shellSettingsManager, IShellHost shellHost, IWorkflowExpressionEvaluator expressionEvaluator, IWorkflowScriptEvaluator scriptEvaluator, IStringLocalizer localizer) + : base(shellSettingsManager, shellHost, expressionEvaluator, scriptEvaluator, localizer) { } @@ -22,7 +26,32 @@ public EnableTenantTask(IShellSettingsManager shellSettingsManager, IShellHost s public override IEnumerable GetPossibleOutcomes(WorkflowExecutionContext workflowContext, ActivityContext activityContext) { - return Outcomes(S["Enabled"]); + return Outcomes(S["Enabled"], S["Failed"]); + } + + public override async Task ExecuteAsync(WorkflowExecutionContext workflowContext, ActivityContext activityContext) + { + if (ShellScope.Context.Settings.Name != ShellHelper.DefaultShellName) + { + return Outcomes("Failed"); + } + + var tenantName = (await ExpressionEvaluator.EvaluateAsync(TenantName, workflowContext))?.Trim(); + + if (!ShellHost.TryGetSettings(tenantName, out var shellSettings)) + { + return Outcomes("Failed"); + } + + if (shellSettings.State != TenantState.Disabled) + { + return Outcomes("Failed"); + } + + shellSettings.State = TenantState.Running; + await ShellHost.UpdateShellSettingsAsync(shellSettings); + + return Outcomes("Enabled"); } } } diff --git a/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/SetupTenantTask.cs b/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/SetupTenantTask.cs index c4346562921..aaa37efc078 100644 --- a/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/SetupTenantTask.cs +++ b/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/SetupTenantTask.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -6,6 +5,7 @@ using OrchardCore.DisplayManagement.ModelBinding; using OrchardCore.Environment.Shell; using OrchardCore.Environment.Shell.Models; +using OrchardCore.Environment.Shell.Scope; using OrchardCore.Modules; using OrchardCore.Setup.Services; using OrchardCore.Workflows.Abstractions.Models; @@ -22,7 +22,7 @@ public class SetupTenantTask : TenantTask private readonly IWorkflowExpressionEvaluator _expressionEvaluator; public SetupTenantTask(IShellSettingsManager shellSettingsManager, IShellHost shellHost, ISetupService setupService, IClock clock, IWorkflowExpressionEvaluator expressionEvaluator, IWorkflowScriptEvaluator scriptEvaluator, IUpdateModelAccessor updateModelAccessor, IStringLocalizer localizer) - : base(shellSettingsManager, shellHost, scriptEvaluator, localizer) + : base(shellSettingsManager, shellHost, expressionEvaluator, scriptEvaluator, localizer) { SetupService = setupService; _clock = clock; @@ -93,55 +93,80 @@ public override IEnumerable GetPossibleOutcomes(WorkflowExecutionContex public override async Task ExecuteAsync(WorkflowExecutionContext workflowContext, ActivityContext activityContext) { - var tenantNameTask = _expressionEvaluator.EvaluateAsync(TenantName, workflowContext); - var siteNameTask = _expressionEvaluator.EvaluateAsync(SiteName, workflowContext); - var adminUsernameTask = _expressionEvaluator.EvaluateAsync(AdminUsername, workflowContext); - var adminEmailTask = _expressionEvaluator.EvaluateAsync(AdminEmail, workflowContext); - var adminPasswordTask = _expressionEvaluator.EvaluateAsync(AdminPassword, workflowContext); - var databaseProviderTask = _expressionEvaluator.EvaluateAsync(DatabaseProvider, workflowContext); - var databaseConnectionStringTask = _expressionEvaluator.EvaluateAsync(DatabaseConnectionString, workflowContext); - var databaseTablePrefixTask = _expressionEvaluator.EvaluateAsync(DatabaseTablePrefix, workflowContext); - var recipeNameTask = _expressionEvaluator.EvaluateAsync(RecipeName, workflowContext); - - await Task.WhenAll(tenantNameTask, siteNameTask, adminUsernameTask, adminEmailTask, adminPasswordTask, databaseProviderTask, databaseConnectionStringTask, databaseTablePrefixTask, recipeNameTask); - - if (!ShellHost.TryGetSettings(tenantNameTask.Result?.Trim(), out var shellSettings)) + if (ShellScope.Context.Settings.Name != ShellHelper.DefaultShellName) { - if (!string.IsNullOrWhiteSpace(tenantNameTask.Result)) - { - shellSettings = new ShellSettings - { - Name = tenantNameTask.Result?.Trim(), - State = TenantState.Uninitialized - }; - shellSettings["ConnectionString"] = databaseConnectionStringTask.Result?.Trim(); - shellSettings["TablePrefix"] = databaseTablePrefixTask.Result?.Trim(); - shellSettings["DatabaseProvider"] = databaseProviderTask.Result?.Trim(); - shellSettings["Secret"] = Guid.NewGuid().ToString(); - shellSettings["RecipeName"] = recipeNameTask.Result.Trim(); - } + return Outcomes("Failed"); + } + + var tenantName = (await ExpressionEvaluator.EvaluateAsync(TenantName, workflowContext))?.Trim(); + + if (string.IsNullOrWhiteSpace(tenantName)) + { + return Outcomes("Failed"); + } + + if (!ShellHost.TryGetSettings(tenantName, out var shellSettings)) + { + return Outcomes("Failed"); + } + + if (shellSettings.State == TenantState.Running) + { + return Outcomes("Failed"); + } - await ShellSettingsManager.SaveSettingsAsync(shellSettings); - var shellContext = await ShellHost.GetOrCreateShellContextAsync(shellSettings); + if (shellSettings.State != TenantState.Uninitialized) + { + return Outcomes("Failed"); + } + + var siteName = (await _expressionEvaluator.EvaluateAsync(SiteName, workflowContext))?.Trim(); + var adminUsername = (await _expressionEvaluator.EvaluateAsync(AdminUsername, workflowContext))?.Trim(); + var adminEmail = (await _expressionEvaluator.EvaluateAsync(AdminEmail, workflowContext))?.Trim(); + var adminPassword = (await _expressionEvaluator.EvaluateAsync(AdminPassword, workflowContext))?.Trim(); + + var databaseProvider = (await _expressionEvaluator.EvaluateAsync(DatabaseProvider, workflowContext))?.Trim(); + var databaseConnectionString = (await _expressionEvaluator.EvaluateAsync(DatabaseConnectionString, workflowContext))?.Trim(); + var databaseTablePrefix = (await _expressionEvaluator.EvaluateAsync(DatabaseTablePrefix, workflowContext))?.Trim(); + var recipeName = (await _expressionEvaluator.EvaluateAsync(RecipeName, workflowContext))?.Trim(); + + if (string.IsNullOrEmpty(databaseProvider)) + { + databaseProvider = shellSettings["DatabaseProvider"]; + } + + if (string.IsNullOrEmpty(databaseConnectionString)) + { + databaseConnectionString = shellSettings["ConnectionString"]; + } + + if (string.IsNullOrEmpty(databaseTablePrefix)) + { + databaseTablePrefix = shellSettings["TablePrefix"]; + } + + if (string.IsNullOrEmpty(recipeName)) + { + recipeName = shellSettings["RecipeName"]; } var recipes = await SetupService.GetSetupRecipesAsync(); - var recipe = recipes.FirstOrDefault(x => x.Name == shellSettings["RecipeName"]); + var recipe = recipes.FirstOrDefault(r => r.Name == recipeName); var setupContext = new SetupContext { ShellSettings = shellSettings, - SiteName = siteNameTask.Result?.Trim(), + SiteName = siteName, EnabledFeatures = null, - AdminUsername = adminUsernameTask.Result?.Trim(), - AdminEmail = adminEmailTask.Result?.Trim(), - AdminPassword = adminPasswordTask.Result?.Trim(), + AdminUsername = adminUsername, + AdminEmail = adminEmail, + AdminPassword = adminPassword, Errors = new Dictionary(), Recipe = recipe, SiteTimeZone = _clock.GetSystemTimeZone().TimeZoneId, - DatabaseProvider = databaseProviderTask.Result?.Trim(), - DatabaseConnectionString = databaseConnectionStringTask.Result?.Trim(), - DatabaseTablePrefix = databaseTablePrefixTask.Result?.Trim(), + DatabaseProvider = databaseProvider, + DatabaseConnectionString = databaseConnectionString, + DatabaseTablePrefix = databaseTablePrefix }; var executionId = await SetupService.SetupAsync(setupContext); diff --git a/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/TenantActivity.cs b/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/TenantActivity.cs index a84ccc7573e..17f4537232e 100644 --- a/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/TenantActivity.cs +++ b/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/TenantActivity.cs @@ -11,11 +11,12 @@ namespace OrchardCore.Tenants.Workflows.Activities public abstract class TenantActivity : Activity { protected readonly IStringLocalizer S; - - protected TenantActivity(IShellSettingsManager shellSettingsManager, IShellHost shellHost, IWorkflowScriptEvaluator scriptEvaluator, IStringLocalizer localizer) + + protected TenantActivity(IShellSettingsManager shellSettingsManager, IShellHost shellHost, IWorkflowExpressionEvaluator expressionEvaluator, IWorkflowScriptEvaluator scriptEvaluator, IStringLocalizer localizer) { ShellSettingsManager = shellSettingsManager; ShellHost = shellHost; + ExpressionEvaluator = expressionEvaluator; ScriptEvaluator = scriptEvaluator; S = localizer; } @@ -28,6 +29,7 @@ public WorkflowExpression TenantName protected IShellSettingsManager ShellSettingsManager { get; } protected IShellHost ShellHost { get; } + protected IWorkflowExpressionEvaluator ExpressionEvaluator { get; } protected IWorkflowScriptEvaluator ScriptEvaluator { get; } public override LocalizedString Category => S["Tenant"]; diff --git a/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/TenantTask.cs b/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/TenantTask.cs index b17fae0eec7..17d323d5445 100644 --- a/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/TenantTask.cs +++ b/src/OrchardCore.Modules/OrchardCore.Tenants/Workflows/Activities/TenantTask.cs @@ -7,8 +7,8 @@ namespace OrchardCore.Tenants.Workflows.Activities { public abstract class TenantTask : TenantActivity, ITask { - protected TenantTask(IShellSettingsManager shellSettingsManager, IShellHost shellHost, IWorkflowScriptEvaluator scriptEvaluator, IStringLocalizer localizer) - : base(shellSettingsManager, shellHost, scriptEvaluator, localizer) + protected TenantTask(IShellSettingsManager shellSettingsManager, IShellHost shellHost, IWorkflowExpressionEvaluator expressionEvaluator, IWorkflowScriptEvaluator scriptEvaluator, IStringLocalizer localizer) + : base(shellSettingsManager, shellHost, expressionEvaluator, scriptEvaluator, localizer) { } } diff --git a/src/OrchardCore.Modules/OrchardCore.Workflows/Http/Activities/HttpRequestTask.cs b/src/OrchardCore.Modules/OrchardCore.Workflows/Http/Activities/HttpRequestTask.cs index 0fbe7e8d267..7e01f948418 100644 --- a/src/OrchardCore.Modules/OrchardCore.Workflows/Http/Activities/HttpRequestTask.cs +++ b/src/OrchardCore.Modules/OrchardCore.Workflows/Http/Activities/HttpRequestTask.cs @@ -15,18 +15,15 @@ namespace OrchardCore.Workflows.Http.Activities { public class HttpRequestTask : TaskActivity { - private readonly IHttpContextAccessor _httpContextAccessor; private readonly IWorkflowExpressionEvaluator _expressionEvaluator; private readonly IStringLocalizer S; public HttpRequestTask( IStringLocalizer localizer, - IHttpContextAccessor httpContextAccessor, IWorkflowExpressionEvaluator expressionEvaluator ) { S = localizer; - _httpContextAccessor = httpContextAccessor; _expressionEvaluator = expressionEvaluator; }