From 057f4e3fa43124e77f76dfe9cbeaa59ccd729712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Thu, 25 May 2023 16:50:43 +0200 Subject: [PATCH 1/5] Adding AddSiteOwnerPermissionToRole maintenance --- .../Constants/FeatureNames.cs | 1 + .../Lombiq.Hosting.Tenants.Maintenance.csproj | 4 ++ ...OwnerPermissionToRoleMaintenanceOptions.cs | 7 ++++ ...wnerPermissionToRoleMaintenanceProvider.cs | 42 +++++++++++++++++++ .../AddSiteOwnerPermissionToRole/Startup.cs | 27 ++++++++++++ .../Manifest.cs | 9 ++++ .../Services/MaintenanceManager.cs | 6 +-- .../Services/MaintenanceRunnerService.cs | 9 ++-- Lombiq.Hosting.Tenants.Maintenance/Startup.cs | 2 + 9 files changed, 100 insertions(+), 7 deletions(-) create mode 100644 Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/SetSiteOwnerPermissionToRoleMaintenanceOptions.cs create mode 100644 Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/SetSiteOwnerPermissionToRoleMaintenanceProvider.cs create mode 100644 Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/Startup.cs diff --git a/Lombiq.Hosting.Tenants.Maintenance/Constants/FeatureNames.cs b/Lombiq.Hosting.Tenants.Maintenance/Constants/FeatureNames.cs index bbe6ae41..b53d3da2 100644 --- a/Lombiq.Hosting.Tenants.Maintenance/Constants/FeatureNames.cs +++ b/Lombiq.Hosting.Tenants.Maintenance/Constants/FeatureNames.cs @@ -6,4 +6,5 @@ public static class FeatureNames public const string Maintenance = Module; public const string UpdateSiteUrl = Maintenance + "." + nameof(UpdateSiteUrl); public const string UpdateShellRequestUrls = Maintenance + "." + nameof(UpdateShellRequestUrls); + public const string AddSiteOwnerPermissionToRole = Maintenance + "." + nameof(AddSiteOwnerPermissionToRole); } diff --git a/Lombiq.Hosting.Tenants.Maintenance/Lombiq.Hosting.Tenants.Maintenance.csproj b/Lombiq.Hosting.Tenants.Maintenance/Lombiq.Hosting.Tenants.Maintenance.csproj index c21d3476..07bf583f 100644 --- a/Lombiq.Hosting.Tenants.Maintenance/Lombiq.Hosting.Tenants.Maintenance.csproj +++ b/Lombiq.Hosting.Tenants.Maintenance/Lombiq.Hosting.Tenants.Maintenance.csproj @@ -41,4 +41,8 @@ + + + + diff --git a/Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/SetSiteOwnerPermissionToRoleMaintenanceOptions.cs b/Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/SetSiteOwnerPermissionToRoleMaintenanceOptions.cs new file mode 100644 index 00000000..016e9c4a --- /dev/null +++ b/Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/SetSiteOwnerPermissionToRoleMaintenanceOptions.cs @@ -0,0 +1,7 @@ +namespace Lombiq.Hosting.Tenants.Maintenance.Maintenance.AddSiteOwnerPermissionToRole; + +public class AddSiteOwnerPermissionToRoleMaintenanceOptions +{ + public bool IsEnabled { get; set; } + public string Role { get; set; } +} diff --git a/Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/SetSiteOwnerPermissionToRoleMaintenanceProvider.cs b/Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/SetSiteOwnerPermissionToRoleMaintenanceProvider.cs new file mode 100644 index 00000000..bd34df66 --- /dev/null +++ b/Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/SetSiteOwnerPermissionToRoleMaintenanceProvider.cs @@ -0,0 +1,42 @@ +using Lombiq.Hosting.Tenants.Maintenance.Extensions; +using Lombiq.Hosting.Tenants.Maintenance.Models; +using Lombiq.Hosting.Tenants.Maintenance.Services; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; +using OrchardCore.Security; +using System.Linq; +using System.Threading.Tasks; +using static OrchardCore.Security.Permissions.Permission; +using static OrchardCore.Security.StandardPermissions; + +namespace Lombiq.Hosting.Tenants.Maintenance.Maintenance.AddSiteOwnerPermissionToRole; + +public class AddSiteOwnerPermissionToRoleMaintenanceProvider : MaintenanceProviderBase +{ + private readonly IOptions _options; + private readonly RoleManager _roleManager; + + public AddSiteOwnerPermissionToRoleMaintenanceProvider( + IOptions options, + RoleManager roleManager) + { + _options = options; + _roleManager = roleManager; + } + + public override Task ShouldExecuteAsync(MaintenanceTaskExecutionContext context) => + Task.FromResult( + _options.Value.IsEnabled && + !context.WasLatestExecutionSuccessful()); + + public override async Task ExecuteAsync(MaintenanceTaskExecutionContext context) + { + if (await _roleManager.FindByNameAsync(_options.Value.Role) is not Role role) return; + + if (role.RoleClaims.Any(claim => claim.ClaimType == ClaimType && claim.ClaimValue == SiteOwner.Name)) return; + + role.RoleClaims.Add(new RoleClaim { ClaimType = ClaimType, ClaimValue = SiteOwner.Name }); + + await _roleManager.UpdateAsync(role); + } +} diff --git a/Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/Startup.cs b/Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/Startup.cs new file mode 100644 index 00000000..4722717d --- /dev/null +++ b/Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/Startup.cs @@ -0,0 +1,27 @@ +using Lombiq.Hosting.Tenants.Maintenance.Constants; +using Lombiq.Hosting.Tenants.Maintenance.Services; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using OrchardCore.Environment.Shell.Configuration; +using OrchardCore.Modules; + +namespace Lombiq.Hosting.Tenants.Maintenance.Maintenance.AddSiteOwnerPermissionToRole; + +[Feature(FeatureNames.AddSiteOwnerPermissionToRole)] +public class Startup : StartupBase +{ + private readonly IShellConfiguration _shellConfiguration; + + public Startup(IShellConfiguration shellConfiguration) => + _shellConfiguration = shellConfiguration; + + public override void ConfigureServices(IServiceCollection services) + { + var options = new AddSiteOwnerPermissionToRoleMaintenanceOptions(); + var configSection = _shellConfiguration.GetSection("Lombiq_Hosting_Tenants_Maintenance:AddSiteOwnerPermissionToRole"); + configSection.Bind(options); + services.Configure(configSection); + + services.AddScoped(); + } +} diff --git a/Lombiq.Hosting.Tenants.Maintenance/Manifest.cs b/Lombiq.Hosting.Tenants.Maintenance/Manifest.cs index ac85a786..07119061 100644 --- a/Lombiq.Hosting.Tenants.Maintenance/Manifest.cs +++ b/Lombiq.Hosting.Tenants.Maintenance/Manifest.cs @@ -33,3 +33,12 @@ DefaultTenantOnly = true, Dependencies = new[] { Maintenance } )] + +[assembly: Feature( + Id = AddSiteOwnerPermissionToRole, + Name = "Lombiq Hosting - Tenants Maintenance - Add Site Owner Permission To Role", + Description = "Adds the Site Owner permission to a role (e.g., when the production database is copied to staging).", + Category = "Maintenance", + DefaultTenantOnly = true, + Dependencies = new[] { Maintenance } +)] diff --git a/Lombiq.Hosting.Tenants.Maintenance/Services/MaintenanceManager.cs b/Lombiq.Hosting.Tenants.Maintenance/Services/MaintenanceManager.cs index afdc86a6..4a05ad12 100644 --- a/Lombiq.Hosting.Tenants.Maintenance/Services/MaintenanceManager.cs +++ b/Lombiq.Hosting.Tenants.Maintenance/Services/MaintenanceManager.cs @@ -3,18 +3,18 @@ using Lombiq.Hosting.Tenants.Maintenance.Models; using Microsoft.Extensions.Logging; using OrchardCore.Environment.Shell; -using OrchardCore.Modules; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using YesSql; +using IOrchardClock = OrchardCore.Modules.IClock; namespace Lombiq.Hosting.Tenants.Maintenance.Services; public class MaintenanceManager : IMaintenanceManager { - private readonly IClock _clock; + private readonly IOrchardClock _clock; private readonly ILogger _logger; private readonly IEnumerable _maintenanceProviders; private readonly ISession _session; @@ -22,7 +22,7 @@ public class MaintenanceManager : IMaintenanceManager private readonly ShellSettings _shellSettings; public MaintenanceManager( - IClock clock, + IOrchardClock clock, ILogger logger, IEnumerable maintenanceProviders, ISession session, diff --git a/Lombiq.Hosting.Tenants.Maintenance/Services/MaintenanceRunnerService.cs b/Lombiq.Hosting.Tenants.Maintenance/Services/MaintenanceRunnerService.cs index a349b0cf..2ef3fc85 100644 --- a/Lombiq.Hosting.Tenants.Maintenance/Services/MaintenanceRunnerService.cs +++ b/Lombiq.Hosting.Tenants.Maintenance/Services/MaintenanceRunnerService.cs @@ -2,6 +2,7 @@ using OrchardCore.Environment.Shell; using OrchardCore.Environment.Shell.Models; using OrchardCore.Modules; +using System; using System.Threading.Tasks; namespace Lombiq.Hosting.Tenants.Maintenance.Services; @@ -10,16 +11,16 @@ public class MaintenanceRunnerService : ModularTenantEvents { private readonly ShellSettings _shellSettings; private readonly ILogger _logger; - private readonly IMaintenanceManager _maintenanceManager; + private readonly Lazy _maintenanceManagerLazy; public MaintenanceRunnerService( ShellSettings shellSettings, ILogger logger, - IMaintenanceManager maintenanceManager) + Lazy maintenanceManagerLazy) { _shellSettings = shellSettings; _logger = logger; - _maintenanceManager = maintenanceManager; + _maintenanceManagerLazy = maintenanceManagerLazy; } public override async Task ActivatedAsync() @@ -29,6 +30,6 @@ public override async Task ActivatedAsync() _logger.LogDebug( "Executing maintenance tasks on shell '{ShellName}'.", _shellSettings.Name); - await _maintenanceManager.ExecuteMaintenanceTasksAsync(); + await _maintenanceManagerLazy.Value.ExecuteMaintenanceTasksAsync(); } } diff --git a/Lombiq.Hosting.Tenants.Maintenance/Startup.cs b/Lombiq.Hosting.Tenants.Maintenance/Startup.cs index aad3dd3c..400b2929 100644 --- a/Lombiq.Hosting.Tenants.Maintenance/Startup.cs +++ b/Lombiq.Hosting.Tenants.Maintenance/Startup.cs @@ -1,3 +1,4 @@ +using Lombiq.HelpfulLibraries.Common.DependencyInjection; using Lombiq.Hosting.Tenants.Maintenance.Constants; using Lombiq.Hosting.Tenants.Maintenance.Indexes; using Lombiq.Hosting.Tenants.Maintenance.Services; @@ -13,6 +14,7 @@ public class Startup : StartupBase { public override void ConfigureServices(IServiceCollection services) { + services.AddLazyInjectionSupport(); services.Configure(options => options.Collections.Add(DocumentCollections.Maintenance)); services.AddScoped(); services.AddSingleton(); From 041b0033531bba96056bb2abc6d26bd014731236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Thu, 25 May 2023 16:51:43 +0200 Subject: [PATCH 2/5] Rename files --- ...tions.cs => AddSiteOwnerPermissionToRoleMaintenanceOptions.cs} | 0 ...ider.cs => AddSiteOwnerPermissionToRoleMaintenanceProvider.cs} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/{SetSiteOwnerPermissionToRoleMaintenanceOptions.cs => AddSiteOwnerPermissionToRoleMaintenanceOptions.cs} (100%) rename Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/{SetSiteOwnerPermissionToRoleMaintenanceProvider.cs => AddSiteOwnerPermissionToRoleMaintenanceProvider.cs} (100%) diff --git a/Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/SetSiteOwnerPermissionToRoleMaintenanceOptions.cs b/Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/AddSiteOwnerPermissionToRoleMaintenanceOptions.cs similarity index 100% rename from Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/SetSiteOwnerPermissionToRoleMaintenanceOptions.cs rename to Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/AddSiteOwnerPermissionToRoleMaintenanceOptions.cs diff --git a/Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/SetSiteOwnerPermissionToRoleMaintenanceProvider.cs b/Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/AddSiteOwnerPermissionToRoleMaintenanceProvider.cs similarity index 100% rename from Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/SetSiteOwnerPermissionToRoleMaintenanceProvider.cs rename to Lombiq.Hosting.Tenants.Maintenance/Maintenance/AddSiteOwnerPermissionToRole/AddSiteOwnerPermissionToRoleMaintenanceProvider.cs From 0f4688894cd96b42d0291d4eb2a1ac663e6eb85a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Thu, 25 May 2023 17:03:15 +0200 Subject: [PATCH 3/5] Adding documentation --- Lombiq.Hosting.Tenants.Maintenance/Readme.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Lombiq.Hosting.Tenants.Maintenance/Readme.md b/Lombiq.Hosting.Tenants.Maintenance/Readme.md index 4ace2cee..6d552793 100644 --- a/Lombiq.Hosting.Tenants.Maintenance/Readme.md +++ b/Lombiq.Hosting.Tenants.Maintenance/Readme.md @@ -22,6 +22,25 @@ public void ConfigureServices(IServiceCollection services) => To add new maintenance tasks, you need to implement the `IMaintenanceProvider` interface and register it as a service. +### `Lombiq.Hosting.Tenants.Maintenance.AddSiteOwnerPermissionToRole` + +It's a maintenance task that adds the `SiteOwner` permission to a role set in the app configuration. It is available on any tenant. + +The following configuration options are available to set the role: + +```json +{ + "OrchardCore": { + "Lombiq_Hosting_Tenants_Maintenance": { + "AddSiteOwnerPermissionToRole": { + "IsEnabled": true, + "RoleName": "NameOfTheRole" + } + } + } +} +``` + ### `Lombiq.Hosting.Tenants.Maintenance.UpdateSiteUrl` It's a maintenance task that updates the site's base URL in the site settings based on the app configuration. It is available on any tenant. From 70056cfcfefa41d92a972cb2fe9f5c22aa3706b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Thu, 25 May 2023 18:32:41 +0200 Subject: [PATCH 4/5] Adding UI test extensions --- .../Extensions/MaintenanceExtensions.cs | 15 +++++++++++++++ .../Extensions/TestCaseUITestContextExtensions.cs | 7 +++++++ 2 files changed, 22 insertions(+) diff --git a/Lombiq.Hosting.Tenants.Maintenance.Tests.UI/Extensions/MaintenanceExtensions.cs b/Lombiq.Hosting.Tenants.Maintenance.Tests.UI/Extensions/MaintenanceExtensions.cs index 0fb468c7..088eed5e 100644 --- a/Lombiq.Hosting.Tenants.Maintenance.Tests.UI/Extensions/MaintenanceExtensions.cs +++ b/Lombiq.Hosting.Tenants.Maintenance.Tests.UI/Extensions/MaintenanceExtensions.cs @@ -19,4 +19,19 @@ public static void SetUpdateSiteUrlMaintenanceConfiguration( return Task.CompletedTask; }; + + public static void SetAddSiteOwnerPermissionToRoleMaintenanceConfiguration( + this OrchardCoreUITestExecutorConfiguration configuration) => configuration.OrchardCoreConfiguration.BeforeAppStart += + (_, argumentsBuilder) => + { + argumentsBuilder + .AddWithValue( + "OrchardCore:Lombiq_Hosting_Tenants_Maintenance:AddSiteOwnerPermissionToRole:IsEnabled", + value: true) + .AddWithValue( + "OrchardCore:Lombiq_Hosting_Tenants_Maintenance:AddSiteOwnerPermissionToRole:Role", + value: "Editor"); + + return Task.CompletedTask; + }; } diff --git a/Lombiq.Hosting.Tenants.Maintenance.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs b/Lombiq.Hosting.Tenants.Maintenance.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs index a2bce6ba..7850edf9 100644 --- a/Lombiq.Hosting.Tenants.Maintenance.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs +++ b/Lombiq.Hosting.Tenants.Maintenance.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs @@ -15,4 +15,11 @@ public static async Task TestSiteUrlMaintenanceExecutionAsync(this UITestContext await context.GoToAdminRelativeUrlAsync("/Settings/general"); context.Get(By.Name("ISite.BaseUrl")).GetValue().ShouldBe("https://test.com"); } + + public static async Task TestSiteOwnerPermissionToRoleMaintenanceExecutionAsync(this UITestContext context) + { + await context.SignInDirectlyAsync(); + await context.GoToAdminRelativeUrlAsync("/Roles/Edit/Editor"); + context.Get(By.Id("Checkbox.SiteOwner")).GetDomProperty("checked").ShouldBe(bool.TrueString); + } } From 41ff3b5d92598d48a74dd2b9df550559ccd0ad0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Thu, 25 May 2023 18:57:44 +0200 Subject: [PATCH 5/5] Adding nuget or project reference conditionally --- .../Lombiq.Hosting.Tenants.Maintenance.csproj | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Lombiq.Hosting.Tenants.Maintenance/Lombiq.Hosting.Tenants.Maintenance.csproj b/Lombiq.Hosting.Tenants.Maintenance/Lombiq.Hosting.Tenants.Maintenance.csproj index 07bf583f..ef8f9c69 100644 --- a/Lombiq.Hosting.Tenants.Maintenance/Lombiq.Hosting.Tenants.Maintenance.csproj +++ b/Lombiq.Hosting.Tenants.Maintenance/Lombiq.Hosting.Tenants.Maintenance.csproj @@ -41,8 +41,12 @@ - - + + + + + +