Merge pull request #1387 from sbwalker/dev
fix #1367 - provides support for multiple entities in auth policy and makes parameter names more intuitive - backward compatible with entityid
This commit is contained in:
commit
35aaf476d0
|
@ -2,7 +2,6 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Oqtane.Modules.HtmlText.Models;
|
||||
using Oqtane.Services;
|
||||
using Oqtane.Shared;
|
||||
|
||||
|
@ -21,23 +20,23 @@ namespace Oqtane.Modules.HtmlText.Services
|
|||
|
||||
public async Task<Models.HtmlText> GetHtmlTextAsync(int moduleId)
|
||||
{
|
||||
var htmltext = await GetJsonAsync<List<Models.HtmlText>>(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", moduleId));
|
||||
var htmltext = await GetJsonAsync<List<Models.HtmlText>>(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", new Dictionary<string, int>() { { EntityNames.Module, moduleId } }));
|
||||
return htmltext.FirstOrDefault();
|
||||
}
|
||||
|
||||
public async Task AddHtmlTextAsync(Models.HtmlText htmlText)
|
||||
{
|
||||
await PostJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}", htmlText.ModuleId), htmlText);
|
||||
await PostJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}", new Dictionary<string, int>() { { EntityNames.Module, htmlText.ModuleId } }), htmlText);
|
||||
}
|
||||
|
||||
public async Task UpdateHtmlTextAsync(Models.HtmlText htmlText)
|
||||
{
|
||||
await PutJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{htmlText.HtmlTextId}", htmlText.ModuleId), htmlText);
|
||||
await PutJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{htmlText.HtmlTextId}", new Dictionary<string, int>() { { EntityNames.Module, htmlText.ModuleId } }), htmlText);
|
||||
}
|
||||
|
||||
public async Task DeleteHtmlTextAsync(int moduleId)
|
||||
{
|
||||
await DeleteAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", moduleId));
|
||||
await DeleteAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", new Dictionary<string, int>() { { EntityNames.Module, moduleId } }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
|
@ -54,10 +55,15 @@ namespace Oqtane.Services
|
|||
return apiurl;
|
||||
}
|
||||
|
||||
// add entityid parameter to url for custom authorization policy
|
||||
public string CreateAuthorizationPolicyUrl(string url, int entityId)
|
||||
// add authentityid parameters to url for custom authorization policy - args in form of entityname = entityid
|
||||
public string CreateAuthorizationPolicyUrl(string url, Dictionary<string, int> args)
|
||||
{
|
||||
string qs = "entityid=" + entityId.ToString();
|
||||
string qs = "";
|
||||
foreach (KeyValuePair<string, int> kvp in args)
|
||||
{
|
||||
qs += (qs != "") ? "&" : "";
|
||||
qs += "auth" + kvp.Key.ToLower() + "id=" + kvp.Value.ToString();
|
||||
}
|
||||
|
||||
if (url.Contains("?"))
|
||||
{
|
||||
|
@ -204,5 +210,20 @@ namespace Oqtane.Services
|
|||
{
|
||||
return CreateApiUrl(serviceName, alias, ControllerRoutes.Default);
|
||||
}
|
||||
|
||||
[Obsolete("This method is obsolete. Use CreateAuthorizationPolicyUrl(string url, Dictionary<string, int> args) instead - in conjunction with _authEntityId in Server Controller.", false)]
|
||||
public string CreateAuthorizationPolicyUrl(string url, int entityId)
|
||||
{
|
||||
string qs = "entityid=" + entityId.ToString();
|
||||
|
||||
if (url.Contains("?"))
|
||||
{
|
||||
return url + "&" + qs;
|
||||
}
|
||||
else
|
||||
{
|
||||
return url + "?" + qs;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -513,28 +513,7 @@
|
|||
{
|
||||
List<PermissionString> permissions;
|
||||
|
||||
if (action == "publish")
|
||||
{
|
||||
// publish all modules
|
||||
foreach (var module in PageState.Modules.Where(item => item.PageId == PageState.Page.PageId))
|
||||
{
|
||||
permissions = UserSecurity.GetPermissionStrings(module.Permissions);
|
||||
foreach (var permissionstring in permissions)
|
||||
{
|
||||
if (permissionstring.PermissionName == PermissionNames.View)
|
||||
{
|
||||
List<string> ids = permissionstring.Permissions.Split(';').ToList();
|
||||
if (!ids.Contains(RoleNames.Everyone)) ids.Add(RoleNames.Everyone);
|
||||
if (!ids.Contains(RoleNames.Registered)) ids.Add(RoleNames.Registered);
|
||||
permissionstring.Permissions = string.Join(";", ids.ToArray());
|
||||
}
|
||||
}
|
||||
module.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
||||
await ModuleService.UpdateModuleAsync(module);
|
||||
}
|
||||
}
|
||||
|
||||
// publish page
|
||||
// publish/unpublish page
|
||||
var page = PageState.Page;
|
||||
permissions = UserSecurity.GetPermissionStrings(page.Permissions);
|
||||
foreach (var permissionstring in permissions)
|
||||
|
|
|
@ -1,21 +1,35 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Oqtane.Infrastructure;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
namespace Oqtane.Controllers
|
||||
{
|
||||
public class ModuleControllerBase : Controller
|
||||
{
|
||||
protected readonly ILogManager _logger;
|
||||
protected int _entityId = -1; // passed as a querystring parameter for policy authorization and used for validation
|
||||
// querystring parameters for policy authorization and validation
|
||||
protected Dictionary<string, int> _authEntityId = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||
protected int _entityId = -1; // deprecated
|
||||
|
||||
public ModuleControllerBase(ILogManager logger, IHttpContextAccessor accessor)
|
||||
{
|
||||
_logger = logger;
|
||||
int value;
|
||||
foreach (var param in accessor.HttpContext.Request.Query)
|
||||
{
|
||||
if (param.Key.StartsWith("auth") && param.Key.EndsWith("id") && int.TryParse(param.Value, out value))
|
||||
{
|
||||
_authEntityId.Add(param.Key.Substring(4, param.Key.Length - 6), int.Parse(param.Value));
|
||||
}
|
||||
}
|
||||
// entityid is deprecated
|
||||
if (accessor.HttpContext.Request.Query.ContainsKey("entityid"))
|
||||
{
|
||||
_entityId = int.Parse(accessor.HttpContext.Request.Query["entityid"]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,17 +19,19 @@ namespace Oqtane.Controllers
|
|||
private readonly IPageRepository _pages;
|
||||
private readonly IModuleRepository _modules;
|
||||
private readonly IPageModuleRepository _pageModules;
|
||||
private readonly IPermissionRepository _permissionRepository;
|
||||
private readonly ISettingRepository _settings;
|
||||
private readonly IUserPermissions _userPermissions;
|
||||
private readonly ISyncManager _syncManager;
|
||||
private readonly ILogManager _logger;
|
||||
private readonly Alias _alias;
|
||||
|
||||
public PageController(IPageRepository pages, IModuleRepository modules, IPageModuleRepository pageModules, ISettingRepository settings, IUserPermissions userPermissions, ITenantManager tenantManager, ISyncManager syncManager, ILogManager logger)
|
||||
public PageController(IPageRepository pages, IModuleRepository modules, IPageModuleRepository pageModules, IPermissionRepository permissionRepository, ISettingRepository settings, IUserPermissions userPermissions, ITenantManager tenantManager, ISyncManager syncManager, ILogManager logger)
|
||||
{
|
||||
_pages = pages;
|
||||
_modules = modules;
|
||||
_pageModules = pageModules;
|
||||
_permissionRepository = permissionRepository;
|
||||
_settings = settings;
|
||||
_userPermissions = userPermissions;
|
||||
_syncManager = syncManager;
|
||||
|
@ -227,7 +229,54 @@ namespace Oqtane.Controllers
|
|||
{
|
||||
if (ModelState.IsValid && _userPermissions.IsAuthorized(User, EntityNames.Page, page.PageId, PermissionNames.Edit))
|
||||
{
|
||||
// preserve page permissions
|
||||
var oldPermissions = _permissionRepository.GetPermissions(EntityNames.Page, page.PageId).ToList();
|
||||
|
||||
page = _pages.UpdatePage(page);
|
||||
|
||||
// get differences between old and new page permissions
|
||||
var newPermissions = _permissionRepository.DecodePermissions(page.Permissions, page.SiteId, EntityNames.Page, page.PageId).ToList();
|
||||
var added = GetPermissionsDifferences(newPermissions, oldPermissions);
|
||||
var removed = GetPermissionsDifferences(oldPermissions, newPermissions);
|
||||
|
||||
// synchronize module permissions
|
||||
if (added.Count > 0 || removed.Count > 0)
|
||||
{
|
||||
foreach (PageModule pageModule in _pageModules.GetPageModules(page.PageId, "").ToList())
|
||||
{
|
||||
var modulePermissions = _permissionRepository.GetPermissions(EntityNames.Module, pageModule.Module.ModuleId).ToList();
|
||||
//var modulePermissions = _permissionRepository.DecodePermissions(pageModule.Module.Permissions, page.SiteId, EntityNames.Module, pageModule.ModuleId).ToList();
|
||||
// permissions added
|
||||
foreach(Permission permission in added)
|
||||
{
|
||||
if (!modulePermissions.Any(item => item.PermissionName == permission.PermissionName
|
||||
&& item.RoleId == permission.RoleId && item.UserId == permission.UserId && item.IsAuthorized == permission.IsAuthorized))
|
||||
{
|
||||
_permissionRepository.AddPermission(new Permission
|
||||
{
|
||||
SiteId = page.SiteId,
|
||||
EntityName = EntityNames.Module,
|
||||
EntityId = pageModule.ModuleId,
|
||||
PermissionName = permission.PermissionName,
|
||||
RoleId = permission.RoleId,
|
||||
UserId = permission.UserId,
|
||||
IsAuthorized = permission.IsAuthorized
|
||||
});
|
||||
}
|
||||
}
|
||||
// permissions removed
|
||||
foreach (Permission permission in removed)
|
||||
{
|
||||
var modulePermission = modulePermissions.FirstOrDefault(item => item.PermissionName == permission.PermissionName
|
||||
&& item.RoleId == permission.RoleId && item.UserId == permission.UserId && item.IsAuthorized == permission.IsAuthorized);
|
||||
if (modulePermission != null)
|
||||
{
|
||||
_permissionRepository.DeletePermission(modulePermission.PermissionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, page.SiteId);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Page Updated {Page}", page);
|
||||
}
|
||||
|
@ -240,6 +289,19 @@ namespace Oqtane.Controllers
|
|||
return page;
|
||||
}
|
||||
|
||||
private List<Permission> GetPermissionsDifferences(List<Permission> permissions1, List<Permission> permissions2)
|
||||
{
|
||||
var differences = new List<Permission>();
|
||||
foreach (Permission p in permissions1)
|
||||
{
|
||||
if (!permissions2.Any(item => item.PermissionName == p.PermissionName && item.RoleId == p.RoleId && item.UserId == p.UserId && item.IsAuthorized == p.IsAuthorized))
|
||||
{
|
||||
differences.Add(p);
|
||||
}
|
||||
}
|
||||
return differences;
|
||||
}
|
||||
|
||||
// PUT api/<controller>/?siteid=x&pageid=y&parentid=z
|
||||
[HttpPut]
|
||||
[Authorize(Roles = RoleNames.Registered)]
|
||||
|
@ -287,4 +349,5 @@ namespace Oqtane.Controllers
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace Oqtane.Modules.HtmlText.Controllers
|
|||
try
|
||||
{
|
||||
Models.HtmlText htmlText = null;
|
||||
if (_entityId == id)
|
||||
if (_authEntityId[EntityNames.Module] == id)
|
||||
{
|
||||
htmlText = _htmlText.GetHtmlText(id);
|
||||
list.Add(htmlText);
|
||||
|
@ -51,7 +51,7 @@ namespace Oqtane.Modules.HtmlText.Controllers
|
|||
{
|
||||
try
|
||||
{
|
||||
if (ModelState.IsValid && htmlText.ModuleId == _entityId)
|
||||
if (ModelState.IsValid && htmlText.ModuleId == _authEntityId[EntityNames.Module])
|
||||
{
|
||||
htmlText = _htmlText.AddHtmlText(htmlText);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Html/Text Added {HtmlText}", htmlText);
|
||||
|
@ -72,7 +72,7 @@ namespace Oqtane.Modules.HtmlText.Controllers
|
|||
{
|
||||
try
|
||||
{
|
||||
if (ModelState.IsValid && htmlText.ModuleId == _entityId)
|
||||
if (ModelState.IsValid && htmlText.ModuleId == _authEntityId[EntityNames.Module])
|
||||
{
|
||||
htmlText = _htmlText.UpdateHtmlText(htmlText);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Html/Text Updated {HtmlText}", htmlText);
|
||||
|
@ -93,7 +93,7 @@ namespace Oqtane.Modules.HtmlText.Controllers
|
|||
{
|
||||
try
|
||||
{
|
||||
if (id == _entityId)
|
||||
if (id == _authEntityId[EntityNames.Module])
|
||||
{
|
||||
_htmlText.DeleteHtmlText(id);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Html/Text Deleted {HtmlTextId}", id);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Oqtane.Enums;
|
||||
|
@ -22,11 +22,19 @@ namespace Oqtane.Security
|
|||
|
||||
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
|
||||
{
|
||||
// permission is scoped based on EntityId which must be passed as a querystring parameter
|
||||
// permission is scoped based on auth{entityname}id (ie ?authmoduleid ) which must be passed as a querystring parameter
|
||||
var ctx = _httpContextAccessor.HttpContext;
|
||||
if (ctx != null && ctx.Request.Query.ContainsKey("entityid"))
|
||||
if (ctx != null)
|
||||
{
|
||||
int entityId = int.Parse(ctx.Request.Query["entityid"]);
|
||||
int entityId = -1;
|
||||
if (ctx.Request.Query.ContainsKey("auth" + requirement.EntityName.ToLower() + "id"))
|
||||
{
|
||||
entityId = int.Parse(ctx.Request.Query["auth" + requirement.EntityName.ToLower() + "id"]);
|
||||
}
|
||||
if (entityId == -1 && ctx.Request.Query.ContainsKey("entityid"))
|
||||
{
|
||||
entityId = int.Parse(ctx.Request.Query["entityid"]);
|
||||
}
|
||||
if (_userPermissions.IsAuthorized(context.User, requirement.EntityName, entityId, requirement.PermissionName))
|
||||
{
|
||||
context.Succeed(requirement);
|
||||
|
@ -39,4 +47,4 @@ namespace Oqtane.Security
|
|||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user