mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-09-22 20:13:50 +08:00
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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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"><%
|
||||
|
@@ -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");
|
||||
}
|
||||
|
@@ -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();
|
||||
|
@@ -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 {
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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();
|
||||
|
@@ -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 });
|
||||
}
|
||||
|
@@ -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"><%
|
||||
|
@@ -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">
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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" />
|
||||
|
12
src/Orchard/OrchardException.cs
Normal file
12
src/Orchard/OrchardException.cs
Normal 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) { }
|
||||
}
|
||||
}
|
@@ -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) {
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
14
src/Orchard/Security/OrchardSecurityException.cs
Normal file
14
src/Orchard/Security/OrchardSecurityException.cs
Normal 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; }
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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,
|
||||
|
@@ -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) {
|
||||
|
Reference in New Issue
Block a user