mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-06-28 15:34:39 +08:00
Fix/cache by role exception (#8574)
This commit is contained in:
parent
f2ec2a70cd
commit
63cfe7babe
@ -24,6 +24,7 @@ namespace Orchard.OutputCache.Filters {
|
|||||||
IRepository<RoleRecord> roleRepo,
|
IRepository<RoleRecord> roleRepo,
|
||||||
IRepository<RolesPermissionsRecord> rolesPermissionsRepo,
|
IRepository<RolesPermissionsRecord> rolesPermissionsRepo,
|
||||||
IRepository<PermissionRecord> permissionRepo) {
|
IRepository<PermissionRecord> permissionRepo) {
|
||||||
|
|
||||||
_authenticationService = authenticationService;
|
_authenticationService = authenticationService;
|
||||||
_authorizer = authorizer;
|
_authorizer = authorizer;
|
||||||
_userRolesRepo = userRolesRepo;
|
_userRolesRepo = userRolesRepo;
|
||||||
@ -33,6 +34,8 @@ namespace Orchard.OutputCache.Filters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void KeyGenerated(StringBuilder key) {
|
public void KeyGenerated(StringBuilder key) {
|
||||||
|
// Can the queries in this method be optimized away so that their results can be memorized
|
||||||
|
// at least within the scope of a request?
|
||||||
List<UserPermission> userRolesPermissions = new List<UserPermission>();
|
List<UserPermission> userRolesPermissions = new List<UserPermission>();
|
||||||
IQueryable<UserPermission> userRolesPermissionsQuery = Enumerable.Empty<UserPermission>().AsQueryable();
|
IQueryable<UserPermission> userRolesPermissionsQuery = Enumerable.Empty<UserPermission>().AsQueryable();
|
||||||
IQueryable<UserPermission> permissionsQuery = Enumerable.Empty<UserPermission>().AsQueryable();
|
IQueryable<UserPermission> permissionsQuery = Enumerable.Empty<UserPermission>().AsQueryable();
|
||||||
@ -41,21 +44,30 @@ namespace Orchard.OutputCache.Filters {
|
|||||||
if (currentUser != null) {
|
if (currentUser != null) {
|
||||||
// add the Authenticated role and its permissions
|
// add the Authenticated role and its permissions
|
||||||
// the Authenticated role is not assigned to the current user
|
// the Authenticated role is not assigned to the current user
|
||||||
permissionsQuery = GetPermissioFromRole("Authenticated");
|
permissionsQuery = GetPermissionsFromRole("Authenticated");
|
||||||
|
|
||||||
if (_authorizer.Authorize(StandardPermissions.SiteOwner)) {
|
if (_authorizer.Authorize(StandardPermissions.SiteOwner)) {
|
||||||
// the site owner has no permissions
|
// The SuperUser is a SiteOwner that has no assigned role. To properly manage
|
||||||
// get the roles of the site owner
|
// that case we make up a "fake" UserPermission here to add to SiteOwners. We
|
||||||
|
// just need to make sure that the role we use there doesn't actually exist.
|
||||||
|
userRolesPermissions.Add(new UserPermission {
|
||||||
|
RoleName = SiteOwnerRoleName(),
|
||||||
|
PermissionName = "AllPermissions" // A SiteOWner has all Permissions
|
||||||
|
});
|
||||||
|
// A user with the SiteOwner permission may also have other roles
|
||||||
userRolesPermissionsQuery = _userRolesRepo
|
userRolesPermissionsQuery = _userRolesRepo
|
||||||
.Table.Where(usr => usr.UserId == currentUser.Id)
|
.Table.Where(usr => usr.UserId == currentUser.Id)
|
||||||
.Join(
|
.Join(
|
||||||
_roleRepo.Table,
|
_roleRepo.Table,
|
||||||
ur => ur.Role.Id,
|
ur => ur.Role.Id,
|
||||||
r => r.Id,
|
r => r.Id,
|
||||||
(ur, r) => r
|
(ur, r) => new UserPermission { RoleName = r.Name }
|
||||||
)
|
);
|
||||||
.Select(urp => new UserPermission { RoleName = urp.Name });
|
// Since SiteOwners have all permissions, we don't need to query for them here.
|
||||||
} else {
|
// We still query for their roles, because we may be displaying different stuff
|
||||||
|
// to users with different roles, even when they happen to have all permissions.
|
||||||
|
}
|
||||||
|
else {
|
||||||
userRolesPermissionsQuery = _userRolesRepo
|
userRolesPermissionsQuery = _userRolesRepo
|
||||||
// get user roles and permissions
|
// get user roles and permissions
|
||||||
.Table.Where(usr => usr.UserId == currentUser.Id)
|
.Table.Where(usr => usr.UserId == currentUser.Id)
|
||||||
@ -85,25 +97,23 @@ namespace Orchard.OutputCache.Filters {
|
|||||||
(rp, p) => new UserPermission { RoleName = rp.Role.Name, PermissionName = p.FeatureName + "." + p.Name }
|
(rp, p) => new UserPermission { RoleName = rp.Role.Name, PermissionName = p.FeatureName + "." + p.Name }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// the anonymous user has no roles, get its permissions
|
// the anonymous user has no roles, get its permissions
|
||||||
permissionsQuery = GetPermissioFromRole("Anonymous");
|
permissionsQuery = GetPermissionsFromRole("Anonymous");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userRolesPermissionsQuery.Any()) {
|
if (userRolesPermissionsQuery.Any()) {
|
||||||
userRolesPermissions.AddRange(userRolesPermissionsQuery
|
userRolesPermissions.AddRange(userRolesPermissionsQuery
|
||||||
.OrderBy(urp => urp.RoleName)
|
|
||||||
.ThenBy(urp => urp.PermissionName)
|
|
||||||
.ToList());
|
.ToList());
|
||||||
}
|
}
|
||||||
if (permissionsQuery.Any()) {
|
if (permissionsQuery.Any()) {
|
||||||
userRolesPermissions.AddRange(permissionsQuery
|
userRolesPermissions.AddRange(permissionsQuery
|
||||||
.OrderBy(urp => urp.RoleName)
|
|
||||||
.ThenBy(urp => urp.PermissionName)
|
|
||||||
.ToList());
|
.ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userRolesPermissions.Any()) {
|
if (userRolesPermissions.Any()) {
|
||||||
|
|
||||||
var userRoles = String.Join(";", userRolesPermissions
|
var userRoles = String.Join(";", userRolesPermissions
|
||||||
.Select(r => r.RoleName)
|
.Select(r => r.RoleName)
|
||||||
.Distinct()
|
.Distinct()
|
||||||
@ -118,12 +128,38 @@ namespace Orchard.OutputCache.Filters {
|
|||||||
key.Append(string.Format("UserRoles={0};UserPermissions={1};",
|
key.Append(string.Format("UserRoles={0};UserPermissions={1};",
|
||||||
userRoles.GetHashCode(),
|
userRoles.GetHashCode(),
|
||||||
userPermissions.GetHashCode()));
|
userPermissions.GetHashCode()));
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
key.Append("UserRoles=;UserPermissions=;");
|
key.Append("UserRoles=;UserPermissions=;");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IQueryable<UserPermission> GetPermissioFromRole(string role) {
|
private const string _siteOwnerRoleName = "SiteOwnerRole";
|
||||||
|
private IEnumerable<string> _siteOwnerRoleNames;
|
||||||
|
private string SiteOwnerRoleName() {
|
||||||
|
if (_siteOwnerRoleNames == null) {
|
||||||
|
// memorize this so it's only executed once per request
|
||||||
|
_siteOwnerRoleNames = _roleRepo.Table
|
||||||
|
.Where(rr => rr.Name.StartsWith(_siteOwnerRoleName))
|
||||||
|
.Select(rr => rr.Name)
|
||||||
|
.ToList()
|
||||||
|
.Distinct() // sanity check
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
var roleName = _siteOwnerRoleName;
|
||||||
|
if (_siteOwnerRoleNames.Any() && _siteOwnerRoleNames.Contains(roleName)) {
|
||||||
|
// compute unique and repeatable roleName
|
||||||
|
var i = 0;
|
||||||
|
do {
|
||||||
|
roleName = $"{_siteOwnerRoleName}-{i}";
|
||||||
|
i++;
|
||||||
|
} while (_siteOwnerRoleNames.Contains(roleName));
|
||||||
|
}
|
||||||
|
return roleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IQueryable<UserPermission> GetPermissionsFromRole(string role) {
|
||||||
return _roleRepo
|
return _roleRepo
|
||||||
.Table.Where(r => r.Name == role)
|
.Table.Where(r => r.Name == role)
|
||||||
.Join(
|
.Join(
|
||||||
|
Loading…
Reference in New Issue
Block a user