diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Drivers/ContentPermissionsPartDriver.cs b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Drivers/ContentPermissionsPartDriver.cs new file mode 100644 index 000000000..03c245a5d --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Drivers/ContentPermissionsPartDriver.cs @@ -0,0 +1,174 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Drivers; +using Orchard.Localization; +using Orchard.Roles.Models; +using Orchard.Roles.Services; +using Orchard.Security; +using Orchard.ContentPermissions.Models; +using Orchard.ContentPermissions.Settings; +using Orchard.ContentPermissions.ViewModels; + +namespace Orchard.ContentPermissions.Drivers { + public class ContentPermissionsPartDriver : ContentPartDriver { + + private const string TemplateName = "Parts.ContentPermissions"; + private readonly IRoleService _roleService; + private readonly IAuthorizer _authorizer; + private readonly IAuthorizationService _authorizationService; + + public ContentPermissionsPartDriver(IRoleService roleService, IAuthorizer authorizer, IAuthorizationService authorizationService) { + _roleService = roleService; + _authorizer = authorizer; + _authorizationService = authorizationService; + } + + public IOrchardServices Services { get; set; } + public Localizer T { get; set; } + + protected override string Prefix { + get { return "ContentPermissionsPermissionPart"; } + } + + protected override DriverResult Display(ContentPermissionsPart part, string displayType, dynamic shapeHelper) { + return ContentShape("Parts_ContentPermissions_SummaryAdmin", () => shapeHelper.Parts_ContentPermissions_SummaryAdmin()); + } + + protected override DriverResult Editor(ContentPermissionsPart part, dynamic shapeHelper) { + return ContentShape("Parts_ContentPermissions_Edit", () => { + + var settings = part.Settings.TryGetModel(); + + var allRoles = _roleService.GetRoles().Select(x => x.Name).OrderBy(x => x).ToList(); + + // ensure the current user is allowed to define permissions + if (!_authorizer.Authorize(Permissions.GrantPermission)) { + return null; + } + + if(settings == null) { + settings = new ContentPermissionsPartSettings { + View = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.ViewContent, UserSimulation.Create(x), null) }).ToList()), + ViewOwn = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.ViewOwnContent, UserSimulation.Create(x), null) }).ToList()), + Publish = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.PublishContent, UserSimulation.Create(x), null) }).ToList()), + PublishOwn = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.PublishOwnContent, UserSimulation.Create(x), null) }).ToList()), + Edit = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.EditContent, UserSimulation.Create(x), null) }).ToList()), + EditOwn = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.EditOwnContent, UserSimulation.Create(x), null) }).ToList()), + Delete = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.DeleteContent, UserSimulation.Create(x), null) }).ToList()), + DeleteOwn = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.DeleteOwnContent, UserSimulation.Create(x), null) }).ToList()), + DisplayedRoles = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = true }).ToList()), + }; + } + + ContentPermissionsPartViewModel model; + + // copy defaults settings if new content item + if (!part.Enabled && !part.ContentItem.HasDraft() || !part.ContentItem.HasPublished()) { + model = new ContentPermissionsPartViewModel { + ViewRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.View), + ViewOwnRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.ViewOwn), + PublishRoles= ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.Publish), + PublishOwnRoles= ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.PublishOwn), + EditRoles= ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.Edit), + EditOwnRoles= ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.EditOwn), + DeleteRoles= ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.Delete), + DeleteOwnRoles= ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.DeleteOwn), + AllRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.DisplayedRoles) + }; + } + else { + model = new ContentPermissionsPartViewModel { + ViewRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, part.ViewContent), + ViewOwnRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, part.ViewOwnContent), + PublishRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, part.PublishContent), + PublishOwnRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, part.PublishOwnContent), + EditRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, part.EditContent), + EditOwnRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, part.EditOwnContent), + DeleteRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, part.DeleteContent), + DeleteOwnRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, part.DeleteOwnContent), + AllRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.DisplayedRoles) + }; + } + + // disable permissions the current user doesn't have + model.ViewRoles = model.ViewRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.ViewContent, part.ContentItem), Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.ViewContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.ViewOwnRoles = model.ViewOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.ViewOwnContent, part.ContentItem), Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.ViewOwnContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.PublishRoles = model.PublishRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.PublishContent, part.ContentItem), Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.PublishContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.PublishOwnRoles = model.PublishOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.PublishOwnContent, part.ContentItem), Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.PublishOwnContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.EditRoles = model.EditRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.EditContent, part.ContentItem), Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.EditContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.EditOwnRoles = model.EditOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.EditOwnContent, part.ContentItem), Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.EditOwnContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.DeleteRoles = model.DeleteRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.DeleteContent, part.ContentItem), Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.DeleteContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.DeleteOwnRoles = model.DeleteOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.DeleteOwnContent, part.ContentItem), Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.DeleteOwnContent, UserSimulation.Create(x.Role), null) }).ToList(); + + model.Enabled = part.Enabled; + + return shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: model, Prefix: Prefix); + }); + } + + protected override DriverResult Editor(ContentPermissionsPart part, IUpdateModel updater, dynamic shapeHelper) { + + var allRoles = _roleService.GetRoles().Select(x => x.Name).OrderBy(x => x).ToList(); + + var model = new ContentPermissionsPartViewModel(); + + if (!updater.TryUpdateModel(model, Prefix, null, null)) { + updater.AddModelError(String.Empty, T("Could not update permissions")); + } + else { + part.Enabled = model.Enabled; + part.ViewContent = ContentPermissionsPartViewModel.SerializePermissions(model.ViewRoles); + part.ViewOwnContent = ContentPermissionsPartViewModel.SerializePermissions(model.ViewOwnRoles); + part.PublishContent = ContentPermissionsPartViewModel.SerializePermissions(model.PublishRoles); + part.PublishOwnContent = ContentPermissionsPartViewModel.SerializePermissions(model.PublishOwnRoles); + part.EditContent = ContentPermissionsPartViewModel.SerializePermissions(model.EditRoles); + part.EditOwnContent = ContentPermissionsPartViewModel.SerializePermissions(model.EditOwnRoles); + part.DeleteContent = ContentPermissionsPartViewModel.SerializePermissions(model.DeleteRoles); + part.DeleteOwnContent = ContentPermissionsPartViewModel.SerializePermissions(model.DeleteOwnRoles); + + var settings = part.Settings.TryGetModel(); + + OverrideDefaultPermissions(part, allRoles, settings); + } + + return Editor(part, shapeHelper); + } + + private void OverrideDefaultPermissions(ContentPermissionsPart part, List allRoles, ContentPermissionsPartSettings settings) { + // reset permissions the user can't change + if (!_authorizer.Authorize(Core.Contents.Permissions.ViewContent, part.ContentItem)) { + part.ViewContent = settings == null ? ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry {Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.ViewContent, UserSimulation.Create(x), null)})) : settings.View; + } + + if (!_authorizer.Authorize(Core.Contents.Permissions.ViewOwnContent, part.ContentItem)) { + part.ViewOwnContent = settings == null ? ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry {Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.ViewOwnContent, UserSimulation.Create(x), null)})) : settings.ViewOwn; + } + + if (!_authorizer.Authorize(Core.Contents.Permissions.PublishContent, part.ContentItem)) { + part.PublishContent = settings == null ? ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry {Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.PublishContent, UserSimulation.Create(x), null)})) : settings.Publish; + } + + if (!_authorizer.Authorize(Core.Contents.Permissions.PublishOwnContent, part.ContentItem)) { + part.PublishOwnContent = settings == null ? ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry {Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.ViewContent, UserSimulation.Create(x), null)})) : settings.PublishOwn; + } + + if (!_authorizer.Authorize(Core.Contents.Permissions.EditContent, part.ContentItem)) { + part.EditContent = settings == null ? ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry {Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.EditContent, UserSimulation.Create(x), null)})) : settings.Edit; + } + + if (!_authorizer.Authorize(Core.Contents.Permissions.EditOwnContent, part.ContentItem)) { + part.EditOwnContent = settings == null ? ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry {Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.EditOwnContent, UserSimulation.Create(x), null)})) : settings.EditOwn; + } + + if (!_authorizer.Authorize(Core.Contents.Permissions.DeleteContent, part.ContentItem)) { + part.DeleteContent = settings == null ? ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry {Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.DeleteContent, UserSimulation.Create(x), null)})) : settings.Delete; + } + + if (!_authorizer.Authorize(Core.Contents.Permissions.DeleteOwnContent, part.ContentItem)) { + part.DeleteOwnContent = settings == null ? ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry {Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.DeleteOwnContent, UserSimulation.Create(x), null)})) : settings.DeleteOwn; + } + } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Handlers/ContentPermissionsPartHandler.cs b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Handlers/ContentPermissionsPartHandler.cs new file mode 100644 index 000000000..c4c0b1a8f --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Handlers/ContentPermissionsPartHandler.cs @@ -0,0 +1,12 @@ +using Orchard.ContentManagement.Handlers; +using Orchard.Data; +using Orchard.ContentPermissions.Models; + +namespace Orchard.ContentPermissions.Handlers { + public class ContentPermissionsPartHandler : ContentHandler { + + public ContentPermissionsPartHandler(IRepository repository) { + Filters.Add(StorageFilter.For(repository)); + } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Migrations.cs b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Migrations.cs new file mode 100644 index 000000000..1a6bf1e14 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Migrations.cs @@ -0,0 +1,26 @@ +using Orchard.Core.Contents.Extensions; +using Orchard.Data.Migration; +using Orchard.ContentManagement.MetaData; + +namespace Orchard.ContentPermissions { + public class Migrations : DataMigrationImpl { + public int Create() { + SchemaBuilder.CreateTable("ContentPermissionsPartRecord", table => table + .ContentPartRecord() + .Column("Enabled") + .Column("ViewContent", c => c.Unlimited()) + .Column("ViewOwnContent", c => c.Unlimited()) + .Column("PublishContent", c => c.Unlimited()) + .Column("PublishOwnContent", c => c.Unlimited()) + .Column("EditContent", c => c.Unlimited()) + .Column("EditOwnContent", c => c.Unlimited()) + .Column("DeleteContent", c => c.Unlimited()) + .Column("DeleteOwnContent", c => c.Unlimited()) + ); + + ContentDefinitionManager.AlterPartDefinition("ContentPermissionsPart", p => p.Attachable()); + + return 1; + } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Models/ContentPermissionsPart.cs b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Models/ContentPermissionsPart.cs new file mode 100644 index 000000000..e60d7f49b --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Models/ContentPermissionsPart.cs @@ -0,0 +1,53 @@ +using Orchard.ContentManagement; + +namespace Orchard.ContentPermissions.Models { + public class ContentPermissionsPart : ContentPart { + /// + /// Whether the access control should be applied for the content item + /// + public bool Enabled { + get { return Record.Enabled; } + set { Record.Enabled = value; } + } + + public string ViewContent { + get { return Record.ViewContent; } + set { Record.ViewContent = value; } + } + + public string ViewOwnContent { + get { return Record.ViewOwnContent; } + set { Record.ViewOwnContent = value; } + } + + public string PublishContent { + get { return Record.PublishContent; } + set { Record.PublishContent = value; } + } + + public string PublishOwnContent { + get { return Record.PublishOwnContent; } + set { Record.PublishOwnContent = value; } + } + + public string EditContent { + get { return Record.EditContent; } + set { Record.EditContent = value; } + } + + public string EditOwnContent { + get { return Record.EditOwnContent; } + set { Record.EditOwnContent = value; } + } + + public string DeleteContent { + get { return Record.DeleteContent; } + set { Record.DeleteContent = value; } + } + + public string DeleteOwnContent { + get { return Record.DeleteOwnContent; } + set { Record.DeleteOwnContent = value; } + } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Models/ContentPermissionsPartRecord.cs b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Models/ContentPermissionsPartRecord.cs new file mode 100644 index 000000000..05327d9cd --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Models/ContentPermissionsPartRecord.cs @@ -0,0 +1,30 @@ +using Orchard.ContentManagement.Records; +using Orchard.Data.Conventions; + +namespace Orchard.ContentPermissions.Models { + public class ContentPermissionsPartRecord : ContentPartRecord { + + /// + /// Whether the access control should be applied for the content item + /// + public virtual bool Enabled { get; set; } + + [StringLengthMax] + public virtual string ViewContent { get; set; } + [StringLengthMax] + public virtual string ViewOwnContent { get; set; } + [StringLengthMax] + public virtual string PublishContent { get; set; } + [StringLengthMax] + public virtual string PublishOwnContent { get; set; } + [StringLengthMax] + public virtual string EditContent { get; set; } + [StringLengthMax] + public virtual string EditOwnContent { get; set; } + [StringLengthMax] + public virtual string DeleteContent { get; set; } + [StringLengthMax] + public virtual string DeleteOwnContent { get; set; } + + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Module.txt b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Module.txt new file mode 100644 index 000000000..81801b4df --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Module.txt @@ -0,0 +1,13 @@ +Name: Orchard.ContentPermissions +AntiForgery: enabled +Author: Chris Pyle, Sébastien Ros +Website: http://orchardproject.net +Version: 1.5 +OrchardVersion: 1.5 +Description: Allows item-level front end view permissions. +Features: + Orchard.ContentPermissions: + Name: Content Item Permissions + Description: Allows item-level front end view permissions. + Dependencies: Orchard.Roles + Category: Security \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Orchard.ContentPermissions.csproj b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Orchard.ContentPermissions.csproj new file mode 100644 index 000000000..8e9e770de --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Orchard.ContentPermissions.csproj @@ -0,0 +1,161 @@ + + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {E826F796-8CE3-4B5B-8423-5AA5F81D2FC3} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Orchard.ContentPermissions + Orchard.ContentPermissions + v4.0 + false + + + 4.0 + + + + false + + + + + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\ + TRACE + prompt + 4 + AllRules.ruleset + + + + + + + 3.5 + + + + False + ..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll + + + + + + + + + + + + + + + + + + + {2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6} + Orchard.Framework + + + {9916839C-39FC-4CEB-A5AF-89CA7E87119F} + Orchard.Core + + + {D10AD48F-407D-4DB5-A328-173EC7CB010F} + Orchard.Roles + + + + + + + + + + + + + + + + + + + Designer + + + + + + + + + + + + + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + + + + $(ProjectDir)\..\Manifests + + + + + + + + + + + + False + True + 19694 + / + + + False + True + http://orchard.codeplex.com + False + + + + + \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Permissions.cs b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Permissions.cs new file mode 100644 index 000000000..ee3fdf29e --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Permissions.cs @@ -0,0 +1,52 @@ +using System.Collections.Generic; +using Orchard.Environment.Extensions.Models; +using Orchard.Security.Permissions; + +namespace Orchard.ContentPermissions { + public class Permissions : IPermissionProvider { + + // Note - in code you should demand GrantPermission + // Do not demand the "Own" variation - it is applied automatically when you demand the main one + + public static readonly Permission GrantPermission = new Permission { Description = "Grant permissions for others", Name = "GrantPermission" }; + public static readonly Permission GrantOwnPermission = new Permission { Description = "Grant permission for own content", Name = "GrantOwnPermission", ImpliedBy = new[] { GrantPermission } }; + + public virtual Feature Feature { get; set; } + + public IEnumerable GetPermissions() { + return new[] { + GrantPermission, + GrantOwnPermission + }; + } + + public IEnumerable GetDefaultStereotypes() { + return new[] { + new PermissionStereotype { + Name = "Administrator", + Permissions = new[] {GrantPermission} + }, + new PermissionStereotype { + Name = "Editor", + }, + new PermissionStereotype { + Name = "Moderator", + }, + new PermissionStereotype { + Name = "Author", + Permissions = new[] {GrantOwnPermission} + }, + new PermissionStereotype { + Name = "Contributor", + }, + new PermissionStereotype { + Name = "Authenticated", + }, + new PermissionStereotype { + Name = "Anonymous", + } + }; + } + + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Placement.info b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Placement.info new file mode 100644 index 000000000..c4729e0b9 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Placement.info @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Properties/AssemblyInfo.cs b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..5ec0b63f1 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Orchard.ContentPermissions")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyProduct("Orchard")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("9bb4d514-2100-4da9-b53c-20cd5d7fa6a7")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.5")] +[assembly: AssemblyFileVersion("1.5")] diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Security/AuthorizationEventHandler.cs b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Security/AuthorizationEventHandler.cs new file mode 100644 index 000000000..24f6fab4d --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Security/AuthorizationEventHandler.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Aspects; +using Orchard.Core.Common.Models; +using Orchard.Roles.Models; +using Orchard.Security; +using Orchard.ContentPermissions.Models; + +namespace Orchard.ContentPermissions.Security { + public class AuthorizationEventHandler : IAuthorizationServiceEventHandler { + private readonly IWorkContextAccessor _workContextAccessor; + private static readonly string[] AnonymousRole = new[] { "Anonymous" }; + private static readonly string[] AuthenticatedRole = new[] { "Authenticated" }; + + public AuthorizationEventHandler(IWorkContextAccessor workContextAccessor) { + _workContextAccessor = workContextAccessor; + } + + public void Checking(CheckAccessContext context) { } + public void Adjust(CheckAccessContext context) { } + + public void Complete(CheckAccessContext context) { + + if (!String.IsNullOrEmpty(_workContextAccessor.GetContext().CurrentSite.SuperUser) + && context.User != null + && String.Equals(context.User.UserName, _workContextAccessor.GetContext().CurrentSite.SuperUser, StringComparison.Ordinal)) { + context.Granted = true; + return; + } + + if (context.Content == null) { + return; + } + + var part = context.Content.As(); + + // if the content item has no right attached, check on the container + if (part == null || !part.Enabled) { + var commonPart = part.As(); + if(commonPart != null && commonPart.Container != null) { + part = commonPart.As(); + } + } + + if (part == null || !part.Enabled) { + return; + } + + var hasOwnership = HasOwnership(context.User, context.Content); + + IEnumerable authorizedRoles; + + if (context.Permission == Core.Contents.Permissions.ViewContent) { + authorizedRoles = (hasOwnership ? part.ViewOwnContent : part.ViewContent).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + } + else if (context.Permission == Core.Contents.Permissions.PublishContent) { + authorizedRoles = (hasOwnership ? part.PublishOwnContent : part.PublishContent).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + } + else if (context.Permission == Core.Contents.Permissions.EditContent) { + authorizedRoles = (hasOwnership ? part.EditOwnContent : part.EditContent).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + } + else if (context.Permission == Core.Contents.Permissions.DeleteContent) { + authorizedRoles = (hasOwnership ? part.DeleteOwnContent : part.DeleteContent).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + } + else { + return; + } + + // determine what set of roles should be examined by the access check + IEnumerable rolesToExamine; + if (context.User == null) { + rolesToExamine = AnonymousRole; + } + else if (context.User.Has()) { + // the current user is not null, so get his roles and add "Authenticated" to it + rolesToExamine = context.User.As().Roles; + + // when it is a simulated anonymous user in the admin + if (!rolesToExamine.Contains(AnonymousRole[0])) { + rolesToExamine = rolesToExamine.Concat(AuthenticatedRole); + } + } + else { + // the user is not null and has no specific role, then it's just "Authenticated" + rolesToExamine = AuthenticatedRole; + } + + context.Granted = rolesToExamine.Any(x => authorizedRoles.Contains(x, StringComparer.OrdinalIgnoreCase)); + context.Adjusted = true; + } + + private static bool HasOwnership(IUser user, IContent content) { + if (user == null || content == null) + return false; + + var common = content.As(); + if (common == null || common.Owner == null) + return false; + + return user.Id == common.Owner.Id; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Settings/ContentPermissionsPartSettings.cs b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Settings/ContentPermissionsPartSettings.cs new file mode 100644 index 000000000..9ea51ffeb --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Settings/ContentPermissionsPartSettings.cs @@ -0,0 +1,177 @@ +using System.Collections.Generic; +using System.Linq; +using Orchard.ContentManagement; +using Orchard.ContentManagement.MetaData; +using Orchard.ContentManagement.MetaData.Builders; +using Orchard.ContentManagement.MetaData.Models; +using Orchard.ContentManagement.ViewModels; +using Orchard.Roles.Models; +using Orchard.Roles.Services; +using Orchard.Security; +using Orchard.ContentPermissions.ViewModels; + +namespace Orchard.ContentPermissions.Settings { + public class ContentPermissionsPartSettings { + public string View { get; set; } + public string ViewOwn { get; set; } + public string Publish { get; set; } + public string PublishOwn { get; set; } + public string Edit { get; set; } + public string EditOwn { get; set; } + public string Delete { get; set; } + public string DeleteOwn { get; set; } + + public string DisplayedRoles { get; set; } + } + + public class ViewPermissionsSettingsHooks : ContentDefinitionEditorEventsBase { + private readonly IAuthorizer _authorizer; + private readonly IAuthorizationService _authorizationService; + private readonly IRoleService _roleService; + + public ViewPermissionsSettingsHooks( + IAuthorizer authorizer, + IAuthorizationService authorizationService, + IRoleService roleService + ) { + _authorizer = authorizer; + _authorizationService = authorizationService; + _roleService = roleService; + } + + public override IEnumerable TypePartEditor(ContentTypePartDefinition definition) { + if (definition.PartDefinition.Name != "ContentPermissionsPart") + yield break; + + // ensure the current user is allowed to define permissions + if(!_authorizer.Authorize(Permissions.GrantPermission)) { + yield break; + } + + var settings = definition.Settings.TryGetModel(); + + var allRoles = _roleService.GetRoles().Select(x => x.Name).OrderBy(x => x).ToList(); + + // copy defaults if new type + if(settings == null) { + settings = new ContentPermissionsPartSettings { + View = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.ViewContent, UserSimulation.Create(x), null) })), + ViewOwn = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.ViewOwnContent, UserSimulation.Create(x), null) })), + Publish = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.PublishContent, UserSimulation.Create(x), null) })), + PublishOwn = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.PublishOwnContent, UserSimulation.Create(x), null) })), + Edit = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.EditContent, UserSimulation.Create(x), null) })), + EditOwn = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.EditOwnContent, UserSimulation.Create(x), null) })), + Delete = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.DeleteContent, UserSimulation.Create(x), null) })), + DeleteOwn = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = _authorizationService.TryCheckAccess(Core.Contents.Permissions.DeleteOwnContent, UserSimulation.Create(x), null) })), + DisplayedRoles = ContentPermissionsPartViewModel.SerializePermissions(allRoles.Select(x => new RoleEntry { Role = x, Checked = true })), + }; + } + + var model = new ContentPermissionsPartViewModel { + ViewRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.View), + ViewOwnRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.ViewOwn), + PublishRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.Publish), + PublishOwnRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.PublishOwn), + EditRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.Edit), + EditOwnRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.EditOwn), + DeleteRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.Delete), + DeleteOwnRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.DeleteOwn), + AllRoles = ContentPermissionsPartViewModel.ExtractRoleEntries(allRoles, settings.DisplayedRoles) + }; + + // disable permissions the current user doesn't have + model.ViewRoles = model.ViewRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.ViewContent) }).ToList(); + model.ViewOwnRoles = model.ViewOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.ViewOwnContent) }).ToList(); + model.PublishRoles = model.PublishRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.PublishContent) }).ToList(); + model.PublishOwnRoles = model.PublishOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.PublishOwnContent) }).ToList(); + model.EditRoles = model.EditRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.EditContent) }).ToList(); + model.EditOwnRoles = model.EditOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.EditOwnContent) }).ToList(); + model.DeleteRoles = model.DeleteRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.DeleteContent) }).ToList(); + model.DeleteOwnRoles = model.DeleteOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.DeleteOwnContent) }).ToList(); + + // initialize default value + model.ViewRoles = model.ViewRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = x.Enabled, Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.ViewContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.ViewOwnRoles = model.ViewOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = x.Enabled, Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.ViewOwnContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.PublishRoles = model.PublishRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = x.Enabled, Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.PublishContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.PublishOwnRoles = model.PublishOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = x.Enabled, Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.PublishOwnContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.EditRoles = model.EditRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = x.Enabled, Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.EditContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.EditOwnRoles = model.EditOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = x.Enabled, Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.EditOwnContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.DeleteRoles = model.DeleteRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = x.Enabled, Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.DeleteContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.DeleteOwnRoles = model.DeleteOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = x.Enabled, Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.DeleteOwnContent, UserSimulation.Create(x.Role), null) }).ToList(); + + yield return DefinitionTemplate(model); + } + + public override IEnumerable TypePartEditorUpdate(ContentTypePartDefinitionBuilder builder, IUpdateModel updateModel) { + if (builder.Name != "ContentPermissionsPart") + yield break; + + if (!_authorizer.Authorize(Permissions.GrantPermission)) { + yield break; + } + + var allRoles = _roleService.GetRoles().Select(x => x.Name).OrderBy(x => x).ToList(); + + var model = new ContentPermissionsPartViewModel(); + + updateModel.TryUpdateModel(model, "ContentPermissionsPartViewModel", null, null); + + // update permissions only for those the current user is granted + if ( _authorizer.Authorize(Core.Contents.Permissions.ViewContent)) { + builder.WithSetting("ContentPermissionsPartSettings.View", ContentPermissionsPartViewModel.SerializePermissions(model.ViewRoles)); + } + + if (_authorizer.Authorize(Core.Contents.Permissions.ViewOwnContent)) { + builder.WithSetting("ContentPermissionsPartSettings.ViewOwn", ContentPermissionsPartViewModel.SerializePermissions(model.ViewOwnRoles)); + } + + if (_authorizer.Authorize(Core.Contents.Permissions.PublishContent)) { + builder.WithSetting("ContentPermissionsPartSettings.Publish", ContentPermissionsPartViewModel.SerializePermissions(model.PublishRoles)); + } + + if (_authorizer.Authorize(Core.Contents.Permissions.PublishOwnContent)) { + builder.WithSetting("ContentPermissionsPartSettings.PublishOwn", ContentPermissionsPartViewModel.SerializePermissions(model.PublishOwnRoles)); + } + + if (_authorizer.Authorize(Core.Contents.Permissions.EditContent)) { + builder.WithSetting("ContentPermissionsPartSettings.Edit", ContentPermissionsPartViewModel.SerializePermissions(model.EditRoles)); + } + + if (_authorizer.Authorize(Core.Contents.Permissions.EditOwnContent)) { + builder.WithSetting("ContentPermissionsPartSettings.EditOwn", ContentPermissionsPartViewModel.SerializePermissions(model.EditOwnRoles)); + } + + if (_authorizer.Authorize(Core.Contents.Permissions.DeleteContent)) { + builder.WithSetting("ContentPermissionsPartSettings.Delete", ContentPermissionsPartViewModel.SerializePermissions(model.DeleteRoles)); + } + + if (_authorizer.Authorize(Core.Contents.Permissions.DeleteOwnContent)) { + builder.WithSetting("ContentPermissionsPartSettings.DeleteOwn", ContentPermissionsPartViewModel.SerializePermissions(model.DeleteOwnRoles)); + } + + builder.WithSetting("ContentPermissionsPartSettings.DisplayedRoles", ContentPermissionsPartViewModel.SerializePermissions(model.AllRoles)); + + // disable permissions the current user doesn't have + model.ViewRoles = model.ViewRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.ViewContent) }).ToList(); + model.ViewOwnRoles = model.ViewOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.ViewOwnContent) }).ToList(); + model.PublishRoles = model.PublishRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.PublishContent) }).ToList(); + model.PublishOwnRoles = model.PublishOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.PublishOwnContent) }).ToList(); + model.EditRoles = model.EditRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.EditContent) }).ToList(); + model.EditOwnRoles = model.EditOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.EditOwnContent) }).ToList(); + model.DeleteRoles = model.DeleteRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.DeleteContent) }).ToList(); + model.DeleteOwnRoles = model.DeleteOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = _authorizer.Authorize(Core.Contents.Permissions.DeleteOwnContent) }).ToList(); + + // initialize default value + model.ViewRoles = model.ViewRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = x.Enabled, Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.ViewContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.ViewOwnRoles = model.ViewOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = x.Enabled, Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.ViewOwnContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.PublishRoles = model.PublishRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = x.Enabled, Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.PublishContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.PublishOwnRoles = model.PublishOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = x.Enabled, Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.PublishOwnContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.EditRoles = model.EditRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = x.Enabled, Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.EditContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.EditOwnRoles = model.EditOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = x.Enabled, Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.EditOwnContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.DeleteRoles = model.DeleteRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = x.Enabled, Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.DeleteContent, UserSimulation.Create(x.Role), null) }).ToList(); + model.DeleteOwnRoles = model.DeleteOwnRoles.Select(x => new RoleEntry { Role = x.Role, Checked = x.Checked, Enabled = x.Enabled, Default = _authorizationService.TryCheckAccess(Core.Contents.Permissions.DeleteOwnContent, UserSimulation.Create(x.Role), null) }).ToList(); + + yield return DefinitionTemplate(model); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Styles/Images/lock.gif b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Styles/Images/lock.gif new file mode 100644 index 000000000..f09f14391 Binary files /dev/null and b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Styles/Images/lock.gif differ diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Styles/Web.config b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Styles/Web.config new file mode 100644 index 000000000..56fa41e3e --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Styles/Web.config @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Styles/orchard-contentpermissions-admin.css b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Styles/orchard-contentpermissions-admin.css new file mode 100644 index 000000000..4c979453a --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Styles/orchard-contentpermissions-admin.css @@ -0,0 +1,18 @@ +.permission +{ + clear:both; +} + +.content-permissions th, .content-permissions td { + width: 150px; +} + +.content-permissions th, .content-permissions td { + text-align: center; +} + +.content-permissions .role { + text-align: right; + padding-right: 2em; + width: inherit; +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/ViewModels/ContentPermissionsPartViewModel.cs b/src/Orchard.Web/Modules/Orchard.ContentPermissions/ViewModels/ContentPermissionsPartViewModel.cs new file mode 100644 index 000000000..8fde81da0 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/ViewModels/ContentPermissionsPartViewModel.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Orchard.ContentPermissions.ViewModels { + public class ContentPermissionsPartViewModel { + public bool Enabled { get; set; } + + // list of available roles + public IList AllRoles { get; set; } + + public IList ViewRoles { get; set; } + public IList ViewOwnRoles { get; set; } + public IList PublishRoles { get; set; } + public IList PublishOwnRoles { get; set; } + public IList EditRoles { get; set; } + public IList EditOwnRoles { get; set; } + public IList DeleteRoles { get; set; } + public IList DeleteOwnRoles { get; set; } + + public static IList ExtractRoleEntries(IEnumerable allRoles, string allowed) { + if(String.IsNullOrWhiteSpace(allowed)) { + allowed = String.Empty; + } + + var allowedRoles = allowed.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + return allRoles.OrderBy(x => x).Select(x => new RoleEntry { Role = x, Checked = allowedRoles.Contains(x, StringComparer.OrdinalIgnoreCase) }).ToList(); + } + + public static string SerializePermissions(IEnumerable roleEntries) { + return String.Join(",", roleEntries.Where(x => x.Checked).Select(x => x.Role).ToArray()); + } + } + + public class RoleEntry { + public string Role { get; set; } + public bool Default { get; set; } + public bool Checked { get; set; } + public bool Enabled { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Views/DefinitionTemplates/ContentPermissionsPartViewModel.cshtml b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Views/DefinitionTemplates/ContentPermissionsPartViewModel.cshtml new file mode 100644 index 000000000..889859042 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Views/DefinitionTemplates/ContentPermissionsPartViewModel.cshtml @@ -0,0 +1,118 @@ +@model Orchard.ContentPermissions.ViewModels.ContentPermissionsPartViewModel + +@{ + Style.Include("orchard-contentpermissions-admin.css"); +} + +@T("Those permissions will be applied by default to any content item of this type. Users with sufficient permissions can change them for each content item.") + +
+
+ + + + + + + + + + @foreach (var r in Model.AllRoles.Select((x, i) => new { Index = i, Name = x.Role })) { + var role = r; + + + + + + + + } +

@T("Role")

@T("View any content")

@T("Edit any content")

@T("Publish any content")

@T("Delete any content")

@role.Name + + @Html.HiddenFor(m => m.ViewRoles[role.Index].Role) + + + @Html.HiddenFor(m => m.PublishRoles[role.Index].Role) + + + @Html.HiddenFor(m => m.EditRoles[role.Index].Role) + + + @Html.HiddenFor(m => m.DeleteRoles[role.Index].Role) +
+ + + + + + + + + + @foreach (var r in Model.AllRoles.Select((x, i) => new { Index = i, Name = x.Role })) { + var role = r; + + + + + + + @Html.HiddenFor(m => m.DeleteOwnRoles[role.Index].Role) + + } +

@T("Role")

@T("View own content")

@T("Edit own content")

@T("Publish own content")

@T("Delete own content")

@role.Name + + @Html.HiddenFor(m => m.ViewOwnRoles[role.Index].Role) + + + @Html.HiddenFor(m => m.PublishOwnRoles[role.Index].Role) + + + @Html.HiddenFor(m => m.EditOwnRoles[role.Index].Role) + +
+
+
+ +

@T("Only show those roles in the editor:")

+ @T("Uncheck the roles for which you don't want the editor to change the permissions for.") +
+
    + + @foreach (var r in Model.AllRoles.Select((x, i) => new { Index = i, Entry = x })) { + var role = r; +
  • + + @Html.HiddenFor(m => m.AllRoles[role.Index].Role) +
  • + } +
+
+
+
diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Views/EditorTemplates/Parts.ContentPermissions.cshtml b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Views/EditorTemplates/Parts.ContentPermissions.cshtml new file mode 100644 index 000000000..d44464d1e --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Views/EditorTemplates/Parts.ContentPermissions.cshtml @@ -0,0 +1,106 @@ +@model Orchard.ContentPermissions.ViewModels.ContentPermissionsPartViewModel + +@{ + Style.Include("orchard-contentpermissions-admin.css"); +} + +
+ @Html.EditorFor(m => m.Enabled) + + @T("Check to define custom permissions for this content item.") +
+ +
+ +
+
+ + + + + + + + + + @foreach (var r in Model.AllRoles.Where(x => x.Checked).Select((x, i) => new { Index = i, Name = x.Role })) { + var role = r; + + + + + + + + } +

@T("Role")

@T("View this item")

@T("Edit this item")

@T("Publish this item")

@T("Delete this item")

@role.Name + + @Html.HiddenFor(m => m.ViewRoles[role.Index].Role) + + + @Html.HiddenFor(m => m.PublishRoles[role.Index].Role) + + + @Html.HiddenFor(m => m.EditRoles[role.Index].Role) + + + @Html.HiddenFor(m => m.DeleteRoles[role.Index].Role) +
+ + + + + + + + + + @foreach (var r in Model.AllRoles.Where(x => x.Checked).Select((x, i) => new { Index = i, Name = x.Role })) { + var role = r; + + + + + + + @Html.HiddenFor(m => m.DeleteOwnRoles[role.Index].Role) + + } +

@T("Role")

@T("View own")

@T("Edit own")

@T("Publish own")

@T("Delete own")

@role.Name + + @Html.HiddenFor(m => m.ViewOwnRoles[role.Index].Role) + + + @Html.HiddenFor(m => m.PublishOwnRoles[role.Index].Role) + + + @Html.HiddenFor(m => m.EditOwnRoles[role.Index].Role) + +
+
+
+
diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Views/Parts.ContentPermissions.SummaryAdmin.cshtml b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Views/Parts.ContentPermissions.SummaryAdmin.cshtml new file mode 100644 index 000000000..d46daa309 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Views/Parts.ContentPermissions.SummaryAdmin.cshtml @@ -0,0 +1,14 @@ +@using Orchard.ContentPermissions.Models; + +@{ + Style.Include("orchard-contentpermissions-admin.css"); + ContentPermissionsPart contentPart = Model.ContentPart; +} + +@if (contentPart.Enabled) { + +
+ @T( + @T("Protected") +
+} diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Views/Web.config b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Views/Web.config new file mode 100644 index 000000000..b7d215131 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Views/Web.config @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Orchard.Web/Modules/Orchard.ContentPermissions/Web.config b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Web.config new file mode 100644 index 000000000..88b84a792 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.ContentPermissions/Web.config @@ -0,0 +1,41 @@ + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +