diff --git a/src/Orchard.Specs/Bindings/ContentRights.cs b/src/Orchard.Specs/Bindings/ContentRights.cs new file mode 100644 index 000000000..d796d2b09 --- /dev/null +++ b/src/Orchard.Specs/Bindings/ContentRights.cs @@ -0,0 +1,108 @@ +using System; +using NUnit.Framework; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Aspects; +using Orchard.Core.Contents; +using Orchard.Data; +using Orchard.Roles.Models; +using Orchard.Roles.Services; +using Orchard.Security; +using Orchard.Security.Permissions; +using Orchard.Specs.Hosting.Orchard.Web; +using TechTalk.SpecFlow; + +namespace Orchard.Specs.Bindings { + [Binding] + public class ContentRights : BindingBase { + + [When(@"I have a role ""(.*)\"" with permissions ""(.*)\""")] + public void WhenIHaveARoleWithPermissions(string roleName, string permissions) { + var webApp = Binding(); + webApp.Host.Execute(() => { + using ( var environment = MvcApplication.CreateStandaloneEnvironment("Default") ) { + var roleService = environment.Resolve(); + + roleService.CreateRole(roleName); + + foreach ( var permissionName in permissions.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries) ) { + roleService.CreatePermissionForRole(roleName, permissionName); + } + } + }); + } + + [When(@"I have a user ""(.*)\"" with roles ""(.*)\""")] + public void GivenIHaveCreatedAUser(string username, string roles) { + + var webApp = Binding(); + webApp.Host.Execute(() => { + using ( var environment = MvcApplication.CreateStandaloneEnvironment("Default") ) { + var memberShipService = environment.Resolve(); + var roleService = environment.Resolve(); + var userRoleRepository = environment.Resolve>(); + var user = memberShipService.CreateUser(new CreateUserParams(username, "qwerty123!", username + "@foo.com", "", "", true)); + + foreach ( var roleName in roles.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries) ) { + var role = roleService.GetRoleByName(roleName); + userRoleRepository.Create(new UserRolesPartRecord { UserId = user.Id, Role = role }); + } + } + }); + } + + [Then(@"""(.*)\"" should be able to ""(.*)\"" a ""(.*)\"" owned by ""(.*)\""")] + public void UserShouldBeAbleToForOthers(string username, string action, string contentType, string otherName) { + + var webApp = Binding(); + webApp.Host.Execute(() => { + using ( var environment = MvcApplication.CreateStandaloneEnvironment("Default") ) { + var memberShipService = environment.Resolve(); + var athorizationService = environment.Resolve(); + var contentManager = environment.Resolve(); + + var contentItem = contentManager.Create(contentType); + var user = memberShipService.GetUser(username); + var otherUser = memberShipService.GetUser(otherName); + contentItem.As().Owner = otherUser; + + Assert.That(athorizationService.TryCheckAccess(GetPermissionForAction(action), user, contentItem), Is.True); + } + }); + } + + [Then(@"""(.*)\"" should not be able to ""(.*)\"" a ""(.*)\"" owned by ""(.*)\""")] + public void UserShouldNotBeAbleToForOthers(string username, string action, string contentType, string otherName) { + + var webApp = Binding(); + webApp.Host.Execute(() => { + using ( var environment = MvcApplication.CreateStandaloneEnvironment("Default") ) { + var memberShipService = environment.Resolve(); + var athorizationService = environment.Resolve(); + var contentManager = environment.Resolve(); + + var contentItem = contentManager.Create(contentType); + var user = memberShipService.GetUser(username); + var otherUser = memberShipService.GetUser(otherName); + contentItem.As().Owner = otherUser; + + Assert.That(athorizationService.TryCheckAccess(GetPermissionForAction(action), user, contentItem), Is.False); + } + }); + } + + // returns permissions as they are used in controllers for each action + private static Permission GetPermissionForAction(string action) { + switch ( action ) { + case "publish": + return Permissions.PublishContent; + case "edit": + return Permissions.EditContent; + case "delete": + return Permissions.DeleteContent; + default: + return null; + } + } + + } +} diff --git a/src/Orchard.Specs/ContentRights.feature b/src/Orchard.Specs/ContentRights.feature new file mode 100644 index 000000000..b7fb70aab --- /dev/null +++ b/src/Orchard.Specs/ContentRights.feature @@ -0,0 +1,97 @@ +Feature: Content rights management + In order to ensure security + As a root Orchard system operator + I want only the allowed users to edit the content + +Scenario: Administrators can manage a Page + Given I have installed Orchard + When I have a user "user1" with roles "Administrator" + Then "user1" should be able to "publish" a "Page" owned by "user1" + And "user1" should be able to "edit" a "Page" owned by "user1" + +Scenario: Users can't create a Page if they don't have the PublishContent permission + Given I have installed Orchard + When I have a role "CustomRole" with permissions "EditContent, DeleteContent" + And I have a user "user1" with roles "CustomRole" + Then "user1" should not be able to "publish" a "Page" owned by "user1" + And "user1" should be able to "edit" a "Page" owned by "user1" + And "user1" should be able to "delete" a "Page" owned by "user1" + +Scenario: Users can create a Page of others if they have PublishContent permission + Given I have installed Orchard + When I have a role "CustomRole" with permissions "PublishContent" + And I have a user "user1" with roles "CustomRole" + And I have a user "user2" with roles "Administrator" + Then "user1" should be able to "publish" a "Page" owned by "user2" + And "user1" should be able to "edit" a "Page" owned by "user2" + And "user1" should not be able to "delete" a "Page" owned by "user2" + +Scenario: Users can create a Page if they have PublishOwnContent for Page + Given I have installed Orchard + When I have a role "CustomRole" with permissions "Publish_Page" + And I have a user "user1" with roles "CustomRole" + Then "user1" should be able to "publish" a "Page" owned by "user1" + And "user1" should be able to "edit" a "Page" owned by "user1" + And "user1" should not be able to "delete" a "Page" owned by "user1" + +Scenario: Users can create and edit a Page even if they only have the PublishOwnContent permission + Given I have installed Orchard + When I have a role "CustomRole" with permissions "PublishOwnContent" + And I have a user "user1" with roles "CustomRole" + Then "user1" should be able to "publish" a "Page" owned by "user1" + And "user1" should be able to "edit" a "Page" owned by "user1" + And "user1" should not be able to "delete" a "Page" owned by "user1" + +Scenario: Users can't edit a Page if they don't have the EditContent permission + Given I have installed Orchard + When I have a role "CustomRole" with permissions "DeleteContent" + And I have a user "user1" with roles "CustomRole" + Then "user1" should not be able to "publish" a "Page" owned by "user1" + And "user1" should not be able to "edit" a "Page" owned by "user1" + And "user1" should be able to "delete" a "Page" owned by "user1" + +Scenario: Users can't create a Page for others if they only have PublishOwnContent + Given I have installed Orchard + When I have a role "CustomRole" with permissions "PublishOwnContent" + And I have a user "user1" with roles "CustomRole" + And I have a user "user2" with roles "Administrator" + Then "user1" should not be able to "publish" a "Page" owned by "user2" + And "user1" should not be able to "edit" a "Page" owned by "user2" + And "user1" should not be able to "delete" a "Page" owned by "user2" + +Scenario: Users can't create a Page for others if they only have Publish_Page + Given I have installed Orchard + When I have a role "CustomRole" with permissions "Publish_Page" + And I have a user "user1" with roles "CustomRole" + And I have a user "user2" with roles "Administrator" + Then "user1" should be able to "publish" a "Page" owned by "user2" + And "user1" should be able to "edit" a "Page" owned by "user2" + And "user1" should not be able to "delete" a "Page" owned by "user2" + +Scenario: Users can create a Page for others if they only have Publish_Page + Given I have installed Orchard + When I have a role "CustomRole" with permissions "Publish_Page" + And I have a user "user1" with roles "CustomRole" + And I have a user "user2" with roles "Administrator" + Then "user1" should be able to "publish" a "Page" owned by "user2" + And "user1" should be able to "edit" a "Page" owned by "user2" + And "user1" should not be able to "delete" a "Page" owned by "user2" + +Scenario: Users can delete a Page for others if they only have Delete_Page + Given I have installed Orchard + When I have a role "CustomRole" with permissions "Delete_Page" + And I have a user "user1" with roles "CustomRole" + And I have a user "user2" with roles "Administrator" + Then "user1" should not be able to "publish" a "Page" owned by "user2" + And "user1" should not be able to "edit" a "Page" owned by "user2" + And "user1" should be able to "delete" a "Page" owned by "user2" + + +Scenario: Users can't delete a Page for others if they only have DeleteOwn_Page + Given I have installed Orchard + When I have a role "CustomRole" with permissions "DeleteOwn_Page" + And I have a user "user1" with roles "CustomRole" + And I have a user "user2" with roles "Administrator" + Then "user1" should not be able to "publish" a "Page" owned by "user2" + And "user1" should not be able to "edit" a "Page" owned by "user2" + And "user1" should not be able to "delete" a "Page" owned by "user2" diff --git a/src/Orchard.Specs/ContentRights.feature.cs b/src/Orchard.Specs/ContentRights.feature.cs new file mode 100644 index 000000000..5991ae5a4 --- /dev/null +++ b/src/Orchard.Specs/ContentRights.feature.cs @@ -0,0 +1,320 @@ +// ------------------------------------------------------------------------------ +// +// This code was generated by SpecFlow (http://www.specflow.org/). +// SpecFlow Version:1.3.0.0 +// Runtime Version:4.0.30319.1 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ +#region Designer generated code +namespace Orchard.Specs +{ + using TechTalk.SpecFlow; + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.3.0.0")] + [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [NUnit.Framework.TestFixtureAttribute()] + [NUnit.Framework.DescriptionAttribute("Content rights management")] + public partial class ContentRightsManagementFeature + { + + private static TechTalk.SpecFlow.ITestRunner testRunner; + +#line 1 "ContentRights.feature" +#line hidden + + [NUnit.Framework.TestFixtureSetUpAttribute()] + public virtual void FeatureSetup() + { + testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner(); + TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Content rights management", "In order to ensure security\r\nAs a root Orchard system operator\r\nI want only the a" + + "llowed users to edit the content", ((string[])(null))); + testRunner.OnFeatureStart(featureInfo); + } + + [NUnit.Framework.TestFixtureTearDownAttribute()] + public virtual void FeatureTearDown() + { + testRunner.OnFeatureEnd(); + testRunner = null; + } + + public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo) + { + testRunner.OnScenarioStart(scenarioInfo); + } + + [NUnit.Framework.TearDownAttribute()] + public virtual void ScenarioTearDown() + { + testRunner.OnScenarioEnd(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Administrators can manage a Page")] + public virtual void AdministratorsCanManageAPage() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Administrators can manage a Page", ((string[])(null))); +#line 6 +this.ScenarioSetup(scenarioInfo); +#line 7 +testRunner.Given("I have installed Orchard"); +#line 8 +testRunner.When("I have a user \"user1\" with roles \"Administrator\""); +#line 9 +testRunner.Then("\"user1\" should be able to \"publish\" a \"Page\" owned by \"user1\""); +#line 10 +testRunner.And("\"user1\" should be able to \"edit\" a \"Page\" owned by \"user1\""); +#line hidden + testRunner.CollectScenarioErrors(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Users can\'t create a Page if they don\'t have the PublishContent permission")] + public virtual void UsersCanTCreateAPageIfTheyDonTHaveThePublishContentPermission() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Users can\'t create a Page if they don\'t have the PublishContent permission", ((string[])(null))); +#line 12 +this.ScenarioSetup(scenarioInfo); +#line 13 +testRunner.Given("I have installed Orchard"); +#line 14 +testRunner.When("I have a role \"CustomRole\" with permissions \"EditContent, DeleteContent\""); +#line 15 +testRunner.And("I have a user \"user1\" with roles \"CustomRole\""); +#line 16 +testRunner.Then("\"user1\" should not be able to \"publish\" a \"Page\" owned by \"user1\""); +#line 17 +testRunner.And("\"user1\" should be able to \"edit\" a \"Page\" owned by \"user1\""); +#line 18 +testRunner.And("\"user1\" should be able to \"delete\" a \"Page\" owned by \"user1\""); +#line hidden + testRunner.CollectScenarioErrors(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Users can create a Page of others if they have PublishContent permission")] + public virtual void UsersCanCreateAPageOfOthersIfTheyHavePublishContentPermission() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Users can create a Page of others if they have PublishContent permission", ((string[])(null))); +#line 20 +this.ScenarioSetup(scenarioInfo); +#line 21 +testRunner.Given("I have installed Orchard"); +#line 22 +testRunner.When("I have a role \"CustomRole\" with permissions \"PublishContent\""); +#line 23 +testRunner.And("I have a user \"user1\" with roles \"CustomRole\""); +#line 24 +testRunner.And("I have a user \"user2\" with roles \"Administrator\""); +#line 25 +testRunner.Then("\"user1\" should be able to \"publish\" a \"Page\" owned by \"user2\""); +#line 26 +testRunner.And("\"user1\" should be able to \"edit\" a \"Page\" owned by \"user2\""); +#line 27 +testRunner.And("\"user1\" should not be able to \"delete\" a \"Page\" owned by \"user2\""); +#line hidden + testRunner.CollectScenarioErrors(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Users can create a Page if they have PublishOwnContent for Page")] + public virtual void UsersCanCreateAPageIfTheyHavePublishOwnContentForPage() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Users can create a Page if they have PublishOwnContent for Page", ((string[])(null))); +#line 29 +this.ScenarioSetup(scenarioInfo); +#line 30 +testRunner.Given("I have installed Orchard"); +#line 31 +testRunner.When("I have a role \"CustomRole\" with permissions \"Publish_Page\""); +#line 32 +testRunner.And("I have a user \"user1\" with roles \"CustomRole\""); +#line 33 +testRunner.Then("\"user1\" should be able to \"publish\" a \"Page\" owned by \"user1\""); +#line 34 +testRunner.And("\"user1\" should be able to \"edit\" a \"Page\" owned by \"user1\""); +#line 35 +testRunner.And("\"user1\" should not be able to \"delete\" a \"Page\" owned by \"user1\""); +#line hidden + testRunner.CollectScenarioErrors(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Users can create and edit a Page even if they only have the PublishOwnContent per" + + "mission")] + public virtual void UsersCanCreateAndEditAPageEvenIfTheyOnlyHaveThePublishOwnContentPermission() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Users can create and edit a Page even if they only have the PublishOwnContent per" + + "mission", ((string[])(null))); +#line 37 +this.ScenarioSetup(scenarioInfo); +#line 38 +testRunner.Given("I have installed Orchard"); +#line 39 +testRunner.When("I have a role \"CustomRole\" with permissions \"PublishOwnContent\""); +#line 40 +testRunner.And("I have a user \"user1\" with roles \"CustomRole\""); +#line 41 +testRunner.Then("\"user1\" should be able to \"publish\" a \"Page\" owned by \"user1\""); +#line 42 +testRunner.And("\"user1\" should be able to \"edit\" a \"Page\" owned by \"user1\""); +#line 43 +testRunner.And("\"user1\" should not be able to \"delete\" a \"Page\" owned by \"user1\""); +#line hidden + testRunner.CollectScenarioErrors(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Users can\'t edit a Page if they don\'t have the EditContent permission")] + public virtual void UsersCanTEditAPageIfTheyDonTHaveTheEditContentPermission() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Users can\'t edit a Page if they don\'t have the EditContent permission", ((string[])(null))); +#line 45 +this.ScenarioSetup(scenarioInfo); +#line 46 +testRunner.Given("I have installed Orchard"); +#line 47 +testRunner.When("I have a role \"CustomRole\" with permissions \"DeleteContent\""); +#line 48 +testRunner.And("I have a user \"user1\" with roles \"CustomRole\""); +#line 49 +testRunner.Then("\"user1\" should not be able to \"publish\" a \"Page\" owned by \"user1\""); +#line 50 +testRunner.And("\"user1\" should not be able to \"edit\" a \"Page\" owned by \"user1\""); +#line 51 +testRunner.And("\"user1\" should be able to \"delete\" a \"Page\" owned by \"user1\""); +#line hidden + testRunner.CollectScenarioErrors(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Users can\'t create a Page for others if they only have PublishOwnContent")] + public virtual void UsersCanTCreateAPageForOthersIfTheyOnlyHavePublishOwnContent() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Users can\'t create a Page for others if they only have PublishOwnContent", ((string[])(null))); +#line 53 +this.ScenarioSetup(scenarioInfo); +#line 54 +testRunner.Given("I have installed Orchard"); +#line 55 +testRunner.When("I have a role \"CustomRole\" with permissions \"PublishOwnContent\""); +#line 56 +testRunner.And("I have a user \"user1\" with roles \"CustomRole\""); +#line 57 +testRunner.And("I have a user \"user2\" with roles \"Administrator\""); +#line 58 +testRunner.Then("\"user1\" should not be able to \"publish\" a \"Page\" owned by \"user2\""); +#line 59 +testRunner.And("\"user1\" should not be able to \"edit\" a \"Page\" owned by \"user2\""); +#line 60 +testRunner.And("\"user1\" should not be able to \"delete\" a \"Page\" owned by \"user2\""); +#line hidden + testRunner.CollectScenarioErrors(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Users can\'t create a Page for others if they only have Publish_Page")] + public virtual void UsersCanTCreateAPageForOthersIfTheyOnlyHavePublish_Page() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Users can\'t create a Page for others if they only have Publish_Page", ((string[])(null))); +#line 62 +this.ScenarioSetup(scenarioInfo); +#line 63 +testRunner.Given("I have installed Orchard"); +#line 64 +testRunner.When("I have a role \"CustomRole\" with permissions \"Publish_Page\""); +#line 65 +testRunner.And("I have a user \"user1\" with roles \"CustomRole\""); +#line 66 +testRunner.And("I have a user \"user2\" with roles \"Administrator\""); +#line 67 +testRunner.Then("\"user1\" should be able to \"publish\" a \"Page\" owned by \"user2\""); +#line 68 +testRunner.And("\"user1\" should be able to \"edit\" a \"Page\" owned by \"user2\""); +#line 69 +testRunner.And("\"user1\" should not be able to \"delete\" a \"Page\" owned by \"user2\""); +#line hidden + testRunner.CollectScenarioErrors(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Users can create a Page for others if they only have Publish_Page")] + public virtual void UsersCanCreateAPageForOthersIfTheyOnlyHavePublish_Page() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Users can create a Page for others if they only have Publish_Page", ((string[])(null))); +#line 71 +this.ScenarioSetup(scenarioInfo); +#line 72 +testRunner.Given("I have installed Orchard"); +#line 73 +testRunner.When("I have a role \"CustomRole\" with permissions \"Publish_Page\""); +#line 74 +testRunner.And("I have a user \"user1\" with roles \"CustomRole\""); +#line 75 +testRunner.And("I have a user \"user2\" with roles \"Administrator\""); +#line 76 +testRunner.Then("\"user1\" should be able to \"publish\" a \"Page\" owned by \"user2\""); +#line 77 +testRunner.And("\"user1\" should be able to \"edit\" a \"Page\" owned by \"user2\""); +#line 78 +testRunner.And("\"user1\" should not be able to \"delete\" a \"Page\" owned by \"user2\""); +#line hidden + testRunner.CollectScenarioErrors(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Users can delete a Page for others if they only have Delete_Page")] + public virtual void UsersCanDeleteAPageForOthersIfTheyOnlyHaveDelete_Page() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Users can delete a Page for others if they only have Delete_Page", ((string[])(null))); +#line 80 +this.ScenarioSetup(scenarioInfo); +#line 81 +testRunner.Given("I have installed Orchard"); +#line 82 +testRunner.When("I have a role \"CustomRole\" with permissions \"Delete_Page\""); +#line 83 +testRunner.And("I have a user \"user1\" with roles \"CustomRole\""); +#line 84 +testRunner.And("I have a user \"user2\" with roles \"Administrator\""); +#line 85 +testRunner.Then("\"user1\" should not be able to \"publish\" a \"Page\" owned by \"user2\""); +#line 86 +testRunner.And("\"user1\" should not be able to \"edit\" a \"Page\" owned by \"user2\""); +#line 87 +testRunner.And("\"user1\" should be able to \"delete\" a \"Page\" owned by \"user2\""); +#line hidden + testRunner.CollectScenarioErrors(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("Users can\'t delete a Page for others if they only have DeleteOwn_Page")] + public virtual void UsersCanTDeleteAPageForOthersIfTheyOnlyHaveDeleteOwn_Page() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Users can\'t delete a Page for others if they only have DeleteOwn_Page", ((string[])(null))); +#line 90 +this.ScenarioSetup(scenarioInfo); +#line 91 +testRunner.Given("I have installed Orchard"); +#line 92 +testRunner.When("I have a role \"CustomRole\" with permissions \"DeleteOwn_Page\""); +#line 93 +testRunner.And("I have a user \"user1\" with roles \"CustomRole\""); +#line 94 +testRunner.And("I have a user \"user2\" with roles \"Administrator\""); +#line 95 +testRunner.Then("\"user1\" should not be able to \"publish\" a \"Page\" owned by \"user2\""); +#line 96 +testRunner.And("\"user1\" should not be able to \"edit\" a \"Page\" owned by \"user2\""); +#line 97 +testRunner.And("\"user1\" should not be able to \"delete\" a \"Page\" owned by \"user2\""); +#line hidden + testRunner.CollectScenarioErrors(); + } + } +} +#endregion diff --git a/src/Orchard.Specs/Media.feature.cs b/src/Orchard.Specs/Media.feature.cs index bb2ceeb63..eb3ba7dea 100644 --- a/src/Orchard.Specs/Media.feature.cs +++ b/src/Orchard.Specs/Media.feature.cs @@ -1,7 +1,7 @@ // ------------------------------------------------------------------------------ // // This code was generated by SpecFlow (http://www.specflow.org/). -// SpecFlow Version:1.3.2.0 +// SpecFlow Version:1.3.0.0 // Runtime Version:4.0.30319.1 // // Changes to this file may cause incorrect behavior and will be lost if @@ -14,7 +14,7 @@ namespace Orchard.Specs using TechTalk.SpecFlow; - [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.3.2.0")] + [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.3.0.0")] [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [NUnit.Framework.TestFixtureAttribute()] [NUnit.Framework.DescriptionAttribute("Media management")] diff --git a/src/Orchard.Specs/Orchard.Specs.csproj b/src/Orchard.Specs/Orchard.Specs.csproj index cdc4d4544..28ff2bac5 100644 --- a/src/Orchard.Specs/Orchard.Specs.csproj +++ b/src/Orchard.Specs/Orchard.Specs.csproj @@ -125,7 +125,13 @@ + + + ContentRights.feature + True + True + @@ -189,6 +195,10 @@ Always + + SpecFlowSingleFileGenerator + ContentRights.feature.cs + Always diff --git a/src/Orchard.Web/Core/Common/Security/AuthorizationEventHandler.cs b/src/Orchard.Web/Core/Common/Security/AuthorizationEventHandler.cs deleted file mode 100644 index fa0beacfb..000000000 --- a/src/Orchard.Web/Core/Common/Security/AuthorizationEventHandler.cs +++ /dev/null @@ -1,57 +0,0 @@ -using JetBrains.Annotations; -using Orchard.ContentManagement; -using Orchard.ContentManagement.Aspects; -using Orchard.Core.Common.Models; -using Orchard.Security; -using Orchard.Security.Permissions; - -namespace Orchard.Core.Common.Security -{ - [UsedImplicitly] - public class AuthorizationEventHandler : IAuthorizationServiceEventHandler - { - public void Checking(CheckAccessContext context) { } - public void Complete(CheckAccessContext context) { } - - public void Adjust(CheckAccessContext context) - { - if (!context.Granted && - context.Content.Is() && - OwnerVariationExists(context.Permission) && - HasOwnership(context.User, context.Content)) - { - - context.Adjusted = true; - context.Permission = GetOwnerVariation(context.Permission); - } - } - - 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; - } - - private static bool OwnerVariationExists(Permission permission) - { - return GetOwnerVariation(permission) != null; - } - - private static Permission GetOwnerVariation(Permission permission) - { - if (permission.Name == Contents.Permissions.PublishOthersContent.Name) - return Contents.Permissions.PublishContent; - if (permission.Name == Contents.Permissions.EditOthersContent.Name) - return Contents.Permissions.EditContent; - if (permission.Name == Contents.Permissions.DeleteOthersContent.Name) - return Contents.Permissions.DeleteContent; - return null; - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs b/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs index 04634e8d7..98c949160 100644 --- a/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs +++ b/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs @@ -251,7 +251,7 @@ namespace Orchard.Core.Contents.Controllers { if (contentItem == null) return new NotFoundResult(); - if (!Services.Authorizer.Authorize(Permissions.EditOthersContent, contentItem, T("Cannot edit content"))) + if (!Services.Authorizer.Authorize(Permissions.EditContent, contentItem, T("Cannot edit content"))) return new HttpUnauthorizedResult(); var model = _contentManager.BuildEditor(contentItem); @@ -266,7 +266,7 @@ namespace Orchard.Core.Contents.Controllers { if (contentItem == null) return new NotFoundResult(); - if (!Services.Authorizer.Authorize(Permissions.EditOthersContent, contentItem, T("Couldn't edit content"))) + if (!Services.Authorizer.Authorize(Permissions.EditContent, contentItem, T("Couldn't edit content"))) return new HttpUnauthorizedResult(); var model = _contentManager.UpdateEditor(contentItem, this); @@ -289,7 +289,7 @@ namespace Orchard.Core.Contents.Controllers { public ActionResult RemovePOST(int id, string returnUrl) { var contentItem = _contentManager.Get(id, VersionOptions.Latest); - if (!Services.Authorizer.Authorize(Permissions.DeleteOthersContent, contentItem, T("Couldn't remove content"))) + if (!Services.Authorizer.Authorize(Permissions.DeleteContent, contentItem, T("Couldn't remove content"))) return new HttpUnauthorizedResult(); if (contentItem != null) { diff --git a/src/Orchard.Web/Core/Contents/DynamicPermissions.cs b/src/Orchard.Web/Core/Contents/DynamicPermissions.cs new file mode 100644 index 000000000..b1f42d39f --- /dev/null +++ b/src/Orchard.Web/Core/Contents/DynamicPermissions.cs @@ -0,0 +1,75 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using Orchard.ContentManagement.MetaData; +using Orchard.ContentManagement.MetaData.Models; +using Orchard.Core.Contents.Settings; +using Orchard.Environment.Extensions.Models; +using Orchard.Security.Permissions; + +namespace Orchard.Core.Contents { + public class DynamicPermissions : IPermissionProvider { + private static readonly Permission PublishContent = new Permission { Description = "Publish or unpublish {0} for others", Name = "Publish_{0}", ImpliedBy = new[] { Permissions.PublishContent } }; + private static readonly Permission PublishOwnContent = new Permission { Description = "Publish or unpublish {0}", Name = "PublishOwn_{0}", ImpliedBy = new[] { PublishContent, Permissions.PublishOwnContent } }; + private static readonly Permission EditContent = new Permission { Description = "Edit {0} for others", Name = "Edit_{0}", ImpliedBy = new[] { PublishContent, Permissions.PublishContent } }; + private static readonly Permission EditOwnContent = new Permission { Description = "Edit {0}", Name = "EditOwn_{0}", ImpliedBy = new[] { EditContent, PublishOwnContent, Permissions.EditOwnContent } }; + private static readonly Permission DeleteContent = new Permission { Description = "Delete {0} for others", Name = "Delete_{0}", ImpliedBy = new[] { Permissions.DeleteContent } }; + private static readonly Permission DeleteOwnContent = new Permission { Description = "Delete {0}", Name = "DeleteOwn_{0}", ImpliedBy = new[] { DeleteContent, Permissions.DeleteOwnContent } }; + + public static readonly Dictionary PermissionTemplates = new Dictionary { + {Permissions.PublishContent.Name, PublishContent}, + {Permissions.PublishOwnContent.Name, PublishOwnContent}, + {Permissions.EditContent.Name, EditContent}, + {Permissions.EditOwnContent.Name, EditOwnContent}, + {Permissions.DeleteContent.Name, DeleteContent}, + {Permissions.DeleteOwnContent.Name, DeleteOwnContent} + }; + + private readonly IContentDefinitionManager _contentDefinitionManager; + + public virtual Feature Feature { get; set; } + + public DynamicPermissions(IContentDefinitionManager contentDefinitionManager) { + _contentDefinitionManager = contentDefinitionManager; + } + + public IEnumerable GetPermissions() { + // manage rights only for Creatable types + var creatableTypes = _contentDefinitionManager.ListTypeDefinitions() + .Where(ctd => ctd.Settings.GetModel().Creatable); + + foreach(var typeDefinition in creatableTypes) { + foreach ( var permissionTemplate in PermissionTemplates.Values ) { + yield return CreateDynamicPermission(permissionTemplate, typeDefinition); + } + } + } + + public IEnumerable GetDefaultStereotypes() { + return Enumerable.Empty(); + } + + /// + /// Returns a dynamic permission for a content type, based on a global content permission template + /// + public static Permission ConvertToDynamicPermission(Permission permission) { + if (PermissionTemplates.ContainsKey(permission.Name) ) { + return PermissionTemplates[permission.Name]; + } + + return null; + } + + /// + /// Generates a permission dynamically for a content type + /// + public static Permission CreateDynamicPermission(Permission template, ContentTypeDefinition typeDefinition) { + return new Permission { + Name = String.Format(template.Name, typeDefinition.Name), + Description = String.Format(template.Description, typeDefinition.DisplayName), + Category = typeDefinition.DisplayName, + ImpliedBy = ( template.ImpliedBy ?? new Permission[0] ).Select(t => CreateDynamicPermission(t, typeDefinition)) + }; + } + } +} diff --git a/src/Orchard.Web/Core/Contents/Permissions.cs b/src/Orchard.Web/Core/Contents/Permissions.cs index a4b82e0e3..469c0f84a 100644 --- a/src/Orchard.Web/Core/Contents/Permissions.cs +++ b/src/Orchard.Web/Core/Contents/Permissions.cs @@ -4,25 +4,25 @@ using Orchard.Security.Permissions; namespace Orchard.Core.Contents { public class Permissions : IPermissionProvider { - public static readonly Permission PublishOthersContent = new Permission { Description = "Publish or unpublish content for others", Name = "PublishOthersContent" }; - public static readonly Permission PublishContent = new Permission { Description = "Publish or unpublish content", Name = "PublishContent", ImpliedBy = new[] { PublishOthersContent } }; - public static readonly Permission EditOthersContent = new Permission { Description = "Edit content for others", Name = "EditOthersContent", ImpliedBy = new[] { PublishOthersContent } }; - public static readonly Permission EditContent = new Permission { Description = "Edit content", Name = "EditContent", ImpliedBy = new[] { EditOthersContent, PublishContent } }; - public static readonly Permission DeleteOthersContent = new Permission { Description = "Delete content for others", Name = "DeleteOthersContent" }; - public static readonly Permission DeleteContent = new Permission { Description = "Delete content", Name = "DeleteContent", ImpliedBy = new[] { DeleteOthersContent } }; + public static readonly Permission PublishContent = new Permission { Description = "Publish or unpublish content for others", Name = "PublishContent" }; + public static readonly Permission PublishOwnContent = new Permission { Description = "Publish or unpublish content", Name = "PublishOwnContent", ImpliedBy = new[] { PublishContent } }; + public static readonly Permission EditContent = new Permission { Description = "Edit content for others", Name = "EditContent", ImpliedBy = new[] { PublishContent } }; + public static readonly Permission EditOwnContent = new Permission { Description = "Edit content", Name = "EditOwnContent", ImpliedBy = new[] { EditContent, PublishOwnContent } }; + public static readonly Permission DeleteContent = new Permission { Description = "Delete content for others", Name = "DeleteContent" }; + public static readonly Permission DeleteOwnContent = new Permission { Description = "Delete content", Name = "DeleteOwnContent", ImpliedBy = new[] { DeleteContent } }; - public static readonly Permission MetaListContent = new Permission { ImpliedBy = new[] { EditContent, PublishContent, DeleteContent } }; + public static readonly Permission MetaListContent = new Permission { ImpliedBy = new[] { EditOwnContent, PublishOwnContent, DeleteOwnContent } }; public virtual Feature Feature { get; set; } public IEnumerable GetPermissions() { return new [] { + EditOwnContent, EditContent, - EditOthersContent, + PublishOwnContent, PublishContent, - PublishOthersContent, + DeleteOwnContent, DeleteContent, - DeleteOthersContent, }; } @@ -30,11 +30,11 @@ namespace Orchard.Core.Contents { return new[] { new PermissionStereotype { Name = "Administrator", - Permissions = new[] {PublishOthersContent,EditOthersContent,DeleteOthersContent} + Permissions = new[] {PublishContent,EditContent,DeleteContent} }, new PermissionStereotype { Name = "Editor", - Permissions = new[] {PublishOthersContent,EditOthersContent,DeleteOthersContent} + Permissions = new[] {PublishContent,EditContent,DeleteContent} }, new PermissionStereotype { Name = "Moderator", @@ -42,11 +42,11 @@ namespace Orchard.Core.Contents { }, new PermissionStereotype { Name = "Author", - Permissions = new[] {PublishContent,EditContent,DeleteContent} + Permissions = new[] {PublishOwnContent,EditOwnContent,DeleteOwnContent} }, new PermissionStereotype { Name = "Contributor", - Permissions = new[] {EditContent} + Permissions = new[] {EditOwnContent} }, }; } diff --git a/src/Orchard.Web/Core/Contents/Security/AuthorizationEventHandler.cs b/src/Orchard.Web/Core/Contents/Security/AuthorizationEventHandler.cs new file mode 100644 index 000000000..2b0d4b0d5 --- /dev/null +++ b/src/Orchard.Web/Core/Contents/Security/AuthorizationEventHandler.cs @@ -0,0 +1,72 @@ +using JetBrains.Annotations; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Aspects; +using Orchard.ContentManagement.MetaData.Models; +using Orchard.Core.Common.Models; +using Orchard.Core.Contents.Settings; +using Orchard.Security; +using Orchard.Security.Permissions; + +namespace Orchard.Core.Contents.Security +{ + [UsedImplicitly] + public class AuthorizationEventHandler : IAuthorizationServiceEventHandler + { + public void Checking(CheckAccessContext context) { } + public void Complete(CheckAccessContext context) { } + + public void Adjust(CheckAccessContext context) { + if ( !context.Granted && + context.Content.Is() ) { + + if (OwnerVariationExists(context.Permission) && + HasOwnership(context.User, context.Content)) { + + context.Adjusted = true; + context.Permission = GetOwnerVariation(context.Permission); + } + + var typeDefinition = context.Content.ContentItem.TypeDefinition; + + // replace permission if a content type specific version exists + if ( typeDefinition.Settings.GetModel().Creatable ) { + var permission = GetContentTypeVariation(context.Permission); + + if ( permission != null) { + context.Adjusted = true; + context.Permission = DynamicPermissions.CreateDynamicPermission(permission, typeDefinition); + } + } + } + } + + 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; + } + + private static bool OwnerVariationExists(Permission permission) { + return GetOwnerVariation(permission) != null; + } + + private static Permission GetOwnerVariation(Permission permission) { + if (permission.Name == Permissions.PublishContent.Name) + return Permissions.PublishOwnContent; + if (permission.Name == Permissions.EditContent.Name) + return Permissions.EditOwnContent; + if (permission.Name == Permissions.DeleteContent.Name) + return Permissions.DeleteOwnContent; + return null; + } + + private static Permission GetContentTypeVariation(Permission permission) { + return DynamicPermissions.ConvertToDynamicPermission(permission); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Orchard.Core.csproj b/src/Orchard.Web/Core/Orchard.Core.csproj index de3bb5af2..31141c616 100644 --- a/src/Orchard.Web/Core/Orchard.Core.csproj +++ b/src/Orchard.Web/Core/Orchard.Core.csproj @@ -72,7 +72,7 @@ - + @@ -88,6 +88,7 @@ + diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/DynamicPermissions.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/DynamicPermissions.cs deleted file mode 100644 index 06b98ea6f..000000000 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/DynamicPermissions.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Linq; -using System.Collections.Generic; -using Orchard.ContentManagement.MetaData; -using Orchard.ContentManagement.MetaData.Models; -using Orchard.Core.Contents.Settings; -using Orchard.Environment.Extensions.Models; -using Orchard.Security.Permissions; - -namespace Orchard.ContentTypes { - public class DynamicPermissions : IPermissionProvider { - public static readonly Permission ManageContentType = new Permission { Name = "ManageContentType{0}", Description = "Manage {0}" }; - - private readonly IContentDefinitionManager _contentDefinitionManager; - - public virtual Feature Feature { get; set; } - - public DynamicPermissions(IContentDefinitionManager contentDefinitionManager) { - _contentDefinitionManager = contentDefinitionManager; - } - - public IEnumerable GetPermissions() { - // manage rights only for Creatable types - var creatableTypes = _contentDefinitionManager.ListTypeDefinitions() - .Where(ctd => ctd.Settings.GetModel().Creatable); - - foreach(var typeDefinition in creatableTypes) { - yield return CreateDynamicPersion(ManageContentType, typeDefinition); - } - } - - public IEnumerable GetDefaultStereotypes() { - return new[] { - new PermissionStereotype { - Name = "Administrator", - Permissions = _contentDefinitionManager.ListTypeDefinitions().Select(typeDefinition => CreateDynamicPersion(ManageContentType, typeDefinition)) - } - }; - } - - private static Permission CreateDynamicPersion(Permission template, ContentTypeDefinition typeDefinition) { - return new Permission { - Name = String.Format(template.Name, typeDefinition.Name), - Description = String.Format(template.Description, typeDefinition.DisplayName), - Category = typeDefinition.DisplayName - }; - } - } -} diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Orchard.ContentTypes.csproj b/src/Orchard.Web/Modules/Orchard.ContentTypes/Orchard.ContentTypes.csproj index feba6252d..6180ebec2 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Orchard.ContentTypes.csproj +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Orchard.ContentTypes.csproj @@ -70,7 +70,6 @@ - diff --git a/src/Orchard.Web/Modules/Orchard.Roles/Views/EditorTemplates/Parts/Roles.UserRoles.cshtml b/src/Orchard.Web/Modules/Orchard.Roles/Views/EditorTemplates/Parts/Roles.UserRoles.cshtml index 07e19c24a..5fb4f68b2 100644 --- a/src/Orchard.Web/Modules/Orchard.Roles/Views/EditorTemplates/Parts/Roles.UserRoles.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Roles/Views/EditorTemplates/Parts/Roles.UserRoles.cshtml @@ -1,21 +1,26 @@ @model UserRolesViewModel @using Orchard.Roles.ViewModels; +
@T("Roles") @if (Model.Roles.Count > 0) { - var index = 0; - foreach (var entry in Model.Roles) { - if (string.Equals(entry.Name, "Authenticated", StringComparison.OrdinalIgnoreCase) || string.Equals(entry.Name, "Anonymous", StringComparison.OrdinalIgnoreCase)) { - continue; - } - Html.Hidden("Roles[" + index + "].RoleId", entry.RoleId); - Html.Hidden("Roles[" + index + "].Name", entry.Name); + var index = 0; + foreach (var entry in Model.Roles) { + if (string.Equals(entry.Name, "Authenticated", StringComparison.OrdinalIgnoreCase) || string.Equals(entry.Name, "Anonymous", StringComparison.OrdinalIgnoreCase)) { + continue; + } + + @Html.Hidden("Roles[" + index + "].RoleId", entry.RoleId) + @Html.Hidden("Roles[" + index + "].Name", entry.Name) +
- @Html.CheckBox("Roles[" + index + "].Granted", entry.Granted) - + @Html.CheckBox("Roles[" + index + "].Granted", entry.Granted) +
- @++index; + index++; } - } - else {

@T("There are no roles.")

} + } + else { +

@T("There are no roles.")

+ }
diff --git a/src/Orchard.Web/Modules/Orchard.Users/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Users/Controllers/AdminController.cs index f5daa9ef9..451a0326e 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Users/Controllers/AdminController.cs @@ -104,9 +104,11 @@ namespace Orchard.Users.Controllers { public ActionResult Edit(int id) { if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage users"))) return new HttpUnauthorizedResult(); - + + var user = Services.ContentManager.Get(id); + return View(new UserEditViewModel { - User = Services.ContentManager.Get(id) + User = Services.ContentManager.BuildEditorModel(user) }); } @@ -114,9 +116,10 @@ namespace Orchard.Users.Controllers { public ActionResult EditPOST(int id) { if (!Services.Authorizer.Authorize(Permissions.ManageUsers, T("Not authorized to manage users"))) return new HttpUnauthorizedResult(); - + + var user = Services.ContentManager.Get(id); var model = new UserEditViewModel { - User = Services.ContentManager.Get(id) + User = Services.ContentManager.UpdateEditorModel(user, this) }; TryUpdateModel(model); diff --git a/src/Orchard.Web/Modules/Orchard.Users/Views/Admin/Create.cshtml b/src/Orchard.Web/Modules/Orchard.Users/Views/Admin/Create.cshtml index b054b7cea..277ffc99a 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Views/Admin/Create.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Users/Views/Admin/Create.cshtml @@ -28,6 +28,8 @@ @Html.ValidationMessageFor(m=>m.ConfirmPassword, "*") + @Display(Model.User) +
diff --git a/src/Orchard.Web/Modules/Orchard.Users/Views/Admin/Edit.cshtml b/src/Orchard.Web/Modules/Orchard.Users/Views/Admin/Edit.cshtml index 7e52c85f5..b138c4af4 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Views/Admin/Edit.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Users/Views/Admin/Edit.cshtml @@ -16,6 +16,8 @@ @Html.ValidationMessageFor(m=>m.Email, "*") + @Display(Model.User) +