diff --git a/.gitignore b/.gitignore index bb7b6a923..ba367b249 100644 --- a/.gitignore +++ b/.gitignore @@ -187,5 +187,4 @@ src/Orchard.Azure/Orchard.Azure.CloudService/Staging/ #enable all /lib artifacts !lib/**/*.* -!src/Orchard.Web/Modules/Orchard.Scripting.CSharp/Lib/*.* */.vs/* diff --git a/src/Orchard.Web/Modules/Orchard.Scripting.CSharp/Lib/Mono.CSharp.dll b/lib/mono/Mono.CSharp.dll similarity index 100% rename from src/Orchard.Web/Modules/Orchard.Scripting.CSharp/Lib/Mono.CSharp.dll rename to lib/mono/Mono.CSharp.dll diff --git a/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs b/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs index 495f3eaeb..4437ab0e1 100644 --- a/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs +++ b/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs @@ -90,7 +90,10 @@ namespace Orchard.Core.Contents.Controllers { model.TypeDisplayName = !string.IsNullOrWhiteSpace(contentTypeDefinition.DisplayName) ? contentTypeDefinition.DisplayName : contentTypeDefinition.Name; - query = query.ForType(model.TypeName); + + // We display a specific type even if it's not listable so that admin pages + // can reuse the Content list page for specific types. + query = _contentManager.Query(versionOptions, model.TypeName); } switch (model.Options.OrderBy) { diff --git a/src/Orchard.Web/Core/Navigation/Services/NavigationManager.cs b/src/Orchard.Web/Core/Navigation/Services/NavigationManager.cs index 7692b7b1a..1caafa12e 100644 --- a/src/Orchard.Web/Core/Navigation/Services/NavigationManager.cs +++ b/src/Orchard.Web/Core/Navigation/Services/NavigationManager.cs @@ -93,16 +93,15 @@ namespace Orchard.Core.Navigation.Services { var schemes = new[] { "http", "https", "tel", "mailto" }; if (!string.IsNullOrEmpty(url) && _urlHelper.RequestContext.HttpContext != null && !(url.StartsWith("/") || schemes.Any(scheme => url.StartsWith(scheme + ":")))) { - if (url.StartsWith("~/")) { - - if (!String.IsNullOrEmpty(_shellSettings.RequestUrlPrefix)) { - url = _shellSettings.RequestUrlPrefix + "/" + url.Substring(2); - } - else { - url = url.Substring(2); - } - } if (!url.StartsWith("#")) { + if (url.StartsWith("~/")) { + if (!String.IsNullOrEmpty(_shellSettings.RequestUrlPrefix)) { + url = _shellSettings.RequestUrlPrefix + "/" + url.Substring(2); + } + else { + url = url.Substring(2); + } + } var appPath = _urlHelper.RequestContext.HttpContext.Request.ApplicationPath; if (appPath == "/") appPath = ""; diff --git a/src/Orchard.Web/Modules/Lucene/Services/LuceneIndexProvider.cs b/src/Orchard.Web/Modules/Lucene/Services/LuceneIndexProvider.cs index ae535e0ec..32f858829 100644 --- a/src/Orchard.Web/Modules/Lucene/Services/LuceneIndexProvider.cs +++ b/src/Orchard.Web/Modules/Lucene/Services/LuceneIndexProvider.cs @@ -41,8 +41,6 @@ namespace Lucene.Services { // TODO: (sebros) Find a common way to get where tenant's specific files should go. "Sites/Tenant" is hard coded in multiple places _basePath = _appDataFolder.Combine("Sites", shellSettings.Name, "Indexes"); - Logger = NullLogger.Instance; - // Ensures the directory exists EnsureDirectoryExists(); diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostAdminController.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostAdminController.cs index 18dfee578..bc389815a 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostAdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Controllers/BlogPostAdminController.cs @@ -44,7 +44,7 @@ namespace Orchard.Blogs.Controllers { var blogPost = Services.ContentManager.New("BlogPost"); blogPost.BlogPart = blog; - if (!Services.Authorizer.Authorize(Permissions.EditBlogPost, blog, T("Not allowed to create blog post"))) + if (!Services.Authorizer.Authorize(Permissions.EditBlogPost, blogPost, T("Not allowed to create blog post"))) return new HttpUnauthorizedResult(); var model = Services.ContentManager.BuildEditor(blogPost); @@ -76,7 +76,7 @@ namespace Orchard.Blogs.Controllers { var blogPost = Services.ContentManager.New("BlogPost"); blogPost.BlogPart = blog; - if (!Services.Authorizer.Authorize(Permissions.EditBlogPost, blog, T("Couldn't create blog post"))) + if (!Services.Authorizer.Authorize(Permissions.EditBlogPost, blogPost, T("Couldn't create blog post"))) return new HttpUnauthorizedResult(); Services.ContentManager.Create(blogPost, VersionOptions.Draft); @@ -88,7 +88,7 @@ namespace Orchard.Blogs.Controllers { } if (publish) { - if (!Services.Authorizer.Authorize(Permissions.PublishBlogPost, blog.ContentItem, T("Couldn't publish blog post"))) + if (!Services.Authorizer.Authorize(Permissions.PublishBlogPost, blogPost.ContentItem, T("Couldn't publish blog post"))) return new HttpUnauthorizedResult(); Services.ContentManager.Publish(blogPost.ContentItem); diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Drivers/ContentPermissionsPartDriver.cs b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Drivers/ContentPermissionsPartDriver.cs index abfc1afc1..c10971e25 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Drivers/ContentPermissionsPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Drivers/ContentPermissionsPartDriver.cs @@ -119,6 +119,11 @@ namespace Orchard.ContentPermissions.Drivers { } protected override DriverResult Editor(ContentPermissionsPart part, IUpdateModel updater, dynamic shapeHelper) { + // ensure the current user is allowed to define permissions + if (!_authorizer.Authorize(Permissions.GrantPermission)) { + return null; + } + var model = new ContentPermissionsPartViewModel(); if (!updater.TryUpdateModel(model, Prefix, null, null)) { @@ -223,4 +228,4 @@ namespace Orchard.ContentPermissions.Drivers { } } } -} +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ContentPicker/Drivers/ContentPickerFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.ContentPicker/Drivers/ContentPickerFieldDriver.cs index b548deb0b..ab2c1d60d 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentPicker/Drivers/ContentPickerFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentPicker/Drivers/ContentPickerFieldDriver.cs @@ -90,6 +90,7 @@ namespace Orchard.ContentPicker.Drivers { if (field.Ids.Any()) { var contentItemIds = field.Ids .Select(x => _contentManager.Get(x)) + .Where(x => x != null) .Select(x => _contentManager.GetItemMetadata(x).Identity.ToString()) .ToArray(); diff --git a/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/ObjectDumper.cs b/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/ObjectDumper.cs index da2699e6a..0debbe6db 100644 --- a/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/ObjectDumper.cs +++ b/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/ObjectDumper.cs @@ -141,13 +141,15 @@ namespace Orchard.DesignerTools.Services { } foreach (var member in members) { - if ((o is ContentItem && (member.Name == "ContentManager" - || member.Name == "Parts" - || member.Name == "Record" - || member.Name == "VersionRecord" - || member.Name == "TypeDefinition" - || member.Name == "TypePartDefinition" - || member.Name == "PartDefinition")) + if ((o is ContentItem && ( + member.Name == "Content" || + member.Name == "ContentManager" || + member.Name == "Parts" || + member.Name == "Record" || + member.Name == "VersionRecord" || + member.Name == "TypeDefinition" || + member.Name == "TypePartDefinition" || + member.Name == "PartDefinition")) || o is Delegate || o is Type ) { diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Views/Elements/TextArea.cshtml b/src/Orchard.Web/Modules/Orchard.DynamicForms/Views/Elements/TextArea.cshtml index a83544ce6..af64c27d5 100644 --- a/src/Orchard.Web/Modules/Orchard.DynamicForms/Views/Elements/TextArea.cshtml +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Views/Elements/TextArea.cshtml @@ -22,7 +22,9 @@ tagBuilder.AddCssClass("input-validation-error"); } - tagBuilder.SetInnerText(Model.ProcessedValue); + if (!String.IsNullOrWhiteSpace((string)Model.ProcessedValue)) { + tagBuilder.SetInnerText(Model.ProcessedValue); + } } @if (element.ShowLabel) { diff --git a/src/Orchard.Web/Modules/Orchard.Layouts/Views/EditorTemplates/LayoutEditor.cshtml b/src/Orchard.Web/Modules/Orchard.Layouts/Views/EditorTemplates/LayoutEditor.cshtml index 73c2f9fd1..f4ecbc725 100644 --- a/src/Orchard.Web/Modules/Orchard.Layouts/Views/EditorTemplates/LayoutEditor.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Layouts/Views/EditorTemplates/LayoutEditor.cshtml @@ -86,7 +86,7 @@
  1. - Clipboard, keyboard shortcuts, etc. + @T("Clipboard, keyboard shortcuts, etc.")
  2. @if (Model.Templates.Any()) { var options = Model.Templates.Select(x => new SelectListItem { Text = Html.ItemDisplayText(x).ToString(), Value = x.Id.ToString(CultureInfo.InvariantCulture), Selected = x.Id == Model.TemplateId }); @@ -105,125 +105,125 @@ @Display.DialogTemplate(Name: "Layout") -
    +
    -

    Clipboard

    +

    @T("Clipboard")

    -

    Elements (including containers) can be cut, copied and pasted using the standard clipboard shortcuts (Ctrl+X / Ctrl+C / Ctrl-V on Windows, ⌘+X / ⌘+C / ⌘+V on Mac OS).

    -

    On browsers that support native clipboard events, clipboard operations can be performed across different layout editor instances, in different tabs or browser windows. Text content can also be pasted into other applications.

    -

    On other browsers, clipboard operations work only within the same layout editor instance.

    +

    @T("Elements (including containers) can be cut, copied and pasted using the standard clipboard shortcuts (Ctrl+X / Ctrl+C / Ctrl-V on Windows, ⌘+X / ⌘+C / ⌘+V on Mac OS).")

    +

    @T("On browsers that support native clipboard events, clipboard operations can be performed across different layout editor instances, in different tabs or browser windows. Text content can also be pasted into other applications.")

    +

    @T("On other browsers, clipboard operations work only within the same layout editor instance.")

    -

    Keyboard shortcuts

    +

    @T("Keyboard shortcuts")

    -

    Resizing columns

    +

    @T("Resizing columns")

    - - + + - - + + - - + + - - + +
    Alt+LeftMoves the left edge of the focused column left@T("Alt+Left")@T("Moves the left edge of the focused column left")
    Alt+RightMoves the left edge of the focused column right@T("Alt+Right")@T("Moves the left edge of the focused column right")
    Shift+LeftMoves the right edge of the focused column left@T("Shift+Left")@T("Moves the right edge of the focused column left")
    Shift+RightMoves the right edge of the focused column right@T("Shift+Right")@T("Moves the right edge of the focused column right")
    -

    The Alt and Shift keys can also be combined to move both edges simultaneously.

    +

    @T("The Alt and Shift keys can also be combined to move both edges simultaneously.")

    -

    Focus

    +

    @T("Focus")

    - - + + - - + + - - + + - - + + - - + + - - + +
    UpMoves focus to the previous element (above)@T("Up")@T("Moves focus to the previous element (above)")
    DownMoves focus to the next element (below)@T("Down")@T("Moves focus to the next element (below)")
    LeftMoves focus to the previous column (to the left)@T("Left")@T("Moves focus to the previous column (to the left)")
    RightMoves focus to the next column (to the right)@T("Right")@T("Moves focus to the next column (to the right)")
    Alt+UpMoves focus to the parent element@T("Alt+Up")@T("Moves focus to the parent element")
    Alt+DownMoves focus to the first child element@T("Alt+Down")@T("Moves focus to the first child element")
    -

    Editing

    +

    @T("Editing")

    - - + + - - + + - - + + - - + +
    EnterOpens the content editor of the focused element@T("Enter")@T("Opens the content editor of the focused element")
    SpaceOpens the properties popup of the focused element@T("Space")@T("Opens the properties popup of the focused element")
    EscCloses the properties popup of the focused element@T("Esc")@T("Closes the properties popup of the focused element")
    DelDeletes the focused element@T("Del")@T("Deletes the focused element")
    -

    Moving

    +

    @T("Moving")

    - - + + - - + + - - + + - - + +
    Ctrl+UpMoves (reorders) the focused element up@T("Ctrl+Up")@T("Moves (reorders) the focused element up")
    Ctrl+DownMoves (reorders) the focused element down@T("Ctrl+Down")@T("Moves (reorders) the focused element down")
    Ctrl+LeftMoves (reorders) the focused column left@T("Ctrl+Left")@T("Moves (reorders) the focused column left")
    Ctrl+RightMoves (reorders) the focused column right@T("Ctrl+Right")@T("Moves (reorders) the focused column right")
    -

    Drag and drop

    +

    @T("Drag and drop")

    -

    Drag any existing element to reorder within its parent.

    -

    Drag a new element from the toolbox and drop it within a compatible container.

    -

    Drag the left and right edges of a focused column to resize the column. By default any adjacent column will be attached and resized accordingly; holding down the Alt key while resizing unattaches from the adjacent column and instead modifies the offset between.

    +

    @T("Drag any existing element to reorder within its parent.")

    +

    @T("Drag a new element from the toolbox and drop it within a compatible container.")

    +

    @T("Drag the left and right edges of a focused column to resize the column. By default any adjacent column will be attached and resized accordingly; holding down the Alt key while resizing unattaches from the adjacent column and instead modifies the offset between.")

    diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaLibraryPickerFieldDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaLibraryPickerFieldDriver.cs index ad82199fa..1d7baa065 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaLibraryPickerFieldDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaLibraryPickerFieldDriver.cs @@ -65,7 +65,7 @@ namespace Orchard.MediaLibrary.Drivers { } if (settings.Required && field.Ids.Length == 0) { - updater.AddModelError("Id", T("The field {0} is mandatory", field.Name.CamelFriendly())); + updater.AddModelError("Id", T("The field {0} is mandatory", field.DisplayName)); } return Editor(part, field, shapeHelper); @@ -87,6 +87,7 @@ namespace Orchard.MediaLibrary.Drivers { if (field.Ids.Any()) { var contentItemIds = field.Ids .Select(x => _contentManager.Get(x)) + .Where(x => x != null) .Select(x => _contentManager.GetItemMetadata(x).Identity.ToString()) .ToArray(); @@ -99,4 +100,4 @@ namespace Orchard.MediaLibrary.Drivers { .Member(null, typeof(string), T("Ids"), T("A formatted list of the ids, e.g., {1},{42}")); } } -} \ No newline at end of file +} diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/media-library-picker.js b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/media-library-picker.js index bc680f92a..e29e39343 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/media-library-picker.js +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/media-library-picker.js @@ -21,12 +21,15 @@ var refreshIds = function() { var id = element.find('.selected-ids'); - id.val(''); - element.find(".media-library-picker-item").each(function() { - id.val(id.val() + "," + $(this).attr("data-id")); + var ids = []; + + element.find(".media-library-picker-item").each(function () { + ids.push($(this).attr("data-id")); }); - var itemsCount = element.find(".media-library-picker-item").length; + id.val(ids.join()); + + var itemsCount = ids.length; if(!multiple && itemsCount > 0) { addButton.hide(); diff --git a/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs b/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs index 4fa7da54e..860236eef 100644 --- a/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs +++ b/src/Orchard.Web/Modules/Orchard.OutputCache/Filters/OutputCacheFilter.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Specialized; using System.Globalization; @@ -26,11 +25,10 @@ using Orchard.UI.Admin; using Orchard.Utility.Extensions; namespace Orchard.OutputCache.Filters { - public class OutputCacheFilter : FilterProvider, IActionFilter, IResultFilter { + public class OutputCacheFilter : FilterProvider, IActionFilter, IResultFilter, IDisposable { private static string _refreshKey = "__r"; private static long _epoch = new DateTime(2014, DateTimeKind.Utc).Ticks; - private static readonly ConcurrentDictionary _cacheKeyLocks = new ConcurrentDictionary(); // Dependencies. private readonly ICacheManager _cacheManager; @@ -43,6 +41,8 @@ namespace Orchard.OutputCache.Filters { private readonly ICacheService _cacheService; private readonly ISignals _signals; private readonly ShellSettings _shellSettings; + private bool _isDisposed = false; + public ILogger Logger { get; set; } public OutputCacheFilter( @@ -98,15 +98,11 @@ namespace Orchard.OutputCache.Filters { return; // Computing the cache key after we know that the request is cacheable means that we are only performing this calculation on requests that require it - _cacheKey = ComputeCacheKey(filterContext, GetCacheKeyParameters(filterContext)); + _cacheKey = String.Intern(ComputeCacheKey(filterContext, GetCacheKeyParameters(filterContext))); _invariantCacheKey = ComputeCacheKey(filterContext, null); Logger.Debug("Cache key '{0}' was created.", _cacheKey); - // The cache key lock for a given cache key is used to synchronize requests to - // ensure only a single request is regenerating the item. - var cacheKeyLock = _cacheKeyLocks.GetOrAdd(_cacheKey, x => new object()); - try { // Is there a cached item, and are we allowed to serve it? @@ -120,7 +116,7 @@ namespace Orchard.OutputCache.Filters { if (cacheItem.IsInGracePeriod(_now)) { // Render the content unless another request is already doing so. - if (Monitor.TryEnter(cacheKeyLock)) { + if (Monitor.TryEnter(_cacheKey)) { Logger.Debug("Item '{0}' is in grace period and not currently being rendered; rendering item...", _cacheKey); BeginRenderItem(filterContext); return; @@ -137,7 +133,7 @@ namespace Orchard.OutputCache.Filters { // No cached item found, or client doesn't want it; acquire the cache key // lock to render the item. Logger.Debug("Item '{0}' was not found in cache or client refuses it. Acquiring cache key lock...", _cacheKey); - if (Monitor.TryEnter(cacheKeyLock, TimeSpan.FromSeconds(20))) { + if (Monitor.TryEnter(_cacheKey)) { Logger.Debug("Cache key lock for item '{0}' was acquired.", _cacheKey); // Item might now have been rendered and cached by another request; if so serve it from cache. @@ -145,7 +141,7 @@ namespace Orchard.OutputCache.Filters { cacheItem = GetCacheItem(_cacheKey); if (cacheItem != null) { Logger.Debug("Item '{0}' was now found; releasing cache key lock and serving from cache.", _cacheKey); - Monitor.Exit(cacheKeyLock); + Monitor.Exit(_cacheKey); ServeCachedItem(filterContext, cacheItem); return; } @@ -161,8 +157,7 @@ namespace Orchard.OutputCache.Filters { catch { // Remember to release the cache key lock in the event of an exception! Logger.Debug("Exception occurred for item '{0}'; releasing any acquired lock.", _cacheKey); - if (Monitor.IsEntered(cacheKeyLock)) - Monitor.Exit(cacheKeyLock); + ReleaseCacheKeyLock(); throw; } } @@ -179,11 +174,11 @@ namespace Orchard.OutputCache.Filters { var captureHandlerIsAttached = false; try { - + // This filter is not reentrant (multiple executions within the same request are // not supported) so child actions are ignored completely. if (filterContext.IsChildAction || !_isCachingRequest) - return; + return; Logger.Debug("Item '{0}' was rendered.", _cacheKey); @@ -360,7 +355,7 @@ namespace Orchard.OutputCache.Filters { protected virtual IDictionary GetCacheKeyParameters(ActionExecutingContext filterContext) { var result = new Dictionary(); - + // Vary by action parameters. foreach (var p in filterContext.ActionParameters) result.Add("PARAM:" + p.Key, p.Value); @@ -383,7 +378,7 @@ namespace Orchard.OutputCache.Filters { result["HEADER:" + varyByRequestHeader] = requestHeaders[varyByRequestHeader]; } - + // Vary by request culture if configured. if (CacheSettings.VaryByCulture) { result["culture"] = _workContext.CurrentCulture.ToLowerInvariant(); @@ -474,7 +469,7 @@ namespace Orchard.OutputCache.Filters { var response = filterContext.HttpContext.Response; // Fix for missing charset in response headers - response.Charset = response.Charset; + response.Charset = response.Charset; // Adds some caching information to the output if requested. if (CacheSettings.DebugMode) { @@ -540,12 +535,10 @@ namespace Orchard.OutputCache.Filters { } private void ReleaseCacheKeyLock() { - if (_cacheKey != null) { - object cacheKeyLock; - if (_cacheKeyLocks.TryGetValue(_cacheKey, out cacheKeyLock) && Monitor.IsEntered(cacheKeyLock)) { - Logger.Debug("Releasing cache key lock for item '{0}'.", _cacheKey); - Monitor.Exit(cacheKeyLock); - } + if (_cacheKey != null && Monitor.IsEntered(_cacheKey)) { + Logger.Debug("Releasing cache key lock for item '{0}'.", _cacheKey); + Monitor.Exit(_cacheKey); + _cacheKey = null; } } @@ -599,12 +592,37 @@ namespace Orchard.OutputCache.Filters { var cacheItem = _cacheStorageProvider.GetCacheItem(key); return cacheItem; } - catch(Exception e) { + catch (Exception e) { Logger.Error(e, "An unexpected error occured while reading a cache entry"); } return null; } + + public void Dispose() { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) { + if (!_isDisposed) { + if (disposing) { + // Free other state (managed objects). + } + + if (_cacheKey != null && Monitor.IsEntered(_cacheKey)) { + Monitor.Exit(_cacheKey); + } + + _isDisposed = true; + } + } + + ~OutputCacheFilter() { + // Ensure locks are released even after an unexpected exception + Dispose(false); + } + } public class ViewDataContainer : IViewDataContainer { diff --git a/src/Orchard.Web/Modules/Orchard.Roles/Orchard.Roles.csproj b/src/Orchard.Web/Modules/Orchard.Roles/Orchard.Roles.csproj index 7422fb051..72493aade 100644 --- a/src/Orchard.Web/Modules/Orchard.Roles/Orchard.Roles.csproj +++ b/src/Orchard.Web/Modules/Orchard.Roles/Orchard.Roles.csproj @@ -125,6 +125,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.Roles/RuleEngine/RoleRuleProvider.cs b/src/Orchard.Web/Modules/Orchard.Roles/RuleEngine/RoleRuleProvider.cs new file mode 100644 index 000000000..ce3b6a398 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.Roles/RuleEngine/RoleRuleProvider.cs @@ -0,0 +1,36 @@ +using Orchard.ContentManagement; +using Orchard.Events; +using Orchard.Roles.Models; +using Orchard.Security; +using System; +using System.Linq; + +namespace Orchard.Roles.RuleEngine { + public interface IRuleProvider : IEventHandler { + void Process(dynamic ruleContext); + } + + public class RoleRuleProvider : IRuleProvider { + private readonly IAuthenticationService _authenticationService; + + public RoleRuleProvider(IAuthenticationService authenticationService) { + _authenticationService = authenticationService; + } + + public void Process(dynamic ruleContext) { + if (!String.Equals(ruleContext.FunctionName, "role", StringComparison.OrdinalIgnoreCase)) { + return; + } + + var user = _authenticationService.GetAuthenticatedUser(); + if (user == null) { + ruleContext.Result = false; + return; + } + + var roles = ((object[])ruleContext.Arguments).Cast(); + var userRoles = user.As(); + ruleContext.Result = userRoles != null ? userRoles.Roles.Intersect(roles).Count() > 0 : false; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Scripting.CSharp/Orchard.Scripting.CSharp.csproj b/src/Orchard.Web/Modules/Orchard.Scripting.CSharp/Orchard.Scripting.CSharp.csproj index 79b55f301..0c607d9ae 100644 --- a/src/Orchard.Web/Modules/Orchard.Scripting.CSharp/Orchard.Scripting.CSharp.csproj +++ b/src/Orchard.Web/Modules/Orchard.Scripting.CSharp/Orchard.Scripting.CSharp.csproj @@ -53,8 +53,9 @@ ..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll True - - Lib\Mono.CSharp.dll + + False + ..\..\..\..\lib\mono\Mono.CSharp.dll diff --git a/src/Rebracer.xml b/src/Rebracer.xml index df145c351..d8ab23353 100644 --- a/src/Rebracer.xml +++ b/src/Rebracer.xml @@ -10,8 +10,8 @@ - HACK:2 - TODO:2 + TODO:2 + HACK:2 UNDONE:2 UnresolvedMergeConflict:3