add support for API permissions at the UI layer - including ability to delegate user, role, profile management

This commit is contained in:
Shaun Walker
2023-01-09 11:38:25 -05:00
parent 1616f94b86
commit e136972cd7
50 changed files with 628 additions and 799 deletions

View File

@ -6,7 +6,6 @@ namespace Oqtane.Repository
public interface IPageModuleRepository
{
IEnumerable<PageModule> GetPageModules(int siteId);
IEnumerable<PageModule> GetPageModules(int pageId, string pane);
PageModule AddPageModule(PageModule pageModule);
PageModule UpdatePageModule(PageModule pageModule);
PageModule GetPageModule(int pageModuleId);

View File

@ -10,46 +10,28 @@ namespace Oqtane.Repository
public class PageModuleRepository : IPageModuleRepository
{
private TenantDBContext _db;
private readonly IModuleDefinitionRepository _moduleDefinitions;
private readonly IPermissionRepository _permissions;
public PageModuleRepository(TenantDBContext context, IPermissionRepository permissions)
public PageModuleRepository(TenantDBContext context, IModuleDefinitionRepository moduleDefinitions, IPermissionRepository permissions)
{
_db = context;
_moduleDefinitions = moduleDefinitions;
_permissions = permissions;
}
public IEnumerable<PageModule> GetPageModules(int siteId)
{
IEnumerable<PageModule> pagemodules = _db.PageModule
var pagemodules = _db.PageModule
.Include(item => item.Module) // eager load modules
.Where(item => item.Module.SiteId == siteId);
.Where(item => item.Module.SiteId == siteId).ToList();
if (pagemodules.Any())
{
IEnumerable<Permission> permissions = _permissions.GetPermissions(siteId, EntityNames.Module).ToList();
foreach (PageModule pagemodule in pagemodules)
var moduledefinitions = _moduleDefinitions.GetModuleDefinitions(siteId).ToList();
var permissions = _permissions.GetPermissions(siteId, EntityNames.Module).ToList();
for (int index = 0; index < pagemodules.Count; index++)
{
pagemodule.Module.Permissions = permissions.Where(item => item.EntityId == pagemodule.ModuleId).EncodePermissions();
}
}
return pagemodules;
}
public IEnumerable<PageModule> GetPageModules(int pageId, string pane)
{
IEnumerable<PageModule> pagemodules = _db.PageModule
.Include(item => item.Module) // eager load modules
.Where(item => item.PageId == pageId);
if (pane != "" && pagemodules.Any())
{
pagemodules = pagemodules.Where(item => item.Pane == pane);
}
if (pagemodules.Any())
{
var siteId = pagemodules.FirstOrDefault().Module.SiteId;
IEnumerable<Permission> permissions = _permissions.GetPermissions(siteId, EntityNames.Module).ToList();
foreach (PageModule pagemodule in pagemodules)
{
pagemodule.Module.Permissions = permissions.Where(item => item.EntityId == pagemodule.ModuleId).EncodePermissions();
pagemodules[index] = GetPageModule(pagemodules[index], moduledefinitions, permissions);
}
}
return pagemodules;
@ -89,7 +71,9 @@ namespace Oqtane.Repository
}
if (pagemodule != null)
{
pagemodule.Module.Permissions = _permissions.GetPermissions(pagemodule.Module.SiteId, EntityNames.Module, pagemodule.ModuleId)?.EncodePermissions();
var moduledefinitions = _moduleDefinitions.GetModuleDefinitions(pagemodule.Module.SiteId).ToList();
var permissions = _permissions.GetPermissions(pagemodule.Module.SiteId, EntityNames.Module).ToList();
pagemodule = GetPageModule(pagemodule, moduledefinitions, permissions);
}
return pagemodule;
}
@ -100,7 +84,9 @@ namespace Oqtane.Repository
.SingleOrDefault(item => item.PageId == pageId && item.ModuleId == moduleId);
if (pagemodule != null)
{
pagemodule.Module.Permissions = _permissions.GetPermissions(pagemodule.Module.SiteId, EntityNames.Module, pagemodule.ModuleId)?.EncodePermissions();
var moduledefinitions = _moduleDefinitions.GetModuleDefinitions(pagemodule.Module.SiteId).ToList();
var permissions = _permissions.GetPermissions(pagemodule.Module.SiteId, EntityNames.Module).ToList();
pagemodule = GetPageModule(pagemodule, moduledefinitions, permissions);
}
return pagemodule;
}
@ -111,5 +97,30 @@ namespace Oqtane.Repository
_db.PageModule.Remove(pageModule);
_db.SaveChanges();
}
private PageModule GetPageModule(PageModule pageModule, List<ModuleDefinition> moduleDefinitions, List<Permission> modulePermissions)
{
var permissions = modulePermissions.Where(item => item.EntityId == pageModule.ModuleId).ToList();
// moduledefinition permissionnames can specify permissions for other entities (ie. API permissions)
pageModule.Module.ModuleDefinition = moduleDefinitions.Find(item => item.ModuleDefinitionName == pageModule.Module.ModuleDefinitionName);
if (!string.IsNullOrEmpty(pageModule.Module.ModuleDefinition.PermissionNames) && pageModule.Module.ModuleDefinition.PermissionNames.Contains(":"))
{
foreach (var permissionname in pageModule.Module.ModuleDefinition.PermissionNames.Split(",", System.StringSplitOptions.RemoveEmptyEntries))
{
if (permissionname.Contains(":"))
{
// moduledefinition permissionnames can be in the form of "EntityName:PermissionName:Roles"
var segments = permissionname.Split(':');
if (segments.Length == 3 && segments[0] != EntityNames.Module)
{
permissions.AddRange(_permissions.GetPermissions(pageModule.Module.SiteId, segments[0], segments[1]).Where(item => item.EntityId == -1));
}
}
}
}
pageModule.Module.Permissions = permissions?.EncodePermissions();
return pageModule;
}
}
}

View File

@ -79,23 +79,52 @@ namespace Oqtane.Repository
public void UpdatePermissions(int siteId, string entityName, int entityId, string permissionStrings)
{
// get current permissions and delete
IEnumerable<Permission> permissions = _db.Permission
.Where(item => item.EntityName == entityName)
.Where(item => item.EntityId == entityId)
.Where(item => item.SiteId == siteId);
foreach (Permission permission in permissions)
bool modified = false;
var existing = new List<Permission>();
var permissions = DecodePermissions(permissionStrings, siteId, entityName, entityId);
foreach (var permission in permissions)
{
_db.Permission.Remove(permission);
if (!existing.Any(item => item.EntityName == permission.EntityName && item.PermissionName == permission.PermissionName))
{
existing.AddRange(GetPermissions(siteId, permission.EntityName, permission.PermissionName)
.Where(item => item.EntityId == entityId || item.EntityId == -1));
}
var current = existing.FirstOrDefault(item => item.EntityName == permission.EntityName && item.EntityId == permission.EntityId
&& item.PermissionName == permission.PermissionName && item.RoleId == permission.RoleId && item.UserId == permission.UserId);
if (current != null)
{
if (current.IsAuthorized != permission.IsAuthorized)
{
current.IsAuthorized = permission.IsAuthorized;
_db.Entry(current).State = EntityState.Modified;
modified = true;
}
}
else
{
_db.Permission.Add(permission);
modified = true;
}
}
// add permissions
permissions = DecodePermissions(permissionStrings, siteId, entityName, entityId);
foreach (Permission permission in permissions)
foreach (var permission in existing)
{
_db.Permission.Add(permission);
if (!permissions.Any(item => item.EntityName == permission.EntityName && item.PermissionName == permission.PermissionName
&& item.EntityId == permission.EntityId && item.RoleId == permission.RoleId && item.UserId == permission.UserId))
{
permission.Role = null; // remove linked reference to Role which can cause errors in EF Core change tracking
_db.Permission.Remove(permission);
modified = true;
}
}
if (modified)
{
_db.SaveChanges();
foreach (var entityname in permissions.Select(item => item.EntityName).Distinct())
{
ClearCache(siteId, entityname);
}
}
_db.SaveChanges();
ClearCache(siteId, entityName);
}
public Permission GetPermission(int permissionId)
@ -200,8 +229,22 @@ namespace Oqtane.Repository
securityid = id;
Permission permission = new Permission();
permission.SiteId = siteId;
permission.EntityName = entityName;
permission.EntityId = entityId;
if (!string.IsNullOrEmpty(permissionstring.EntityName))
{
permission.EntityName = permissionstring.EntityName;
}
else
{
permission.EntityName = entityName;
}
if (permission.EntityName == entityName)
{
permission.EntityId = entityId;
}
else
{
permission.EntityId = -1;
}
permission.PermissionName = permissionstring.PermissionName;
permission.RoleId = null;
permission.UserId = null;

View File

@ -431,6 +431,7 @@ namespace Oqtane.Repository
PagePermissions = new List<Permission>
{
new Permission(PermissionNames.View, RoleNames.Admin, true),
new Permission(PermissionNames.View, RoleNames.Registered, true),
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
}.EncodePermissions(),
PageTemplateModules = new List<PageTemplateModule>
@ -441,6 +442,7 @@ namespace Oqtane.Repository
ModulePermissions = new List<Permission>
{
new Permission(PermissionNames.View, RoleNames.Admin, true),
new Permission(PermissionNames.View, RoleNames.Registered, true),
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
}.EncodePermissions(),
Content = ""