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 @@
+