Updating security processing. Adding a base for an OrchardException hierarchy.

--HG--
extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4045830
This commit is contained in:
loudej
2010-01-22 06:32:54 +00:00
parent c455394cc2
commit 7f09516e8c
20 changed files with 88 additions and 32 deletions

View File

@@ -19,7 +19,10 @@ namespace Orchard.Tests.UI.Navigation {
}
public class StubAuth : IAuthorizationService {
public bool CheckAccess(IUser user, Permission permission) {
public void CheckAccess(IUser user, Permission permission) {
}
public bool TryCheckAccess(IUser user, Permission permission) {
return true;
}
}

View File

@@ -134,7 +134,7 @@ namespace Orchard.Core.Common.Providers {
private void GetEditor(BuildEditorModelContext context, CommonAspect instance) {
var currentUser = _authenticationService.GetAuthenticatedUser();
if (!_authorizationService.CheckAccess(currentUser, Permissions.ChangeOwner)) {
if (!_authorizationService.TryCheckAccess(currentUser, Permissions.ChangeOwner)) {
return;
}
var viewModel = new OwnerEditorViewModel();
@@ -152,7 +152,7 @@ namespace Orchard.Core.Common.Providers {
instance.VersionModifiedUtc = _clock.UtcNow;
var currentUser = _authenticationService.GetAuthenticatedUser();
if (!_authorizationService.CheckAccess(currentUser, Permissions.ChangeOwner)) {
if (!_authorizationService.TryCheckAccess(currentUser, Permissions.ChangeOwner)) {
return;
}

View File

@@ -4,7 +4,6 @@ Html.RegisterStyle("site.css");
Model.Zones.AddRenderPartial("header", "header", Model);
Model.Zones.AddRenderPartial("header:after", "user", Model);
Model.Zones.AddRenderPartial("menu", "menu", Model);
Model.Zones.AddRenderPartial("content:before", "messages", Model.Messages);
%>
<div id="page">
<div id="header"><%

View File

@@ -46,7 +46,7 @@ namespace Orchard.Media.Services {
XRpcStruct file) {
var user = _membershipService.ValidateUser(userName, password);
if (!_authorizationService.CheckAccess(user, Permissions.UploadMediaFiles)) {
if (!_authorizationService.TryCheckAccess(user, Permissions.UploadMediaFiles)) {
//TEMP: return appropriate access-denied response for user
throw new ApplicationException("Access denied");
}

View File

@@ -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.CheckAccess(simulation, permission))
.Where(permission => _authorizationService.TryCheckAccess(simulation, permission))
.Select(permission=>permission.Name)
.Distinct()
.ToList();

View File

@@ -40,7 +40,7 @@ namespace Orchard.Roles.Controllers {
protected override DriverResult Editor(UserRoles userRoles) {
// don't show editor without apply roles permission
if (!_authorizationService.CheckAccess(_authenticationService.GetAuthenticatedUser(), Permissions.ApplyRoles))
if (!_authorizationService.TryCheckAccess(_authenticationService.GetAuthenticatedUser(), Permissions.ApplyRoles))
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.CheckAccess(_authenticationService.GetAuthenticatedUser(), Permissions.ApplyRoles))
if (!_authorizationService.TryCheckAccess(_authenticationService.GetAuthenticatedUser(), Permissions.ApplyRoles))
return null;
var model = new UserRolesViewModel {

View File

@@ -24,7 +24,13 @@ namespace Orchard.Roles.Services {
#region Implementation of IAuthorizationService
public bool CheckAccess(IUser user, Permission permission) {
public void CheckAccess(IUser user, Permission permission) {
if (!TryCheckAccess(user, permission)) {
throw new OrchardSecurityException { PermissionName = permission.Name };
}
}
public bool TryCheckAccess(IUser user, Permission permission) {
if (user == null) {
return false;
}

View File

@@ -28,7 +28,7 @@ namespace Orchard.Tags.Controllers {
}
protected override DriverResult Editor(HasTags part) {
if (!_authorizationService.CheckAccess(CurrentUser, Permissions.ApplyTag))
if (!_authorizationService.TryCheckAccess(CurrentUser, Permissions.ApplyTag))
return null;
var model = new EditTagsViewModel {
@@ -38,7 +38,7 @@ namespace Orchard.Tags.Controllers {
}
protected override DriverResult Editor(HasTags part, IUpdateModel updater) {
if (!_authorizationService.CheckAccess(CurrentUser, Permissions.ApplyTag))
if (!_authorizationService.TryCheckAccess(CurrentUser, Permissions.ApplyTag))
return null;
var model = new EditTagsViewModel();

View File

@@ -66,8 +66,7 @@ namespace Orchard.Tags.Services {
public void CreateTag(string tagName) {
if (_tagRepository.Get(x => x.TagName == tagName) == null) {
if (!_authorizationService.CheckAccess(CurrentUser, Permissions.CreateTag))
throw new UnauthorizedException();
_authorizationService.CheckAccess(CurrentUser, Permissions.CreateTag);
Tag tag = new Tag { TagName = tagName };
_tagRepository.Create(tag);
@@ -130,8 +129,7 @@ namespace Orchard.Tags.Services {
foreach (var tagContentItem in currentTagsForContentItem) {
if (!newTagsForContentItem.Contains(tagContentItem.TagId)) {
if (!_authorizationService.CheckAccess(CurrentUser, Permissions.ApplyTag))
throw new UnauthorizedException();
_authorizationService.CheckAccess(CurrentUser, Permissions.ApplyTag);
_tagsContentItemsRepository.Delete(tagContentItem);
}
@@ -141,8 +139,7 @@ namespace Orchard.Tags.Services {
}
foreach (var newTagForContentItem in newTagsForContentItem) {
if (!_authorizationService.CheckAccess(CurrentUser, Permissions.ApplyTag))
throw new UnauthorizedException();
_authorizationService.CheckAccess(CurrentUser, Permissions.ApplyTag);
_tagsContentItemsRepository.Create(new TagsContentItems { ContentItemId = contentItemId, TagId = newTagForContentItem });
}

View File

@@ -4,7 +4,6 @@ Html.RegisterStyle("site.css");
Model.Zones.AddRenderPartial("header", "header", Model);
Model.Zones.AddRenderPartial("header:after", "user", Model);
Model.Zones.AddRenderPartial("menu", "menu", Model);
Model.Zones.AddRenderPartial("content:before", "messages", Model.Messages);
%>
<div class="page">
<div id="header"><%

View File

@@ -5,7 +5,6 @@ Html.RegisterStyle("site.css");
Model.Zones.AddRenderPartial("header", "header", Model);
Model.Zones.AddRenderPartial("header:after", "user", Model); // todo: (heskew) should be a user display or widget
Model.Zones.AddRenderPartial("menu", "menu", Model);
Model.Zones.AddRenderPartial("content:before", "messages", Model.Messages);
%>
<div id="header" role="banner"><% Html.Zone("header"); %></div>
<div id="content">

View File

@@ -1,6 +1,10 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security;
using System.Threading;
using Orchard.Logging;
using Orchard.Security;
namespace Orchard {
public interface IEvents : IDependency {
@@ -27,12 +31,19 @@ namespace Orchard {
}
}
private static bool IsLogged(Exception exception) {
return true;
private static bool IsLogged(Exception ex) {
return ex is OrchardSecurityException || !IsFatal(ex);
}
private static bool IsFatal(Exception exception) {
return false;
private static bool IsFatal(Exception ex) {
return ex is OrchardSecurityException ||
ex is StackOverflowException ||
ex is AccessViolationException ||
ex is AppDomainUnloadedException ||
ex is ExecutionEngineException ||
ex is ThreadAbortException ||
ex is SecurityException ||
ex is SEHException;
}
}
}

View File

@@ -136,8 +136,9 @@
<Compile Include="Extensions\ExtensionFolders.cs" />
<Compile Include="Extensions\Loaders\AreaExtensionLoader.cs" />
<Compile Include="Extensions\UriExtensions.cs" />
<Compile Include="OrchardException.cs" />
<Compile Include="Security\StandardPermissions.cs" />
<Compile Include="Security\UnauthorizedException.cs" />
<Compile Include="Security\OrchardSecurityException.cs" />
<Compile Include="Tasks\Scheduling\IScheduledTask.cs" />
<Compile Include="ContentManagement\ContentExtensions.cs" />
<Compile Include="ContentManagement\ContentItem.cs" />

View File

@@ -0,0 +1,12 @@
using System;
using System.Runtime.Serialization;
namespace Orchard {
public class OrchardException : ApplicationException {
public OrchardException() : base("An exception occurred in the content management system.") { }
public OrchardException(Exception innerException) : base(innerException.Message, innerException) { }
public OrchardException(string message) : base(message) { }
protected OrchardException(SerializationInfo info, StreamingContext context) : base(info, context) { }
public OrchardException(string message, Exception innerException) : base(message, innerException) { }
}
}

View File

@@ -24,7 +24,7 @@ namespace Orchard.Security {
public Localizer T { get; set; }
public bool Authorize(Permission permission, LocalizedString message) {
if (_authorizationService.CheckAccess(CurrentUser, permission))
if (_authorizationService.TryCheckAccess(CurrentUser, permission))
return true;
if (CurrentUser == null) {

View File

@@ -6,6 +6,7 @@ namespace Orchard.Security {
/// provided by default.
/// </summary>
public interface IAuthorizationService : IDependency {
bool CheckAccess(IUser user, Permission permission);
void CheckAccess(IUser user, Permission permission);
bool TryCheckAccess(IUser user, Permission permission);
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Runtime.Serialization;
namespace Orchard.Security {
public class OrchardSecurityException : OrchardException {
public OrchardSecurityException() : base("A security exception occurred in the content management system.") { }
public OrchardSecurityException(Exception innerException) : base(innerException.Message, innerException) { }
public OrchardSecurityException(string message) : base(message) { }
protected OrchardSecurityException(SerializationInfo info, StreamingContext context) : base(info, context) { }
public OrchardSecurityException(string message, Exception innerException) : base(message, innerException) { }
public string PermissionName { get; set; }
}
}

View File

@@ -2,6 +2,7 @@
using System.Linq;
using System.Web.Mvc;
using JetBrains.Annotations;
using Orchard.Logging;
using Orchard.Mvc.Filters;
using Orchard.Mvc.ViewModels;
@@ -12,8 +13,11 @@ namespace Orchard.Security {
public SecurityFilter(IAuthenticationService authenticationService) {
_authenticationService = authenticationService;
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
public void OnResultExecuting(ResultExecutingContext filterContext) {
var viewResult = filterContext.Result as ViewResultBase;
if (viewResult == null)
@@ -32,10 +36,19 @@ namespace Orchard.Security {
}
public void OnException(ExceptionContext filterContext) {
if (filterContext.Exception is UnauthorizedException) {
filterContext.Result = new HttpUnauthorizedResult();
filterContext.ExceptionHandled = true;
if (!(filterContext.Exception is OrchardSecurityException)) {
return;
}
try {
Logger.Information(filterContext.Exception, "Security exception converted to access denied result");
}
catch {
//a logger exception can't be allowed to interrupt this process
}
filterContext.Result = new HttpUnauthorizedResult();
filterContext.ExceptionHandled = true;
}
}
}

View File

@@ -27,11 +27,11 @@ namespace Orchard.UI.Navigation {
}
private IEnumerable<MenuItem> Reduce(IEnumerable<MenuItem> items) {
var hasDebugShowAllMenuItems = _authorizationService.CheckAccess(CurrentUser, Permission.Named("DebugShowAllMenuItems"));
var hasDebugShowAllMenuItems = _authorizationService.TryCheckAccess(CurrentUser, Permission.Named("DebugShowAllMenuItems"));
foreach (var item in items) {
if (hasDebugShowAllMenuItems ||
!item.Permissions.Any() ||
item.Permissions.Any(x => _authorizationService.CheckAccess(CurrentUser, x))) {
item.Permissions.Any(x => _authorizationService.TryCheckAccess(CurrentUser, x))) {
yield return new MenuItem {
Items = Reduce(item.Items),
Permissions = item.Permissions,

View File

@@ -81,6 +81,7 @@ namespace Orchard.UI.Notify {
}
baseViewModel.Messages = baseViewModel.Messages == null ? messageEntries : baseViewModel.Messages.Union(messageEntries).ToList();
baseViewModel.Zones.AddRenderPartial("content:before", "Messages", baseViewModel.Messages);
}
public void OnResultExecuted(ResultExecutedContext filterContext) {