mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-04-05 21:01:35 +08:00
Different cache key by role (#8510)
* feature: adds roles and permissions of the user in to cache key
This commit is contained in:
parent
be55aad08a
commit
5e5bf19863
@ -0,0 +1,151 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Orchard.Data;
|
||||||
|
using Orchard.Environment.Extensions;
|
||||||
|
using Orchard.Roles.Models;
|
||||||
|
using Orchard.Security;
|
||||||
|
|
||||||
|
namespace Orchard.OutputCache.Filters {
|
||||||
|
[OrchardFeature("Orchard.OutputCache.CacheByRole")]
|
||||||
|
public class CacheByRoleFilter : ICachingEventHandler {
|
||||||
|
private readonly IAuthenticationService _authenticationService;
|
||||||
|
private readonly IAuthorizer _authorizer;
|
||||||
|
private readonly IRepository<UserRolesPartRecord> _userRolesRepo;
|
||||||
|
private readonly IRepository<RoleRecord> _roleRepo;
|
||||||
|
private readonly IRepository<RolesPermissionsRecord> _rolesPermissionsRepo;
|
||||||
|
private readonly IRepository<PermissionRecord> _permissionRepo;
|
||||||
|
|
||||||
|
public CacheByRoleFilter(
|
||||||
|
IAuthenticationService authenticationService,
|
||||||
|
IAuthorizer authorizer,
|
||||||
|
IRepository<UserRolesPartRecord> userRolesRepo,
|
||||||
|
IRepository<RoleRecord> roleRepo,
|
||||||
|
IRepository<RolesPermissionsRecord> rolesPermissionsRepo,
|
||||||
|
IRepository<PermissionRecord> permissionRepo) {
|
||||||
|
_authenticationService = authenticationService;
|
||||||
|
_authorizer = authorizer;
|
||||||
|
_userRolesRepo = userRolesRepo;
|
||||||
|
_roleRepo = roleRepo;
|
||||||
|
_rolesPermissionsRepo = rolesPermissionsRepo;
|
||||||
|
_permissionRepo = permissionRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void KeyGenerated(StringBuilder key) {
|
||||||
|
List<UserPermission> userRolesPermissions = new List<UserPermission>();
|
||||||
|
IQueryable<UserPermission> userRolesPermissionsQuery = Enumerable.Empty<UserPermission>().AsQueryable();
|
||||||
|
IQueryable<UserPermission> permissionsQuery = Enumerable.Empty<UserPermission>().AsQueryable();
|
||||||
|
|
||||||
|
var currentUser = _authenticationService.GetAuthenticatedUser();
|
||||||
|
if (currentUser != null) {
|
||||||
|
// add the Authenticated role and its permissions
|
||||||
|
// the Authenticated role is not assigned to the current user
|
||||||
|
permissionsQuery = GetPermissioFromRole("Authenticated");
|
||||||
|
|
||||||
|
if (_authorizer.Authorize(StandardPermissions.SiteOwner)) {
|
||||||
|
// the site owner has no permissions
|
||||||
|
// get the roles of the site owner
|
||||||
|
userRolesPermissionsQuery = _userRolesRepo
|
||||||
|
.Table.Where(usr => usr.UserId == currentUser.Id)
|
||||||
|
.Join(
|
||||||
|
_roleRepo.Table,
|
||||||
|
ur => ur.Role.Id,
|
||||||
|
r => r.Id,
|
||||||
|
(ur, r) => r
|
||||||
|
)
|
||||||
|
.Select(urp => new UserPermission { RoleName = urp.Name });
|
||||||
|
} else {
|
||||||
|
userRolesPermissionsQuery = _userRolesRepo
|
||||||
|
// get user roles and permissions
|
||||||
|
.Table.Where(usr => usr.UserId == currentUser.Id)
|
||||||
|
// given the ids of the roles related to the user
|
||||||
|
// join with the RoleRecord table
|
||||||
|
// get the role name
|
||||||
|
.Join(
|
||||||
|
_roleRepo.Table,
|
||||||
|
ur => ur.Role.Id,
|
||||||
|
r => r.Id,
|
||||||
|
(ur, r) => new { ContentItemRecord = r }
|
||||||
|
)
|
||||||
|
// join table RolePermissionRecord
|
||||||
|
// for each role, get id of role permissions
|
||||||
|
.Join(
|
||||||
|
_rolesPermissionsRepo.Table,
|
||||||
|
obj => obj.ContentItemRecord,
|
||||||
|
rp => rp.Role,
|
||||||
|
(obj, rp) => rp
|
||||||
|
)
|
||||||
|
// join PermissionRecord
|
||||||
|
// for each id permission get feature and permission name
|
||||||
|
.Join(
|
||||||
|
_permissionRepo.Table,
|
||||||
|
rp => rp.Permission.Id,
|
||||||
|
p => p.Id,
|
||||||
|
(rp, p) => new UserPermission { RoleName = rp.Role.Name, PermissionName = p.FeatureName + "." + p.Name }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// the anonymous user has no roles, get its permissions
|
||||||
|
permissionsQuery = GetPermissioFromRole("Anonymous");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userRolesPermissionsQuery.Any()) {
|
||||||
|
userRolesPermissions.AddRange(userRolesPermissionsQuery
|
||||||
|
.OrderBy(urp => urp.RoleName)
|
||||||
|
.ThenBy(urp => urp.PermissionName)
|
||||||
|
.ToList());
|
||||||
|
}
|
||||||
|
if (permissionsQuery.Any()) {
|
||||||
|
userRolesPermissions.AddRange(permissionsQuery
|
||||||
|
.OrderBy(urp => urp.RoleName)
|
||||||
|
.ThenBy(urp => urp.PermissionName)
|
||||||
|
.ToList());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userRolesPermissions.Any()) {
|
||||||
|
var userRoles = String.Join(";", userRolesPermissions
|
||||||
|
.Select(r => r.RoleName)
|
||||||
|
.Distinct()
|
||||||
|
.OrderBy(s => s));
|
||||||
|
|
||||||
|
var userPermissions = String.Join(";", userRolesPermissions
|
||||||
|
.Select(p => p.PermissionName)
|
||||||
|
.Distinct() // permissions may be duplicate: two different roles may give the same permission
|
||||||
|
.OrderBy(s => s));
|
||||||
|
|
||||||
|
|
||||||
|
key.Append(string.Format("UserRoles={0};UserPermissions={1};",
|
||||||
|
userRoles.GetHashCode(),
|
||||||
|
userPermissions.GetHashCode()));
|
||||||
|
} else {
|
||||||
|
key.Append("UserRoles=;UserPermissions=;");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IQueryable<UserPermission> GetPermissioFromRole(string role) {
|
||||||
|
return _roleRepo
|
||||||
|
.Table.Where(r => r.Name == role)
|
||||||
|
.Join(
|
||||||
|
_rolesPermissionsRepo.Table,
|
||||||
|
r => r.Id,
|
||||||
|
rp => rp.Role.Id,
|
||||||
|
(obj, rp) => rp
|
||||||
|
)
|
||||||
|
.Join(
|
||||||
|
_permissionRepo.Table,
|
||||||
|
rp => rp.Permission.Id,
|
||||||
|
p => p.Id,
|
||||||
|
(rp, p) => new UserPermission { RoleName = rp.Role.Name, PermissionName = p.FeatureName + "." + p.Name }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class UserPermission {
|
||||||
|
public UserPermission() {
|
||||||
|
RoleName = string.Empty;
|
||||||
|
PermissionName = string.Empty;
|
||||||
|
}
|
||||||
|
public string RoleName { get; set; }
|
||||||
|
public string PermissionName { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -20,3 +20,8 @@ Features:
|
|||||||
Description: Activates a provider that stores output cache data in the App_Data folder.
|
Description: Activates a provider that stores output cache data in the App_Data folder.
|
||||||
Category: Performance
|
Category: Performance
|
||||||
Dependencies: Orchard.OutputCache
|
Dependencies: Orchard.OutputCache
|
||||||
|
Orchard.OutputCache.CacheByRole:
|
||||||
|
Name: Cache By Role
|
||||||
|
Description: Adds the user role in the cache key
|
||||||
|
Category: Performance
|
||||||
|
Dependencies: Orchard.OutputCache, Orchard.Roles
|
||||||
|
@ -104,6 +104,7 @@
|
|||||||
<Content Include="Web.config" />
|
<Content Include="Web.config" />
|
||||||
<Content Include="Scripts\Web.config" />
|
<Content Include="Scripts\Web.config" />
|
||||||
<Content Include="Styles\Web.config" />
|
<Content Include="Styles\Web.config" />
|
||||||
|
<Compile Include="Filters\CacheByRoleFilter.cs" />
|
||||||
<Compile Include="Handlers\CacheItemInvalidationHandler.cs" />
|
<Compile Include="Handlers\CacheItemInvalidationHandler.cs" />
|
||||||
<Compile Include="ICachingEventHandler.cs" />
|
<Compile Include="ICachingEventHandler.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
@ -120,6 +121,10 @@
|
|||||||
<Name>Orchard.Core</Name>
|
<Name>Orchard.Core</Name>
|
||||||
<Private>$(MvcBuildViews)</Private>
|
<Private>$(MvcBuildViews)</Private>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\Orchard.Roles\Orchard.Roles.csproj">
|
||||||
|
<Project>{D10AD48F-407D-4DB5-A328-173EC7CB010F}</Project>
|
||||||
|
<Name>Orchard.Roles</Name>
|
||||||
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="AdminMenu.cs" />
|
<Compile Include="AdminMenu.cs" />
|
||||||
@ -213,4 +218,4 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Error Condition="!Exists('..\..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net46\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net46\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" />
|
<Error Condition="!Exists('..\..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net46\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net46\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" />
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in New Issue
Block a user