Merge pull request #2300 from sbwalker/dev

performance optimization for permissions
This commit is contained in:
Shaun Walker 2022-07-19 10:49:52 -04:00 committed by GitHub
commit c62e6c0045
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 18 deletions

View File

@ -1,11 +1,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Security.Policy;
using Oqtane.Models; using Oqtane.Models;
// ReSharper disable once CheckNamespace // ReSharper disable once CheckNamespace
namespace Oqtane.Repository namespace Oqtane.Repository
{ {
public interface IPermissionRepository public interface IPermissionRepository
{ {
IEnumerable<Permission> GetPermissions(int siteId, string entityName); IEnumerable<Permission> GetPermissions(int siteId, string entityName);
IEnumerable<Permission> GetPermissions(string entityName, int entityId); IEnumerable<Permission> GetPermissions(string entityName, int entityId);
IEnumerable<Permission> GetPermissions(string entityName, int entityId, string permissionName); IEnumerable<Permission> GetPermissions(string entityName, int entityId, string permissionName);

View File

@ -3,6 +3,7 @@ using System.Linq;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Oqtane.Extensions; using Oqtane.Extensions;
using Oqtane.Models; using Oqtane.Models;
using Oqtane.Shared;
namespace Oqtane.Repository namespace Oqtane.Repository
{ {
@ -24,7 +25,7 @@ namespace Oqtane.Repository
.Where(item => item.Module.SiteId == siteId); .Where(item => item.Module.SiteId == siteId);
if (pagemodules.Any()) if (pagemodules.Any())
{ {
IEnumerable<Permission> permissions = _permissions.GetPermissions(pagemodules.FirstOrDefault().Module.SiteId, "Module").ToList(); IEnumerable<Permission> permissions = _permissions.GetPermissions(siteId, EntityNames.Module).ToList();
foreach (PageModule pagemodule in pagemodules) foreach (PageModule pagemodule in pagemodules)
{ {
pagemodule.Module.Permissions = permissions.Where(item => item.EntityId == pagemodule.ModuleId).EncodePermissions(); pagemodule.Module.Permissions = permissions.Where(item => item.EntityId == pagemodule.ModuleId).EncodePermissions();
@ -44,7 +45,8 @@ namespace Oqtane.Repository
} }
if (pagemodules.Any()) if (pagemodules.Any())
{ {
IEnumerable<Permission> permissions = _permissions.GetPermissions(pagemodules.FirstOrDefault().Module.SiteId, "Module").ToList(); var siteId = pagemodules.FirstOrDefault().Module.SiteId;
IEnumerable<Permission> permissions = _permissions.GetPermissions(siteId, EntityNames.Module).ToList();
foreach (PageModule pagemodule in pagemodules) foreach (PageModule pagemodule in pagemodules)
{ {
pagemodule.Module.Permissions = permissions.Where(item => item.EntityId == pagemodule.ModuleId).EncodePermissions(); pagemodule.Module.Permissions = permissions.Where(item => item.EntityId == pagemodule.ModuleId).EncodePermissions();
@ -87,7 +89,7 @@ namespace Oqtane.Repository
} }
if (pagemodule != null) if (pagemodule != null)
{ {
pagemodule.Module.Permissions = _permissions.GetPermissionString("Module", pagemodule.ModuleId); pagemodule.Module.Permissions = _permissions.GetPermissionString(EntityNames.Module, pagemodule.ModuleId);
} }
return pagemodule; return pagemodule;
} }
@ -98,7 +100,7 @@ namespace Oqtane.Repository
.SingleOrDefault(item => item.PageId == pageId && item.ModuleId == moduleId); .SingleOrDefault(item => item.PageId == pageId && item.ModuleId == moduleId);
if (pagemodule != null) if (pagemodule != null)
{ {
pagemodule.Module.Permissions = _permissions.GetPermissionString("Module", pagemodule.ModuleId); pagemodule.Module.Permissions = _permissions.GetPermissionString(EntityNames.Module, pagemodule.ModuleId);
} }
return pagemodule; return pagemodule;
} }

View File

@ -1,11 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Oqtane.Extensions; using Oqtane.Extensions;
using Oqtane.Models; using Oqtane.Models;
using Microsoft.Extensions.Caching.Memory;
namespace Oqtane.Repository namespace Oqtane.Repository
{ {
@ -13,33 +15,49 @@ namespace Oqtane.Repository
{ {
private TenantDBContext _db; private TenantDBContext _db;
private readonly IRoleRepository _roles; private readonly IRoleRepository _roles;
private readonly IMemoryCache _cache;
private readonly IHttpContextAccessor _accessor;
public PermissionRepository(TenantDBContext context, IRoleRepository roles) public PermissionRepository(TenantDBContext context, IRoleRepository roles, IMemoryCache cache, IHttpContextAccessor accessor)
{ {
_db = context; _db = context;
_roles = roles; _roles = roles;
_cache = cache;
_accessor = accessor;
} }
public IEnumerable<Permission> GetPermissions(int siteId, string entityName) public IEnumerable<Permission> GetPermissions(int siteId, string entityName)
{ {
return _db.Permission.Where(item => item.SiteId == siteId) var alias = _accessor.HttpContext.GetAlias();
.Where(item => item.EntityName == entityName) if (alias != null)
.Include(item => item.Role); // eager load roles {
return _cache.GetOrCreate($"permissions:{alias.SiteKey}:{entityName}", entry =>
{
entry.SlidingExpiration = TimeSpan.FromMinutes(30);
return _db.Permission.Where(item => item.SiteId == alias.SiteId)
.Where(item => item.EntityName == entityName)
.Include(item => item.Role).ToList(); // eager load roles
});
}
else
{
return _db.Permission.Where(item => item.SiteId == siteId || siteId == -1)
.Where(item => item.EntityName == entityName)
.Include(item => item.Role).ToList(); // eager load roles
}
} }
public IEnumerable<Permission> GetPermissions(string entityName, int entityId) public IEnumerable<Permission> GetPermissions(string entityName, int entityId)
{ {
return _db.Permission.Where(item => item.EntityName == entityName) var permissions = GetPermissions(-1, entityName);
.Where(item => item.EntityId == entityId) return permissions.Where(item => item.EntityId == entityId);
.Include(item => item.Role); // eager load roles
} }
public IEnumerable<Permission> GetPermissions(string entityName, int entityId, string permissionName) public IEnumerable<Permission> GetPermissions(string entityName, int entityId, string permissionName)
{ {
return _db.Permission.Where(item => item.EntityName == entityName) var permissions = GetPermissions(-1, entityName);
.Where(item => item.EntityId == entityId) return permissions.Where(item => item.EntityId == entityId)
.Where(item => item.PermissionName == permissionName) .Where(item => item.PermissionName == permissionName);
.Include(item => item.Role); // eager load roles
} }
public string GetPermissionString(int siteId, string entityName) public string GetPermissionString(int siteId, string entityName)
@ -62,6 +80,7 @@ namespace Oqtane.Repository
{ {
_db.Permission.Add(permission); _db.Permission.Add(permission);
_db.SaveChanges(); _db.SaveChanges();
ClearCache(permission.EntityName);
return permission; return permission;
} }
@ -69,6 +88,7 @@ namespace Oqtane.Repository
{ {
_db.Entry(permission).State = EntityState.Modified; _db.Entry(permission).State = EntityState.Modified;
_db.SaveChanges(); _db.SaveChanges();
ClearCache(permission.EntityName);
return permission; return permission;
} }
@ -90,6 +110,7 @@ namespace Oqtane.Repository
_db.Permission.Add(permission); _db.Permission.Add(permission);
} }
_db.SaveChanges(); _db.SaveChanges();
ClearCache(entityName);
} }
public Permission GetPermission(int permissionId) public Permission GetPermission(int permissionId)
@ -102,6 +123,7 @@ namespace Oqtane.Repository
Permission permission = _db.Permission.Find(permissionId); Permission permission = _db.Permission.Find(permissionId);
_db.Permission.Remove(permission); _db.Permission.Remove(permission);
_db.SaveChanges(); _db.SaveChanges();
ClearCache(permission.EntityName);
} }
public void DeletePermissions(int siteId, string entityName, int entityId) public void DeletePermissions(int siteId, string entityName, int entityId)
@ -115,6 +137,16 @@ namespace Oqtane.Repository
_db.Permission.Remove(permission); _db.Permission.Remove(permission);
} }
_db.SaveChanges(); _db.SaveChanges();
ClearCache(entityName);
}
private void ClearCache(string entityName)
{
var alias = _accessor.HttpContext.GetAlias();
if (alias != null)
{
_cache.Remove($"permissions:{alias.SiteKey}:{entityName}");
}
} }
// permissions are stored in the format "{permissionname:!rolename1;![userid1];rolename2;rolename3;[userid2];[userid3]}" where "!" designates Deny permissions // permissions are stored in the format "{permissionname:!rolename1;![userid1];rolename2;rolename3;[userid2];[userid3]}" where "!" designates Deny permissions