Further work updating security model

--HG--
extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4045825
This commit is contained in:
loudej 2010-01-22 05:25:54 +00:00
parent 95d5398f50
commit 6d95217b6a
33 changed files with 290 additions and 83 deletions

View File

@ -13,7 +13,9 @@ using Orchard.Environment;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers; using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.Records; using Orchard.ContentManagement.Records;
using Orchard.Localization;
using Orchard.Security; using Orchard.Security;
using Orchard.Security.Permissions;
using Orchard.UI.Notify; using Orchard.UI.Notify;
using Orchard.Users.Controllers; using Orchard.Users.Controllers;
using Orchard.Users.Models; using Orchard.Users.Models;
@ -24,6 +26,7 @@ namespace Orchard.Tests.Packages.Users.Controllers {
[TestFixture] [TestFixture]
public class AdminControllerTests : DatabaseEnabledTestsBase { public class AdminControllerTests : DatabaseEnabledTestsBase {
private AdminController _controller; private AdminController _controller;
private Mock<IAuthorizer> _authorizer;
public override void Register(ContainerBuilder builder) { public override void Register(ContainerBuilder builder) {
builder.Register<AdminController>(); builder.Register<AdminController>();
@ -34,7 +37,8 @@ namespace Orchard.Tests.Packages.Users.Controllers {
builder.Register<OrchardServices>().As<IOrchardServices>(); builder.Register<OrchardServices>().As<IOrchardServices>();
builder.Register<TransactionManager>().As<ITransactionManager>(); builder.Register<TransactionManager>().As<ITransactionManager>();
builder.Register(new Mock<INotifier>().Object); builder.Register(new Mock<INotifier>().Object);
builder.Register(new Mock<IAuthorizer>().Object); _authorizer = new Mock<IAuthorizer>();
builder.Register(_authorizer.Object);
} }
protected override IEnumerable<Type> DatabaseTypes { protected override IEnumerable<Type> DatabaseTypes {
@ -73,6 +77,8 @@ namespace Orchard.Tests.Packages.Users.Controllers {
[Test] [Test]
public void IndexShouldReturnRowsForUsers() { public void IndexShouldReturnRowsForUsers() {
_authorizer.Setup(x => x.Authorize(It.IsAny<Permission>(), It.IsAny<LocalizedString>())).Returns(true);
var controller = _container.Resolve<AdminController>(); var controller = _container.Resolve<AdminController>();
var result = (ViewResult)controller.Index(); var result = (ViewResult)controller.Index();
var model = (UsersIndexViewModel)result.ViewData.Model; var model = (UsersIndexViewModel)result.ViewData.Model;
@ -83,13 +89,15 @@ namespace Orchard.Tests.Packages.Users.Controllers {
[Test] [Test]
public void CreateShouldAddUserAndRedirect() { public void CreateShouldAddUserAndRedirect() {
_authorizer.Setup(x => x.Authorize(It.IsAny<Permission>(), It.IsAny<LocalizedString>())).Returns(true);
var controller = _container.Resolve<AdminController>(); var controller = _container.Resolve<AdminController>();
controller.ValueProvider = Values.From(new { controller.ValueProvider = Values.From(new {
UserName = "four", UserName = "four",
Password = "five", Password = "five",
ConfirmPassword = "five" ConfirmPassword = "five"
}); });
var result = controller._Create(); var result = controller.CreatePOST();
Assert.That(result, Is.TypeOf<RedirectToRouteResult>()); Assert.That(result, Is.TypeOf<RedirectToRouteResult>());
var redirect = (RedirectToRouteResult)result; var redirect = (RedirectToRouteResult)result;
@ -101,6 +109,8 @@ namespace Orchard.Tests.Packages.Users.Controllers {
[Test] [Test]
public void EditShouldDisplayUserAndStoreChanges() { public void EditShouldDisplayUserAndStoreChanges() {
_authorizer.Setup(x => x.Authorize(It.IsAny<Permission>(), It.IsAny<LocalizedString>())).Returns(true);
var repository = _container.Resolve<IRepository<UserRecord>>(); var repository = _container.Resolve<IRepository<UserRecord>>();
var id = repository.Get(x => x.UserName == "two").Id; var id = repository.Get(x => x.UserName == "two").Id;
var result = (ViewResult)_container.Resolve<AdminController>().Edit(id); var result = (ViewResult)_container.Resolve<AdminController>().Edit(id);
@ -112,7 +122,7 @@ namespace Orchard.Tests.Packages.Users.Controllers {
UserName = "bubba", UserName = "bubba",
Email = "hotep", Email = "hotep",
}); });
var result2 = controller._Edit(id); var result2 = controller.EditPOST(id);
Assert.That(result2, Is.TypeOf<RedirectToRouteResult>()); Assert.That(result2, Is.TypeOf<RedirectToRouteResult>());
} }
} }

View File

@ -7,7 +7,7 @@ namespace Orchard.Core.Settings {
public void GetNavigation(NavigationBuilder builder) { public void GetNavigation(NavigationBuilder builder) {
builder.Add("Settings", "11", builder.Add("Settings", "11",
menu => menu menu => menu
.Add("Manage Settings", "2.0", item => item.Action("Index", "Admin", new { area = "Settings" }))); .Add("Manage Settings", "2.0", item => item.Action("Index", "Admin", new { area = "Settings" }).Permission(Permissions.ManageSettings)));
} }
} }
} }

View File

@ -3,6 +3,8 @@ using Orchard.Core.Settings.Models;
using Orchard.Core.Settings.ViewModels; using Orchard.Core.Settings.ViewModels;
using Orchard.Localization; using Orchard.Localization;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.Security;
using Orchard.Security.Permissions;
using Orchard.Settings; using Orchard.Settings;
using Orchard.UI.Notify; using Orchard.UI.Notify;
@ -10,40 +12,43 @@ namespace Orchard.Core.Settings.Controllers {
[ValidateInput(false)] [ValidateInput(false)]
public class AdminController : Controller, IUpdateModel { public class AdminController : Controller, IUpdateModel {
private readonly ISiteService _siteService; private readonly ISiteService _siteService;
private readonly IContentManager _modelManager; public IOrchardServices Services { get; private set; }
private readonly INotifier _notifier;
public AdminController(ISiteService siteService, IContentManager modelManager, INotifier notifier) { public AdminController(ISiteService siteService, IOrchardServices services) {
_siteService = siteService; _siteService = siteService;
_modelManager = modelManager; Services = services;
_notifier = notifier;
T = NullLocalizer.Instance; T = NullLocalizer.Instance;
} }
public Localizer T { get; set; } public Localizer T { get; set; }
public ActionResult Index(string tabName) { public ActionResult Index(string tabName) {
if (!Services.Authorizer.Authorize(Permissions.ManageSettings, T("Not authorized to manage settings")))
return new HttpUnauthorizedResult();
var model = new SettingsIndexViewModel { var model = new SettingsIndexViewModel {
Site = _siteService.GetSiteSettings().As<SiteSettings>() Site = _siteService.GetSiteSettings().As<SiteSettings>()
}; };
model.ViewModel = _modelManager.BuildEditorModel(model.Site); model.ViewModel = Services.ContentManager.BuildEditorModel(model.Site);
return View(model); return View(model);
} }
[HttpPost, ActionName("Index")] [HttpPost, ActionName("Index")]
public ActionResult IndexPOST(string tabName) { public ActionResult IndexPOST(string tabName) {
if (!Services.Authorizer.Authorize(Permissions.ManageSettings, T("Not authorized to manage settings")))
return new HttpUnauthorizedResult();
var viewModel = new SettingsIndexViewModel { Site = _siteService.GetSiteSettings().As<SiteSettings>() }; var viewModel = new SettingsIndexViewModel { Site = _siteService.GetSiteSettings().As<SiteSettings>() };
viewModel.ViewModel = _modelManager.UpdateEditorModel(viewModel.Site.ContentItem, this); viewModel.ViewModel = Services.ContentManager.UpdateEditorModel(viewModel.Site.ContentItem, this);
if (!TryUpdateModel(viewModel)) { if (!TryUpdateModel(viewModel)) {
return View(viewModel); return View(viewModel);
} }
_notifier.Information(T("Settings updated")); Services.Notifier.Information(T("Settings updated"));
return RedirectToAction("Index"); return RedirectToAction("Index");
} }
#region IUpdateModel Members
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) { bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
return TryUpdateModel(model, prefix, includeProperties, excludeProperties); return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
@ -52,7 +57,5 @@ namespace Orchard.Core.Settings.Controllers {
void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) { void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) {
ModelState.AddModelError(key, errorMessage.ToString()); ModelState.AddModelError(key, errorMessage.ToString());
} }
#endregion
} }
} }

View File

@ -7,7 +7,8 @@ namespace Orchard.Core.Themes {
public void GetNavigation(NavigationBuilder builder) { public void GetNavigation(NavigationBuilder builder) {
builder.Add("Themes", "11", builder.Add("Themes", "11",
menu => menu menu => menu
.Add("Manage Themes", "2.0", item => item.Action("Index", "Admin", new { area = "Themes" }))); .Add("Manage Themes", "2.0", item => item.Action("Index", "Admin", new { area = "Themes" })
.Permission(Permissions.ManageThemes).Permission(Permissions.ApplyTheme)));
} }
} }
} }

View File

@ -7,8 +7,8 @@ namespace Orchard.Blogs {
public void GetNavigation(NavigationBuilder builder) { public void GetNavigation(NavigationBuilder builder) {
builder.Add("Blogs", "2", builder.Add("Blogs", "2",
menu => menu menu => menu
.Add("Manage Blogs", "1.0", item => item.Action("List", "BlogAdmin", new { area = "Orchard.Blogs" })) .Add("Manage Blogs", "1.0", item => item.Action("List", "BlogAdmin", new { area = "Orchard.Blogs" }).Permission(Permissions.MetaListBlogs))
.Add("Add New Blog", "1.1", item => item.Action("Create", "BlogAdmin", new { area = "Orchard.Blogs" }))); .Add("Add New Blog", "1.1", item => item.Action("Create", "BlogAdmin", new { area = "Orchard.Blogs" }).Permission(Permissions.ManageBlogs)));
} }
} }
} }

View File

@ -4,15 +4,17 @@ using Orchard.Security.Permissions;
namespace Orchard.Blogs { namespace Orchard.Blogs {
public class Permissions : IPermissionProvider { public class Permissions : IPermissionProvider {
public static readonly Permission ManageBlogs = new Permission { Description = "Edit blog properties", Name = "ManageBlogs" };//q: Should edit_blog be ManageBlogs? public static readonly Permission ManageBlogs = new Permission { Description = "Manage blogs", Name = "ManageBlogs" };//q: Should edit_blog be ManageBlogs?
public static readonly Permission EditBlogPost = new Permission { Description = "Edit own blog posts", Name = "EditBlogPost" }; public static readonly Permission PublishOthersBlogPost = new Permission { Description = "Publish or unpublish blog post for others", Name = "PublishOthersBlogPost", ImpliedBy = new[] { ManageBlogs } };
public static readonly Permission EditOthersBlogPost = new Permission { Description = "Edit any blog posts", Name = "EditOthersBlogPost" }; public static readonly Permission PublishBlogPost = new Permission { Description = "Publish or unpublish blog post", Name = "PublishBlogPost", ImpliedBy = new[] { PublishOthersBlogPost } };
public static readonly Permission PublishBlogPost = new Permission { Description = "Publish or unpublish blog post", Name = "PublishBlogPost" }; public static readonly Permission EditOthersBlogPost = new Permission { Description = "Edit any blog posts", Name = "EditOthersBlogPost", ImpliedBy = new[] { PublishOthersBlogPost } };
public static readonly Permission PublishOthersBlogPost = new Permission { Description = "Publish or unpublish blog post for others", Name = "PublishOthersBlogPost" }; public static readonly Permission EditBlogPost = new Permission { Description = "Edit own blog posts", Name = "EditBlogPost", ImpliedBy = new[] { EditOthersBlogPost, PublishBlogPost } };
public static readonly Permission DeleteBlogPost = new Permission { Description = "Delete blog post", Name = "DeleteBlogPost" }; public static readonly Permission DeleteOthersBlogPost = new Permission { Description = "Delete blog post for others", Name = "DeleteOthersBlogPost", ImpliedBy = new[] { ManageBlogs } };
public static readonly Permission DeleteOthersBlogPost = new Permission { Description = "Delete blog post for others", Name = "DeleteOthersBlogPost" }; public static readonly Permission DeleteBlogPost = new Permission { Description = "Delete blog post", Name = "DeleteBlogPost", ImpliedBy = new[] { DeleteOthersBlogPost } };
public static readonly Permission MetaListOthersBlogs = new Permission { ImpliedBy = new[] { EditOthersBlogPost, PublishOthersBlogPost, DeleteOthersBlogPost } };
public static readonly Permission MetaListBlogs = new Permission { ImpliedBy = new[] { EditBlogPost, PublishBlogPost, DeleteBlogPost } };
public string PackageName { public string PackageName {
get { get {

View File

@ -7,7 +7,7 @@ namespace Orchard.Comments {
public void GetNavigation(NavigationBuilder builder) { public void GetNavigation(NavigationBuilder builder) {
builder.Add("Comments", "3", builder.Add("Comments", "3",
menu => menu menu => menu
.Add("Manage Comments", "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Comments" })) .Add("Manage Comments", "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Comments" }).Permission(Permissions.ManageComments))
); );
} }
} }

View File

@ -1,14 +1,11 @@
using Orchard.UI.Navigation; using Orchard.UI.Navigation;
namespace Orchard.Media { namespace Orchard.DevTools {
public class AdminMenu : INavigationProvider { public class AdminMenu : INavigationProvider {
public string MenuName { get { return "admin"; } } public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) { public void GetNavigation(NavigationBuilder builder) {
builder.Add("Media", "4",
menu => menu
.Add("Manage Folders", "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Media" }))
);
} }
} }
} }

View File

@ -70,6 +70,7 @@
<Compile Include="Controllers\HomeController.cs" /> <Compile Include="Controllers\HomeController.cs" />
<Compile Include="Models\DebugLinkHandler.cs" /> <Compile Include="Models\DebugLinkHandler.cs" />
<Compile Include="Models\ShowDebugLink.cs" /> <Compile Include="Models\ShowDebugLink.cs" />
<Compile Include="Permissions.cs" />
<Compile Include="Profiler.cs" /> <Compile Include="Profiler.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ViewModels\ContentIndexViewModel.cs" /> <Compile Include="ViewModels\ContentIndexViewModel.cs" />

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Orchard.Security.Permissions;
namespace Orchard.DevTools {
public class Permissions : IPermissionProvider {
public static readonly Permission DebugShowAllMenuItems = new Permission { Description = "DevTools: Show all menu items", Name = "DebugShowAllMenuItems" };
public string PackageName {
get {
return "DevTools";
}
}
public IEnumerable<Permission> GetPermissions() {
return new Permission[] {
DebugShowAllMenuItems,
};
}
public IEnumerable<PermissionStereotype> GetDefaultStereotypes() {
return Enumerable.Empty<PermissionStereotype>();
}
}
}

View File

@ -7,7 +7,7 @@ namespace Orchard.Media {
public void GetNavigation(NavigationBuilder builder) { public void GetNavigation(NavigationBuilder builder) {
builder.Add("Media", "4", builder.Add("Media", "4",
menu => menu menu => menu
.Add("Manage Folders", "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Media" })) .Add("Manage Folders", "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Media" }).Permission(Permissions.ManageMediaFiles))
); );
} }
} }

View File

@ -7,8 +7,8 @@ namespace Orchard.Pages {
public void GetNavigation(NavigationBuilder builder) { public void GetNavigation(NavigationBuilder builder) {
builder.Add("Pages", "1", builder.Add("Pages", "1",
menu => menu menu => menu
.Add("Manage Pages", "1.0", item => item.Action("List", "Admin", new { area = "Orchard.Pages" })) .Add("Manage Pages", "1.0", item => item.Action("List", "Admin", new { area = "Orchard.Pages" }).Permission(Permissions.MetaListPages))
.Add("Add New Page", "1.1", item => item.Action("Create", "Admin", new { area = "Orchard.Pages" }))); .Add("Add New Page", "1.1", item => item.Action("Create", "Admin", new { area = "Orchard.Pages" }).Permission(Permissions.EditPages)));
} }
} }
} }

View File

@ -4,12 +4,14 @@ using Orchard.Security.Permissions;
namespace Orchard.Pages { namespace Orchard.Pages {
public class Permissions : IPermissionProvider { public class Permissions : IPermissionProvider {
public static readonly Permission EditPages = new Permission { Description = "Edit page", Name = "EditPages" };
public static readonly Permission EditOthersPages = new Permission { Description = "Edit page for others", Name = "EditOthersPages" };
public static readonly Permission PublishPages = new Permission { Description = "Publish or unpublish page", Name = "PublishPages" };
public static readonly Permission PublishOthersPages = new Permission { Description = "Publish or unpublish page for others", Name = "PublishOthersPages" }; public static readonly Permission PublishOthersPages = new Permission { Description = "Publish or unpublish page for others", Name = "PublishOthersPages" };
public static readonly Permission DeletePages = new Permission { Description = "Delete page", Name = "DeletePages" }; public static readonly Permission PublishPages = new Permission { Description = "Publish or unpublish page", Name = "PublishPages", ImpliedBy = new[] { PublishOthersPages } };
public static readonly Permission EditOthersPages = new Permission { Description = "Edit page for others", Name = "EditOthersPages", ImpliedBy = new[] { PublishOthersPages } };
public static readonly Permission EditPages = new Permission { Description = "Edit page", Name = "EditPages", ImpliedBy = new[] { EditOthersPages, PublishPages } };
public static readonly Permission DeleteOthersPages = new Permission { Description = "Delete page for others", Name = "DeleteOthersPages" }; public static readonly Permission DeleteOthersPages = new Permission { Description = "Delete page for others", Name = "DeleteOthersPages" };
public static readonly Permission DeletePages = new Permission { Description = "Delete page", Name = "DeletePages", ImpliedBy = new[] { DeleteOthersPages } };
public static readonly Permission MetaListPages = new Permission { ImpliedBy = new[] { EditPages, PublishPages, DeletePages } };
public string PackageName { public string PackageName {
get { get {

View File

@ -7,8 +7,8 @@ namespace Orchard.Roles {
public void GetNavigation(NavigationBuilder builder) { public void GetNavigation(NavigationBuilder builder) {
builder.Add("Users", "5", builder.Add("Users", "5",
menu => menu menu => menu
.Add("Manage Roles", "2.0", item => item.Action("Index", "Admin", new { area = "Orchard.Roles" })) .Add("Manage Roles", "2.0", item => item.Action("Index", "Admin", new { area = "Orchard.Roles" }).Permission(Permissions.ManageRoles))
.Add("Add New Role", "2.1", item => item.Action("Create", "Admin", new { area = "Orchard.Roles" }))); .Add("Add New Role", "2.1", item => item.Action("Create", "Admin", new { area = "Orchard.Roles" }).Permission(Permissions.ManageRoles)));
} }
} }
} }

View File

@ -1,10 +1,15 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Web; using System.Web;
using System.Web.Mvc; using System.Web.Mvc;
using Orchard.Localization;
using Orchard.Roles.Models;
using Orchard.Roles.Records; using Orchard.Roles.Records;
using Orchard.Roles.Services; using Orchard.Roles.Services;
using Orchard.Roles.ViewModels; using Orchard.Roles.ViewModels;
using Orchard.Security;
using Orchard.Security.Permissions;
using Orchard.UI.Notify; using Orchard.UI.Notify;
namespace Orchard.Roles.Controllers { namespace Orchard.Roles.Controllers {
@ -12,13 +17,27 @@ namespace Orchard.Roles.Controllers {
public class AdminController : Controller { public class AdminController : Controller {
private readonly IRoleService _roleService; private readonly IRoleService _roleService;
private readonly INotifier _notifier; private readonly INotifier _notifier;
private readonly IAuthorizationService _authorizationService;
public AdminController(IRoleService roleService, INotifier notifier) { public AdminController(
IOrchardServices services,
IRoleService roleService,
INotifier notifier,
IAuthorizationService authorizationService) {
Services = services;
_roleService = roleService; _roleService = roleService;
_notifier = notifier; _notifier = notifier;
_authorizationService = authorizationService;
} }
public IOrchardServices Services { get; set; }
public Localizer T { get; set; }
public ActionResult Index() { public ActionResult Index() {
if (!Services.Authorizer.Authorize(Permissions.ManageRoles, T("Not authorized to manage roles")))
return new HttpUnauthorizedResult();
var model = new RolesIndexViewModel { Rows = _roleService.GetRoles() as IList<RoleRecord> }; var model = new RolesIndexViewModel { Rows = _roleService.GetRoles() as IList<RoleRecord> };
return View(model); return View(model);
@ -26,6 +45,9 @@ namespace Orchard.Roles.Controllers {
[HttpPost, ActionName("Index")] [HttpPost, ActionName("Index")]
public ActionResult IndexPOST() { public ActionResult IndexPOST() {
if (!Services.Authorizer.Authorize(Permissions.ManageRoles, T("Not authorized to manage roles")))
return new HttpUnauthorizedResult();
try { try {
foreach (string key in Request.Form.Keys) { foreach (string key in Request.Form.Keys) {
if (key.StartsWith("Checkbox.") && Request.Form[key] == "true") { if (key.StartsWith("Checkbox.") && Request.Form[key] == "true") {
@ -42,12 +64,18 @@ namespace Orchard.Roles.Controllers {
} }
public ActionResult Create() { public ActionResult Create() {
if (!Services.Authorizer.Authorize(Permissions.ManageRoles, T("Not authorized to manage roles")))
return new HttpUnauthorizedResult();
var model = new RoleCreateViewModel { PackagePermissions = _roleService.GetInstalledPermissions() }; var model = new RoleCreateViewModel { PackagePermissions = _roleService.GetInstalledPermissions() };
return View(model); return View(model);
} }
[HttpPost, ActionName("Create")] [HttpPost, ActionName("Create")]
public ActionResult CreatePOST() { public ActionResult CreatePOST() {
if (!Services.Authorizer.Authorize(Permissions.ManageRoles, T("Not authorized to manage roles")))
return new HttpUnauthorizedResult();
var viewModel = new RoleCreateViewModel(); var viewModel = new RoleCreateViewModel();
try { try {
UpdateModel(viewModel); UpdateModel(viewModel);
@ -55,7 +83,7 @@ namespace Orchard.Roles.Controllers {
foreach (string key in Request.Form.Keys) { foreach (string key in Request.Form.Keys) {
if (key.StartsWith("Checkbox.") && Request.Form[key] == "true") { if (key.StartsWith("Checkbox.") && Request.Form[key] == "true") {
string permissionName = key.Substring("Checkbox.".Length); string permissionName = key.Substring("Checkbox.".Length);
_roleService.CreatePermissionForRole(viewModel.Name, _roleService.CreatePermissionForRole(viewModel.Name,
permissionName); permissionName);
} }
} }
@ -68,6 +96,9 @@ namespace Orchard.Roles.Controllers {
} }
public ActionResult Edit(int id) { public ActionResult Edit(int id) {
if (!Services.Authorizer.Authorize(Permissions.ManageRoles, T("Not authorized to manage roles")))
return new HttpUnauthorizedResult();
var role = _roleService.GetRole(id); var role = _roleService.GetRole(id);
if (role == null) { if (role == null) {
//TODO: Error message //TODO: Error message
@ -77,11 +108,22 @@ namespace Orchard.Roles.Controllers {
PackagePermissions = _roleService.GetInstalledPermissions(), PackagePermissions = _roleService.GetInstalledPermissions(),
CurrentPermissions = _roleService.GetPermissionsForRole(id)}; CurrentPermissions = _roleService.GetPermissionsForRole(id)};
var simulation = UserSimulation.Create(role.Name);
model.EffectivePermissions = model.PackagePermissions
.SelectMany(group => group.Value)
.Where(permission => _authorizationService.CheckAccess(simulation, permission))
.Select(permission=>permission.Name)
.Distinct()
.ToList();
return View(model); return View(model);
} }
[HttpPost, ActionName("Edit")] [HttpPost, ActionName("Edit")]
public ActionResult EditPOST() { public ActionResult EditPOST() {
if (!Services.Authorizer.Authorize(Permissions.ManageRoles, T("Not authorized to manage roles")))
return new HttpUnauthorizedResult();
var viewModel = new RoleEditViewModel(); var viewModel = new RoleEditViewModel();
try { try {
UpdateModel(viewModel); UpdateModel(viewModel);
@ -99,7 +141,7 @@ namespace Orchard.Roles.Controllers {
else if (!String.IsNullOrEmpty(HttpContext.Request.Form["submit.Delete"])) { else if (!String.IsNullOrEmpty(HttpContext.Request.Form["submit.Delete"])) {
_roleService.DeleteRole(viewModel.Id); _roleService.DeleteRole(viewModel.Id);
} }
return RedirectToAction("Index"); return RedirectToAction("Edit", new { viewModel.Id });
} }
catch (Exception exception) { catch (Exception exception) {
_notifier.Error("Editing Role failed: " + exception.Message); _notifier.Error("Editing Role failed: " + exception.Message);

View File

@ -1,12 +1,8 @@
using System; using System.Linq;
using System.Collections.Generic; using JetBrains.Annotations;
using System.Linq;
using System.Web;
using Orchard.ContentManagement.Drivers; using Orchard.ContentManagement.Drivers;
using Orchard.Data; using Orchard.Data;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.ViewModels;
using Orchard.Roles.Models.NoRecord; using Orchard.Roles.Models.NoRecord;
using Orchard.Roles.Records; using Orchard.Roles.Records;
using Orchard.Roles.Services; using Orchard.Roles.Services;
@ -15,18 +11,25 @@ using Orchard.Security;
using Orchard.UI.Notify; using Orchard.UI.Notify;
namespace Orchard.Roles.Controllers { namespace Orchard.Roles.Controllers {
[UsedImplicitly]
public class UserRolesDriver : ContentPartDriver<UserRoles> { public class UserRolesDriver : ContentPartDriver<UserRoles> {
private readonly IRepository<UserRolesRecord> _userRolesRepository; private readonly IRepository<UserRolesRecord> _userRolesRepository;
private readonly IRoleService _roleService; private readonly IRoleService _roleService;
private readonly INotifier _notifier; private readonly INotifier _notifier;
private readonly IAuthenticationService _authenticationService;
private readonly IAuthorizationService _authorizationService;
public UserRolesDriver( public UserRolesDriver(
IRepository<UserRolesRecord> userRolesRepository, IRepository<UserRolesRecord> userRolesRepository,
IRoleService roleService, IRoleService roleService,
INotifier notifier) { INotifier notifier,
IAuthenticationService authenticationService,
IAuthorizationService authorizationService) {
_userRolesRepository = userRolesRepository; _userRolesRepository = userRolesRepository;
_roleService = roleService; _roleService = roleService;
_notifier = notifier; _notifier = notifier;
_authenticationService = authenticationService;
_authorizationService = authorizationService;
} }
protected override string Prefix { protected override string Prefix {
@ -36,6 +39,10 @@ namespace Orchard.Roles.Controllers {
} }
protected override DriverResult Editor(UserRoles userRoles) { protected override DriverResult Editor(UserRoles userRoles) {
// don't show editor without apply roles permission
if (!_authorizationService.CheckAccess(_authenticationService.GetAuthenticatedUser(), Permissions.ApplyRoles))
return null;
var roles = var roles =
_roleService.GetRoles().Select( _roleService.GetRoles().Select(
x => new UserRoleEntry { x => new UserRoleEntry {
@ -53,6 +60,10 @@ namespace Orchard.Roles.Controllers {
} }
protected override DriverResult Editor(UserRoles userRoles, IUpdateModel updater) { protected override DriverResult Editor(UserRoles userRoles, IUpdateModel updater) {
// don't apply editor without apply roles permission
if (!_authorizationService.CheckAccess(_authenticationService.GetAuthenticatedUser(), Permissions.ApplyRoles))
return null;
var model = new UserRolesViewModel { var model = new UserRolesViewModel {
User = userRoles.As<IUser>(), User = userRoles.As<IUser>(),
UserRoles = userRoles, UserRoles = userRoles,

View File

@ -65,6 +65,7 @@
<Compile Include="Controllers\AdminController.cs" /> <Compile Include="Controllers\AdminController.cs" />
<Compile Include="Controllers\UserRolesDriver.cs" /> <Compile Include="Controllers\UserRolesDriver.cs" />
<Compile Include="Extension.cs" /> <Compile Include="Extension.cs" />
<Compile Include="Models\UserSimulation.cs" />
<Compile Include="Permissions.cs" /> <Compile Include="Permissions.cs" />
<Compile Include="Records\PermissionRecord.cs" /> <Compile Include="Records\PermissionRecord.cs" />
<Compile Include="Records\RoleRecord.cs" /> <Compile Include="Records\RoleRecord.cs" />

View File

@ -7,7 +7,7 @@ namespace Orchard.Roles {
[UsedImplicitly] [UsedImplicitly]
public class Permissions : IPermissionProvider { public class Permissions : IPermissionProvider {
public static readonly Permission ManageRoles = new Permission { Description = "Create and manage roles", Name = "ManageRoles" }; public static readonly Permission ManageRoles = new Permission { Description = "Create and manage roles", Name = "ManageRoles" };
public static readonly Permission AssignUsersToRoles = new Permission { Description = "Assign users to roles", Name = "AssignUsersToRoles" }; public static readonly Permission ApplyRoles = new Permission { Description = "Assign users to roles", Name = "AssignUsersToRoles", ImpliedBy = new[] { ManageRoles } };
public string PackageName { public string PackageName {
get { get {
@ -18,7 +18,7 @@ namespace Orchard.Roles {
public IEnumerable<Permission> GetPermissions() { public IEnumerable<Permission> GetPermissions() {
return new Permission[] { return new Permission[] {
ManageRoles, ManageRoles,
AssignUsersToRoles, ApplyRoles,
}; };
} }

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using Orchard.Logging; using Orchard.Logging;
using Orchard.ContentManagement; using Orchard.ContentManagement;
@ -28,17 +29,20 @@ namespace Orchard.Roles.Services {
return false; return false;
} }
if (String.Equals(user.UserName, "Administrator", StringComparison.OrdinalIgnoreCase) || if (String.Equals(user.UserName, "Administrator", StringComparison.OrdinalIgnoreCase) ||
((!String.IsNullOrEmpty(CurrentSite.SuperUser) && ((!String.IsNullOrEmpty(CurrentSite.SuperUser) &&
String.Equals(user.UserName, CurrentSite.SuperUser, StringComparison.OrdinalIgnoreCase)))) { String.Equals(user.UserName, CurrentSite.SuperUser, StringComparison.OrdinalIgnoreCase)))) {
return true; return true;
} }
var grantingNames = PermissionNames(permission, Enumerable.Empty<string>()).ToArray();
IEnumerable<string> rolesForUser = user.As<IUserRoles>().Roles; IEnumerable<string> rolesForUser = user.As<IUserRoles>().Roles;
foreach (var role in rolesForUser) { foreach (var role in rolesForUser) {
RoleRecord roleRecord = _roleService.GetRoleByName(role); RoleRecord roleRecord = _roleService.GetRoleByName(role);
foreach (var permissionName in _roleService.GetPermissionsForRole(roleRecord.Id)) { foreach (var permissionName in _roleService.GetPermissionsForRole(roleRecord.Id)) {
if (String.Equals(permissionName, permission.Name, StringComparison.OrdinalIgnoreCase)) { string possessedName = permissionName;
if (grantingNames.Any(grantingName => String.Equals(possessedName, grantingName, StringComparison.OrdinalIgnoreCase))) {
return true; return true;
} }
} }
@ -47,6 +51,25 @@ namespace Orchard.Roles.Services {
return false; return false;
} }
private static IEnumerable<string> PermissionNames(Permission permission, IEnumerable<string> stack) {
// the given name is tested
yield return permission.Name;
// iterate implied permissions to grant, it present
if (permission.ImpliedBy != null && permission.ImpliedBy.Any()) {
foreach (var impliedBy in permission.ImpliedBy) {
// avoid potential recursion
if (stack.Contains(impliedBy.Name))
continue;
// otherwise accumulate the implied permission names recursively
foreach (var impliedName in PermissionNames(impliedBy, stack.Concat(new[] { permission.Name }))) {
yield return impliedName;
}
}
}
}
#endregion #endregion
} }
} }

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using Orchard.Mvc.ViewModels; using Orchard.Mvc.ViewModels;
using Orchard.Security.Permissions; using Orchard.Security.Permissions;
@ -10,5 +11,6 @@ namespace Orchard.Roles.ViewModels {
public string Name { get; set; } public string Name { get; set; }
public IDictionary<string, IEnumerable<Permission>> PackagePermissions { get; set; } public IDictionary<string, IEnumerable<Permission>> PackagePermissions { get; set; }
public IEnumerable<string> CurrentPermissions { get; set; } public IEnumerable<string> CurrentPermissions { get; set; }
public IEnumerable<string> EffectivePermissions { get; set; }
} }
} }

View File

@ -23,6 +23,7 @@
<tr> <tr>
<th scope="col"><%=_Encoded("Permission") %></th> <th scope="col"><%=_Encoded("Permission") %></th>
<th scope="col"><%=_Encoded("Allow") %></th> <th scope="col"><%=_Encoded("Allow") %></th>
<th scope="col"><%=_Encoded("Effective") %></th>
</tr> </tr>
</thead> </thead>
<% foreach (var permission in Model.PackagePermissions[packageName]) { %> <% foreach (var permission in Model.PackagePermissions[packageName]) { %>
@ -34,7 +35,14 @@
<% } else {%> <% } else {%>
<input type="checkbox" value="true" name="<%=_Encoded("Checkbox.{0}", permission.Name) %>"/> <input type="checkbox" value="true" name="<%=_Encoded("Checkbox.{0}", permission.Name) %>"/>
<% }%> <% }%>
</td> </td>
<td style="width:60px;/* todo: (heskew) make not inline :(">
<% if (Model.EffectivePermissions.Contains(permission.Name)) { %>
<input type="checkbox" disabled="disabled" name="<%=_Encoded("Effective.{0}", permission.Name) %>" checked="checked"/>
<% } else {%>
<input type="checkbox" disabled="disabled" name="<%=_Encoded("Effective.{0}", permission.Name) %>"/>
<% }%>
</td>
</tr> </tr>
<% } %> <% } %>
</table> </table>

View File

@ -7,7 +7,7 @@ namespace Orchard.Tags {
public void GetNavigation(NavigationBuilder builder) { public void GetNavigation(NavigationBuilder builder) {
builder.Add("Tags", "3", builder.Add("Tags", "3",
menu => menu menu => menu
.Add("Manage Tags", "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Tags" })) .Add("Manage Tags", "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Tags" }).Permission(Permissions.ManageTags))
); );
} }
} }

View File

@ -2,6 +2,7 @@
using JetBrains.Annotations; using JetBrains.Annotations;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers; using Orchard.ContentManagement.Drivers;
using Orchard.Security;
using Orchard.Tags.Helpers; using Orchard.Tags.Helpers;
using Orchard.Tags.Models; using Orchard.Tags.Models;
using Orchard.Tags.Services; using Orchard.Tags.Services;
@ -12,16 +13,24 @@ namespace Orchard.Tags.Controllers {
[UsedImplicitly] [UsedImplicitly]
public class HasTagsDriver : ContentPartDriver<HasTags> { public class HasTagsDriver : ContentPartDriver<HasTags> {
private readonly ITagService _tagService; private readonly ITagService _tagService;
private readonly IAuthorizationService _authorizationService;
public HasTagsDriver(ITagService tagService) { public HasTagsDriver(ITagService tagService,
IAuthorizationService authorizationService) {
_tagService = tagService; _tagService = tagService;
_authorizationService = authorizationService;
} }
public virtual IUser CurrentUser { get; set; }
protected override DriverResult Display(HasTags part, string displayType) { protected override DriverResult Display(HasTags part, string displayType) {
return ContentPartTemplate(part, "Parts/Tags.ShowTags").Location("primary", "49"); return ContentPartTemplate(part, "Parts/Tags.ShowTags").Location("primary", "49");
} }
protected override DriverResult Editor(HasTags part) { protected override DriverResult Editor(HasTags part) {
if (!_authorizationService.CheckAccess(CurrentUser, Permissions.ApplyTag))
return null;
var model = new EditTagsViewModel { var model = new EditTagsViewModel {
Tags = string.Join(", ", part.CurrentTags.Select((t, i) => t.TagName).ToArray()) Tags = string.Join(", ", part.CurrentTags.Select((t, i) => t.TagName).ToArray())
}; };
@ -29,6 +38,8 @@ namespace Orchard.Tags.Controllers {
} }
protected override DriverResult Editor(HasTags part, IUpdateModel updater) { protected override DriverResult Editor(HasTags part, IUpdateModel updater) {
if (!_authorizationService.CheckAccess(CurrentUser, Permissions.ApplyTag))
return null;
var model = new EditTagsViewModel(); var model = new EditTagsViewModel();
updater.TryUpdateModel(model, Prefix, null, null); updater.TryUpdateModel(model, Prefix, null, null);

View File

@ -5,8 +5,8 @@ using Orchard.Security.Permissions;
namespace Orchard.Tags { namespace Orchard.Tags {
public class Permissions : IPermissionProvider { public class Permissions : IPermissionProvider {
public static readonly Permission ManageTags = new Permission { Description = "Manage tags", Name = "ManageTags" }; public static readonly Permission ManageTags = new Permission { Description = "Manage tags", Name = "ManageTags" };
public static readonly Permission CreateTag = new Permission { Description = "Create tag", Name = "CreateTag" }; public static readonly Permission CreateTag = new Permission { Description = "Create tag", Name = "CreateTag", ImpliedBy = new[] { ManageTags } };
public static readonly Permission ApplyTag = new Permission { Description = "Applying a Tag", Name = "ApplyTag" }; public static readonly Permission ApplyTag = new Permission { Description = "Applying a Tag", Name = "ApplyTag", ImpliedBy = new[] { ManageTags, CreateTag } };
public string PackageName { public string PackageName {
get { get {

View File

@ -6,6 +6,7 @@ using Orchard.Data;
using Orchard.Localization; using Orchard.Localization;
using Orchard.Logging; using Orchard.Logging;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.Security;
using Orchard.Settings; using Orchard.Settings;
using Orchard.Tags.Models; using Orchard.Tags.Models;
using Orchard.UI.Notify; using Orchard.UI.Notify;
@ -28,21 +29,25 @@ namespace Orchard.Tags.Services {
private readonly IRepository<TagsContentItems> _tagsContentItemsRepository; private readonly IRepository<TagsContentItems> _tagsContentItemsRepository;
private readonly IContentManager _contentManager; private readonly IContentManager _contentManager;
private readonly INotifier _notifier; private readonly INotifier _notifier;
private readonly IAuthorizationService _authorizationService;
public TagService(IRepository<Tag> tagRepository, public TagService(IRepository<Tag> tagRepository,
IRepository<TagsContentItems> tagsContentItemsRepository, IRepository<TagsContentItems> tagsContentItemsRepository,
IContentManager contentManager, IContentManager contentManager,
INotifier notifier) { INotifier notifier,
IAuthorizationService authorizationService) {
_tagRepository = tagRepository; _tagRepository = tagRepository;
_tagsContentItemsRepository = tagsContentItemsRepository; _tagsContentItemsRepository = tagsContentItemsRepository;
_contentManager = contentManager; _contentManager = contentManager;
_notifier = notifier; _notifier = notifier;
_authorizationService = authorizationService;
Logger = NullLogger.Instance; Logger = NullLogger.Instance;
T = NullLocalizer.Instance; T = NullLocalizer.Instance;
} }
public ILogger Logger { get; set; } public ILogger Logger { get; set; }
protected virtual ISite CurrentSite { get; [UsedImplicitly] private set; } public virtual ISite CurrentSite { get; set; }
public virtual IUser CurrentUser { get; set; }
public Localizer T { get; set; } public Localizer T { get; set; }
#region ITagService Members #region ITagService Members
@ -61,6 +66,9 @@ namespace Orchard.Tags.Services {
public void CreateTag(string tagName) { public void CreateTag(string tagName) {
if (_tagRepository.Get(x => x.TagName == tagName) == null) { if (_tagRepository.Get(x => x.TagName == tagName) == null) {
if (!_authorizationService.CheckAccess(CurrentUser, Permissions.CreateTag))
throw new UnauthorizedException();
Tag tag = new Tag { TagName = tagName }; Tag tag = new Tag { TagName = tagName };
_tagRepository.Create(tag); _tagRepository.Create(tag);
} }
@ -119,15 +127,23 @@ namespace Orchard.Tags.Services {
private void ModifyTagsForContentItem(int contentItemId, IEnumerable<int> tagsForContentItem) { private void ModifyTagsForContentItem(int contentItemId, IEnumerable<int> tagsForContentItem) {
List<int> newTagsForContentItem = new List<int>(tagsForContentItem); List<int> newTagsForContentItem = new List<int>(tagsForContentItem);
IEnumerable<TagsContentItems> currentTagsForContentItem = _tagsContentItemsRepository.Fetch(x => x.ContentItemId == contentItemId); IEnumerable<TagsContentItems> currentTagsForContentItem = _tagsContentItemsRepository.Fetch(x => x.ContentItemId == contentItemId);
foreach (var tagContentItem in currentTagsForContentItem) { foreach (var tagContentItem in currentTagsForContentItem) {
if (!newTagsForContentItem.Contains(tagContentItem.TagId)) { if (!newTagsForContentItem.Contains(tagContentItem.TagId)) {
if (!_authorizationService.CheckAccess(CurrentUser, Permissions.ApplyTag))
throw new UnauthorizedException();
_tagsContentItemsRepository.Delete(tagContentItem); _tagsContentItemsRepository.Delete(tagContentItem);
} }
else { else {
newTagsForContentItem.Remove(tagContentItem.TagId); newTagsForContentItem.Remove(tagContentItem.TagId);
} }
} }
foreach (var newTagForContentItem in newTagsForContentItem) { foreach (var newTagForContentItem in newTagsForContentItem) {
if (!_authorizationService.CheckAccess(CurrentUser, Permissions.ApplyTag))
throw new UnauthorizedException();
_tagsContentItemsRepository.Create(new TagsContentItems { ContentItemId = contentItemId, TagId = newTagForContentItem }); _tagsContentItemsRepository.Create(new TagsContentItems { ContentItemId = contentItemId, TagId = newTagForContentItem });
} }
} }

View File

@ -7,8 +7,8 @@ namespace Orchard.Users {
public void GetNavigation(NavigationBuilder builder) { public void GetNavigation(NavigationBuilder builder) {
builder.Add("Users", "5", builder.Add("Users", "5",
menu => menu menu => menu
.Add("Manage Users", "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Users" })) .Add("Manage Users", "1.0", item => item.Action("Index", "Admin", new { area = "Orchard.Users" }).Permission(Permissions.ManageUsers))
.Add("Add New User", "1.1", item => item.Action("Create", "Admin", new { area = "Orchard.Users" }))); .Add("Add New User", "1.1", item => item.Action("Create", "Admin", new { area = "Orchard.Users" }).Permission(Permissions.ManageUsers)));
} }
} }
} }

View File

@ -26,6 +26,9 @@ namespace Orchard.Users.Controllers {
public ActionResult Index() { public ActionResult Index() {
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage settings")))
return new HttpUnauthorizedResult();
var users = Services.ContentManager var users = Services.ContentManager
.Query<User, UserRecord>() .Query<User, UserRecord>()
.Where(x => x.UserName != null) .Where(x => x.UserName != null)
@ -41,6 +44,9 @@ namespace Orchard.Users.Controllers {
} }
public ActionResult Create() { public ActionResult Create() {
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage settings")))
return new HttpUnauthorizedResult();
var user = Services.ContentManager.New<IUser>(UserDriver.ContentType.Name); var user = Services.ContentManager.New<IUser>(UserDriver.ContentType.Name);
var model = new UserCreateViewModel { var model = new UserCreateViewModel {
User = Services.ContentManager.BuildEditorModel(user) User = Services.ContentManager.BuildEditorModel(user)
@ -49,7 +55,9 @@ namespace Orchard.Users.Controllers {
} }
[HttpPost, ActionName("Create")] [HttpPost, ActionName("Create")]
public ActionResult _Create() { public ActionResult CreatePOST() {
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage settings")))
return new HttpUnauthorizedResult();
var model = new UserCreateViewModel(); var model = new UserCreateViewModel();
UpdateModel(model); UpdateModel(model);
@ -75,13 +83,19 @@ namespace Orchard.Users.Controllers {
} }
public ActionResult Edit(int id) { public ActionResult Edit(int id) {
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage settings")))
return new HttpUnauthorizedResult();
return View(new UserEditViewModel { return View(new UserEditViewModel {
User = Services.ContentManager.BuildEditorModel<User>(id) User = Services.ContentManager.BuildEditorModel<User>(id)
}); });
} }
[HttpPost, ActionName("Edit")] [HttpPost, ActionName("Edit")]
public ActionResult _Edit(int id) { public ActionResult EditPOST(int id) {
if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage settings")))
return new HttpUnauthorizedResult();
var model = new UserEditViewModel { var model = new UserEditViewModel {
User = Services.ContentManager.UpdateEditorModel<User>(id, this) User = Services.ContentManager.UpdateEditorModel<User>(id, this)
}; };

View File

@ -7,7 +7,6 @@ namespace Orchard.Users {
[UsedImplicitly] [UsedImplicitly]
public class Permissions : IPermissionProvider { public class Permissions : IPermissionProvider {
public static readonly Permission ManageUsers = new Permission { Description = "Manage users", Name = "ManageUsers" }; public static readonly Permission ManageUsers = new Permission { Description = "Manage users", Name = "ManageUsers" };
public static readonly Permission AddUsers = new Permission { Description = "Add users", Name = "AddUsers" };
public string PackageName { public string PackageName {
get { get {
@ -18,7 +17,6 @@ namespace Orchard.Users {
public IEnumerable<Permission> GetPermissions() { public IEnumerable<Permission> GetPermissions() {
return new Permission[] { return new Permission[] {
ManageUsers, ManageUsers,
AddUsers,
}; };
} }

View File

@ -13,12 +13,26 @@ namespace Orchard {
dispatch(sink); dispatch(sink);
} }
catch (Exception ex) { catch (Exception ex) {
logger.Error(ex, "{2} thrown from {0} by {1}", if (IsLogged(ex)) {
typeof(TEvents).Name, logger.Error(ex, "{2} thrown from {0} by {1}",
sink.GetType().FullName, typeof(TEvents).Name,
ex.GetType().Name); sink.GetType().FullName,
ex.GetType().Name);
}
if (IsFatal(ex)) {
throw;
}
} }
} }
} }
private static bool IsLogged(Exception exception) {
return true;
}
private static bool IsFatal(Exception exception) {
return false;
}
} }
} }

View File

@ -137,6 +137,7 @@
<Compile Include="Extensions\Loaders\AreaExtensionLoader.cs" /> <Compile Include="Extensions\Loaders\AreaExtensionLoader.cs" />
<Compile Include="Extensions\UriExtensions.cs" /> <Compile Include="Extensions\UriExtensions.cs" />
<Compile Include="Security\StandardPermissions.cs" /> <Compile Include="Security\StandardPermissions.cs" />
<Compile Include="Security\UnauthorizedException.cs" />
<Compile Include="Tasks\Scheduling\IScheduledTask.cs" /> <Compile Include="Tasks\Scheduling\IScheduledTask.cs" />
<Compile Include="ContentManagement\ContentExtensions.cs" /> <Compile Include="ContentManagement\ContentExtensions.cs" />
<Compile Include="ContentManagement\ContentItem.cs" /> <Compile Include="ContentManagement\ContentItem.cs" />

View File

@ -1,6 +1,14 @@
namespace Orchard.Security.Permissions { using System;
using System.Collections.Generic;
namespace Orchard.Security.Permissions {
public class Permission { public class Permission {
public string Name { get; set; } public string Name { get; set; }
public string Description { get; set; } public string Description { get; set; }
public IEnumerable<Permission> ImpliedBy { get; set; }
public static Permission Named(string name) {
return new Permission { Name = name };
}
} }
} }

View File

@ -1,15 +1,19 @@
using System.Web.Mvc; using System;
using System.Linq;
using System.Web.Mvc;
using JetBrains.Annotations;
using Orchard.Mvc.Filters; using Orchard.Mvc.Filters;
using Orchard.Mvc.ViewModels; using Orchard.Mvc.ViewModels;
namespace Orchard.Security { namespace Orchard.Security {
public class SecurityFilter : FilterProvider, IResultFilter { [UsedImplicitly]
public class SecurityFilter : FilterProvider, IResultFilter, IExceptionFilter {
private readonly IAuthenticationService _authenticationService; private readonly IAuthenticationService _authenticationService;
public SecurityFilter(IAuthenticationService authenticationService) { public SecurityFilter(IAuthenticationService authenticationService) {
_authenticationService = authenticationService; _authenticationService = authenticationService;
} }
public void OnResultExecuting(ResultExecutingContext filterContext) { public void OnResultExecuting(ResultExecutingContext filterContext) {
var viewResult = filterContext.Result as ViewResultBase; var viewResult = filterContext.Result as ViewResultBase;
if (viewResult == null) if (viewResult == null)
@ -26,5 +30,12 @@ namespace Orchard.Security {
public void OnResultExecuted(ResultExecutedContext filterContext) { public void OnResultExecuted(ResultExecutedContext filterContext) {
} }
public void OnException(ExceptionContext filterContext) {
if (filterContext.Exception is UnauthorizedException) {
filterContext.Result = new HttpUnauthorizedResult();
filterContext.ExceptionHandled = true;
}
}
} }
} }

View File

@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using Orchard.Security; using Orchard.Security;
using Orchard.Security.Permissions;
namespace Orchard.UI.Navigation { namespace Orchard.UI.Navigation {
public interface INavigationManager : IDependency { public interface INavigationManager : IDependency {
@ -26,9 +27,11 @@ namespace Orchard.UI.Navigation {
} }
private IEnumerable<MenuItem> Reduce(IEnumerable<MenuItem> items) { private IEnumerable<MenuItem> Reduce(IEnumerable<MenuItem> items) {
foreach(var item in items) { var hasDebugShowAllMenuItems = _authorizationService.CheckAccess(CurrentUser, Permission.Named("DebugShowAllMenuItems"));
if (!item.Permissions.Any() || foreach (var item in items) {
item.Permissions.Any(x=>_authorizationService.CheckAccess(CurrentUser, x))) { if (hasDebugShowAllMenuItems ||
!item.Permissions.Any() ||
item.Permissions.Any(x => _authorizationService.CheckAccess(CurrentUser, x))) {
yield return new MenuItem { yield return new MenuItem {
Items = Reduce(item.Items), Items = Reduce(item.Items),
Permissions = item.Permissions, Permissions = item.Permissions,
@ -68,7 +71,7 @@ namespace Orchard.UI.Navigation {
RouteValues = items.First().RouteValues, RouteValues = items.First().RouteValues,
Items = Merge(items.Select(x => x.Items)).ToArray(), Items = Merge(items.Select(x => x.Items)).ToArray(),
Position = SelectBestPositionValue(items.Select(x => x.Position)), Position = SelectBestPositionValue(items.Select(x => x.Position)),
Permissions = items.SelectMany(x=>x.Permissions), Permissions = items.SelectMany(x => x.Permissions),
}; };
return joined; return joined;
} }