diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-breadcrumbs.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-breadcrumbs.less index d25744a108..47ed97fde2 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-breadcrumbs.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-breadcrumbs.less @@ -35,3 +35,10 @@ margin-right: 5px; color: @gray-7; } + +input.umb-breadcrumbs__add-ancestor { + height: 25px; + margin-top: -2px; + margin-left: 3px; + width: 100px; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js index a6a2ddcbab..ccb033a57c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js @@ -56,6 +56,46 @@ angular.module("umbraco") $scope.target = dialogOptions.currentTarget; } + function onInit() { + if ($scope.startNodeId !== -1) { + entityResource.getById($scope.startNodeId, "media") + .then(function (ent) { + $scope.startNodeId = ent.id; + run(); + }); + } else { + run(); + } + } + + function run() { + //default root item + if (!$scope.target) { + if ($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) { + entityResource.getById($scope.lastOpenedNode, "media") + .then(ensureWithinStartNode, gotoStartNode); + } else { + gotoStartNode(); + } + } else { + //if a target is specified, go look it up - generally this target will just contain ids not the actual full + //media object so we need to look it up + var id = $scope.target.udi ? $scope.target.udi : $scope.target.id + var altText = $scope.target.altText; + mediaResource.getById(id) + .then(function (node) { + $scope.target = node; + if (ensureWithinStartNode(node)) { + selectImage(node); + $scope.target.url = mediaHelper.resolveFile(node); + $scope.target.altText = altText; + $scope.openDetailsDialog(); + } + }, + gotoStartNode); + } + } + $scope.upload = function(v) { angular.element(".umb-file-dropzone-directive .file-select").click(); }; @@ -107,7 +147,7 @@ angular.module("umbraco") if (folder.id > 0) { entityResource.getAncestors(folder.id, "media") - .then(function(anc) { + .then(function(anc) { $scope.path = _.filter(anc, function(f) { return f.path.indexOf($scope.startNodeId) !== -1; @@ -218,32 +258,6 @@ angular.module("umbraco") $scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" }); } - //default root item - if (!$scope.target) { - if ($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) { - entityResource.getById($scope.lastOpenedNode, "media") - .then(ensureWithinStartNode, gotoStartNode); - } else { - gotoStartNode(); - } - } else { - //if a target is specified, go look it up - generally this target will just contain ids not the actual full - //media object so we need to look it up - var id = $scope.target.udi ? $scope.target.udi : $scope.target.id - var altText = $scope.target.altText; - mediaResource.getById(id) - .then(function(node) { - $scope.target = node; - if (ensureWithinStartNode(node)) { - selectImage(node); - $scope.target.url = mediaHelper.resolveFile(node); - $scope.target.altText = altText; - $scope.openDetailsDialog(); - } - }, - gotoStartNode); - } - $scope.openDetailsDialog = function() { $scope.mediaPickerDetailsOverlay = {}; @@ -368,4 +382,7 @@ angular.module("umbraco") } } } + + onInit(); + }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html index 8c726f4a17..73b0915161 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html @@ -48,14 +48,14 @@ / -
  • +
  • (f); @@ -636,66 +638,15 @@ namespace Umbraco.Web.Editors if (result.FileData.Count == 0) { return Request.CreateResponse(HttpStatusCode.NotFound); - } - + } + //get the string json from the request - int parentId; bool entityFound; GuidUdi parentUdi; - string currentFolderId = result.FormData["currentFolder"]; - // test for udi - if (GuidUdi.TryParse(currentFolderId, out parentUdi)) - { - currentFolderId = parentUdi.Guid.ToString(); - } - - if (int.TryParse(currentFolderId, out parentId) == false) - { - // if a guid then try to look up the entity - Guid idGuid; - if (Guid.TryParse(currentFolderId, out idGuid)) - { - var entity = Services.EntityService.GetByKey(idGuid); - if (entity != null) - { - entityFound = true; - parentId = entity.Id; - } - else - { - throw new EntityNotFoundException(currentFolderId, "The passed id doesn't exist"); - } - } - else - { - return Request.CreateValidationErrorResponse("The request was not formatted correctly, the currentFolder is not an integer or Guid"); - } - - if (entityFound == false) - { - return Request.CreateValidationErrorResponse("The request was not formatted correctly, the currentFolder is not an integer or Guid"); - } - } - - - //ensure the user has access to this folder by parent id! - if (CheckPermissions( - new Dictionary(), - Security.CurrentUser, - Services.MediaService, - Services.EntityService, - parentId) == false) - { - return Request.CreateResponse( - HttpStatusCode.Forbidden, - new SimpleNotificationModel(new Notification( - Services.TextService.Localize("speechBubbles/operationFailedHeader"), - Services.TextService.Localize("speechBubbles/invalidUserPermissionsText"), - SpeechBubbleIcon.Warning))); - } - + string currentFolderId = result.FormData["currentFolder"]; + int parentId = GetParentIdAsInt(currentFolderId, validatePermissions: true); + var tempFiles = new PostedFiles(); var mediaService = ApplicationContext.Services.MediaService; - - + //in case we pass a path with a folder in it, we will create it and upload media to it. if (result.FormData.ContainsKey("path")) { @@ -830,6 +781,69 @@ namespace Umbraco.Web.Editors return Request.CreateResponse(HttpStatusCode.OK, tempFiles); } + /// + /// Given a parent id which could be a GUID, UDI or an INT, this will resolve the INT + /// + /// + /// + /// If true, this will check if the current user has access to the resolved integer parent id + /// and if that check fails an unauthorized exception will occur + /// + /// + private int GetParentIdAsInt(string parentId, bool validatePermissions) + { + int intParentId; + GuidUdi parentUdi; + + // test for udi + if (GuidUdi.TryParse(parentId, out parentUdi)) + { + parentId = parentUdi.Guid.ToString(); + } + + //if it's not an INT then we'll check for GUID + if (int.TryParse(parentId, out intParentId) == false) + { + // if a guid then try to look up the entity + Guid idGuid; + if (Guid.TryParse(parentId, out idGuid)) + { + var entity = Services.EntityService.GetByKey(idGuid); + if (entity != null) + { + intParentId = entity.Id; + } + else + { + throw new EntityNotFoundException(parentId, "The passed id doesn't exist"); + } + } + else + { + throw new HttpResponseException( + Request.CreateValidationErrorResponse("The request was not formatted correctly, the parentId is not an integer, Guid or UDI")); + } + } + + //ensure the user has access to this folder by parent id! + if (validatePermissions && CheckPermissions( + new Dictionary(), + Security.CurrentUser, + Services.MediaService, + Services.EntityService, + intParentId) == false) + { + throw new HttpResponseException(Request.CreateResponse( + HttpStatusCode.Forbidden, + new SimpleNotificationModel(new Notification( + Services.TextService.Localize("speechBubbles/operationFailedHeader"), + Services.TextService.Localize("speechBubbles/invalidUserPermissionsText"), + SpeechBubbleIcon.Warning)))); + } + + return intParentId; + } + /// /// Ensures the item can be moved/copied to the new location /// diff --git a/src/Umbraco.Web/Models/ContentEditing/PostedFolder.cs b/src/Umbraco.Web/Models/ContentEditing/PostedFolder.cs new file mode 100644 index 0000000000..35cd908787 --- /dev/null +++ b/src/Umbraco.Web/Models/ContentEditing/PostedFolder.cs @@ -0,0 +1,17 @@ +using System.Runtime.Serialization; + +namespace Umbraco.Web.Models.ContentEditing +{ + /// + /// Used to create a folder with the MediaController + /// + [DataContract] + public class PostedFolder + { + [DataMember(Name = "parentId")] + public string ParentId { get; set; } + + [DataMember(Name = "name")] + public string Name { get; set; } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index c86b86db30..014d204d95 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -392,6 +392,7 @@ +