mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-09-23 04:43:35 +08:00
Extending security model for owned/other content permission support
Added an IContent parameter to IAuthorizationService and IAuthorizer Added an IAuthorizationServiceEvents interface for modules to participate in the process Updated the role-based authorization service to fire events and recheck access based on adjustments Added hook in Orchard.Pages/Security/Authorization.cs with "pages" specific auth adjustments --HG-- extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4045861
This commit is contained in:
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Security;
|
||||
using Orchard.Security.Permissions;
|
||||
using Orchard.UI.Navigation;
|
||||
@@ -19,10 +20,10 @@ namespace Orchard.Tests.UI.Navigation {
|
||||
}
|
||||
|
||||
public class StubAuth : IAuthorizationService {
|
||||
public void CheckAccess(IUser user, Permission permission) {
|
||||
public void CheckAccess(Permission permission, IUser user, IContent content) {
|
||||
}
|
||||
|
||||
public bool TryCheckAccess(IUser user, Permission permission) {
|
||||
public bool TryCheckAccess(Permission permission, IUser user, IContent content) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -134,7 +134,7 @@ namespace Orchard.Core.Common.Providers {
|
||||
|
||||
private void GetEditor(BuildEditorModelContext context, CommonAspect instance) {
|
||||
var currentUser = _authenticationService.GetAuthenticatedUser();
|
||||
if (!_authorizationService.TryCheckAccess(currentUser, Permissions.ChangeOwner)) {
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ChangeOwner, currentUser, instance)) {
|
||||
return;
|
||||
}
|
||||
var viewModel = new OwnerEditorViewModel();
|
||||
@@ -152,7 +152,7 @@ namespace Orchard.Core.Common.Providers {
|
||||
instance.VersionModifiedUtc = _clock.UtcNow;
|
||||
|
||||
var currentUser = _authenticationService.GetAuthenticatedUser();
|
||||
if (!_authorizationService.TryCheckAccess(currentUser, Permissions.ChangeOwner)) {
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ChangeOwner, currentUser, instance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -46,7 +46,7 @@ namespace Orchard.Media.Services {
|
||||
XRpcStruct file) {
|
||||
|
||||
var user = _membershipService.ValidateUser(userName, password);
|
||||
if (!_authorizationService.TryCheckAccess(user, Permissions.UploadMediaFiles)) {
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.UploadMediaFiles, user, null)) {
|
||||
//TEMP: return appropriate access-denied response for user
|
||||
throw new ApplicationException("Access denied");
|
||||
}
|
||||
|
@@ -14,15 +14,15 @@ using Orchard.UI.Notify;
|
||||
namespace Orchard.Pages.Controllers {
|
||||
[ValidateInput(false)]
|
||||
public class AdminController : Controller, IUpdateModel {
|
||||
private readonly IOrchardServices _services;
|
||||
private readonly IPageService _pageService;
|
||||
|
||||
public AdminController(IOrchardServices services, IPageService pageService) {
|
||||
_services = services;
|
||||
Services = services;
|
||||
_pageService = pageService;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public IOrchardServices Services { get; private set; }
|
||||
private Localizer T { get; set; }
|
||||
|
||||
public ActionResult List(PagesOptions options) {
|
||||
@@ -58,7 +58,7 @@ namespace Orchard.Pages.Controllers {
|
||||
case PagesBulkAction.None:
|
||||
break;
|
||||
case PagesBulkAction.PublishNow:
|
||||
if (!_services.Authorizer.Authorize(Permissions.PublishPages, T("Couldn't publish page")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.PublishPages, T("Couldn't publish page")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
foreach (PageEntry entry in checkedEntries) {
|
||||
@@ -67,7 +67,7 @@ namespace Orchard.Pages.Controllers {
|
||||
}
|
||||
break;
|
||||
case PagesBulkAction.Unpublish:
|
||||
if (!_services.Authorizer.Authorize(Permissions.PublishPages, T("Couldn't unpublish page")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.PublishPages, T("Couldn't unpublish page")))
|
||||
return new HttpUnauthorizedResult();
|
||||
foreach (PageEntry entry in checkedEntries) {
|
||||
var page = _pageService.GetLatest(entry.PageId);
|
||||
@@ -75,7 +75,7 @@ namespace Orchard.Pages.Controllers {
|
||||
}
|
||||
break;
|
||||
case PagesBulkAction.Delete:
|
||||
if (!_services.Authorizer.Authorize(Permissions.DeletePages, T("Couldn't delete page")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.DeletePages, T("Couldn't delete page")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
foreach (PageEntry entry in checkedEntries) {
|
||||
@@ -99,10 +99,10 @@ namespace Orchard.Pages.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult Create() {
|
||||
if (!_services.Authorizer.Authorize(Permissions.EditPages, T("Not allowed to create a page")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.EditPages, T("Not allowed to create a page")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var page = _services.ContentManager.BuildEditorModel(_services.ContentManager.New<Page>("page"));
|
||||
var page = Services.ContentManager.BuildEditorModel(Services.ContentManager.New<Page>("page"));
|
||||
|
||||
var model = new PageCreateViewModel {
|
||||
Page = page
|
||||
@@ -113,7 +113,7 @@ namespace Orchard.Pages.Controllers {
|
||||
|
||||
[HttpPost, ActionName("Create")]
|
||||
public ActionResult CreatePOST(PageCreateViewModel model) {
|
||||
if (!_services.Authorizer.Authorize(Permissions.EditPages, T("Couldn't create page")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.EditPages, T("Couldn't create page")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
//TODO: (erikpo) Move this duplicate code somewhere else
|
||||
@@ -129,38 +129,37 @@ namespace Orchard.Pages.Controllers {
|
||||
}
|
||||
}
|
||||
|
||||
model.Page = _services.ContentManager.UpdateEditorModel(_services.ContentManager.New<Page>("page"), this);
|
||||
model.Page = Services.ContentManager.UpdateEditorModel(Services.ContentManager.New<Page>("page"), this);
|
||||
if (!publishNow && publishDate != null)
|
||||
model.Page.Item.Published = publishDate.Value;
|
||||
|
||||
if (!ModelState.IsValid) {
|
||||
_services.TransactionManager.Cancel();
|
||||
Services.TransactionManager.Cancel();
|
||||
return View(model);
|
||||
}
|
||||
|
||||
_services.ContentManager.Create(model.Page.Item.ContentItem, publishNow ? VersionOptions.Published : VersionOptions.Draft);
|
||||
Services.ContentManager.Create(model.Page.Item.ContentItem, publishNow ? VersionOptions.Published : VersionOptions.Draft);
|
||||
|
||||
if (publishNow)
|
||||
_services.Notifier.Information(T("Page has been published"));
|
||||
Services.Notifier.Information(T("Page has been published"));
|
||||
else if (publishDate != null)
|
||||
_services.Notifier.Information(T("Page has been scheduled for publishing"));
|
||||
Services.Notifier.Information(T("Page has been scheduled for publishing"));
|
||||
else
|
||||
_services.Notifier.Information(T("Page draft has been saved"));
|
||||
Services.Notifier.Information(T("Page draft has been saved"));
|
||||
|
||||
return RedirectToAction("Edit", "Admin", new { id = model.Page.Item.ContentItem.Id });
|
||||
}
|
||||
|
||||
public ActionResult Edit(int id) {
|
||||
if (!_services.Authorizer.Authorize(Permissions.EditPages, T("Couldn't edit page")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
Page page = _pageService.GetLatest(id);
|
||||
|
||||
if (page == null)
|
||||
return new NotFoundResult();
|
||||
|
||||
if (!Services.Authorizer.Authorize(Permissions.EditOthersPages, page, T("Couldn't edit page")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var model = new PageEditViewModel {
|
||||
Page = _services.ContentManager.BuildEditorModel(page)
|
||||
Page = Services.ContentManager.BuildEditorModel(page)
|
||||
};
|
||||
|
||||
return View(model);
|
||||
@@ -168,14 +167,14 @@ namespace Orchard.Pages.Controllers {
|
||||
|
||||
[HttpPost, ActionName("Edit")]
|
||||
public ActionResult EditPOST(int id) {
|
||||
if (!_services.Authorizer.Authorize(Permissions.EditPages, T("Couldn't edit page")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
Page page = _pageService.GetPageOrDraft(id);
|
||||
|
||||
if (page == null)
|
||||
return new NotFoundResult();
|
||||
|
||||
if (!Services.Authorizer.Authorize(Permissions.EditOthersPages, page, T("Couldn't edit page")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
|
||||
//TODO: (erikpo) Move this duplicate code somewhere else
|
||||
DateTime? publishDate = null;
|
||||
bool publishNow = false;
|
||||
@@ -198,40 +197,39 @@ namespace Orchard.Pages.Controllers {
|
||||
_pageService.Unpublish(page);
|
||||
|
||||
var model = new PageEditViewModel {
|
||||
Page = _services.ContentManager.UpdateEditorModel(page, this)
|
||||
Page = Services.ContentManager.UpdateEditorModel(page, this)
|
||||
};
|
||||
|
||||
TryUpdateModel(model);
|
||||
|
||||
if (!ModelState.IsValid) {
|
||||
_services.TransactionManager.Cancel();
|
||||
Services.TransactionManager.Cancel();
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
if (publishNow)
|
||||
_services.Notifier.Information(T("Page has been published"));
|
||||
Services.Notifier.Information(T("Page has been published"));
|
||||
else if (publishDate != null)
|
||||
_services.Notifier.Information(T("Page has been scheduled for publishing"));
|
||||
Services.Notifier.Information(T("Page has been scheduled for publishing"));
|
||||
else
|
||||
_services.Notifier.Information(T("Page draft has been saved"));
|
||||
Services.Notifier.Information(T("Page draft has been saved"));
|
||||
|
||||
return RedirectToAction("Edit", "Admin", new { id = model.Page.Item.ContentItem.Id });
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Delete(int id) {
|
||||
if (!_services.Authorizer.Authorize(Permissions.DeletePages, T("Couldn't delete page")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
Page page = _pageService.Get(id);
|
||||
|
||||
if (page == null)
|
||||
return new NotFoundResult();
|
||||
|
||||
if (!Services.Authorizer.Authorize(Permissions.DeleteOthersPages, page, T("Couldn't delete page")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
_pageService.Delete(page);
|
||||
|
||||
_services.Notifier.Information(T("Page was successfully deleted"));
|
||||
Services.Notifier.Information(T("Page was successfully deleted"));
|
||||
|
||||
return RedirectToAction("List");
|
||||
}
|
||||
|
@@ -82,6 +82,7 @@
|
||||
<Compile Include="Permissions.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Routes.cs" />
|
||||
<Compile Include="Security\Authorization.cs" />
|
||||
<Compile Include="Services\IPageService.cs" />
|
||||
<Compile Include="Services\PageService.cs" />
|
||||
<Compile Include="Services\SlugConstraint.cs">
|
||||
|
@@ -0,0 +1,96 @@
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Aspects;
|
||||
using Orchard.Pages.Models;
|
||||
using Orchard.Security;
|
||||
using Orchard.Security.Permissions;
|
||||
|
||||
namespace Orchard.Pages.Security {
|
||||
[UsedImplicitly]
|
||||
public class Authorization : AuthorizationServiceEvents {
|
||||
public override void Adjust(CheckAccessContext context) {
|
||||
if (context.Granted == false &&
|
||||
context.Content.Is<Page>() &&
|
||||
HasOwnerVariation(context.Permission) &&
|
||||
HasOwnership(context.User, context.Content)) {
|
||||
|
||||
context.Adjusted = true;
|
||||
context.Permission = GetOwnerVariation(context.Permission);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool HasOwnership(IUser user, IContent content) {
|
||||
if (user==null || content==null)
|
||||
return false;
|
||||
|
||||
var common = content.As<ICommonAspect>();
|
||||
if (common==null || common.Owner==null)
|
||||
return false;
|
||||
|
||||
return user.Id == common.Owner.Id;
|
||||
}
|
||||
|
||||
private static bool HasOwnerVariation(Permission permission) {
|
||||
return GetOwnerVariation(permission) != null;
|
||||
}
|
||||
|
||||
private static Permission GetOwnerVariation(Permission permission) {
|
||||
if (permission.Name == Permissions.PublishOthersPages.Name)
|
||||
return Permissions.PublishPages;
|
||||
if (permission.Name == Permissions.EditOthersPages.Name)
|
||||
return Permissions.EditPages;
|
||||
if (permission.Name == Permissions.DeleteOthersPages.Name)
|
||||
return Permissions.DeletePages;
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Aspects;
|
||||
using Orchard.Pages.Models;
|
||||
using Orchard.Security;
|
||||
using Orchard.Security.Permissions;
|
||||
|
||||
namespace Orchard.Pages.Security {
|
||||
[UsedImplicitly]
|
||||
public class Authorization : AuthorizationServiceEvents {
|
||||
public override void Adjust(CheckAccessContext context) {
|
||||
if (context.Granted == false &&
|
||||
context.Content.Is<Page>() &&
|
||||
HasOwnerVariation(context.Permission) &&
|
||||
HasOwnership(context.User, context.Content)) {
|
||||
|
||||
context.Adjusted = true;
|
||||
context.Permission = GetOwnerVariation(context.Permission);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool HasOwnership(IUser user, IContent content) {
|
||||
if (user==null || content==null)
|
||||
return false;
|
||||
|
||||
var common = content.As<ICommonAspect>();
|
||||
if (common==null || common.Owner==null)
|
||||
return false;
|
||||
|
||||
return user.Id == common.Owner.Id;
|
||||
}
|
||||
|
||||
private static bool HasOwnerVariation(Permission permission) {
|
||||
return GetOwnerVariation(permission) != null;
|
||||
}
|
||||
|
||||
private static Permission GetOwnerVariation(Permission permission) {
|
||||
if (permission.Name == Permissions.PublishOthersPages.Name)
|
||||
return Permissions.PublishPages;
|
||||
if (permission.Name == Permissions.EditOthersPages.Name)
|
||||
return Permissions.EditPages;
|
||||
if (permission.Name == Permissions.DeleteOthersPages.Name)
|
||||
return Permissions.DeletePages;
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -111,7 +111,7 @@ namespace Orchard.Roles.Controllers {
|
||||
var simulation = UserSimulation.Create(role.Name);
|
||||
model.EffectivePermissions = model.PackagePermissions
|
||||
.SelectMany(group => group.Value)
|
||||
.Where(permission => _authorizationService.TryCheckAccess(simulation, permission))
|
||||
.Where(permission => _authorizationService.TryCheckAccess(permission, simulation, null))
|
||||
.Select(permission=>permission.Name)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
@@ -40,7 +40,7 @@ namespace Orchard.Roles.Controllers {
|
||||
|
||||
protected override DriverResult Editor(UserRoles userRoles) {
|
||||
// don't show editor without apply roles permission
|
||||
if (!_authorizationService.TryCheckAccess(_authenticationService.GetAuthenticatedUser(), Permissions.ApplyRoles))
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ApplyRoles, _authenticationService.GetAuthenticatedUser(), userRoles))
|
||||
return null;
|
||||
|
||||
var roles =
|
||||
@@ -61,7 +61,7 @@ namespace Orchard.Roles.Controllers {
|
||||
|
||||
protected override DriverResult Editor(UserRoles userRoles, IUpdateModel updater) {
|
||||
// don't apply editor without apply roles permission
|
||||
if (!_authorizationService.TryCheckAccess(_authenticationService.GetAuthenticatedUser(), Permissions.ApplyRoles))
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ApplyRoles, _authenticationService.GetAuthenticatedUser(), userRoles))
|
||||
return null;
|
||||
|
||||
var model = new UserRolesViewModel {
|
||||
|
@@ -13,9 +13,11 @@ using Orchard.Settings;
|
||||
namespace Orchard.Roles.Services {
|
||||
public class RolesBasedAuthorizationService : IAuthorizationService {
|
||||
private readonly IRoleService _roleService;
|
||||
private readonly IEnumerable<IAuthorizationServiceEvents> _events;
|
||||
|
||||
public RolesBasedAuthorizationService(IRoleService roleService) {
|
||||
public RolesBasedAuthorizationService(IRoleService roleService, IEnumerable<IAuthorizationServiceEvents> events) {
|
||||
_roleService = roleService;
|
||||
_events = events;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
@@ -24,37 +26,54 @@ namespace Orchard.Roles.Services {
|
||||
|
||||
#region Implementation of IAuthorizationService
|
||||
|
||||
public void CheckAccess(IUser user, Permission permission) {
|
||||
if (!TryCheckAccess(user, permission)) {
|
||||
public void CheckAccess(Permission permission, IUser user, IContent content) {
|
||||
if (!TryCheckAccess(permission, user, content)) {
|
||||
throw new OrchardSecurityException { PermissionName = permission.Name };
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryCheckAccess(IUser user, Permission permission) {
|
||||
if (user == null) {
|
||||
return false;
|
||||
}
|
||||
public bool TryCheckAccess(Permission permission, IUser user, IContent content) {
|
||||
var context = new CheckAccessContext { Permission = permission, User = user, Content = content };
|
||||
|
||||
if (String.Equals(user.UserName, "Administrator", StringComparison.OrdinalIgnoreCase) ||
|
||||
((!String.IsNullOrEmpty(CurrentSite.SuperUser) &&
|
||||
String.Equals(user.UserName, CurrentSite.SuperUser, StringComparison.OrdinalIgnoreCase)))) {
|
||||
return true;
|
||||
}
|
||||
_events.Invoke(x => x.Checking(context), Logger);
|
||||
|
||||
var grantingNames = PermissionNames(permission, Enumerable.Empty<string>()).ToArray();
|
||||
|
||||
IEnumerable<string> rolesForUser = user.As<IUserRoles>().Roles;
|
||||
foreach (var role in rolesForUser) {
|
||||
RoleRecord roleRecord = _roleService.GetRoleByName(role);
|
||||
foreach (var permissionName in _roleService.GetPermissionsForRole(roleRecord.Id)) {
|
||||
string possessedName = permissionName;
|
||||
if (grantingNames.Any(grantingName => String.Equals(possessedName, grantingName, StringComparison.OrdinalIgnoreCase))) {
|
||||
return true;
|
||||
for (var adjustmentLimiter = 0; adjustmentLimiter != 3; ++adjustmentLimiter) {
|
||||
if (!context.Granted && context.User != null) {
|
||||
if (String.Equals(context.User.UserName, "Administrator", StringComparison.OrdinalIgnoreCase) ||
|
||||
((!String.IsNullOrEmpty(CurrentSite.SuperUser) &&
|
||||
String.Equals(context.User.UserName, CurrentSite.SuperUser, StringComparison.OrdinalIgnoreCase)))) {
|
||||
context.Granted = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!context.Granted && context.User != null && context.User.Has<IUserRoles>()) {
|
||||
var grantingNames = PermissionNames(context.Permission, Enumerable.Empty<string>()).ToArray();
|
||||
IEnumerable<string> rolesForUser = context.User.As<IUserRoles>().Roles;
|
||||
|
||||
foreach (var role in rolesForUser) {
|
||||
RoleRecord roleRecord = _roleService.GetRoleByName(role);
|
||||
foreach (var permissionName in _roleService.GetPermissionsForRole(roleRecord.Id)) {
|
||||
string possessedName = permissionName;
|
||||
if (grantingNames.Any(grantingName => String.Equals(possessedName, grantingName, StringComparison.OrdinalIgnoreCase))) {
|
||||
context.Granted = true;
|
||||
}
|
||||
|
||||
if (context.Granted)
|
||||
break;
|
||||
}
|
||||
|
||||
if (context.Granted)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
context.Adjusted = false;
|
||||
_events.Invoke(x => x.Adjust(context), Logger);
|
||||
}
|
||||
|
||||
return false;
|
||||
_events.Invoke(x => x.Complete(context), Logger);
|
||||
|
||||
return context.Granted;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> PermissionNames(Permission permission, IEnumerable<string> stack) {
|
||||
|
@@ -28,7 +28,7 @@ namespace Orchard.Tags.Controllers {
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(HasTags part) {
|
||||
if (!_authorizationService.TryCheckAccess(CurrentUser, Permissions.ApplyTag))
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ApplyTag, CurrentUser, part))
|
||||
return null;
|
||||
|
||||
var model = new EditTagsViewModel {
|
||||
@@ -38,7 +38,7 @@ namespace Orchard.Tags.Controllers {
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(HasTags part, IUpdateModel updater) {
|
||||
if (!_authorizationService.TryCheckAccess(CurrentUser, Permissions.ApplyTag))
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ApplyTag, CurrentUser, part))
|
||||
return null;
|
||||
|
||||
var model = new EditTagsViewModel();
|
||||
|
@@ -66,7 +66,7 @@ namespace Orchard.Tags.Services {
|
||||
|
||||
public void CreateTag(string tagName) {
|
||||
if (_tagRepository.Get(x => x.TagName == tagName) == null) {
|
||||
_authorizationService.CheckAccess(CurrentUser, Permissions.CreateTag);
|
||||
_authorizationService.CheckAccess(Permissions.CreateTag, CurrentUser, null);
|
||||
|
||||
Tag tag = new Tag { TagName = tagName };
|
||||
_tagRepository.Create(tag);
|
||||
@@ -129,7 +129,7 @@ namespace Orchard.Tags.Services {
|
||||
|
||||
foreach (var tagContentItem in currentTagsForContentItem) {
|
||||
if (!newTagsForContentItem.Contains(tagContentItem.TagId)) {
|
||||
_authorizationService.CheckAccess(CurrentUser, Permissions.ApplyTag);
|
||||
_authorizationService.CheckAccess(Permissions.ApplyTag, CurrentUser, null);
|
||||
|
||||
_tagsContentItemsRepository.Delete(tagContentItem);
|
||||
}
|
||||
@@ -139,7 +139,7 @@ namespace Orchard.Tags.Services {
|
||||
}
|
||||
|
||||
foreach (var newTagForContentItem in newTagsForContentItem) {
|
||||
_authorizationService.CheckAccess(CurrentUser, Permissions.ApplyTag);
|
||||
_authorizationService.CheckAccess(Permissions.ApplyTag, CurrentUser, null);
|
||||
|
||||
_tagsContentItemsRepository.Create(new TagsContentItems { ContentItemId = contentItemId, TagId = newTagForContentItem });
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ namespace Orchard.Users.Controllers {
|
||||
|
||||
|
||||
public ActionResult Index() {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage settings")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to list users")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var users = Services.ContentManager
|
||||
@@ -44,7 +44,7 @@ namespace Orchard.Users.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult Create() {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage settings")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage users")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var user = Services.ContentManager.New<IUser>(UserDriver.ContentType.Name);
|
||||
@@ -56,7 +56,7 @@ namespace Orchard.Users.Controllers {
|
||||
|
||||
[HttpPost, ActionName("Create")]
|
||||
public ActionResult CreatePOST() {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage settings")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage users")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var model = new UserCreateViewModel();
|
||||
@@ -83,7 +83,7 @@ namespace Orchard.Users.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult Edit(int id) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage settings")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage users")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
return View(new UserEditViewModel {
|
||||
@@ -93,7 +93,7 @@ namespace Orchard.Users.Controllers {
|
||||
|
||||
[HttpPost, ActionName("Edit")]
|
||||
public ActionResult EditPOST(int id) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage settings")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage users")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var model = new UserEditViewModel {
|
||||
|
@@ -137,6 +137,7 @@
|
||||
<Compile Include="Extensions\Loaders\AreaExtensionLoader.cs" />
|
||||
<Compile Include="Extensions\UriExtensions.cs" />
|
||||
<Compile Include="OrchardException.cs" />
|
||||
<Compile Include="Security\IAuthorizationServiceEvents.cs" />
|
||||
<Compile Include="Security\StandardPermissions.cs" />
|
||||
<Compile Include="Security\OrchardSecurityException.cs" />
|
||||
<Compile Include="Tasks\Scheduling\IScheduledTask.cs" />
|
||||
|
@@ -1,4 +1,7 @@
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Aspects;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Security.Permissions;
|
||||
using Orchard.UI.Notify;
|
||||
@@ -6,6 +9,7 @@ using Orchard.UI.Notify;
|
||||
namespace Orchard.Security {
|
||||
public interface IAuthorizer : IDependency {
|
||||
bool Authorize(Permission permission, LocalizedString message);
|
||||
bool Authorize(Permission permission, IContent content, LocalizedString message);
|
||||
}
|
||||
|
||||
public class Authorizer : IAuthorizer {
|
||||
@@ -24,7 +28,11 @@ namespace Orchard.Security {
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public bool Authorize(Permission permission, LocalizedString message) {
|
||||
if (_authorizationService.TryCheckAccess(CurrentUser, permission))
|
||||
return Authorize(permission, null, message);
|
||||
}
|
||||
|
||||
public bool Authorize(Permission permission, IContent content, LocalizedString message) {
|
||||
if (_authorizationService.TryCheckAccess(permission, CurrentUser, content))
|
||||
return true;
|
||||
|
||||
if (CurrentUser == null) {
|
||||
@@ -37,5 +45,6 @@ namespace Orchard.Security {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Orchard.Security.Permissions;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Security.Permissions;
|
||||
|
||||
namespace Orchard.Security {
|
||||
/// <summary>
|
||||
@@ -6,7 +7,9 @@ namespace Orchard.Security {
|
||||
/// provided by default.
|
||||
/// </summary>
|
||||
public interface IAuthorizationService : IDependency {
|
||||
void CheckAccess(IUser user, Permission permission);
|
||||
bool TryCheckAccess(IUser user, Permission permission);
|
||||
void CheckAccess(Permission permission, IUser user, IContent content);
|
||||
bool TryCheckAccess(Permission permission, IUser user, IContent content);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
50
src/Orchard/Security/IAuthorizationServiceEvents.cs
Normal file
50
src/Orchard/Security/IAuthorizationServiceEvents.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Security.Permissions;
|
||||
|
||||
namespace Orchard.Security {
|
||||
public interface IAuthorizationServiceEvents : IEvents {
|
||||
void Checking(CheckAccessContext context);
|
||||
void Adjust(CheckAccessContext context);
|
||||
void Complete(CheckAccessContext context);
|
||||
}
|
||||
|
||||
public class CheckAccessContext {
|
||||
public Permission Permission { get; set; }
|
||||
public IUser User { get; set; }
|
||||
public IContent Content { get; set; }
|
||||
public bool Granted { get; set; }
|
||||
public bool Adjusted { get; set; }
|
||||
}
|
||||
|
||||
public abstract class AuthorizationServiceEvents : IAuthorizationServiceEvents {
|
||||
public virtual void Checking(CheckAccessContext context) { }
|
||||
public virtual void Adjust(CheckAccessContext context) { }
|
||||
public virtual void Complete(CheckAccessContext context) { }
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Security.Permissions;
|
||||
|
||||
namespace Orchard.Security {
|
||||
public interface IAuthorizationServiceEvents : IEvents {
|
||||
void Checking(CheckAccessContext context);
|
||||
void Adjust(CheckAccessContext context);
|
||||
void Complete(CheckAccessContext context);
|
||||
}
|
||||
|
||||
public class CheckAccessContext {
|
||||
public Permission Permission { get; set; }
|
||||
public IUser User { get; set; }
|
||||
public IContent Content { get; set; }
|
||||
public bool Granted { get; set; }
|
||||
public bool Adjusted { get; set; }
|
||||
}
|
||||
|
||||
public abstract class AuthorizationServiceEvents : IAuthorizationServiceEvents {
|
||||
public virtual void Checking(CheckAccessContext context) { }
|
||||
public virtual void Adjust(CheckAccessContext context) { }
|
||||
public virtual void Complete(CheckAccessContext context) { }
|
||||
}
|
||||
}
|
@@ -5,7 +5,9 @@ namespace Orchard.Security.Permissions {
|
||||
public class Permission {
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
|
||||
public IEnumerable<Permission> ImpliedBy { get; set; }
|
||||
public bool RequiresOwnership { get; set; }
|
||||
|
||||
public static Permission Named(string name) {
|
||||
return new Permission { Name = name };
|
||||
|
@@ -34,11 +34,11 @@ namespace Orchard.UI.Navigation {
|
||||
}
|
||||
|
||||
private IEnumerable<MenuItem> Reduce(IEnumerable<MenuItem> items) {
|
||||
var hasDebugShowAllMenuItems = _authorizationService.TryCheckAccess(CurrentUser, Permission.Named("DebugShowAllMenuItems"));
|
||||
var hasDebugShowAllMenuItems = _authorizationService.TryCheckAccess(Permission.Named("DebugShowAllMenuItems"), CurrentUser, null);
|
||||
foreach (var item in items) {
|
||||
if (hasDebugShowAllMenuItems ||
|
||||
!item.Permissions.Any() ||
|
||||
item.Permissions.Any(x => _authorizationService.TryCheckAccess(CurrentUser, x))) {
|
||||
item.Permissions.Any(x => _authorizationService.TryCheckAccess(x, CurrentUser, null))) {
|
||||
yield return new MenuItem {
|
||||
Items = Reduce(item.Items),
|
||||
Permissions = item.Permissions,
|
||||
|
Reference in New Issue
Block a user