diff --git a/src/Orchard.Specs/ContentTypes.feature b/src/Orchard.Specs/ContentTypes.feature new file mode 100644 index 000000000..cb994d201 --- /dev/null +++ b/src/Orchard.Specs/ContentTypes.feature @@ -0,0 +1,84 @@ +Feature: Content Types + In order to add new types to my site + As an adminitrator + I want to create create content types + +Scenario: I can create a new content type + Given I have installed Orchard + And I have installed "Orchard.ContentTypes" + When I go to "Admin/ContentTypes" + Then I should see "]*>.*?Create new type" + When I go to "Admin/ContentTypes/Create" + And I fill in + | name | value | + | DisplayName | Event | + | Name | Event | + And I hit "Create" + And I go to "Admin/ContentTypes/" + Then I should see "Event" + +Scenario: I can't create a content type with an already existing name + Given I have installed Orchard + And I have installed "Orchard.ContentTypes" + When I go to "Admin/ContentTypes/Create" + And I fill in + | name | value | + | DisplayName | Event | + | Name | Event | + And I hit "Create" + And I go to "Admin/ContentTypes/" + Then I should see "Event" + When I go to "Admin/ContentTypes/Create" + And I fill in + | name | value | + | DisplayName | Event | + | Name | Event-2 | + And I hit "Create" + Then I should see "]*>.*?New Content Type.*?" + And I should see "validation-summary-errors" + +Scenario: I can't create a content type with an already existing technical name + Given I have installed Orchard + And I have installed "Orchard.ContentTypes" + When I go to "Admin/ContentTypes/Create" + And I fill in + | name | value | + | DisplayName | Dinner | + | Name | Dinner | + And I hit "Create" + And I go to "Admin/ContentTypes/" + Then I should see "Dinner" + When I go to "Admin/ContentTypes/Create" + And I fill in + | name | value | + | DisplayName | Dinner2 | + | Name | Dinner | + And I hit "Create" + Then I should see "]*>.*?New Content Type.*?" + And I should see "validation-summary-errors" + +Scenario: I can't rename a content type with an already existing name + Given I have installed Orchard + And I have installed "Orchard.ContentTypes" + When I go to "Admin/ContentTypes/Create" + And I fill in + | name | value | + | DisplayName | Dinner | + | Name | Dinner | + And I hit "Create" + And I go to "Admin/ContentTypes/" + Then I should see "Dinner" + When I go to "Admin/ContentTypes/Create" + And I fill in + | name | value | + | DisplayName | Event | + | Name | Event | + And I hit "Create" + And I go to "Admin/ContentTypes/" + Then I should see "Event" + When I go to "Admin/ContentTypes/Edit/Dinner" + And I fill in + | name | value | + | DisplayName | Event | + And I hit "Save" + Then I should see "validation-summary-errors" diff --git a/src/Orchard.Specs/ContentTypes.feature.cs b/src/Orchard.Specs/ContentTypes.feature.cs new file mode 100644 index 000000000..1d5dc2ee1 --- /dev/null +++ b/src/Orchard.Specs/ContentTypes.feature.cs @@ -0,0 +1,276 @@ +// ------------------------------------------------------------------------------ +// +// 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 Types")] + public partial class ContentTypesFeature + { + + private static TechTalk.SpecFlow.ITestRunner testRunner; + +#line 1 "ContentTypes.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 Types", "In order to add new types to my site\r\nAs an adminitrator\r\nI want to create create" + + " content types", ((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("I can create a new content type")] + public virtual void ICanCreateANewContentType() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I can create a new content type", ((string[])(null))); +#line 6 +this.ScenarioSetup(scenarioInfo); +#line 7 +testRunner.Given("I have installed Orchard"); +#line 8 +testRunner.And("I have installed \"Orchard.ContentTypes\""); +#line 9 +testRunner.When("I go to \"Admin/ContentTypes\""); +#line 10 +testRunner.Then("I should see \"]*>.*?Create new type\""); +#line 11 +testRunner.When("I go to \"Admin/ContentTypes/Create\""); +#line hidden + TechTalk.SpecFlow.Table table1 = new TechTalk.SpecFlow.Table(new string[] { + "name", + "value"}); + table1.AddRow(new string[] { + "DisplayName", + "Event"}); + table1.AddRow(new string[] { + "Name", + "Event"}); +#line 12 +testRunner.And("I fill in", ((string)(null)), table1); +#line 16 +testRunner.And("I hit \"Create\""); +#line 17 +testRunner.And("I go to \"Admin/ContentTypes/\""); +#line 18 +testRunner.Then("I should see \"Event\""); +#line hidden + testRunner.CollectScenarioErrors(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("I can\'t create a content type with an already existing name")] + public virtual void ICanTCreateAContentTypeWithAnAlreadyExistingName() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I can\'t create a content type with an already existing name", ((string[])(null))); +#line 20 +this.ScenarioSetup(scenarioInfo); +#line 21 +testRunner.Given("I have installed Orchard"); +#line 22 +testRunner.And("I have installed \"Orchard.ContentTypes\""); +#line 23 +testRunner.When("I go to \"Admin/ContentTypes/Create\""); +#line hidden + TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] { + "name", + "value"}); + table2.AddRow(new string[] { + "DisplayName", + "Event"}); + table2.AddRow(new string[] { + "Name", + "Event"}); +#line 24 +testRunner.And("I fill in", ((string)(null)), table2); +#line 28 +testRunner.And("I hit \"Create\""); +#line 29 +testRunner.And("I go to \"Admin/ContentTypes/\""); +#line 30 +testRunner.Then("I should see \"Event\""); +#line 31 +testRunner.When("I go to \"Admin/ContentTypes/Create\""); +#line hidden + TechTalk.SpecFlow.Table table3 = new TechTalk.SpecFlow.Table(new string[] { + "name", + "value"}); + table3.AddRow(new string[] { + "DisplayName", + "Event"}); + table3.AddRow(new string[] { + "Name", + "Event-2"}); +#line 32 +testRunner.And("I fill in", ((string)(null)), table3); +#line 36 +testRunner.And("I hit \"Create\""); +#line 37 +testRunner.Then("I should see \"]*>.*?New Content Type.*?\""); +#line 38 +testRunner.And("I should see \"validation-summary-errors\""); +#line hidden + testRunner.CollectScenarioErrors(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("I can\'t create a content type with an already existing technical name")] + public virtual void ICanTCreateAContentTypeWithAnAlreadyExistingTechnicalName() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I can\'t create a content type with an already existing technical name", ((string[])(null))); +#line 40 +this.ScenarioSetup(scenarioInfo); +#line 41 +testRunner.Given("I have installed Orchard"); +#line 42 +testRunner.And("I have installed \"Orchard.ContentTypes\""); +#line 43 +testRunner.When("I go to \"Admin/ContentTypes/Create\""); +#line hidden + TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] { + "name", + "value"}); + table4.AddRow(new string[] { + "DisplayName", + "Dinner"}); + table4.AddRow(new string[] { + "Name", + "Dinner"}); +#line 44 +testRunner.And("I fill in", ((string)(null)), table4); +#line 48 +testRunner.And("I hit \"Create\""); +#line 49 +testRunner.And("I go to \"Admin/ContentTypes/\""); +#line 50 +testRunner.Then("I should see \"Dinner\""); +#line 51 +testRunner.When("I go to \"Admin/ContentTypes/Create\""); +#line hidden + TechTalk.SpecFlow.Table table5 = new TechTalk.SpecFlow.Table(new string[] { + "name", + "value"}); + table5.AddRow(new string[] { + "DisplayName", + "Dinner2"}); + table5.AddRow(new string[] { + "Name", + "Dinner"}); +#line 52 +testRunner.And("I fill in", ((string)(null)), table5); +#line 56 +testRunner.And("I hit \"Create\""); +#line 57 +testRunner.Then("I should see \"]*>.*?New Content Type.*?\""); +#line 58 +testRunner.And("I should see \"validation-summary-errors\""); +#line hidden + testRunner.CollectScenarioErrors(); + } + + [NUnit.Framework.TestAttribute()] + [NUnit.Framework.DescriptionAttribute("I can\'t rename a content type with an already existing name")] + public virtual void ICanTRenameAContentTypeWithAnAlreadyExistingName() + { + TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I can\'t rename a content type with an already existing name", ((string[])(null))); +#line 60 +this.ScenarioSetup(scenarioInfo); +#line 61 +testRunner.Given("I have installed Orchard"); +#line 62 +testRunner.And("I have installed \"Orchard.ContentTypes\""); +#line 63 +testRunner.When("I go to \"Admin/ContentTypes/Create\""); +#line hidden + TechTalk.SpecFlow.Table table6 = new TechTalk.SpecFlow.Table(new string[] { + "name", + "value"}); + table6.AddRow(new string[] { + "DisplayName", + "Dinner"}); + table6.AddRow(new string[] { + "Name", + "Dinner"}); +#line 64 +testRunner.And("I fill in", ((string)(null)), table6); +#line 68 +testRunner.And("I hit \"Create\""); +#line 69 +testRunner.And("I go to \"Admin/ContentTypes/\""); +#line 70 +testRunner.Then("I should see \"Dinner\""); +#line 71 +testRunner.When("I go to \"Admin/ContentTypes/Create\""); +#line hidden + TechTalk.SpecFlow.Table table7 = new TechTalk.SpecFlow.Table(new string[] { + "name", + "value"}); + table7.AddRow(new string[] { + "DisplayName", + "Event"}); + table7.AddRow(new string[] { + "Name", + "Event"}); +#line 72 +testRunner.And("I fill in", ((string)(null)), table7); +#line 76 +testRunner.And("I hit \"Create\""); +#line 77 +testRunner.And("I go to \"Admin/ContentTypes/\""); +#line 78 +testRunner.Then("I should see \"Event\""); +#line 79 +testRunner.When("I go to \"Admin/ContentTypes/Edit/Dinner\""); +#line hidden + TechTalk.SpecFlow.Table table8 = new TechTalk.SpecFlow.Table(new string[] { + "name", + "value"}); + table8.AddRow(new string[] { + "DisplayName", + "Event"}); +#line 80 +testRunner.And("I fill in", ((string)(null)), table8); +#line 83 +testRunner.And("I hit \"Save\""); +#line 84 +testRunner.Then("I should see \"validation-summary-errors\""); +#line hidden + testRunner.CollectScenarioErrors(); + } + } +} +#endregion diff --git a/src/Orchard.Specs/Orchard.Specs.csproj b/src/Orchard.Specs/Orchard.Specs.csproj index 748a34584..ef1f40764 100644 --- a/src/Orchard.Specs/Orchard.Specs.csproj +++ b/src/Orchard.Specs/Orchard.Specs.csproj @@ -142,6 +142,11 @@ True True + + ContentTypes.feature + True + True + SiteCompilation.feature @@ -228,6 +233,10 @@ SpecFlowSingleFileGenerator ContentRights.feature.cs + + SpecFlowSingleFileGenerator + ContentTypes.feature.cs + SpecFlowSingleFileGenerator SiteCompilation.feature.cs diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/Controllers/AdminController.cs index f4d408d2e..61cc18316 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Controllers/AdminController.cs @@ -47,8 +47,12 @@ namespace Orchard.ContentTypes.Controllers { if(String.IsNullOrWhiteSpace(viewModel.DisplayName)) { ModelState.AddModelError("DisplayName", T("The Content Type name can't be empty.").ToString()); } + + if ( _contentDefinitionService.GetTypes().Any(t => String.Equals(t.Name.Trim(), viewModel.Name.Trim(), StringComparison.OrdinalIgnoreCase)) ) { + ModelState.AddModelError("Name", T("A type with the same technical name already exists.").ToString()); + } - if(_contentDefinitionService.GetTypes().Any(t => t.DisplayName == viewModel.DisplayName)) { + if ( _contentDefinitionService.GetTypes().Any(t => String.Equals(t.DisplayName.Trim(), viewModel.DisplayName.Trim(), StringComparison.OrdinalIgnoreCase)) ) { ModelState.AddModelError("DisplayName", T("A type with the same name already exists.").ToString()); } @@ -57,13 +61,19 @@ namespace Orchard.ContentTypes.Controllers { return View(viewModel); } - var typeViewModel = _contentDefinitionService.AddType(viewModel); + var contentTypeDefinition = _contentDefinitionService.AddType(viewModel.Name, viewModel.DisplayName); + var typeViewModel = new EditTypeViewModel(contentTypeDefinition); + Services.Notifier.Information(T("The \"{0}\" content type has been created.", typeViewModel.DisplayName)); return RedirectToAction("Edit", new { id = typeViewModel.Name }); } + public ActionResult ContentTypeName(string displayName) { + return Json(_contentDefinitionService.GenerateName(displayName)); + } + public ActionResult Edit(string id) { if (!Services.Authorizer.Authorize(Permissions.CreateContentTypes, T("Not allowed to edit a content type."))) return new HttpUnauthorizedResult(); @@ -90,9 +100,18 @@ namespace Orchard.ContentTypes.Controllers { TryUpdateModel(edited); typeViewModel.DisplayName = edited.DisplayName; + if ( String.IsNullOrWhiteSpace(typeViewModel.DisplayName) ) { + ModelState.AddModelError("DisplayName", T("The Content Type name can't be empty.").ToString()); + } + + if ( _contentDefinitionService.GetTypes().Any(t => String.Equals(t.DisplayName.Trim(), typeViewModel.DisplayName.Trim(), StringComparison.OrdinalIgnoreCase) && !String.Equals(t.Name, id)) ) { + ModelState.AddModelError("DisplayName", T("A type with the same name already exists.").ToString()); + } + if (!ModelState.IsValid) return View(typeViewModel); + _contentDefinitionService.AlterType(typeViewModel, this); if (!ModelState.IsValid) { diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/ContentDefinitionService.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/ContentDefinitionService.cs index 9c3d936af..de42386e3 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/ContentDefinitionService.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/ContentDefinitionService.cs @@ -65,18 +65,24 @@ namespace Orchard.ContentTypes.Services { return viewModel; } - public EditTypeViewModel AddType(CreateTypeViewModel typeViewModel) { - var name = GenerateName(typeViewModel.DisplayName); + public ContentTypeDefinition AddType(string name, string displayName) { + if(String.IsNullOrWhiteSpace(displayName)) { + throw new ArgumentException("displayName"); + } - while (_contentDefinitionManager.GetTypeDefinition(name) != null) + if(String.IsNullOrWhiteSpace(name)) { + name = GenerateName(displayName); + } + + while ( _contentDefinitionManager.GetTypeDefinition(name) != null ) name = VersionName(name); - var contentTypeDefinition = new ContentTypeDefinition(name, typeViewModel.DisplayName); + var contentTypeDefinition = new ContentTypeDefinition(name, displayName); _contentDefinitionManager.StoreTypeDefinition(contentTypeDefinition); _contentDefinitionManager.AlterTypeDefinition(name, cfg => cfg.Creatable().Draftable()); - return new EditTypeViewModel(contentTypeDefinition); + return contentTypeDefinition; } public void AlterType(EditTypeViewModel typeViewModel, IUpdateModel updateModel) { @@ -210,20 +216,21 @@ namespace Orchard.ContentTypes.Services { } //gratuitously stolen from the RoutableService - private static string GenerateName(string displayName) { - if (string.IsNullOrWhiteSpace(displayName)) - return ""; + public string GenerateName(string name) { + if ( string.IsNullOrWhiteSpace(name) ) + return String.Empty; - var name = displayName; - //todo: might need to be made more restrictive depending on how name is used (like as an XML node name, for instance) - var dissallowed = new Regex(@"[/:?#\[\]@!$&'()*+,;=\s]+"); + var dissallowed = new Regex(@"[/:?#\[\]@!$&'()*+,;=\s\""<>]+"); - name = dissallowed.Replace(name, "-"); - name = name.Trim('-'); + name = dissallowed.Replace(name, String.Empty); + name = name.Trim(); if (name.Length > 128) name = name.Substring(0, 128); + while ( _contentDefinitionManager.GetTypeDefinition(name) != null ) + name = VersionName(name); + return name; } diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/IContentDefinitionService.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/IContentDefinitionService.cs index 70c59e4a7..44fc6b8ae 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/IContentDefinitionService.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Services/IContentDefinitionService.cs @@ -1,17 +1,19 @@ using System.Collections.Generic; using Orchard.ContentManagement; using Orchard.ContentManagement.MetaData; +using Orchard.ContentManagement.MetaData.Models; using Orchard.ContentTypes.ViewModels; namespace Orchard.ContentTypes.Services { public interface IContentDefinitionService : IDependency { IEnumerable GetTypes(); EditTypeViewModel GetType(string name); - EditTypeViewModel AddType(CreateTypeViewModel typeViewModel); + ContentTypeDefinition AddType(string name, string displayName); void AlterType(EditTypeViewModel typeViewModel, IUpdateModel updater); void RemoveType(string name); void AddPartToType(string partName, string typeName); void RemovePartFromType(string partName, string typeName); + string GenerateName(string displayName); IEnumerable GetParts(); EditPartViewModel GetPart(string name); diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/ViewModels/CreateTypeViewModel.cs b/src/Orchard.Web/Modules/Orchard.ContentTypes/ViewModels/CreateTypeViewModel.cs index 29a57e6e6..a53768699 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/ViewModels/CreateTypeViewModel.cs +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/ViewModels/CreateTypeViewModel.cs @@ -1,5 +1,6 @@ namespace Orchard.ContentTypes.ViewModels { public class CreateTypeViewModel { public string DisplayName { get; set; } + public string Name { get; set; } } } diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Create.cshtml b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Create.cshtml index fe3758232..847f21fa9 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Create.cshtml +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Create.cshtml @@ -1,10 +1,40 @@ @model Orchard.ContentTypes.ViewModels.CreateTypeViewModel +

@Html.TitleForPage(T("New Content Type").ToString())

@using (Html.BeginFormAntiForgeryPost()) { @Html.ValidationSummary()
@Html.TextBoxFor(m => m.DisplayName, new {@class = "textMedium", autofocus = "autofocus"}) + + @Html.TextBoxFor(m => m.Name, new {@class = "text"})
-
} \ No newline at end of file + } + +@using(Script.Foot()){ + +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Edit.cshtml b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Edit.cshtml index 22520e69c..7e50efb4b 100644 --- a/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Edit.cshtml +++ b/src/Orchard.Web/Modules/Orchard.ContentTypes/Views/Admin/Edit.cshtml @@ -12,7 +12,7 @@ @Html.ValidationSummary()
- @Html.TextBoxFor(m => m.DisplayName, new { @class = "textMedium" }) + @Html.TextBoxFor(m => m.DisplayName, new { @class = "textMedium" }) @T("Technical name: {0}", Model.Name) @* todo: if we continue to go down the midrodata route, some helpers would be nice *@ @* has unintended consequences (renamging the type) - changing the name creates a new type of that name *@ diff --git a/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs index f5b2fe736..ba6b08c0d 100644 --- a/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Media/Controllers/AdminController.cs @@ -3,15 +3,12 @@ using System.Collections.Generic; using System.IO; using System.Web; using System.Web.Mvc; -using JetBrains.Annotations; -using Orchard.ContentManagement; +using Orchard.Core.Contents.Controllers; using Orchard.Localization; using Orchard.Media.Models; using Orchard.Media.Services; using Orchard.Media.ViewModels; -using Orchard.Settings; using Orchard.UI.Notify; -using Orchard.Utility.Extensions; namespace Orchard.Media.Controllers { [ValidateInput(false)] @@ -56,11 +53,13 @@ namespace Orchard.Media.Controllers { [HttpPost] public ActionResult Create() { + if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't create media folder"))) + return new HttpUnauthorizedResult(); + var viewModel = new MediaFolderCreateViewModel(); try { UpdateModel(viewModel); - if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't create media folder"))) - return new HttpUnauthorizedResult(); + _mediaService.CreateFolder(viewModel.MediaPath, viewModel.Name); return RedirectToAction("Index"); } @@ -109,24 +108,17 @@ namespace Orchard.Media.Controllers { return View(model); } - [HttpPost] - public ActionResult EditProperties() { + [HttpPost, ActionName("EditProperties")] + [FormValueRequired("submit.Delete")] + public ActionResult EditPropertiesDeletePOST() { + if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't delete media folder"))) + return new HttpUnauthorizedResult(); + var viewModel = new MediaFolderEditPropertiesViewModel(); try { UpdateModel(viewModel); - //TODO: There may be better ways to do this. - // Delete - if (!String.IsNullOrEmpty(HttpContext.Request.Form["submit.Delete"])) { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't delete media folder"))) - return new HttpUnauthorizedResult(); - _mediaService.DeleteFolder(viewModel.MediaPath); - } - // Save - else { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't rename media folder"))) - return new HttpUnauthorizedResult(); - _mediaService.RenameFolder(viewModel.MediaPath, viewModel.Name); - } + + _mediaService.DeleteFolder(viewModel.MediaPath); return RedirectToAction("Index"); } @@ -136,6 +128,25 @@ namespace Orchard.Media.Controllers { } } + [HttpPost, ActionName("EditProperties")] + [FormValueRequired("submit.Save")] + public ActionResult EditProperties() { + if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't rename media folder"))) + return new HttpUnauthorizedResult(); + + var viewModel = new MediaFolderEditPropertiesViewModel(); + try { + UpdateModel(viewModel); + + _mediaService.RenameFolder(viewModel.MediaPath, viewModel.Name); + + return RedirectToAction("Index"); + } catch (Exception exception) { + Services.Notifier.Error(T("Modifying Folder Properties failed: {0}", exception.Message)); + return View(viewModel); + } + } + public ActionResult Add(string folderName, string mediaPath) { var model = new MediaItemAddViewModel { FolderName = folderName, MediaPath = mediaPath }; return View(model); @@ -143,11 +154,12 @@ namespace Orchard.Media.Controllers { [HttpPost] public ActionResult Add() { + if (!Services.Authorizer.Authorize(Permissions.UploadMediaFiles, T("Couldn't upload media file"))) + return new HttpUnauthorizedResult(); + var viewModel = new MediaItemAddViewModel(); try { UpdateModel(viewModel); - if (!Services.Authorizer.Authorize(Permissions.UploadMediaFiles, T("Couldn't upload media file"))) - return new HttpUnauthorizedResult(); if(String.IsNullOrWhiteSpace(Request.Files[0].FileName)) { ModelState.AddModelError("File", T("Select a file to upload").ToString()); @@ -180,11 +192,12 @@ namespace Orchard.Media.Controllers { [HttpPost] public ContentResult AddFromClient() { + if (!Services.Authorizer.Authorize(Permissions.UploadMediaFiles)) + return Content(string.Format("", T("ERROR: You don't have permission to upload media files"))); + var viewModel = new MediaItemAddViewModel(); try { UpdateModel(viewModel); - if (!Services.Authorizer.Authorize(Permissions.UploadMediaFiles)) - return Content(string.Format("", T("ERROR: You don't have permission to upload media files"))); if (Request.Files.Count < 1 || Request.Files[0].ContentLength == 0) return Content(string.Format("", T("HEY: You didn't give me a file to upload"))); @@ -220,32 +233,42 @@ namespace Orchard.Media.Controllers { return View(model); } - [HttpPost] - public ActionResult EditMedia(FormCollection input) { + [HttpPost, ActionName("EditMedia")] + [FormValueRequired("submit.Delete")] + public ActionResult EditMediaDeletePOST(FormCollection input) { + if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't delete media file"))) + return new HttpUnauthorizedResult(); + var viewModel = new MediaItemEditViewModel(); try { UpdateModel(viewModel); - if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't modify media file"))) - return new HttpUnauthorizedResult(); - // Delete - if (!String.IsNullOrEmpty(HttpContext.Request.Form["submit.Delete"])) { - if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't delete media file"))) - return new HttpUnauthorizedResult(); - _mediaService.DeleteFile(viewModel.Name, viewModel.MediaPath); - return RedirectToAction("Edit", new { name = viewModel.FolderName, mediaPath = viewModel.MediaPath }); - } - // Save and Rename + + _mediaService.DeleteFile(viewModel.Name, viewModel.MediaPath); + return RedirectToAction("Edit", new { name = viewModel.FolderName, mediaPath = viewModel.MediaPath }); + } catch (Exception exception) { + Services.Notifier.Error(T("Removing media file failed: {0}", exception.Message)); + return View(viewModel); + } + } + + [HttpPost, ActionName("EditMedia")] + [FormValueRequired("submit.Save")] + public ActionResult EditMedia(FormCollection input) { + if (!Services.Authorizer.Authorize(Permissions.ManageMediaFiles, T("Couldn't modify media file"))) + return new HttpUnauthorizedResult(); + + var viewModel = new MediaItemEditViewModel(); + try { + UpdateModel(viewModel); + string viewModelName = viewModel.Name; + + // Rename if (!String.Equals(viewModel.Name, input["NewName"], StringComparison.OrdinalIgnoreCase)) { _mediaService.RenameFile(viewModel.Name, input["NewName"], viewModel.MediaPath); - return RedirectToAction("EditMedia", new { name = input["NewName"], - caption = viewModel.Caption, - lastUpdated = viewModel.LastUpdated, - size = viewModel.Size, - folderName = viewModel.FolderName, - mediaPath = viewModel.MediaPath }); + viewModelName = input["NewName"]; } - // Save - return RedirectToAction("EditMedia", new { name = viewModel.Name, + + return RedirectToAction("EditMedia", new { name = viewModelName, caption = viewModel.Caption, lastUpdated = viewModel.LastUpdated, size = viewModel.Size, @@ -258,4 +281,4 @@ namespace Orchard.Media.Controllers { } } } -} +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Media/Services/MediaService.cs b/src/Orchard.Web/Modules/Orchard.Media/Services/MediaService.cs index e990545bb..459264f0e 100644 --- a/src/Orchard.Web/Modules/Orchard.Media/Services/MediaService.cs +++ b/src/Orchard.Web/Modules/Orchard.Media/Services/MediaService.cs @@ -83,9 +83,11 @@ namespace Orchard.Media.Services { } public void RenameFile(string name, string newName, string folderName) { - if (FileAllowed(newName, false)) { - _storageProvider.RenameFile(_storageProvider.Combine(folderName, name), _storageProvider.Combine(folderName, newName)); + if (!FileAllowed(newName, false)) { + throw new ArgumentException("New file name " + newName + " not allowed."); } + + _storageProvider.RenameFile(_storageProvider.Combine(folderName, name), _storageProvider.Combine(folderName, newName)); } public string UploadMediaFile(string folderName, HttpPostedFileBase postedFile) { diff --git a/src/Orchard.Web/Modules/Orchard.Media/Views/Admin/EditMedia.cshtml b/src/Orchard.Web/Modules/Orchard.Media/Views/Admin/EditMedia.cshtml index 311ccac8d..c99882e08 100644 --- a/src/Orchard.Web/Modules/Orchard.Media/Views/Admin/EditMedia.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Media/Views/Admin/EditMedia.cshtml @@ -13,62 +13,48 @@ new {name = navigation.FolderName, mediaPath = navigation.FolderPath}) > } @T("Edit Media")

- - + +
- @using (Html.BeginFormAntiForgeryPost()) { - @Html.ValidationSummary() -
-
- -
-
- @* todo: make these real (including markup) *@ -
- @* *@ - - - - -
-
- - - @T("Copy this html to add this image to your site.") -
- +
+
+ +
+ + @* todo: make these real (including markup) *@ +
+ @* *@ + + + + +
+ +
+ + + @T("Copy this html to add this image to your site.") +
+ + @using (Html.BeginFormAntiForgeryPost()) { + @Html.ValidationSummary() +
- - -
+ + +
- - - - -
-
-
+ + + + +
+
+ +
- - @* -
-

@T("Preview")

-
-
    - @// todo: make these real (including markup) -
  • -
  • -
  • -
  • - - ", ResolveUrl("~/Media/" + Model.RelativePath + "/" + Model.Name), 500, 375)" /> - @T("Copy this html to add this image to your site.")

    -
  • -
-
- *@ - } + } + \ No newline at end of file