diff --git a/src/OrchardCore.Modules/OrchardCore.Roles/Migrations/SystemRolesMigrations.cs b/src/OrchardCore.Modules/OrchardCore.Roles/Migrations/SystemRolesMigrations.cs new file mode 100644 index 00000000000..4ca7c7a884d --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Roles/Migrations/SystemRolesMigrations.cs @@ -0,0 +1,40 @@ +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Logging; +using OrchardCore.Data.Migration; +using OrchardCore.Security; + +namespace OrchardCore.Roles.Migrations; + +public sealed class SystemRolesMigrations : DataMigration +{ + private readonly ISystemRoleProvider _systemRoleProvider; + private readonly RoleManager _roleManager; + private readonly ILogger _logger; + + public SystemRolesMigrations( + ISystemRoleProvider systemRoleProvider, + RoleManager roleManager, + ILogger logger) + { + _systemRoleProvider = systemRoleProvider; + _roleManager = roleManager; + _logger = logger; + } + + public async Task CreateAsync() + { + var systemRoles = _systemRoleProvider.GetSystemRoles(); + + foreach (var systemRole in systemRoles) + { + if (!await _roleManager.RoleExistsAsync(systemRole.RoleName)) + { + await _roleManager.CreateAsync(systemRole); + } + } + + _logger.LogInformation("The system roles have been created successfully."); + + return 1; + } +} diff --git a/src/OrchardCore.Modules/OrchardCore.Roles/Recipes/RolesStep.cs b/src/OrchardCore.Modules/OrchardCore.Roles/Recipes/RolesStep.cs index f6031d9b0ed..6b7d9e332cc 100644 --- a/src/OrchardCore.Modules/OrchardCore.Roles/Recipes/RolesStep.cs +++ b/src/OrchardCore.Modules/OrchardCore.Roles/Recipes/RolesStep.cs @@ -13,15 +13,15 @@ namespace OrchardCore.Roles.Recipes; public sealed class RolesStep : NamedRecipeStepHandler { private readonly RoleManager _roleManager; - private readonly ISystemRoleNameProvider _systemRoleNameProvider; + private readonly ISystemRoleProvider _systemRoleProvider; public RolesStep( RoleManager roleManager, - ISystemRoleNameProvider systemRoleNameProvider) + ISystemRoleProvider systemRoleProvider) : base("Roles") { _roleManager = roleManager; - _systemRoleNameProvider = systemRoleNameProvider; + _systemRoleProvider = systemRoleProvider; } protected override async Task HandleAsync(RecipeExecutionContext context) @@ -59,7 +59,7 @@ protected override async Task HandleAsync(RecipeExecutionContext context) r.RoleClaims.RemoveAll(c => c.ClaimType == Permission.ClaimType); } - if (!await _systemRoleNameProvider.IsAdminRoleAsync(roleName)) + if (!_systemRoleProvider.IsAdminRole(roleName)) { if (roleEntry.PermissionBehavior == PermissionBehavior.Remove) { diff --git a/src/OrchardCore.Modules/OrchardCore.Roles/Services/RoleClaimsProvider.cs b/src/OrchardCore.Modules/OrchardCore.Roles/Services/RoleClaimsProvider.cs index 5e423fef13b..3bef2d20232 100644 --- a/src/OrchardCore.Modules/OrchardCore.Roles/Services/RoleClaimsProvider.cs +++ b/src/OrchardCore.Modules/OrchardCore.Roles/Services/RoleClaimsProvider.cs @@ -11,18 +11,18 @@ public class RoleClaimsProvider : IUserClaimsProvider { private readonly UserManager _userManager; private readonly RoleManager _roleManager; - private readonly ISystemRoleNameProvider _systemRoleNameProvider; + private readonly ISystemRoleProvider _systemRoleProvider; private readonly IdentityOptions _identityOptions; public RoleClaimsProvider( UserManager userManager, RoleManager roleManager, - ISystemRoleNameProvider systemRoleNameProvider, + ISystemRoleProvider systemRoleProvider, IOptions identityOptions) { _userManager = userManager; _roleManager = roleManager; - _systemRoleNameProvider = systemRoleNameProvider; + _systemRoleProvider = systemRoleProvider; _identityOptions = identityOptions.Value; } @@ -39,7 +39,7 @@ public async Task GenerateAsync(IUser user, ClaimsIdentity claims) foreach (var roleName in roleNames) { - if (await _systemRoleNameProvider.IsAdminRoleAsync(roleName)) + if (_systemRoleProvider.IsAdminRole(roleName)) { isAdministrator = true; break; diff --git a/src/OrchardCore.Modules/OrchardCore.Roles/Services/RoleStore.cs b/src/OrchardCore.Modules/OrchardCore.Roles/Services/RoleStore.cs index 9d427afcb79..f8783a8f609 100644 --- a/src/OrchardCore.Modules/OrchardCore.Roles/Services/RoleStore.cs +++ b/src/OrchardCore.Modules/OrchardCore.Roles/Services/RoleStore.cs @@ -13,16 +13,17 @@ namespace OrchardCore.Roles.Services; public class RoleStore : IRoleClaimStore, IQueryableRoleStore { private readonly IServiceProvider _serviceProvider; - private readonly ISystemRoleNameProvider _systemRoleProvider; + private readonly ISystemRoleProvider _systemRoleProvider; private readonly IDocumentManager _documentManager; - protected readonly IStringLocalizer S; private readonly ILogger _logger; + protected readonly IStringLocalizer S; + private bool _updating; public RoleStore( IServiceProvider serviceProvider, - ISystemRoleNameProvider systemRoleProvider, + ISystemRoleProvider systemRoleProvider, IDocumentManager documentManager, IStringLocalizer stringLocalizer, ILogger logger) @@ -91,7 +92,7 @@ public async Task DeleteAsync(IRole role, CancellationToken canc }); } - if (await _systemRoleProvider.IsSystemRoleAsync(roleToRemove.RoleName)) + if (_systemRoleProvider.IsSystemRole(roleToRemove.RoleName)) { return IdentityResult.Failed(new IdentityError { diff --git a/src/OrchardCore.Modules/OrchardCore.Roles/Services/RoleUpdater.cs b/src/OrchardCore.Modules/OrchardCore.Roles/Services/RoleUpdater.cs index 140c5f193c6..1845cc342f3 100644 --- a/src/OrchardCore.Modules/OrchardCore.Roles/Services/RoleUpdater.cs +++ b/src/OrchardCore.Modules/OrchardCore.Roles/Services/RoleUpdater.cs @@ -15,7 +15,7 @@ public class RoleUpdater : FeatureEventHandler, IRoleCreatedEventHandler, IRoleR private readonly ShellDescriptor _shellDescriptor; private readonly IExtensionManager _extensionManager; private readonly IDocumentManager _documentManager; - private readonly ISystemRoleNameProvider _systemRoleNameProvider; + private readonly ISystemRoleProvider _systemRoleProvider; private readonly IEnumerable _permissionProviders; private readonly ITypeFeatureProvider _typeFeatureProvider; private readonly ILogger _logger; @@ -26,7 +26,7 @@ public RoleUpdater( ShellDescriptor shellDescriptor, IExtensionManager extensionManager, IDocumentManager documentManager, - ISystemRoleNameProvider systemRoleNameProvider, + ISystemRoleProvider systemRoleProvider, IEnumerable permissionProviders, ITypeFeatureProvider typeFeatureProvider, ILogger logger) @@ -34,7 +34,7 @@ public RoleUpdater( _shellDescriptor = shellDescriptor; _extensionManager = extensionManager; _documentManager = documentManager; - _systemRoleNameProvider = systemRoleNameProvider; + _systemRoleProvider = systemRoleProvider; _permissionProviders = permissionProviders; _typeFeatureProvider = typeFeatureProvider; _logger = logger; @@ -80,7 +80,7 @@ private async Task UpdateRolesForInstalledFeatureAsync(IFeatureInfo feature) var permissions = (stereotype.Permissions ?? []) .Select(stereotype => stereotype.Name); - if (await UpdatePermissionsAsync(role, permissions)) + if (UpdatePermissions(role, permissions)) { updated = true; } @@ -121,7 +121,7 @@ private async Task UpdateRolesForEnabledFeatureAsync(IFeatureInfo feature) updated = true; missingFeatures.Remove(feature.Id); - await UpdateRolesForEnabledFeatureAsync(role, providers); + UpdateRolesForEnabledFeature(role, providers); } if (updated) @@ -166,7 +166,7 @@ private async Task UpdateRoleForInstalledFeaturesAsync(string roleName) .SelectMany(stereotype => stereotype.Permissions ?? []) .Select(stereotype => stereotype.Name); - await UpdatePermissionsAsync(role, permissions); + UpdatePermissions(role, permissions); } private async Task RemoveRoleForMissingFeaturesAsync(string roleName) @@ -179,7 +179,7 @@ private async Task RemoveRoleForMissingFeaturesAsync(string roleName) } } - private Task UpdateRolesForEnabledFeatureAsync(Role role, IEnumerable providers) + private bool UpdateRolesForEnabledFeature(Role role, IEnumerable providers) { var stereotypes = providers .SelectMany(provider => provider.GetDefaultStereotypes()) @@ -187,7 +187,7 @@ private Task UpdateRolesForEnabledFeatureAsync(Role role, IEnumerable UpdateRolesForEnabledFeatureAsync(Role role, IEnumerable UpdatePermissionsAsync(Role role, IEnumerable permissions) + private bool UpdatePermissions(Role role, IEnumerable permissions) { - if (await _systemRoleNameProvider.IsAdminRoleAsync(role.RoleName)) + if (_systemRoleProvider.IsAdminRole(role.RoleName)) { // Don't update claims for admin role. return true; diff --git a/src/OrchardCore.Modules/OrchardCore.Roles/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Roles/Startup.cs index 6adff2c006c..226ea3e9e8a 100644 --- a/src/OrchardCore.Modules/OrchardCore.Roles/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Roles/Startup.cs @@ -33,7 +33,10 @@ public Startup(IShellConfiguration shellConfiguration) public override void ConfigureServices(IServiceCollection services) { services.AddScoped(); + + services.AddDataMigration(); services.AddDataMigration(); + services.AddScoped(); services.Replace(ServiceDescriptor.Scoped>(sp => sp.GetRequiredService())); services.Replace(ServiceDescriptor.Scoped>(sp => sp.GetRequiredService())); diff --git a/src/OrchardCore.Modules/OrchardCore.Settings/Services/SuperUserHandler.cs b/src/OrchardCore.Modules/OrchardCore.Settings/Services/SuperUserHandler.cs index f6c9c37c67b..cae844eb27f 100644 --- a/src/OrchardCore.Modules/OrchardCore.Settings/Services/SuperUserHandler.cs +++ b/src/OrchardCore.Modules/OrchardCore.Settings/Services/SuperUserHandler.cs @@ -11,14 +11,14 @@ namespace OrchardCore.Settings.Services; public class SuperUserHandler : IAuthorizationHandler { private readonly ISiteService _siteService; - private readonly ISystemRoleNameProvider _systemRoleNameProvider; + private readonly ISystemRoleProvider _systemRoleProvider; public SuperUserHandler( ISiteService siteService, - ISystemRoleNameProvider systemRoleNameProvider) + ISystemRoleProvider systemRoleProvider) { _siteService = siteService; - _systemRoleNameProvider = systemRoleNameProvider; + _systemRoleProvider = systemRoleProvider; } public async Task HandleAsync(AuthorizationHandlerContext context) @@ -30,7 +30,9 @@ public async Task HandleAsync(AuthorizationHandlerContext context) return; } - if (user.IsInRole(await _systemRoleNameProvider.GetAdminRoleAsync())) + var adminRole = _systemRoleProvider.GetAdminRole(); + + if (user.IsInRole(adminRole.RoleName)) { SucceedAllRequirements(context); diff --git a/src/OrchardCore.Themes/TheAdmin/Recipes/blank.recipe.json b/src/OrchardCore.Themes/TheAdmin/Recipes/blank.recipe.json index 5b170e73669..0e9cdc2a774 100644 --- a/src/OrchardCore.Themes/TheAdmin/Recipes/blank.recipe.json +++ b/src/OrchardCore.Themes/TheAdmin/Recipes/blank.recipe.json @@ -69,11 +69,6 @@ { "name": "Roles", "Roles": [ - { - "Name": "Administrator", - "Description": "A system role that grants all permissions to the assigned users.", - "Permissions": [] - }, { "Name": "Moderator", "Description": "Grants users the ability to moderate content.", @@ -93,16 +88,6 @@ "Name": "Contributor", "Description": "Grants users the ability to contribute content.", "Permissions": [] - }, - { - "Name": "Authenticated", - "Description": "A system role representing all authenticated users.", - "Permissions": [] - }, - { - "Name": "Anonymous", - "Description": "A system role representing all non-authenticated users.", - "Permissions": [] } ] } diff --git a/src/OrchardCore.Themes/TheAdmin/Recipes/headless.recipe.json b/src/OrchardCore.Themes/TheAdmin/Recipes/headless.recipe.json index 65a4b0a24d3..a050cdf8920 100644 --- a/src/OrchardCore.Themes/TheAdmin/Recipes/headless.recipe.json +++ b/src/OrchardCore.Themes/TheAdmin/Recipes/headless.recipe.json @@ -64,11 +64,6 @@ { "name": "Roles", "Roles": [ - { - "Name": "Administrator", - "Description": "A system role that grants all permissions to the assigned users.", - "Permissions": [] - }, { "Name": "Moderator", "Description": "Grants users the ability to moderate content.", @@ -97,11 +92,6 @@ "ExecuteGraphQL", "ExecuteApiAll" ] - }, - { - "Name": "Anonymous", - "Description": "A system role representing all non-authenticated users.", - "Permissions": [] } ] }, diff --git a/src/OrchardCore.Themes/TheAgencyTheme/Recipes/agency.recipe.json b/src/OrchardCore.Themes/TheAgencyTheme/Recipes/agency.recipe.json index 9c99ed5b29d..c8dd925d27e 100644 --- a/src/OrchardCore.Themes/TheAgencyTheme/Recipes/agency.recipe.json +++ b/src/OrchardCore.Themes/TheAgencyTheme/Recipes/agency.recipe.json @@ -73,11 +73,6 @@ { "name": "Roles", "Roles": [ - { - "Name": "Administrator", - "Description": "A system role that grants all permissions to the assigned users.", - "Permissions": [] - }, { "Name": "Moderator", "Description": "Grants users the ability to moderate content.", @@ -97,16 +92,6 @@ "Name": "Contributor", "Description": "Grants users the ability to contribute content.", "Permissions": [] - }, - { - "Name": "Authenticated", - "Description": "A system role representing all authenticated users.", - "Permissions": [] - }, - { - "Name": "Anonymous", - "Description": "A system role representing all non-authenticated users.", - "Permissions": [] } ] }, diff --git a/src/OrchardCore.Themes/TheBlogTheme/Recipes/blog.recipe.json b/src/OrchardCore.Themes/TheBlogTheme/Recipes/blog.recipe.json index ceabdaee507..662f6ecd704 100644 --- a/src/OrchardCore.Themes/TheBlogTheme/Recipes/blog.recipe.json +++ b/src/OrchardCore.Themes/TheBlogTheme/Recipes/blog.recipe.json @@ -87,11 +87,6 @@ { "name": "Roles", "Roles": [ - { - "Name": "Administrator", - "Description": "A system role that grants all permissions to the assigned users.", - "Permissions": [] - }, { "Name": "Moderator", "Description": "Grants users the ability to moderate content.", @@ -111,16 +106,6 @@ "Name": "Contributor", "Description": "Grants users the ability to contribute content.", "Permissions": [] - }, - { - "Name": "Authenticated", - "Description": "A system role representing all authenticated users.", - "Permissions": [] - }, - { - "Name": "Anonymous", - "Description": "A system role representing all non-authenticated users.", - "Permissions": [] } ] }, diff --git a/src/OrchardCore.Themes/TheComingSoonTheme/Recipes/comingsoon.recipe.json b/src/OrchardCore.Themes/TheComingSoonTheme/Recipes/comingsoon.recipe.json index bc8b03a9ebe..03a0016101a 100644 --- a/src/OrchardCore.Themes/TheComingSoonTheme/Recipes/comingsoon.recipe.json +++ b/src/OrchardCore.Themes/TheComingSoonTheme/Recipes/comingsoon.recipe.json @@ -70,11 +70,6 @@ { "name": "Roles", "Roles": [ - { - "Name": "Administrator", - "Description": "A system role that grants all permissions to the assigned users.", - "Permissions": [] - }, { "Name": "Moderator", "Description": "Grants users the ability to moderate content.", @@ -94,16 +89,6 @@ "Name": "Contributor", "Description": "Grants users the ability to contribute content.", "Permissions": [] - }, - { - "Name": "Authenticated", - "Description": "A system role representing all authenticated users.", - "Permissions": [] - }, - { - "Name": "Anonymous", - "Description": "A system role representing all non-authenticated users.", - "Permissions": [] } ] }, diff --git a/src/OrchardCore.Themes/TheTheme/Recipes/saas.recipe.json b/src/OrchardCore.Themes/TheTheme/Recipes/saas.recipe.json index 51bb484fe18..6c3177230ba 100644 --- a/src/OrchardCore.Themes/TheTheme/Recipes/saas.recipe.json +++ b/src/OrchardCore.Themes/TheTheme/Recipes/saas.recipe.json @@ -40,26 +40,6 @@ "admin": "TheAdmin", "site": "TheTheme" }, - { - "name": "Roles", - "Roles": [ - { - "Name": "Administrator", - "Description": "A system role that grants all permissions to the assigned users.", - "Permissions": [] - }, - { - "Name": "Authenticated", - "Description": "A system role representing all authenticated users.", - "Permissions": [] - }, - { - "Name": "Anonymous", - "Description": "A system role representing all non-authenticated users.", - "Permissions": [] - } - ] - }, { "name": "settings", "HomeRoute": { diff --git a/src/OrchardCore/OrchardCore.Roles.Abstractions/Extensions/SystemRoleProviderExtensions.cs b/src/OrchardCore/OrchardCore.Roles.Abstractions/Extensions/SystemRoleProviderExtensions.cs new file mode 100644 index 00000000000..8c73e9b8d84 --- /dev/null +++ b/src/OrchardCore/OrchardCore.Roles.Abstractions/Extensions/SystemRoleProviderExtensions.cs @@ -0,0 +1,13 @@ +namespace OrchardCore.Roles; + +public static class SystemRoleProviderExtensions +{ + public static bool IsAdminRole(this ISystemRoleProvider systemRoleNameProvider, string name) + { + ArgumentException.ThrowIfNullOrEmpty(name); + + var adminRole = systemRoleNameProvider.GetAdminRole(); + + return adminRole.RoleName.Equals(name, StringComparison.OrdinalIgnoreCase); + } +} diff --git a/src/OrchardCore/OrchardCore.Roles.Abstractions/ISystemRoleNameProvider.cs b/src/OrchardCore/OrchardCore.Roles.Abstractions/ISystemRoleNameProvider.cs index 7b7190acd8c..619449f3bb0 100644 --- a/src/OrchardCore/OrchardCore.Roles.Abstractions/ISystemRoleNameProvider.cs +++ b/src/OrchardCore/OrchardCore.Roles.Abstractions/ISystemRoleNameProvider.cs @@ -2,6 +2,7 @@ namespace OrchardCore.Roles; +[Obsolete("This interface has been deprecated, use ISystemRoleProvider instead.")] public interface ISystemRoleNameProvider { ValueTask GetAdminRoleAsync(); diff --git a/src/OrchardCore/OrchardCore.Roles.Abstractions/ISystemRoleProvider.cs b/src/OrchardCore/OrchardCore.Roles.Abstractions/ISystemRoleProvider.cs new file mode 100644 index 00000000000..f370e317baf --- /dev/null +++ b/src/OrchardCore/OrchardCore.Roles.Abstractions/ISystemRoleProvider.cs @@ -0,0 +1,12 @@ +using OrchardCore.Security; + +namespace OrchardCore.Roles; + +public interface ISystemRoleProvider +{ + IEnumerable GetSystemRoles(); + + IRole GetAdminRole(); + + bool IsSystemRole(string name); +} diff --git a/src/OrchardCore/OrchardCore.Roles.Core/DefaultSystemRoleProvider.cs b/src/OrchardCore/OrchardCore.Roles.Core/DefaultSystemRoleProvider.cs new file mode 100644 index 00000000000..f409da74b83 --- /dev/null +++ b/src/OrchardCore/OrchardCore.Roles.Core/DefaultSystemRoleProvider.cs @@ -0,0 +1,67 @@ +using System.Collections.Frozen; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Options; +using OrchardCore.Environment.Shell; +using OrchardCore.Security; + +namespace OrchardCore.Roles; + +public sealed class DefaultSystemRoleProvider : ISystemRoleProvider +{ + private readonly FrozenDictionary _systemRoles; + private readonly Role _adminRole; + + public DefaultSystemRoleProvider( + ShellSettings shellSettings, + IOptions options, + IStringLocalizer S) + { + var adminRoleName = shellSettings["AdminRoleName"]; + if (string.IsNullOrWhiteSpace(adminRoleName)) + { + adminRoleName = options.Value.SystemAdminRoleName; + } + + if (string.IsNullOrWhiteSpace(adminRoleName)) + { + adminRoleName = OrchardCoreConstants.Roles.Administrator; + } + + _adminRole = new Role + { + RoleName = adminRoleName, + RoleDescription = S["A system role that grants all permissions to the assigned users."] + }; + + _systemRoles = new Dictionary() + { + { _adminRole.RoleName, _adminRole }, + { + OrchardCoreConstants.Roles.Authenticated, new Role + { + RoleName = OrchardCoreConstants.Roles.Authenticated, + RoleDescription = S["A system role representing all authenticated users."] + } + }, + { + OrchardCoreConstants.Roles.Anonymous, new Role + { + RoleName = OrchardCoreConstants.Roles.Anonymous, + RoleDescription = S["A system role representing all non-authenticated users."] + } + } + }.ToFrozenDictionary(StringComparer.OrdinalIgnoreCase); + } + + public IEnumerable GetSystemRoles() + => _systemRoles.Values; + + public IRole GetAdminRole() => _adminRole; + + public bool IsSystemRole(string name) + { + ArgumentException.ThrowIfNullOrEmpty(name); + + return _systemRoles.ContainsKey(name); + } +} diff --git a/src/OrchardCore/OrchardCore.Roles.Core/ServiceCollectionExtensions.cs b/src/OrchardCore/OrchardCore.Roles.Core/ServiceCollectionExtensions.cs index f27ce780e99..11e99c812f1 100644 --- a/src/OrchardCore/OrchardCore.Roles.Core/ServiceCollectionExtensions.cs +++ b/src/OrchardCore/OrchardCore.Roles.Core/ServiceCollectionExtensions.cs @@ -7,7 +7,11 @@ public static class ServiceCollectionExtensions { public static IServiceCollection AddRolesCoreServices(this IServiceCollection services) { +#pragma warning disable CS0618 // Type or member is obsolete services.TryAddSingleton(); +#pragma warning restore CS0618 // Type or member is obsolete + + services.TryAddSingleton(); return services; } diff --git a/src/OrchardCore/OrchardCore.Roles.Core/Services/DefaultSystemRoleNameProvider.cs b/src/OrchardCore/OrchardCore.Roles.Core/Services/DefaultSystemRoleNameProvider.cs index 9b981320cfe..7fe4bd6e5e4 100644 --- a/src/OrchardCore/OrchardCore.Roles.Core/Services/DefaultSystemRoleNameProvider.cs +++ b/src/OrchardCore/OrchardCore.Roles.Core/Services/DefaultSystemRoleNameProvider.cs @@ -4,40 +4,22 @@ namespace OrchardCore.Roles; +#pragma warning disable CS0618 // Type or member is obsolete internal sealed class DefaultSystemRoleNameProvider : ISystemRoleNameProvider +#pragma warning restore CS0618 // Type or member is obsolete { - private readonly string _adminRoleName; + private readonly ISystemRoleProvider _provider; private readonly FrozenSet _systemRoleNames; - public DefaultSystemRoleNameProvider( - ShellSettings shellSettings, - IOptions options) + public DefaultSystemRoleNameProvider(ISystemRoleProvider provider) { - _adminRoleName = shellSettings["AdminRoleName"]; - - if (string.IsNullOrWhiteSpace(_adminRoleName)) - { - _adminRoleName = options.Value.SystemAdminRoleName; - } - - if (string.IsNullOrWhiteSpace(_adminRoleName)) - { - _adminRoleName = OrchardCoreConstants.Roles.Administrator; - } - - var roles = new HashSet(StringComparer.OrdinalIgnoreCase) - { - OrchardCoreConstants.Roles.Anonymous, - OrchardCoreConstants.Roles.Authenticated, - _adminRoleName, - }; - - _systemRoleNames = roles.ToFrozenSet(StringComparer.OrdinalIgnoreCase); + _provider = provider; + _systemRoleNames = provider.GetSystemRoles().Select(x => x.RoleName).ToFrozenSet(StringComparer.OrdinalIgnoreCase); } public ValueTask GetAdminRoleAsync() - => ValueTask.FromResult(_adminRoleName); + => ValueTask.FromResult(_provider.GetAdminRole().RoleName); public ValueTask> GetSystemRolesAsync() => ValueTask.FromResult(_systemRoleNames); diff --git a/src/OrchardCore/OrchardCore.Roles.Core/Services/RoleService.cs b/src/OrchardCore/OrchardCore.Roles.Core/Services/RoleService.cs index 7f8f0dbc7fc..7d35155800b 100644 --- a/src/OrchardCore/OrchardCore.Roles.Core/Services/RoleService.cs +++ b/src/OrchardCore/OrchardCore.Roles.Core/Services/RoleService.cs @@ -8,11 +8,11 @@ namespace OrchardCore.Roles.Services; public class RoleService : IRoleService { private readonly RoleManager _roleManager; - private readonly ISystemRoleNameProvider _systemRoleProvider; + private readonly ISystemRoleProvider _systemRoleProvider; public RoleService( RoleManager roleManager, - ISystemRoleNameProvider systemRoleProvider) + ISystemRoleProvider systemRoleProvider) { _roleManager = roleManager; _systemRoleProvider = systemRoleProvider; @@ -50,8 +50,8 @@ public Task> GetNormalizedRoleNamesAsync() } public ValueTask IsAdminRoleAsync(string role) - => _systemRoleProvider.IsAdminRoleAsync(role); + => ValueTask.FromResult(_systemRoleProvider.IsAdminRole(role)); public ValueTask IsSystemRoleAsync(string role) - => _systemRoleProvider.IsSystemRoleAsync(role); + => ValueTask.FromResult(_systemRoleProvider.IsSystemRole(role)); } diff --git a/src/OrchardCore/OrchardCore.Roles.Core/SystemRoleNameProviderExtensions.cs b/src/OrchardCore/OrchardCore.Roles.Core/SystemRoleNameProviderExtensions.cs index 6ae30673bd0..1f19d7f86dd 100644 --- a/src/OrchardCore/OrchardCore.Roles.Core/SystemRoleNameProviderExtensions.cs +++ b/src/OrchardCore/OrchardCore.Roles.Core/SystemRoleNameProviderExtensions.cs @@ -1,5 +1,6 @@ namespace OrchardCore.Roles; +[Obsolete("This class has been deprecated, please use SystemRoleProviderExtensions instead.")] public static class SystemRoleNameProviderExtensions { public static async ValueTask IsAdminRoleAsync(this ISystemRoleNameProvider provider, string roleName) diff --git a/test/OrchardCore.Tests.Functional/cms-tests/Recipes/migrations.recipe.json b/test/OrchardCore.Tests.Functional/cms-tests/Recipes/migrations.recipe.json index dcb325626a3..5e9a605034f 100644 --- a/test/OrchardCore.Tests.Functional/cms-tests/Recipes/migrations.recipe.json +++ b/test/OrchardCore.Tests.Functional/cms-tests/Recipes/migrations.recipe.json @@ -11,7 +11,7 @@ // The variables are evaluated the first time they are accessed, and reused across steps "variables": { - "homeContentItemId": "[js:uuid()]", + "homeContentItemId": "[js:uuid()]" }, "steps": [ @@ -84,26 +84,6 @@ "admin": "TheAdmin", "site": "TheBlogTheme" }, - { - "name": "Roles", - "Roles": [ - { - "Name": "Administrator", - "Description": "A system role that grants all permissions to the assigned users.", - "Permissions": [] - }, - { - "Name": "Authenticated", - "Description": "A system role representing all authenticated users.", - "Permissions": [] - }, - { - "Name": "Anonymous", - "Description": "A system role representing all non-authenticated users.", - "Permissions": [] - } - ] - }, { "name": "settings", "HomeRoute": { diff --git a/test/OrchardCore.Tests.Pages/OrchardCore.Application.Pages/Recipes/pages.recipe.json b/test/OrchardCore.Tests.Pages/OrchardCore.Application.Pages/Recipes/pages.recipe.json index 5b2faf258ed..3ca773de57c 100644 --- a/test/OrchardCore.Tests.Pages/OrchardCore.Application.Pages/Recipes/pages.recipe.json +++ b/test/OrchardCore.Tests.Pages/OrchardCore.Application.Pages/Recipes/pages.recipe.json @@ -74,11 +74,6 @@ { "name": "Roles", "Roles": [ - { - "Name": "Administrator", - "Description": "A system role that grants all permissions to the assigned users.", - "Permissions": [] - }, { "Name": "Moderator", "Description": "Grants users the ability to moderate content.", @@ -98,16 +93,6 @@ "Name": "Contributor", "Description": "Grants users the ability to contribute content.", "Permissions": [] - }, - { - "Name": "Authenticated", - "Description": "A system role representing all authenticated users.", - "Permissions": [] - }, - { - "Name": "Anonymous", - "Description": "A system role representing all non-authenticated users.", - "Permissions": [] } ] } diff --git a/test/OrchardCore.Tests/Roles/DefaultSystemRoleProviderTests.cs b/test/OrchardCore.Tests/Roles/DefaultSystemRoleProviderTests.cs new file mode 100644 index 00000000000..813da08b72a --- /dev/null +++ b/test/OrchardCore.Tests/Roles/DefaultSystemRoleProviderTests.cs @@ -0,0 +1,103 @@ +using OrchardCore.Environment.Shell; + +namespace OrchardCore.Roles.Tests; + +public class DefaultSystemRoleProviderTests +{ + [Fact] + public void GetSystemRoles_Have_Administrator_Authenticated_Anonymous() + { + // Arrange + var stringLocalizer = Mock.Of>(); + var shellSettings = new ShellSettings(); + var options = new Mock>(); + options.Setup(o => o.Value) + .Returns(new SystemRoleOptions()); + + var provider = new DefaultSystemRoleProvider(shellSettings, options.Object, stringLocalizer); + + // Act + var roles = provider.GetSystemRoles(); + + // Assert + var roleNames = roles.Select(r => r.RoleName); + Assert.Contains(OrchardCoreConstants.Roles.Administrator, roleNames); + Assert.Contains(OrchardCoreConstants.Roles.Authenticated, roleNames); + Assert.Contains(OrchardCoreConstants.Roles.Anonymous, roleNames); + } + + [Fact] + public void GetAdminRole_FromConfiguredAdminRole() + { + // Arrange + var stringLocalizer = Mock.Of>(); + var shellSettings = new ShellSettings(); + var configureSystemAdminRoleName = "SystemAdmin"; + var options = new Mock>(); + options.Setup(o => o.Value) + .Returns(new SystemRoleOptions + { + SystemAdminRoleName = configureSystemAdminRoleName, + }); + + var provider = new DefaultSystemRoleProvider(shellSettings, options.Object, stringLocalizer); + + // Act + var role = provider.GetAdminRole(); + + // Assert + Assert.Equal(configureSystemAdminRoleName, role.RoleName); + Assert.NotEqual(OrchardCoreConstants.Roles.Administrator, role.RoleName); + } + + [Fact] + public void GetAdminRole_FromAppSettings() + { + // Arrange + var adminRoleName = "Foo"; + var stringLocalizer = Mock.Of>(); + var shellSettings = new ShellSettings(); + shellSettings["AdminRoleName"] = adminRoleName; + + var options = new Mock>(); + options.Setup(o => o.Value) + .Returns(new SystemRoleOptions()); + + var provider = new DefaultSystemRoleProvider(shellSettings, options.Object, stringLocalizer); + + // Act + var role = provider.GetAdminRole(); + + // Assert + Assert.Equal(adminRoleName, role.RoleName); + Assert.NotEqual(OrchardCoreConstants.Roles.Administrator, role.RoleName); + } + + [Theory] + [InlineData("Administrator", true)] + [InlineData("ADMINISTRATOR", true)] + [InlineData("Authenticated", true)] + [InlineData("authenticated", true)] + [InlineData("Anonymous", true)] + [InlineData("AnonYmouS", true)] + [InlineData("Test", false)] + [InlineData("TEST", false)] + [InlineData("TesT", false)] + [InlineData("test", false)] + public void IsSystemRole_ReturnsTrue_IfTheRoleExists(string roleName, bool expectedResult) + { + // Arrange + var stringLocalizer = Mock.Of>(); + var shellSettings = new ShellSettings(); + + var options = new Mock>(); + options.Setup(o => o.Value) + .Returns(new SystemRoleOptions()); + + // Act + var provider = new DefaultSystemRoleProvider(shellSettings, options.Object, stringLocalizer); + + // Assert + Assert.Equal(expectedResult, provider.IsSystemRole(roleName)); + } +} diff --git a/test/OrchardCore.Tests/Roles/Extensions/SystemRoleProviderExtensionsTests.cs b/test/OrchardCore.Tests/Roles/Extensions/SystemRoleProviderExtensionsTests.cs new file mode 100644 index 00000000000..2cf779c66b3 --- /dev/null +++ b/test/OrchardCore.Tests/Roles/Extensions/SystemRoleProviderExtensionsTests.cs @@ -0,0 +1,32 @@ +using OrchardCore.Environment.Shell; + +namespace OrchardCore.Roles.Tests; + +public class SystemRoleProviderExtensionsTests +{ + [Theory] + [InlineData("Administrator", true)] + [InlineData("ADMINISTRATOR", true)] + [InlineData("administrator", true)] + [InlineData("AdminiSTratoR", true)] + [InlineData("Test", false)] + [InlineData("TEST", false)] + [InlineData("TesT", false)] + [InlineData("test", false)] + public void IsAdminRole_ReturnsTrue_IfTheRoleExists(string roleName, bool expectedResult) + { + // Arrange + var stringLocalizer = Mock.Of>(); + var shellSettings = new ShellSettings(); + + var options = new Mock>(); + options.Setup(o => o.Value) + .Returns(new SystemRoleOptions()); + + // Act + var provider = new DefaultSystemRoleProvider(shellSettings, options.Object, stringLocalizer); + + // Assert + Assert.Equal(expectedResult, provider.IsAdminRole(roleName)); + } +} diff --git a/test/OrchardCore.Tests/Security/DefaultSystemRoleNameProviderTests.cs b/test/OrchardCore.Tests/Security/DefaultSystemRoleNameProviderTests.cs deleted file mode 100644 index 4d28f1360b9..00000000000 --- a/test/OrchardCore.Tests/Security/DefaultSystemRoleNameProviderTests.cs +++ /dev/null @@ -1,82 +0,0 @@ -using OrchardCore.Environment.Shell; -using OrchardCore.Roles; - -namespace OrchardCore.Tests.Security; - -public class DefaultSystemRoleNameProviderTests -{ - [Fact] - public async Task SystemRoleNamesContains_WhenConstructed_ContainsDefaultAdminRole() - { - // Arrange - var shellSettings = new ShellSettings(); - - var options = new Mock>(); - options.Setup(x => x.Value).Returns(new SystemRoleOptions()); - - var provider = new DefaultSystemRoleNameProvider(shellSettings, options.Object); - - // Assert - var roles = await provider.GetSystemRolesAsync(); - - Assert.Contains(OrchardCoreConstants.Roles.Administrator, roles as IEnumerable); - } - - [Fact] - public async Task SystemRoleNamesContains_WhenConstructed_ContainsConfiguredAdminRole() - { - // Arrange - var shellSettings = new ShellSettings(); - var configureSystemAdminRoleName = "SystemAdmin"; - - var options = new Mock>(); - options.Setup(x => x.Value).Returns(new SystemRoleOptions - { - SystemAdminRoleName = configureSystemAdminRoleName, - }); - - var provider = new DefaultSystemRoleNameProvider(shellSettings, options.Object); - - // Assert - var roles = await provider.GetSystemRolesAsync(); - - Assert.Contains(configureSystemAdminRoleName, roles as IEnumerable); - Assert.DoesNotContain(OrchardCoreConstants.Roles.Administrator, roles as IEnumerable); - } - - [Fact] - public async Task SystemRoleNamesContains_WhenConstructed_ContainsAppSettingsRole() - { - // Arrange - var shellSettings = new ShellSettings(); - shellSettings["AdminRoleName"] = "Foo"; - - var options = new Mock>(); - options.Setup(x => x.Value).Returns(new SystemRoleOptions()); - - var provider = new DefaultSystemRoleNameProvider(shellSettings, options.Object); - // Assert - var roles = await provider.GetSystemRolesAsync(); - - Assert.DoesNotContain(OrchardCoreConstants.Roles.Administrator, roles as IEnumerable); - Assert.Contains("Foo", roles as IEnumerable); - } - - [Fact] - public async Task SystemRoleNamesContains_WhenCalled_ReturnsCaseInsensitive() - { - // Arrange - var shellSettings = new ShellSettings(); - shellSettings["AdminRoleName"] = "Foo"; - - var options = new Mock>(); - options.Setup(x => x.Value).Returns(new SystemRoleOptions()); - - var provider = new DefaultSystemRoleNameProvider(shellSettings, options.Object); - - // Assert - var roles = await provider.GetSystemRolesAsync(); - - Assert.Contains("fOo", roles as IEnumerable); - } -}