Refactoring menu permissions

This commit is contained in:
Sebastien Ros
2014-08-20 17:12:50 -07:00
parent 126efc2028
commit 4157896464
11 changed files with 128 additions and 24 deletions
+21 -3
View File
@@ -1,18 +1,36 @@
using Orchard.Localization; using Orchard.ContentManagement;
using Orchard.Localization;
using Orchard.UI.Navigation; using Orchard.UI.Navigation;
using System.Linq;
namespace Orchard.Core.Navigation { namespace Orchard.Core.Navigation {
public class AdminMenu : INavigationProvider { public class AdminMenu : INavigationProvider {
public Localizer T { get; set; } public Localizer T { get; set; }
public string MenuName { get { return "admin"; } } public string MenuName { get { return "admin"; } }
public IOrchardServices Services { get; set; }
public AdminMenu(IOrchardServices services) {
Services = services;
}
public void GetNavigation(NavigationBuilder builder) { public void GetNavigation(NavigationBuilder builder) {
//todo: - add new menu? and list menus? ...and remove hard-coded menu name here var user = Services.WorkContext.CurrentUser;
// if the current user cannot manage menus, check if they can manage at least one
if (!Services.Authorizer.Authorize(Permissions.ManageMenus)) {
var menus = Services.ContentManager.Query("Menu").List();
if (!menus.Any(x => Services.Authorizer.Authorize(Permissions.ManageMenus, x))) {
return;
}
}
builder.AddImageSet("navigation") builder.AddImageSet("navigation")
.Add(T("Navigation"), "7", .Add(T("Navigation"), "7",
menu => menu menu => menu
.Add(T("Main Menu"), "0", item => item.Action("Index", "Admin", new { area = "Navigation" }) .Add(T("Main Menu"), "0", item => item.Action("Index", "Admin", new { area = "Navigation" })
.Permission(Permissions.ManageMainMenu))); ));
} }
} }
} }
@@ -44,17 +44,18 @@ namespace Orchard.Core.Navigation.Controllers {
public IOrchardServices Services { get; set; } public IOrchardServices Services { get; set; }
public ActionResult Index(NavigationManagementViewModel model, int? menuId) { public ActionResult Index(NavigationManagementViewModel model, int? menuId) {
var menus = Services.ContentManager.Query<TitlePart, TitlePartRecord>().OrderBy(x => x.Title).ForType("Menu").List().ToList(); var menus = Services.ContentManager.Query("Menu").List().ToList()
.OrderBy(x => x.ContentManager.GetItemMetadata(x).DisplayText);
if (!menus.Any()) { if (!menus.Any()) {
if (!Services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Not allowed to manage menus"))) { if (!Services.Authorizer.Authorize(Permissions.ManageMenus, T("Not allowed to manage menus"))) {
return new HttpUnauthorizedResult(); return new HttpUnauthorizedResult();
} }
return RedirectToAction("Create", "Admin", new { area = "Contents", id = "Menu", returnUrl = Request.RawUrl }); return RedirectToAction("Create", "Admin", new { area = "Contents", id = "Menu", returnUrl = Request.RawUrl });
} }
var allowedMenus = menus.Where(menu => Services.Authorizer.Authorize(Permissions.ManageMainMenu, menu)).ToList(); var allowedMenus = menus.Where(menu => Services.Authorizer.Authorize(Permissions.ManageMenus, menu)).ToList();
if (!allowedMenus.Any()) { if (!allowedMenus.Any()) {
return new HttpUnauthorizedResult(); return new HttpUnauthorizedResult();
@@ -86,7 +87,7 @@ namespace Orchard.Core.Navigation.Controllers {
[HttpPost, ActionName("Index")] [HttpPost, ActionName("Index")]
public ActionResult IndexPOST(IList<MenuItemEntry> menuItemEntries, int? menuId) { public ActionResult IndexPOST(IList<MenuItemEntry> menuItemEntries, int? menuId) {
if (!Services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Couldn't manage the main menu"))) if (!Services.Authorizer.Authorize(Permissions.ManageMenus, T("Couldn't manage the main menu")))
return new HttpUnauthorizedResult(); return new HttpUnauthorizedResult();
// See http://orchard.codeplex.com/workitem/17116 // See http://orchard.codeplex.com/workitem/17116
@@ -115,7 +116,7 @@ namespace Orchard.Core.Navigation.Controllers {
[HttpPost] [HttpPost]
public ActionResult Delete(int id) { public ActionResult Delete(int id) {
if (!Services.Authorizer.Authorize(Permissions.ManageMainMenu, T("Couldn't manage the main menu"))) if (!Services.Authorizer.Authorize(Permissions.ManageMenus, T("Couldn't manage the main menu")))
return new HttpUnauthorizedResult(); return new HttpUnauthorizedResult();
MenuPart menuPart = _menuService.Get(id); MenuPart menuPart = _menuService.Get(id);
@@ -154,7 +155,7 @@ namespace Orchard.Core.Navigation.Controllers {
} }
public ActionResult CreateMenuItem(string id, int menuId, string returnUrl) { public ActionResult CreateMenuItem(string id, int menuId, string returnUrl) {
if (!Services.Authorizer.Authorize(Permissions.ManageMainMenu, _menuService.GetMenu(menuId), T("Couldn't manage the main menu"))) if (!Services.Authorizer.Authorize(Permissions.ManageMenus, _menuService.GetMenu(menuId), T("Couldn't manage the main menu")))
return new HttpUnauthorizedResult(); return new HttpUnauthorizedResult();
// create a new temporary menu item // create a new temporary menu item
@@ -186,7 +187,7 @@ namespace Orchard.Core.Navigation.Controllers {
[HttpPost, ActionName("CreateMenuItem")] [HttpPost, ActionName("CreateMenuItem")]
public ActionResult CreateMenuItemPost(string id, int menuId, string returnUrl) { public ActionResult CreateMenuItemPost(string id, int menuId, string returnUrl) {
if (!Services.Authorizer.Authorize(Permissions.ManageMainMenu, _menuService.GetMenu(menuId), T("Couldn't manage the main menu"))) if (!Services.Authorizer.Authorize(Permissions.ManageMenus, _menuService.GetMenu(menuId), T("Couldn't manage the main menu")))
return new HttpUnauthorizedResult(); return new HttpUnauthorizedResult();
var menuPart = Services.ContentManager.New<MenuPart>(id); var menuPart = Services.ContentManager.New<MenuPart>(id);
@@ -38,7 +38,7 @@ namespace Orchard.Core.Navigation.Drivers {
protected override DriverResult Editor(AdminMenuPart part, dynamic shapeHelper) { protected override DriverResult Editor(AdminMenuPart part, dynamic shapeHelper) {
// todo: we need a 'ManageAdminMenu' too? // todo: we need a 'ManageAdminMenu' too?
if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, _orchardServices.WorkContext.CurrentUser, part)) { if (!_authorizationService.TryCheckAccess(Permissions.ManageMenus, _orchardServices.WorkContext.CurrentUser, part)) {
return null; return null;
} }
@@ -51,7 +51,7 @@ namespace Orchard.Core.Navigation.Drivers {
} }
protected override DriverResult Editor(AdminMenuPart part, IUpdateModel updater, dynamic shapeHelper) { protected override DriverResult Editor(AdminMenuPart part, IUpdateModel updater, dynamic shapeHelper) {
if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, _orchardServices.WorkContext.CurrentUser, part)) if (!_authorizationService.TryCheckAccess(Permissions.ManageMenus, _orchardServices.WorkContext.CurrentUser, part))
return null; return null;
updater.TryUpdateModel(part, Prefix, null, null); updater.TryUpdateModel(part, Prefix, null, null);
@@ -17,7 +17,7 @@ namespace Orchard.Core.Navigation.Drivers {
protected override DriverResult Editor(MenuItemPart part, dynamic shapeHelper) { protected override DriverResult Editor(MenuItemPart part, dynamic shapeHelper) {
var currentUser = _workContextAccessor.GetContext().CurrentUser; var currentUser = _workContextAccessor.GetContext().CurrentUser;
if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, currentUser, part)) if (!_authorizationService.TryCheckAccess(Permissions.ManageMenus, currentUser, part))
return null; return null;
return ContentShape("Parts_MenuItem_Edit", return ContentShape("Parts_MenuItem_Edit",
@@ -26,7 +26,7 @@ namespace Orchard.Core.Navigation.Drivers {
protected override DriverResult Editor(MenuItemPart part, IUpdateModel updater, dynamic shapeHelper) { protected override DriverResult Editor(MenuItemPart part, IUpdateModel updater, dynamic shapeHelper) {
var currentUser = _workContextAccessor.GetContext().CurrentUser; var currentUser = _workContextAccessor.GetContext().CurrentUser;
if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, currentUser, part)) if (!_authorizationService.TryCheckAccess(Permissions.ManageMenus, currentUser, part))
return null; return null;
if (updater != null) { if (updater != null) {
@@ -39,7 +39,7 @@ namespace Orchard.Core.Navigation.Drivers {
} }
protected override DriverResult Editor(MenuPart part, dynamic shapeHelper) { protected override DriverResult Editor(MenuPart part, dynamic shapeHelper) {
var allowedMenus = _menuService.GetMenus().Where(menu => _authorizationService.TryCheckAccess(Permissions.ManageMainMenu, _orchardServices.WorkContext.CurrentUser, menu)).ToList(); var allowedMenus = _menuService.GetMenus().Where(menu => _authorizationService.TryCheckAccess(Permissions.ManageMenus, _orchardServices.WorkContext.CurrentUser, menu)).ToList();
if (!allowedMenus.Any()) if (!allowedMenus.Any())
return null; return null;
@@ -63,7 +63,7 @@ namespace Orchard.Core.Navigation.Drivers {
if(updater.TryUpdateModel(model, Prefix, null, null)) { if(updater.TryUpdateModel(model, Prefix, null, null)) {
var menu = model.OnMenu ? _orchardServices.ContentManager.Get(model.CurrentMenuId) : null; var menu = model.OnMenu ? _orchardServices.ContentManager.Get(model.CurrentMenuId) : null;
if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, _orchardServices.WorkContext.CurrentUser, menu)) if (!_authorizationService.TryCheckAccess(Permissions.ManageMenus, _orchardServices.WorkContext.CurrentUser, menu))
return null; return null;
part.MenuText = model.MenuText; part.MenuText = model.MenuText;
@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.Core.Navigation.Services;
using Orchard.Core.Title.Models;
using Orchard.Environment.Extensions.Models;
using Orchard.Security.Permissions;
namespace Orchard.Core.Navigation {
public class DynamicPermissions : IPermissionProvider {
private static readonly Permission ManageMenu = new Permission { Description = "Manage '{0}' menu", Name = "Manage_{0}", ImpliedBy = new[] { Permissions.ManageMenus } };
private readonly IMenuService _menuService;
private readonly IContentManager _contentManager;
public virtual Feature Feature { get; set; }
public DynamicPermissions(
IMenuService menuService,
IContentManager contentManager) {
_menuService = menuService;
_contentManager = contentManager;
}
public IEnumerable<Permission> GetPermissions() {
return _menuService.GetMenus().Select(menu => CreateMenuPermission(menu, _contentManager));
}
public IEnumerable<PermissionStereotype> GetDefaultStereotypes() {
return Enumerable.Empty<PermissionStereotype>();
}
public static Permission CreateMenuPermission(ContentItem menu, IContentManager contentManager) {
var metadata = contentManager.GetItemMetadata(menu);
return new Permission {
Name = String.Format(ManageMenu.Name, metadata.Identity),
Description = String.Format(ManageMenu.Description, metadata.DisplayText),
Category = "Navigation Feature",
ImpliedBy = new[] { Permissions.ManageMenus }
};
}
}
}
@@ -4,13 +4,13 @@ using Orchard.Security.Permissions;
namespace Orchard.Core.Navigation { namespace Orchard.Core.Navigation {
public class Permissions : IPermissionProvider { public class Permissions : IPermissionProvider {
public static readonly Permission ManageMainMenu = new Permission { Name = "ManageMainMenu", Description = "Manage main menu" }; public static readonly Permission ManageMenus = new Permission { Name = "ManageMenus", Description = "Manage all menus" };
public virtual Feature Feature { get; set; } public virtual Feature Feature { get; set; }
public IEnumerable<Permission> GetPermissions() { public IEnumerable<Permission> GetPermissions() {
return new[] { return new[] {
ManageMainMenu ManageMenus
}; };
} }
@@ -18,7 +18,7 @@ namespace Orchard.Core.Navigation {
return new[] { return new[] {
new PermissionStereotype { new PermissionStereotype {
Name = "Administrator", Name = "Administrator",
Permissions = new[] {ManageMainMenu} Permissions = new[] {ManageMenus}
} }
}; };
} }
@@ -0,0 +1,30 @@
using JetBrains.Annotations;
using Orchard.ContentManagement;
using Orchard.Security;
namespace Orchard.Core.Navigation.Security {
[UsedImplicitly]
public class AuthorizationEventHandler : IAuthorizationServiceEventHandler {
private readonly IContentManager _contentManager;
public AuthorizationEventHandler(IContentManager contentManager) {
_contentManager = contentManager;
}
public void Checking(CheckAccessContext context) { }
public void Complete(CheckAccessContext context) { }
public void Adjust(CheckAccessContext context) {
if (!context.Granted && context.Permission.Name == Permissions.ManageMenus.Name && context.Content != null) {
var menuAsContentItem = context.Content.As<ContentItem>();
if (menuAsContentItem == null || menuAsContentItem.Id <= 0) {
return;
}
context.Adjusted = true;
context.Permission = DynamicPermissions.CreateMenuPermission(menuAsContentItem, _contentManager);
}
}
}
}
@@ -9,6 +9,8 @@
Script.Require("jQueryUI_Sortable").AtFoot(); Script.Require("jQueryUI_Sortable").AtFoot();
Script.Include("jquery.mjs.nestedSortable.js").AtFoot(); Script.Include("jquery.mjs.nestedSortable.js").AtFoot();
Script.Include("navigation-admin.js").AtFoot(); Script.Include("navigation-admin.js").AtFoot();
var hasPermission = Authorizer.Authorize(Orchard.Core.Navigation.Permissions.ManageMenus);
} }
<div id="save-message" class="message message-Warning">@T("You need to hit \"Save All\" in order to save your changes.")</div> <div id="save-message" class="message message-Warning">@T("You need to hit \"Save All\" in order to save your changes.")</div>
@@ -23,14 +25,17 @@
@Html.SelectOption(Model.CurrentMenu.Id, menu.Id, Convert.ToString(Html.ItemDisplayText(menu))) @Html.SelectOption(Model.CurrentMenu.Id, menu.Id, Convert.ToString(Html.ItemDisplayText(menu)))
} }
</select> </select>
<button type="submit" class="apply-bulk-actions-auto">@T("Show")</button> @if (hasPermission) {
@Html.ActionLink(T("Edit").Text, "Edit", "Admin", new { area = "Contents", id = Model.CurrentMenu.Id, returnUrl = Url.Action("Index", "Admin", new { area = "Navigation", menuId = Model.CurrentMenu.Id }) }, new { @class = "button" }) @Html.ActionLink(T("Edit").Text, "Edit", "Admin", new { area = "Contents", id = Model.CurrentMenu.Id, returnUrl = Url.Action("Index", "Admin", new { area = "Navigation", menuId = Model.CurrentMenu.Id }) }, new { @class = "button" })
}
</fieldset> </fieldset>
} }
} }
@if (hasPermission) {
<div id="navigation-menu-add"> <div id="navigation-menu-add">
@Html.Link(T("Add a new menu...").Text, Url.Action("Create", "Admin", new { area = "Contents", id = "Menu", returnUrl = Request.RawUrl })) @Html.Link(T("Add a new menu...").Text, Url.Action("Create", "Admin", new { area = "Contents", id = "Menu", returnUrl = Request.RawUrl }))
</div> </div>
}
</div> </div>
@@ -131,6 +136,10 @@
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
var leaveConfirmation = '@T("Some items where not saved.")'; var leaveConfirmation = '@T("Some items where not saved.")';
$('#menuId').change(function () {
$(this).parents('form').submit();
});
//]]> //]]>
</script> </script>
} }
@@ -43,7 +43,7 @@ namespace Orchard.ContentPicker.Drivers {
protected override DriverResult Editor(ContentMenuItemPart part, IUpdateModel updater, dynamic shapeHelper) { protected override DriverResult Editor(ContentMenuItemPart part, IUpdateModel updater, dynamic shapeHelper) {
var currentUser = _workContextAccessor.GetContext().CurrentUser; var currentUser = _workContextAccessor.GetContext().CurrentUser;
if (!_authorizationService.TryCheckAccess(Permissions.ManageMainMenu, currentUser, part)) if (!_authorizationService.TryCheckAccess(Permissions.ManageMenus, currentUser, part))
return null; return null;
var model = new ContentMenuItemEditViewModel(); var model = new ContentMenuItemEditViewModel();
@@ -46,7 +46,7 @@ namespace Orchard.ContentPicker.Drivers {
protected override DriverResult Editor(NavigationPart part, dynamic shapeHelper) { protected override DriverResult Editor(NavigationPart part, dynamic shapeHelper) {
var currentUser = _workContextAccessor.GetContext().CurrentUser; var currentUser = _workContextAccessor.GetContext().CurrentUser;
var allowedMenus = _menuService.GetMenus().Where(menu => _authorizationService.TryCheckAccess(Permissions.ManageMainMenu, currentUser, menu)).ToList(); var allowedMenus = _menuService.GetMenus().Where(menu => _authorizationService.TryCheckAccess(Permissions.ManageMenus, currentUser, menu)).ToList();
if (!allowedMenus.Any()) if (!allowedMenus.Any())
return null; return null;
@@ -70,7 +70,7 @@ namespace Orchard.ContentPicker.Drivers {
protected override DriverResult Editor(NavigationPart part, IUpdateModel updater, dynamic shapeHelper) { protected override DriverResult Editor(NavigationPart part, IUpdateModel updater, dynamic shapeHelper) {
var currentUser = _workContextAccessor.GetContext().CurrentUser; var currentUser = _workContextAccessor.GetContext().CurrentUser;
var allowedMenus = _menuService.GetMenus().Where(menu => _authorizationService.TryCheckAccess(Permissions.ManageMainMenu, currentUser, menu)).ToList(); var allowedMenus = _menuService.GetMenus().Where(menu => _authorizationService.TryCheckAccess(Permissions.ManageMenus, currentUser, menu)).ToList();
if (!allowedMenus.Any()) if (!allowedMenus.Any())
return null; return null;