From d93ff4307f99bfc13ec8b96b1909efe1774a94fd Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Thu, 9 Jan 2025 12:02:00 -0800 Subject: [PATCH] Add Roles Abstraction and clean up Users module (#17088) --- Directory.Packages.props | 4 +- OrchardCore.sln | 7 ++++ .../OrchardCore.Cors/OrchardCore.Cors.csproj | 1 + .../Handlers}/RoleAuthorizationHandler.cs | 0 .../RoleTwoFactorAuthenticationHandler.cs | 0 .../Handlers}/UserRoleRemovedEventHandler.cs | 0 .../Services/RolesAdminListFilterProvider.cs | 39 ++++++++++++++++++ .../Services}/UserRolePermissions.cs | 0 .../Services/RolesAdminListFilterProvider.cs | 40 ------------------- .../Security/Services/RoleHelper.cs | 11 ----- .../IRole.cs | 0 .../IRoleCreatedEventHandler.cs | 0 .../IRoleRemovedEventHandler.cs | 0 .../IRoleService.cs | 0 .../ISystemRoleNameProvider.cs | 0 .../OrchardCore.Roles.Abstractions.csproj | 23 +++++++++++ .../Role.cs | 0 .../RoleClaim.cs | 0 .../RoleServiceExtensions.cs | 8 ---- .../OrchardCore.Roles.Core.csproj | 1 + .../Services/NullRoleStore.cs | 0 .../Services/RoleService.cs | 0 22 files changed, 74 insertions(+), 60 deletions(-) rename src/OrchardCore.Modules/OrchardCore.Users/{Services => Roles/Handlers}/RoleAuthorizationHandler.cs (100%) rename src/OrchardCore.Modules/OrchardCore.Users/{Services => Roles/Handlers}/RoleTwoFactorAuthenticationHandler.cs (100%) rename src/OrchardCore.Modules/OrchardCore.Users/{Services => Roles/Handlers}/UserRoleRemovedEventHandler.cs (100%) create mode 100644 src/OrchardCore.Modules/OrchardCore.Users/Roles/Services/RolesAdminListFilterProvider.cs rename src/OrchardCore.Modules/OrchardCore.Users/{ => Roles/Services}/UserRolePermissions.cs (100%) delete mode 100644 src/OrchardCore.Modules/OrchardCore.Users/Services/RolesAdminListFilterProvider.cs delete mode 100644 src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Services/RoleHelper.cs rename src/OrchardCore/{OrchardCore.Infrastructure.Abstractions/Security => OrchardCore.Roles.Abstractions}/IRole.cs (100%) rename src/OrchardCore/{OrchardCore.Infrastructure.Abstractions/Security => OrchardCore.Roles.Abstractions}/IRoleCreatedEventHandler.cs (100%) rename src/OrchardCore/{OrchardCore.Infrastructure.Abstractions/Security => OrchardCore.Roles.Abstractions}/IRoleRemovedEventHandler.cs (100%) rename src/OrchardCore/{OrchardCore.Infrastructure.Abstractions/Security/Services => OrchardCore.Roles.Abstractions}/IRoleService.cs (100%) rename src/OrchardCore/{OrchardCore.Roles.Core => OrchardCore.Roles.Abstractions}/ISystemRoleNameProvider.cs (100%) create mode 100644 src/OrchardCore/OrchardCore.Roles.Abstractions/OrchardCore.Roles.Abstractions.csproj rename src/OrchardCore/{OrchardCore.Infrastructure.Abstractions/Security => OrchardCore.Roles.Abstractions}/Role.cs (100%) rename src/OrchardCore/{OrchardCore.Infrastructure.Abstractions/Security => OrchardCore.Roles.Abstractions}/RoleClaim.cs (100%) rename src/OrchardCore/{OrchardCore.Infrastructure.Abstractions/Security/Services => OrchardCore.Roles.Abstractions}/RoleServiceExtensions.cs (77%) rename src/OrchardCore/{OrchardCore.Users.Core => OrchardCore.Roles.Core}/Services/NullRoleStore.cs (100%) rename src/OrchardCore/{OrchardCore.Users.Core => OrchardCore.Roles.Core}/Services/RoleService.cs (100%) diff --git a/Directory.Packages.props b/Directory.Packages.props index 0b6b17d0d8c..d8e0dfb59d7 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -145,6 +145,7 @@ + @@ -164,7 +165,8 @@ - + + diff --git a/OrchardCore.sln b/OrchardCore.sln index 5b8d76e538a..817e3821854 100644 --- a/OrchardCore.sln +++ b/OrchardCore.sln @@ -532,6 +532,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.UrlRewriting.Ab EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.UrlRewriting.Core", "src\OrchardCore\OrchardCore.UrlRewriting.Core\OrchardCore.UrlRewriting.Core.csproj", "{7B18DD99-A7BB-4297-8679-D87289758756}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OrchardCore.Roles.Abstractions", "src\OrchardCore\OrchardCore.Roles.Abstractions\OrchardCore.Roles.Abstractions.csproj", "{F5E7DCC3-12C2-4363-9702-639561A8101C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1408,6 +1410,10 @@ Global {7B18DD99-A7BB-4297-8679-D87289758756}.Debug|Any CPU.Build.0 = Debug|Any CPU {7B18DD99-A7BB-4297-8679-D87289758756}.Release|Any CPU.ActiveCfg = Release|Any CPU {7B18DD99-A7BB-4297-8679-D87289758756}.Release|Any CPU.Build.0 = Release|Any CPU + {F5E7DCC3-12C2-4363-9702-639561A8101C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F5E7DCC3-12C2-4363-9702-639561A8101C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F5E7DCC3-12C2-4363-9702-639561A8101C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F5E7DCC3-12C2-4363-9702-639561A8101C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1651,6 +1657,7 @@ Global {D0F8B342-BDA8-44CB-AA43-7A65C79636A2} = {A066395F-6F73-45DC-B5A6-B4E306110DCE} {675C8A76-C64F-47EC-B4F5-06D4F2D9662A} = {F23AC6C2-DE44-4699-999D-3C478EF3D691} {7B18DD99-A7BB-4297-8679-D87289758756} = {F23AC6C2-DE44-4699-999D-3C478EF3D691} + {F5E7DCC3-12C2-4363-9702-639561A8101C} = {F23AC6C2-DE44-4699-999D-3C478EF3D691} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {46A1D25A-78D1-4476-9CBF-25B75E296341} diff --git a/src/OrchardCore.Modules/OrchardCore.Cors/OrchardCore.Cors.csproj b/src/OrchardCore.Modules/OrchardCore.Cors/OrchardCore.Cors.csproj index 7a4d9a95739..222104ededa 100644 --- a/src/OrchardCore.Modules/OrchardCore.Cors/OrchardCore.Cors.csproj +++ b/src/OrchardCore.Modules/OrchardCore.Cors/OrchardCore.Cors.csproj @@ -13,6 +13,7 @@ + diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Services/RoleAuthorizationHandler.cs b/src/OrchardCore.Modules/OrchardCore.Users/Roles/Handlers/RoleAuthorizationHandler.cs similarity index 100% rename from src/OrchardCore.Modules/OrchardCore.Users/Services/RoleAuthorizationHandler.cs rename to src/OrchardCore.Modules/OrchardCore.Users/Roles/Handlers/RoleAuthorizationHandler.cs diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Services/RoleTwoFactorAuthenticationHandler.cs b/src/OrchardCore.Modules/OrchardCore.Users/Roles/Handlers/RoleTwoFactorAuthenticationHandler.cs similarity index 100% rename from src/OrchardCore.Modules/OrchardCore.Users/Services/RoleTwoFactorAuthenticationHandler.cs rename to src/OrchardCore.Modules/OrchardCore.Users/Roles/Handlers/RoleTwoFactorAuthenticationHandler.cs diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Services/UserRoleRemovedEventHandler.cs b/src/OrchardCore.Modules/OrchardCore.Users/Roles/Handlers/UserRoleRemovedEventHandler.cs similarity index 100% rename from src/OrchardCore.Modules/OrchardCore.Users/Services/UserRoleRemovedEventHandler.cs rename to src/OrchardCore.Modules/OrchardCore.Users/Roles/Handlers/UserRoleRemovedEventHandler.cs diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Roles/Services/RolesAdminListFilterProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Roles/Services/RolesAdminListFilterProvider.cs new file mode 100644 index 00000000000..06cd1de8b98 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Users/Roles/Services/RolesAdminListFilterProvider.cs @@ -0,0 +1,39 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using OrchardCore.Security.Services; +using OrchardCore.Users.Indexes; +using OrchardCore.Users.Models; +using YesSql.Filters.Query; +using YesSql.Services; + +namespace OrchardCore.Users.Services; + +public sealed class RolesAdminListFilterProvider : IUsersAdminListFilterProvider +{ + public void Build(QueryEngineBuilder builder) + { + builder.WithNamedTerm("role-restriction", builder => builder + .OneCondition(async (contentType, query, ctx) => + { + var context = (UserQueryContext)ctx; + + var httpContextAccessor = context.ServiceProvider.GetRequiredService(); + var authorizationService = context.ServiceProvider.GetRequiredService(); + var roleService = context.ServiceProvider.GetRequiredService(); + + var user = httpContextAccessor.HttpContext?.User; + + if (user != null && !await authorizationService.AuthorizeAsync(user, CommonPermissions.ListUsers)) + { + // At this point the user cannot see all users, so lets see what role does he have access too and filter by them. + var accessibleRoles = (await roleService.GetAssignableRolesAsync()).Select(x => x.RoleName); + + query.With(index => index.RoleName.IsIn(accessibleRoles)); + } + + return query; + }).AlwaysRun() + ); + } +} diff --git a/src/OrchardCore.Modules/OrchardCore.Users/UserRolePermissions.cs b/src/OrchardCore.Modules/OrchardCore.Users/Roles/Services/UserRolePermissions.cs similarity index 100% rename from src/OrchardCore.Modules/OrchardCore.Users/UserRolePermissions.cs rename to src/OrchardCore.Modules/OrchardCore.Users/Roles/Services/UserRolePermissions.cs diff --git a/src/OrchardCore.Modules/OrchardCore.Users/Services/RolesAdminListFilterProvider.cs b/src/OrchardCore.Modules/OrchardCore.Users/Services/RolesAdminListFilterProvider.cs deleted file mode 100644 index 989adf026ee..00000000000 --- a/src/OrchardCore.Modules/OrchardCore.Users/Services/RolesAdminListFilterProvider.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; -using OrchardCore.Security.Services; -using OrchardCore.Users.Indexes; -using OrchardCore.Users.Models; -using YesSql.Filters.Query; -using YesSql.Services; - -namespace OrchardCore.Users.Services; - -public sealed class RolesAdminListFilterProvider : IUsersAdminListFilterProvider -{ - public void Build(QueryEngineBuilder builder) - { - builder.WithNamedTerm("role-restriction", builder => builder - .OneCondition(async (contentType, query, ctx) => - { - var context = (UserQueryContext)ctx; - - var httpContextAccessor = context.ServiceProvider.GetRequiredService(); - var authorizationService = context.ServiceProvider.GetRequiredService(); - var roleService = context.ServiceProvider.GetRequiredService(); - - var user = httpContextAccessor.HttpContext?.User; - - if (user != null && !await authorizationService.AuthorizeAsync(user, CommonPermissions.ListUsers)) - { - // At this point the user cannot see all users, so lets see what role does he have access too and filter by them. - var accessibleRoles = (await roleService.GetAssignableRolesAsync()).Select(x => x.RoleName); - - query.With(index => index.RoleName.IsIn(accessibleRoles)); - } - - return query; - }) - .AlwaysRun() - ); - } -} diff --git a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Services/RoleHelper.cs b/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Services/RoleHelper.cs deleted file mode 100644 index d9313983258..00000000000 --- a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Services/RoleHelper.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace OrchardCore.Security.Services; - -public static class RoleHelper -{ - [Obsolete("This method has been marked as obsolete and will be removed in future releases. Instead of using this helper, please use the IRoleService.IsSystemRoleAsync() method.")] - public static readonly HashSet SystemRoleNames = new(StringComparer.OrdinalIgnoreCase) - { - OrchardCoreConstants.Roles.Anonymous, - OrchardCoreConstants.Roles.Authenticated, - }; -} diff --git a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/IRole.cs b/src/OrchardCore/OrchardCore.Roles.Abstractions/IRole.cs similarity index 100% rename from src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/IRole.cs rename to src/OrchardCore/OrchardCore.Roles.Abstractions/IRole.cs diff --git a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/IRoleCreatedEventHandler.cs b/src/OrchardCore/OrchardCore.Roles.Abstractions/IRoleCreatedEventHandler.cs similarity index 100% rename from src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/IRoleCreatedEventHandler.cs rename to src/OrchardCore/OrchardCore.Roles.Abstractions/IRoleCreatedEventHandler.cs diff --git a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/IRoleRemovedEventHandler.cs b/src/OrchardCore/OrchardCore.Roles.Abstractions/IRoleRemovedEventHandler.cs similarity index 100% rename from src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/IRoleRemovedEventHandler.cs rename to src/OrchardCore/OrchardCore.Roles.Abstractions/IRoleRemovedEventHandler.cs diff --git a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Services/IRoleService.cs b/src/OrchardCore/OrchardCore.Roles.Abstractions/IRoleService.cs similarity index 100% rename from src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Services/IRoleService.cs rename to src/OrchardCore/OrchardCore.Roles.Abstractions/IRoleService.cs diff --git a/src/OrchardCore/OrchardCore.Roles.Core/ISystemRoleNameProvider.cs b/src/OrchardCore/OrchardCore.Roles.Abstractions/ISystemRoleNameProvider.cs similarity index 100% rename from src/OrchardCore/OrchardCore.Roles.Core/ISystemRoleNameProvider.cs rename to src/OrchardCore/OrchardCore.Roles.Abstractions/ISystemRoleNameProvider.cs diff --git a/src/OrchardCore/OrchardCore.Roles.Abstractions/OrchardCore.Roles.Abstractions.csproj b/src/OrchardCore/OrchardCore.Roles.Abstractions/OrchardCore.Roles.Abstractions.csproj new file mode 100644 index 00000000000..2349904e7c7 --- /dev/null +++ b/src/OrchardCore/OrchardCore.Roles.Abstractions/OrchardCore.Roles.Abstractions.csproj @@ -0,0 +1,23 @@ + + + + OrchardCore.Roles + + OrchardCore Roles Abstractions + + $(OCCMSDescription) + + Abstractions for OrchardCoreCMS Roles + + $(PackageTags) OrchardCoreCMS Roles Abstractions + + + + + + + + + + + diff --git a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Role.cs b/src/OrchardCore/OrchardCore.Roles.Abstractions/Role.cs similarity index 100% rename from src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Role.cs rename to src/OrchardCore/OrchardCore.Roles.Abstractions/Role.cs diff --git a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/RoleClaim.cs b/src/OrchardCore/OrchardCore.Roles.Abstractions/RoleClaim.cs similarity index 100% rename from src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/RoleClaim.cs rename to src/OrchardCore/OrchardCore.Roles.Abstractions/RoleClaim.cs diff --git a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Services/RoleServiceExtensions.cs b/src/OrchardCore/OrchardCore.Roles.Abstractions/RoleServiceExtensions.cs similarity index 77% rename from src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Services/RoleServiceExtensions.cs rename to src/OrchardCore/OrchardCore.Roles.Abstractions/RoleServiceExtensions.cs index 5234a95143f..f64d42a142b 100644 --- a/src/OrchardCore/OrchardCore.Infrastructure.Abstractions/Security/Services/RoleServiceExtensions.cs +++ b/src/OrchardCore/OrchardCore.Roles.Abstractions/RoleServiceExtensions.cs @@ -49,12 +49,4 @@ public static async Task> GetAccessibleRolesAsync(this IRoleS return accessibleRoles; } - - [Obsolete("This method is obsolete and will be removed in future releases.")] - public static async Task> GetAccessibleRoleNamesAsync(this IRoleService roleService, IAuthorizationService authorizationService, ClaimsPrincipal user, Permission permission) - { - var roles = await roleService.GetAccessibleRolesAsync(authorizationService, user, permission); - - return roles.Select(x => x.RoleName); - } } diff --git a/src/OrchardCore/OrchardCore.Roles.Core/OrchardCore.Roles.Core.csproj b/src/OrchardCore/OrchardCore.Roles.Core/OrchardCore.Roles.Core.csproj index 798696b6db3..3edd5a946d6 100644 --- a/src/OrchardCore/OrchardCore.Roles.Core/OrchardCore.Roles.Core.csproj +++ b/src/OrchardCore/OrchardCore.Roles.Core/OrchardCore.Roles.Core.csproj @@ -22,6 +22,7 @@ + diff --git a/src/OrchardCore/OrchardCore.Users.Core/Services/NullRoleStore.cs b/src/OrchardCore/OrchardCore.Roles.Core/Services/NullRoleStore.cs similarity index 100% rename from src/OrchardCore/OrchardCore.Users.Core/Services/NullRoleStore.cs rename to src/OrchardCore/OrchardCore.Roles.Core/Services/NullRoleStore.cs diff --git a/src/OrchardCore/OrchardCore.Users.Core/Services/RoleService.cs b/src/OrchardCore/OrchardCore.Roles.Core/Services/RoleService.cs similarity index 100% rename from src/OrchardCore/OrchardCore.Users.Core/Services/RoleService.cs rename to src/OrchardCore/OrchardCore.Roles.Core/Services/RoleService.cs