mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-09-23 04:43:35 +08:00
Updated Admin filter and access control
AdminController convention or [Admin] attribute activates both the security check and "TheAdmin" theme --HG-- branch : dev
This commit is contained in:
@@ -156,7 +156,8 @@
|
|||||||
<Compile Include="Mvc\RouteCollectionPublisherTests.cs" />
|
<Compile Include="Mvc\RouteCollectionPublisherTests.cs" />
|
||||||
<Compile Include="Mvc\Routes\StandardExtensionRouteProviderTests.cs" />
|
<Compile Include="Mvc\Routes\StandardExtensionRouteProviderTests.cs" />
|
||||||
<Compile Include="Tasks\SweepGeneratorTests.cs" />
|
<Compile Include="Tasks\SweepGeneratorTests.cs" />
|
||||||
<Compile Include="UI\Admin\AdminAttributeTests.cs" />
|
<Compile Include="UI\Admin\AdminAuthorizationFilterTests.cs" />
|
||||||
|
<Compile Include="UI\Admin\AdminThemeSelectorTests.cs" />
|
||||||
<Compile Include="UI\Notify\NotifierTests.cs" />
|
<Compile Include="UI\Notify\NotifierTests.cs" />
|
||||||
<Compile Include="UI\Notify\NotifyFilterTests.cs" />
|
<Compile Include="UI\Notify\NotifyFilterTests.cs" />
|
||||||
<Compile Include="Services\ClockTests.cs" />
|
<Compile Include="Services\ClockTests.cs" />
|
||||||
|
@@ -1,8 +1,11 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
|
|
||||||
namespace Orchard.Tests.Stubs {
|
namespace Orchard.Tests.Stubs {
|
||||||
public class StubHttpContext : HttpContextBase {
|
public class StubHttpContext : HttpContextBase {
|
||||||
private readonly string _appRelativeCurrentExecutionFilePath;
|
private readonly string _appRelativeCurrentExecutionFilePath;
|
||||||
|
private readonly IDictionary _items = new Dictionary<object, object>();
|
||||||
|
|
||||||
public StubHttpContext() {
|
public StubHttpContext() {
|
||||||
_appRelativeCurrentExecutionFilePath = "~/yadda";
|
_appRelativeCurrentExecutionFilePath = "~/yadda";
|
||||||
@@ -16,6 +19,10 @@ namespace Orchard.Tests.Stubs {
|
|||||||
get { return new StupHttpRequest(_appRelativeCurrentExecutionFilePath); }
|
get { return new StupHttpRequest(_appRelativeCurrentExecutionFilePath); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override IDictionary Items {
|
||||||
|
get { return _items; }
|
||||||
|
}
|
||||||
|
|
||||||
public class StupHttpRequest : HttpRequestBase {
|
public class StupHttpRequest : HttpRequestBase {
|
||||||
private readonly string _appRelativeCurrentExecutionFilePath;
|
private readonly string _appRelativeCurrentExecutionFilePath;
|
||||||
|
|
||||||
|
@@ -1,22 +1,19 @@
|
|||||||
using System;
|
using System.Web.Mvc;
|
||||||
using System.Collections.Generic;
|
using System.Web.Routing;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Web.Mvc;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.Security;
|
using Orchard.Security;
|
||||||
using Orchard.Security.Permissions;
|
using Orchard.Tests.Stubs;
|
||||||
using Orchard.UI.Admin;
|
using Orchard.UI.Admin;
|
||||||
|
|
||||||
namespace Orchard.Tests.UI.Admin {
|
namespace Orchard.Tests.UI.Admin {
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class AdminAttributeTests {
|
public class AdminAuthorizationFilterTests {
|
||||||
|
|
||||||
private static AuthorizationContext GetAuthorizationContext<TController>() {
|
private static AuthorizationContext GetAuthorizationContext<TController>() where TController : ControllerBase, new() {
|
||||||
var controllerDescriptor = new ReflectedControllerDescriptor(typeof(TController));
|
var controllerDescriptor = new ReflectedControllerDescriptor(typeof(TController));
|
||||||
var controllerContext = new ControllerContext();
|
var controllerContext = new ControllerContext(new StubHttpContext(), new RouteData(), new TController());
|
||||||
return new AuthorizationContext(
|
return new AuthorizationContext(
|
||||||
controllerContext,
|
controllerContext,
|
||||||
controllerDescriptor.FindAction(controllerContext, "Index"));
|
controllerDescriptor.FindAction(controllerContext, "Index"));
|
||||||
@@ -40,56 +37,39 @@ namespace Orchard.Tests.UI.Admin {
|
|||||||
Assert.That(authorizationContext.Result, Is.Null);
|
Assert.That(authorizationContext.Result, Is.Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
private static void TestActionThatShouldRequirePermission<TController>() where TController : ControllerBase, new() {
|
||||||
public void AdminRequestShouldRequirePermission() {
|
var authorizationContext = GetAuthorizationContext<TController>();
|
||||||
var authorizationContext = GetAuthorizationContext<AdminController>();
|
|
||||||
var filter = new AdminAuthorizationFilter(GetAuthorizer(false));
|
var filter = new AdminAuthorizationFilter(GetAuthorizer(false));
|
||||||
filter.OnAuthorization(authorizationContext);
|
filter.OnAuthorization(authorizationContext);
|
||||||
Assert.That(authorizationContext.Result, Is.InstanceOf<HttpUnauthorizedResult>());
|
Assert.That(authorizationContext.Result, Is.InstanceOf<HttpUnauthorizedResult>());
|
||||||
|
Assert.That(AdminThemeSelector.IsApplied(authorizationContext.RequestContext), Is.True);
|
||||||
|
|
||||||
var authorizationContext2 = GetAuthorizationContext<AdminController>();
|
var authorizationContext2 = GetAuthorizationContext<TController>();
|
||||||
var filter2 = new AdminAuthorizationFilter(GetAuthorizer(true));
|
var filter2 = new AdminAuthorizationFilter(GetAuthorizer(true));
|
||||||
filter2.OnAuthorization(authorizationContext2);
|
filter2.OnAuthorization(authorizationContext2);
|
||||||
Assert.That(authorizationContext2.Result, Is.Null);
|
Assert.That(authorizationContext2.Result, Is.Null);
|
||||||
|
Assert.That(AdminThemeSelector.IsApplied(authorizationContext2.RequestContext), Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AdminRequestShouldRequirePermission() {
|
||||||
|
TestActionThatShouldRequirePermission<AdminController>();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void NormalWithAttribRequestShouldRequirePermission() {
|
public void NormalWithAttribRequestShouldRequirePermission() {
|
||||||
var authorizationContext = GetAuthorizationContext<NormalWithAttribController>();
|
TestActionThatShouldRequirePermission<NormalWithAttribController>();
|
||||||
var filter = new AdminAuthorizationFilter(GetAuthorizer(false));
|
|
||||||
filter.OnAuthorization(authorizationContext);
|
|
||||||
Assert.That(authorizationContext.Result, Is.InstanceOf<HttpUnauthorizedResult>());
|
|
||||||
|
|
||||||
var authorizationContext2 = GetAuthorizationContext<NormalWithAttribController>();
|
|
||||||
var filter2 = new AdminAuthorizationFilter(GetAuthorizer(true));
|
|
||||||
filter2.OnAuthorization(authorizationContext2);
|
|
||||||
Assert.That(authorizationContext2.Result, Is.Null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void NormalWithActionAttribRequestShouldRequirePermission() {
|
public void NormalWithActionAttribRequestShouldRequirePermission() {
|
||||||
var authorizationContext = GetAuthorizationContext<NormalWithActionAttribController>();
|
TestActionThatShouldRequirePermission<NormalWithActionAttribController>();
|
||||||
var filter = new AdminAuthorizationFilter(GetAuthorizer(false));
|
|
||||||
filter.OnAuthorization(authorizationContext);
|
|
||||||
Assert.That(authorizationContext.Result, Is.InstanceOf<HttpUnauthorizedResult>());
|
|
||||||
|
|
||||||
var authorizationContext2 = GetAuthorizationContext<NormalWithActionAttribController>();
|
|
||||||
var filter2 = new AdminAuthorizationFilter(GetAuthorizer(true));
|
|
||||||
filter2.OnAuthorization(authorizationContext2);
|
|
||||||
Assert.That(authorizationContext2.Result, Is.Null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void InheritedAttribRequestShouldRequirePermission() {
|
public void InheritedAttribRequestShouldRequirePermission() {
|
||||||
var authorizationContext = GetAuthorizationContext<InheritedAttribController>();
|
TestActionThatShouldRequirePermission<InheritedAttribController>();
|
||||||
var filter = new AdminAuthorizationFilter(GetAuthorizer(false));
|
|
||||||
filter.OnAuthorization(authorizationContext);
|
|
||||||
Assert.That(authorizationContext.Result, Is.InstanceOf<HttpUnauthorizedResult>());
|
|
||||||
|
|
||||||
var authorizationContext2 = GetAuthorizationContext<InheritedAttribController>();
|
|
||||||
var filter2 = new AdminAuthorizationFilter(GetAuthorizer(true));
|
|
||||||
filter2.OnAuthorization(authorizationContext2);
|
|
||||||
Assert.That(authorizationContext2.Result, Is.Null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
58
src/Orchard.Tests/UI/Admin/AdminThemeSelectorTests.cs
Normal file
58
src/Orchard.Tests/UI/Admin/AdminThemeSelectorTests.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
using System.Web.Routing;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Orchard.Tests.Stubs;
|
||||||
|
using Orchard.UI.Admin;
|
||||||
|
|
||||||
|
namespace Orchard.Tests.UI.Admin {
|
||||||
|
[TestFixture]
|
||||||
|
public class AdminThemeSelectorTests {
|
||||||
|
[Test]
|
||||||
|
public void IsAppliedShouldBeFalseByDefault() {
|
||||||
|
var context = new RequestContext(new StubHttpContext(), new RouteData());
|
||||||
|
var isApplied = AdminThemeSelector.IsApplied(context);
|
||||||
|
Assert.That(isApplied, Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void IsAppliedShouldBeTrueAfterBeingApplied() {
|
||||||
|
var context = new RequestContext(new StubHttpContext(), new RouteData());
|
||||||
|
Assert.That(AdminThemeSelector.IsApplied(context), Is.False);
|
||||||
|
AdminThemeSelector.Apply(context);
|
||||||
|
Assert.That(AdminThemeSelector.IsApplied(context), Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void IsAppliedIsFalseOnNewContext() {
|
||||||
|
var context = new RequestContext(new StubHttpContext(), new RouteData());
|
||||||
|
Assert.That(AdminThemeSelector.IsApplied(context), Is.False);
|
||||||
|
AdminThemeSelector.Apply(context);
|
||||||
|
Assert.That(AdminThemeSelector.IsApplied(context), Is.True);
|
||||||
|
context = new RequestContext(new StubHttpContext(), new RouteData());
|
||||||
|
Assert.That(AdminThemeSelector.IsApplied(context), Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ThemeResultShouldBeNullNormally() {
|
||||||
|
var context = new RequestContext(new StubHttpContext(), new RouteData());
|
||||||
|
|
||||||
|
var selector = new AdminThemeSelector();
|
||||||
|
var result = selector.GetTheme(context);
|
||||||
|
Assert.That(result, Is.Null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ThemeResultShouldBeTheAdminAt100AfterBeingSet() {
|
||||||
|
var context = new RequestContext(new StubHttpContext(), new RouteData());
|
||||||
|
|
||||||
|
AdminThemeSelector.Apply(context);
|
||||||
|
|
||||||
|
var selector = new AdminThemeSelector();
|
||||||
|
var result = selector.GetTheme(context);
|
||||||
|
Assert.That(result, Is.Not.Null);
|
||||||
|
Assert.That(result.ThemeName, Is.EqualTo("TheAdmin"));
|
||||||
|
Assert.That(result.Priority, Is.EqualTo(100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -11,10 +11,11 @@ using Orchard.Core.Common.Models;
|
|||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.Mvc.Results;
|
using Orchard.Mvc.Results;
|
||||||
using Orchard.Settings;
|
using Orchard.Settings;
|
||||||
|
using Orchard.UI.Admin;
|
||||||
using Orchard.UI.Notify;
|
using Orchard.UI.Notify;
|
||||||
|
|
||||||
namespace Orchard.Blogs.Controllers {
|
namespace Orchard.Blogs.Controllers {
|
||||||
[ValidateInput(false)]
|
[ValidateInput(false), Admin]
|
||||||
public class BlogAdminController : Controller, IUpdateModel {
|
public class BlogAdminController : Controller, IUpdateModel {
|
||||||
private readonly IBlogService _blogService;
|
private readonly IBlogService _blogService;
|
||||||
private readonly IBlogPostService _blogPostService;
|
private readonly IBlogPostService _blogPostService;
|
||||||
|
@@ -6,10 +6,11 @@ using Orchard.Blogs.ViewModels;
|
|||||||
using Orchard.ContentManagement;
|
using Orchard.ContentManagement;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.Mvc.Results;
|
using Orchard.Mvc.Results;
|
||||||
|
using Orchard.UI.Admin;
|
||||||
using Orchard.UI.Notify;
|
using Orchard.UI.Notify;
|
||||||
|
|
||||||
namespace Orchard.Blogs.Controllers {
|
namespace Orchard.Blogs.Controllers {
|
||||||
[ValidateInput(false)]
|
[ValidateInput(false), Admin]
|
||||||
public class BlogPostAdminController : Controller, IUpdateModel {
|
public class BlogPostAdminController : Controller, IUpdateModel {
|
||||||
private readonly IBlogService _blogService;
|
private readonly IBlogService _blogService;
|
||||||
private readonly IBlogPostService _blogPostService;
|
private readonly IBlogPostService _blogPostService;
|
||||||
|
@@ -18,17 +18,17 @@ namespace Orchard.UI.Admin {
|
|||||||
public Localizer T { get; set; }
|
public Localizer T { get; set; }
|
||||||
|
|
||||||
public void OnAuthorization(AuthorizationContext filterContext) {
|
public void OnAuthorization(AuthorizationContext filterContext) {
|
||||||
if (!IsAdmin(filterContext))
|
if (IsAdmin(filterContext)) {
|
||||||
return;
|
|
||||||
|
|
||||||
if (!_authorizer.Authorize(StandardPermissions.AccessAdminPanel, T("Can't access the admin"))) {
|
if (!_authorizer.Authorize(StandardPermissions.AccessAdminPanel, T("Can't access the admin"))) {
|
||||||
filterContext.Result = new HttpUnauthorizedResult();
|
filterContext.Result = new HttpUnauthorizedResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AdminThemeSelector.Apply(filterContext.RequestContext);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsAdmin(AuthorizationContext filterContext) {
|
private static bool IsAdmin(AuthorizationContext filterContext) {
|
||||||
if (string.Equals(filterContext.ActionDescriptor.ControllerDescriptor.ControllerName, "Admin",
|
if (IsNameAdmin(filterContext) || IsNameAdminProxy(filterContext)) {
|
||||||
StringComparison.InvariantCultureIgnoreCase)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,6 +39,17 @@ namespace Orchard.UI.Admin {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsNameAdmin(AuthorizationContext filterContext) {
|
||||||
|
return string.Equals(filterContext.ActionDescriptor.ControllerDescriptor.ControllerName, "Admin",
|
||||||
|
StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsNameAdminProxy(AuthorizationContext filterContext) {
|
||||||
|
return filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.StartsWith(
|
||||||
|
"AdminControllerProxy", StringComparison.InvariantCultureIgnoreCase) &&
|
||||||
|
filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.Length == "AdminControllerProxy".Length + 32;
|
||||||
|
}
|
||||||
|
|
||||||
private static IEnumerable<AdminAttribute> GetAdminAttributes(ActionDescriptor descriptor) {
|
private static IEnumerable<AdminAttribute> GetAdminAttributes(ActionDescriptor descriptor) {
|
||||||
return descriptor.GetCustomAttributes(typeof(AdminAttribute), true)
|
return descriptor.GetCustomAttributes(typeof(AdminAttribute), true)
|
||||||
.Concat(descriptor.ControllerDescriptor.GetCustomAttributes(typeof(AdminAttribute), true))
|
.Concat(descriptor.ControllerDescriptor.GetCustomAttributes(typeof(AdminAttribute), true))
|
||||||
|
@@ -1,24 +1,23 @@
|
|||||||
using System.Globalization;
|
using System.Web.Routing;
|
||||||
using System.IO;
|
|
||||||
using System.Web.Routing;
|
|
||||||
using Orchard.Settings;
|
|
||||||
using Orchard.Themes;
|
using Orchard.Themes;
|
||||||
|
|
||||||
namespace Orchard.UI.Admin {
|
namespace Orchard.UI.Admin {
|
||||||
public class AdminThemeSelector : IThemeSelector {
|
public class AdminThemeSelector : IThemeSelector {
|
||||||
private readonly ISiteService _siteService;
|
public ThemeSelectorResult GetTheme(RequestContext context) {
|
||||||
|
if (IsApplied(context)) {
|
||||||
public AdminThemeSelector(ISiteService siteService) {
|
return new ThemeSelectorResult { Priority = 100, ThemeName = "TheAdmin" };
|
||||||
_siteService = siteService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ThemeSelectorResult GetTheme(RequestContext context) {
|
|
||||||
var siteUrl = _siteService.GetSiteSettings().SiteUrl;
|
|
||||||
//todo: (heskew) get at the admin path in a less hacky way
|
|
||||||
if (!context.HttpContext.Request.Path.StartsWith(Path.Combine(siteUrl, "admin").Replace("\\", "/"), true, CultureInfo.InvariantCulture))
|
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return new ThemeSelectorResult { Priority = 100, ThemeName = "TheAdmin" };
|
public static void Apply(RequestContext context) {
|
||||||
|
// the value isn't important
|
||||||
|
context.HttpContext.Items[typeof(AdminThemeSelector)] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsApplied(RequestContext context) {
|
||||||
|
return context.HttpContext.Items.Contains(typeof(AdminThemeSelector));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user