Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NEST-391: Maintenance to make a role site owner #64

Merged
merged 6 commits into from
May 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,12 @@
<None Remove="Tests\**" />
</ItemGroup>

<ItemGroup Condition="'$(NuGetBuild)' != 'true'">
<ProjectReference Include="..\..\..\Libraries\Lombiq.HelpfulLibraries\Lombiq.HelpfulLibraries.Common\Lombiq.HelpfulLibraries.Common.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(NuGetBuild)' == 'true'">
<PackageReference Include="Lombiq.HelpfulLibraries.Common" Version="5.1.1" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Lombiq.Hosting.Tenants.Maintenance.Maintenance.AddSiteOwnerPermissionToRole;

public class AddSiteOwnerPermissionToRoleMaintenanceOptions
{
public bool IsEnabled { get; set; }
public string Role { get; set; }
}
Original file line number Diff line number Diff line change
@@ -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<AddSiteOwnerPermissionToRoleMaintenanceOptions> _options;
private readonly RoleManager<IRole> _roleManager;

public AddSiteOwnerPermissionToRoleMaintenanceProvider(
IOptions<AddSiteOwnerPermissionToRoleMaintenanceOptions> options,
RoleManager<IRole> roleManager)
{
_options = options;
_roleManager = roleManager;
}

public override Task<bool> 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);
}
}
Original file line number Diff line number Diff line change
@@ -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<AddSiteOwnerPermissionToRoleMaintenanceOptions>(configSection);

services.AddScoped<IMaintenanceProvider, AddSiteOwnerPermissionToRoleMaintenanceProvider>();
}
}
9 changes: 9 additions & 0 deletions Lombiq.Hosting.Tenants.Maintenance/Manifest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
)]
19 changes: 19 additions & 0 deletions Lombiq.Hosting.Tenants.Maintenance/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,26 @@
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<MaintenanceManager> _logger;
private readonly IEnumerable<IMaintenanceProvider> _maintenanceProviders;
private readonly ISession _session;
private readonly IShellHost _shellHost;
private readonly ShellSettings _shellSettings;

public MaintenanceManager(
IClock clock,
IOrchardClock clock,
ILogger<MaintenanceManager> logger,
IEnumerable<IMaintenanceProvider> maintenanceProviders,
ISession session,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -10,16 +11,16 @@ public class MaintenanceRunnerService : ModularTenantEvents
{
private readonly ShellSettings _shellSettings;
private readonly ILogger<MaintenanceRunnerService> _logger;
private readonly IMaintenanceManager _maintenanceManager;
private readonly Lazy<IMaintenanceManager> _maintenanceManagerLazy;

public MaintenanceRunnerService(
ShellSettings shellSettings,
ILogger<MaintenanceRunnerService> logger,
IMaintenanceManager maintenanceManager)
Lazy<IMaintenanceManager> maintenanceManagerLazy)
{
_shellSettings = shellSettings;
_logger = logger;
_maintenanceManager = maintenanceManager;
_maintenanceManagerLazy = maintenanceManagerLazy;
}

public override async Task ActivatedAsync()
Expand All @@ -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();
}
}
2 changes: 2 additions & 0 deletions Lombiq.Hosting.Tenants.Maintenance/Startup.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -13,6 +14,7 @@ public class Startup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddLazyInjectionSupport();
services.Configure<StoreCollectionOptions>(options => options.Collections.Add(DocumentCollections.Maintenance));
services.AddScoped<IDataMigration, Migrations>();
services.AddSingleton<IIndexProvider, MaintenanceTaskExecutionIndexProvider>();
Expand Down