From 8ad1d247fa5aea715e8bc128fb356375912166d1 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 6 Sep 2017 11:49:00 +1000 Subject: [PATCH] U4-10389 Some webforms editors do not authorize on the user's path access or permissions set for the editing node --- src/Umbraco.Core/ActionsResolver.cs | 27 +- src/Umbraco.Core/Models/UmbracoEntity.cs | 2 + src/Umbraco.Core/Models/UserExtensions.cs | 7 +- .../Trees/ContentTreeControllerBase.cs | 5 +- .../UI/Pages/UmbracoEnsuredPage.cs | 36 ++ src/Umbraco.Web/Umbraco.Web.csproj | 3 - .../umbraco/dialogs/AssignDomain2.aspx.cs | 19 +- .../umbraco/dialogs/moveOrCopy.aspx.cs | 442 ------------------ .../umbraco/dialogs/sort.aspx.cs | 40 +- .../BasePages/UmbracoEnsuredPage.cs | 38 +- src/umbraco.cms/Actions/Action.cs | 25 +- 11 files changed, 155 insertions(+), 489 deletions(-) delete mode 100644 src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/moveOrCopy.aspx.cs diff --git a/src/Umbraco.Core/ActionsResolver.cs b/src/Umbraco.Core/ActionsResolver.cs index 206182c6f2..ff2eaa8553 100644 --- a/src/Umbraco.Core/ActionsResolver.cs +++ b/src/Umbraco.Core/ActionsResolver.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Reflection; using Umbraco.Core.Logging; @@ -34,7 +35,31 @@ namespace Umbraco.Core { return Values; } - } + } + + /// + /// This method will return a list of IAction's based on a string (letter) list. Each character in the list may represent + /// an IAction. This will associate any found IActions based on the Letter property of the IAction with the character being referenced. + /// + /// + /// returns a list of actions that have an associated letter found in the action string list + public IEnumerable FromActionSymbols(IEnumerable actions) + { + var allActions = Actions.ToArray(); + return actions + .Select(c => allActions.FirstOrDefault(a => a.Letter.ToString(CultureInfo.InvariantCulture) == c)) + .WhereNotNull() + .ToArray(); + } + + /// + /// Returns the string (letter) representation of the actions that make up the actions collection + /// + /// + public IEnumerable ToActionSymbols(IEnumerable actions) + { + return actions.Select(x => x.Letter.ToString(CultureInfo.InvariantCulture)).ToArray(); + } /// /// Gets an Action if it exists. diff --git a/src/Umbraco.Core/Models/UmbracoEntity.cs b/src/Umbraco.Core/Models/UmbracoEntity.cs index 48752468d5..b789698704 100644 --- a/src/Umbraco.Core/Models/UmbracoEntity.cs +++ b/src/Umbraco.Core/Models/UmbracoEntity.cs @@ -51,6 +51,8 @@ namespace Umbraco.Core.Models private string _contentTypeIcon; private string _contentTypeThumbnail; + public static readonly UmbracoEntity Root = new UmbracoEntity(false) {Path = "-1", Name = "root", HasChildren = true}; + public UmbracoEntity() { AdditionalData = new Dictionary(); diff --git a/src/Umbraco.Core/Models/UserExtensions.cs b/src/Umbraco.Core/Models/UserExtensions.cs index b842fb8f54..7455d840c6 100644 --- a/src/Umbraco.Core/Models/UserExtensions.cs +++ b/src/Umbraco.Core/Models/UserExtensions.cs @@ -13,7 +13,12 @@ using Umbraco.Core.Services; namespace Umbraco.Core.Models { public static class UserExtensions - { + { + public static IEnumerable GetPermissions(this IUser user, string path, IUserService userService) + { + return userService.GetPermissionsForPath(user, path).GetAllPermissions(); + } + public static bool HasSectionAccess(this IUser user, string app) { var apps = user.AllowedSections; diff --git a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs index fa18e703bd..1232aaf832 100644 --- a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs @@ -271,8 +271,9 @@ namespace Umbraco.Web.Trees internal IEnumerable GetAllowedUserMenuItemsForNode(IUmbracoEntity dd) { - var actions = global::umbraco.BusinessLogic.Actions.Action.FromString(UmbracoUser.GetPermissions(dd.Path)); - + var actions = ActionsResolver.Current.FromActionSymbols(Security.CurrentUser.GetPermissions(dd.Path, Services.UserService)) + .ToList(); + // A user is allowed to delete their own stuff if (dd.CreatorId == UmbracoUser.Id && actions.Contains(ActionDelete.Instance) == false) actions.Add(ActionDelete.Instance); diff --git a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs index c09fd0fa0c..c78f66ab97 100644 --- a/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs +++ b/src/Umbraco.Web/UI/Pages/UmbracoEnsuredPage.cs @@ -7,7 +7,9 @@ using Umbraco.Web.Security; using umbraco; using umbraco.BusinessLogic; using umbraco.businesslogic.Exceptions; +using umbraco.interfaces; using Umbraco.Core; +using Umbraco.Core.Models; using Umbraco.Core.Security; namespace Umbraco.Web.UI.Pages @@ -32,6 +34,40 @@ namespace Umbraco.Web.UI.Pages } } + /// + /// Performs an authorization check for the user against the requested entity/path and permission set, this is only relevant to content and media + /// + /// + /// + /// + protected void CheckPathAndPermissions(int entityId, UmbracoObjectTypes objectType, IAction actionToCheck) + { + if (objectType == UmbracoObjectTypes.Document || objectType == UmbracoObjectTypes.Media) + { + //check path access + + var entity = entityId == Constants.System.Root + ? UmbracoEntity.Root + : Services.EntityService.Get( + entityId, + objectType); + var hasAccess = Security.CurrentUser.HasPathAccess( + entity, + Services.EntityService, + objectType == UmbracoObjectTypes.Document ? Constants.System.RecycleBinContent : Constants.System.RecycleBinMedia); + if (hasAccess == false) + throw new UserAuthorizationException(string.Format("The current user doesn't have access to the path '{0}'", entity.Path)); + + //only documents have action permissions + if (objectType == UmbracoObjectTypes.Document) + { + var allowedActions = ActionsResolver.Current.FromActionSymbols(Security.CurrentUser.GetPermissions(entity.Path, Services.UserService)).ToArray(); + if (allowedActions.Contains(actionToCheck) == false) + throw new UserAuthorizationException(string.Format("The current user doesn't have permission to {0} on the path '{1}'", actionToCheck.Alias, entity.Path)); + } + } + } + private bool _hasValidated = false; /// diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index a210c269d0..fb628ad137 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -1137,9 +1137,6 @@ - - ASPXCodeBehind - ASPXCodeBehind diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/AssignDomain2.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/AssignDomain2.aspx.cs index 4f71e20d08..de1e563776 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/AssignDomain2.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/AssignDomain2.aspx.cs @@ -15,6 +15,14 @@ namespace umbraco.dialogs { public partial class AssignDomain2 : UmbracoEnsuredPage { + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + var nodeId = GetNodeId(); + CheckPathAndPermissions(nodeId, UmbracoObjectTypes.Document, ActionAssignDomain.Instance); + } + protected override void OnLoad(EventArgs e) { base.OnLoad(e); @@ -29,16 +37,7 @@ namespace umbraco.dialogs pane_domains.Visible = false; p_buttons.Visible = false; return; - } - - if (UmbracoUser.GetPermissions(node.Path).Contains(ActionAssignDomain.Instance.Letter) == false) - { - feedback.Text = ui.Text("assignDomain", "permissionDenied"); - pane_language.Visible = false; - pane_domains.Visible = false; - p_buttons.Visible = false; - return; - } + } pane_language.Title = ui.Text("assignDomain", "setLanguage"); pane_domains.Title = ui.Text("assignDomain", "setDomains"); diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/moveOrCopy.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/moveOrCopy.aspx.cs deleted file mode 100644 index f8fc1d3ea3..0000000000 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/moveOrCopy.aspx.cs +++ /dev/null @@ -1,442 +0,0 @@ -using System; -using System.Collections; -using System.Globalization; -using System.Web.UI; -using System.Web.UI.WebControls; -using System.Xml; -using Umbraco.Core; -using Umbraco.Core.IO; -using Umbraco.Core.Models; -using umbraco.BasePages; -using System.Linq; -using umbraco.interfaces; -using Umbraco.Web; -using Umbraco.Core; - -namespace umbraco.dialogs -{ - /// - /// Summary description for moveOrCopy. - /// - public partial class moveOrCopy : UmbracoEnsuredPage - { - - protected override void OnInit(EventArgs e) - { - CurrentApp = Request["app"]; - - base.OnInit(e); - } - - protected void Page_Load(object sender, EventArgs e) - { - JTree.DataBind(); - - // Put user code to initialize the page here - if (IsPostBack == false) - { - pp_relate.Text = ui.Text("moveOrCopy", "relateToOriginal"); - - //Document Type copy Hack... - - if (CurrentApp == Constants.Applications.Settings) - { - pane_form.Visible = false; - pane_form_notice.Visible = false; - pane_settings.Visible = true; - - ok.Text = ui.Text("general", "ok", UmbracoUser); - ok.Attributes.Add("style", "width: 60px"); - - var documentType = Services.ContentTypeService.GetContentType(int.Parse(Request.GetItemAsString("id"))); - - //Load master types... - masterType.Attributes.Add("style", "width: 350px;"); - masterType.Items.Add(new ListItem(ui.Text("none") + "...", "0")); - - foreach (var docT in Services.ContentTypeService.GetAllContentTypes().OrderBy(x => x.Name)) - { - masterType.Items.Add(new ListItem(docT.Name, docT.Id.ToString(CultureInfo.InvariantCulture))); - } - - masterType.SelectedValue = (documentType.ParentId > 0 ? documentType.ParentId : 0).ToString(CultureInfo.InvariantCulture); - - rename.Text = documentType.Name + " (copy)"; - pane_settings.Text = "Make a copy of the document type '" + documentType.Name + "' and save it under a new name"; - - } - else - { - pane_form.Visible = true; - pane_form_notice.Visible = true; - - pane_settings.Visible = false; - - // Caption and properies on BUTTON - ok.Text = ui.Text("general", "ok", UmbracoUser); - ok.Attributes.Add("style", "width: 60px"); - ok.Attributes.Add("disabled", "true"); - - IContentBase currContent; - if (CurrentApp == "content") - { - currContent = Services.ContentService.GetById(Request.GetItemAs("id")); - } - else - { - currContent = Services.MediaService.GetById(Request.GetItemAs("id")); - } - - // Preselect the parent of the seslected item. - if (currContent.ParentId > 0) - JTree.SelectedNodePath = currContent.Path.Substring(0, currContent.Path.LastIndexOf(',')); - - var validAction = true; - if (CurrentApp == Constants.Applications.Content && Umbraco.Core.Models.ContentExtensions.HasChildren(currContent, Services)) - { - validAction = ValidAction(currContent, Request.GetItemAsString("mode") == "cut" ? 'M' : 'O'); - } - - if (Request.GetItemAsString("mode") == "cut") - { - pane_form.Text = ui.Text("moveOrCopy", "moveTo", currContent.Name, UmbracoUser); - pp_relate.Visible = false; - } - else - { - pane_form.Text = ui.Text("moveOrCopy", "copyTo", currContent.Name, UmbracoUser); - pp_relate.Visible = true; - } - - if (validAction == false) - { - panel_buttons.Visible = false; - ScriptManager.RegisterStartupScript(this, GetType(), "notvalid", "notValid();", true); - } - } - } - - } - - private bool ValidAction(IContentBase cmsNode, char actionLetter) - { - var currentAction = BusinessLogic.Actions.Action.GetPermissionAssignable().First(a => a.Letter == actionLetter); - return CheckPermissions(cmsNode, currentAction); - } - - /// - /// Checks if the current user has permissions to execute this action against this node - /// - /// - /// - /// - /// - /// This used to do a recursive check for all descendent nodes but this is not required and is a massive CPU hog. - /// See: http://issues.umbraco.org/issue/U4-2632, https://groups.google.com/forum/?fromgroups=#!topic/umbraco-dev/L1D4LwVSP2Y - /// - private bool CheckPermissions(IContentBase node, IAction currentAction) - { - var userService = ApplicationContext.Current.Services.UserService; - var currUserPermissions = userService.GetPermissions(UmbracoContext.Current.Security.CurrentUser, node.Id).GetAllPermissions(); - return currUserPermissions != null && currUserPermissions.Contains(currentAction.Letter.ToString(CultureInfo.InvariantCulture)); - } - - private void HandleDocumentTypeCopy() - { - var contentTypeService = ApplicationContext.Current.Services.ContentTypeService; - var contentType = contentTypeService.GetContentType( - int.Parse(Request.GetItemAsString("id"))); - - //set the master - //http://issues.umbraco.org/issue/U4-2843 - //http://issues.umbraco.org/issue/U4-3552 - var parentId = int.Parse(masterType.SelectedValue); - - var alias = rename.Text.Trim().Replace("'", "''"); - var clone = contentTypeService.Copy(contentType, alias, rename.Text.Trim(), parentId); - - var returnUrl = string.Format("{0}/settings/editNodeTypeNew.aspx?id={1}", SystemDirectories.Umbraco, clone.Id); - - pane_settings.Visible = false; - panel_buttons.Visible = false; - - feedback.Text = "Document type copied"; - feedback.type = uicontrols.Feedback.feedbacktype.success; - - ClientTools.ChangeContentFrameUrl(returnUrl); - } - - public void HandleMoveOrCopy(object sender, EventArgs e) - { - if (CurrentApp == Constants.Applications.Settings) - HandleDocumentTypeCopy(); - else - HandleDocumentMoveOrCopy(); - } - - protected override void OnPreRender(EventArgs e) - { - base.OnPreRender(e); - ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("../webservices/cmsnode.asmx")); - ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("../webservices/legacyAjaxCalls.asmx")); - } - - private void HandleDocumentMoveOrCopy() - { - if (Request.GetItemAsString("copyTo") != "" && Request.GetItemAsString("id") != "") - { - // Check if the current node is allowed at new position - var nodeAllowed = false; - - IContentBase currContent; - IContentBase parentContent = null; - IContentTypeBase parentContentType = null; - if (CurrentApp == "content") - { - currContent = Services.ContentService.GetById(Request.GetItemAs("id")); - if (Request.GetItemAs("copyTo") != -1) - { - parentContent = Services.ContentService.GetById(Request.GetItemAs("copyTo")); - if (parentContent != null) - { - parentContentType = Services.ContentTypeService.GetContentType(parentContent.ContentTypeId); - } - } - } - else - { - currContent = Services.MediaService.GetById(Request.GetItemAs("id")); - if (Request.GetItemAs("copyTo") != -1) - { - parentContent = Services.MediaService.GetById(Request.GetItemAs("copyTo")); - if (parentContent != null) - { - parentContentType = Services.ContentTypeService.GetMediaType(parentContent.ContentTypeId); - } - } - } - - // Check on contenttypes - if (parentContentType == null) - { - //check if this is allowed at root - IContentTypeBase currContentType; - if (CurrentApp == "content") - { - currContentType = Services.ContentTypeService.GetContentType(currContent.ContentTypeId); - } - else - { - currContentType = Services.ContentTypeService.GetMediaType(currContent.ContentTypeId); - } - nodeAllowed = currContentType.AllowedAsRoot; - if (!nodeAllowed) - { - feedback.Text = ui.Text("moveOrCopy", "notAllowedAtRoot", UmbracoUser); - feedback.type = uicontrols.Feedback.feedbacktype.error; - } - } - else - { - var allowedChildContentTypeIds = parentContentType.AllowedContentTypes.Select(x => x.Id).ToArray(); - if (allowedChildContentTypeIds.Any(x => x.Value == currContent.ContentTypeId)) - { - nodeAllowed = true; - } - - if (nodeAllowed == false) - { - feedback.Text = ui.Text("moveOrCopy", "notAllowedByContentType", UmbracoUser); - feedback.type = uicontrols.Feedback.feedbacktype.error; - } - else - { - // Check on paths - if ((string.Format(",{0},", parentContent.Path)).IndexOf(string.Format(",{0},", currContent.Id)) > -1) - { - nodeAllowed = false; - feedback.Text = ui.Text("moveOrCopy", "notAllowedByPath", UmbracoUser); - feedback.type = uicontrols.Feedback.feedbacktype.error; - } - } - } - - if (nodeAllowed) - { - pane_form.Visible = false; - pane_form_notice.Visible = false; - panel_buttons.Visible = false; - - var newNodeCaption = parentContent == null - ? ui.Text(CurrentApp) - : parentContent.Name; - - string[] nodes = { currContent.Name, newNodeCaption }; - - if (Request["mode"] == "cut") - { - if (CurrentApp == Constants.Applications.Content) - { - var doc = (IContent)currContent; - var copyToId = Request.GetItemAs("copyTo"); - Services.ContentService.Move(doc, copyToId, UmbracoUser.Id); - - } - else - { - var media = (IMedia)currContent; - var copyToId = Request.GetItemAs("copyTo"); - Services.MediaService.Move(media, copyToId, UmbracoUser.Id); - } - - feedback.Text = ui.Text("moveOrCopy", "moveDone", nodes, UmbracoUser) + "

" + ui.Text("closeThisWindow") + ""; - feedback.type = uicontrols.Feedback.feedbacktype.success; - - // refresh tree - ClientTools.MoveNode(currContent.Id.ToString(), currContent.Path); - } - else - { - //NOTE: We ONLY support Copy on content not media for some reason. - - var newContent = (IContent)currContent; - Services.ContentService.Copy(newContent, Request.GetItemAs("copyTo"), RelateDocuments.Checked, UmbracoUser.Id); - - feedback.Text = ui.Text("moveOrCopy", "copyDone", nodes, UmbracoUser) + "

" + ui.Text("closeThisWindow") + ""; - feedback.type = uicontrols.Feedback.feedbacktype.success; - - // refresh tree - ClientTools.CopyNode(currContent.Id.ToString(), newContent.Path); - } - } - } - } - - ///

- /// JsInclude1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::ClientDependency.Core.Controls.JsInclude JsInclude1; - - /// - /// feedback control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Feedback feedback; - - /// - /// pane_form control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane pane_form; - - /// - /// JTree control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.controls.Tree.TreeControl JTree; - - /// - /// pp_relate control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel pp_relate; - - /// - /// RelateDocuments control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.CheckBox RelateDocuments; - - /// - /// pane_form_notice control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.PlaceHolder pane_form_notice; - - /// - /// pane_settings control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.Pane pane_settings; - - /// - /// PropertyPanel1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::umbraco.uicontrols.PropertyPanel PropertyPanel1; - - /// - /// masterType control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.ListBox masterType; - - /// - /// rename control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.TextBox rename; - - /// - /// RequiredFieldValidator1 control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator1; - - /// - /// panel_buttons control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Panel panel_buttons; - - /// - /// ok control. - /// - /// - /// Auto-generated field. - /// To modify move field declaration from designer file to code-behind file. - /// - protected global::System.Web.UI.WebControls.Button ok; - - } -} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sort.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sort.aspx.cs index f3dbb43519..f3bb4c8fdc 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sort.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/sort.aspx.cs @@ -13,6 +13,8 @@ using umbraco.cms.businesslogic.media; using umbraco.cms.businesslogic.web; using System.Web.UI; using System.Collections.Generic; +using umbraco.businesslogic.Exceptions; +using Umbraco.Core.Models; namespace umbraco.cms.presentation { @@ -20,7 +22,13 @@ namespace umbraco.cms.presentation /// Summary description for sort. ///
public partial class sort : UmbracoEnsuredPage - { + { + /// + /// The Parent Id being sorted + /// + protected int? ParentIdAsInt { get; private set; } + protected string ParentIdAsString { get; private set; } + private readonly List _nodes = new List(); protected bool HideDateColumn @@ -33,6 +41,21 @@ namespace umbraco.cms.presentation { CurrentApp = helper.Request("app"); + ParentIdAsString = Request.GetItemAsString("ID"); + int parentId; + if (int.TryParse(ParentIdAsString, out parentId)) + { + ParentIdAsInt = parentId; + + if (CurrentApp == Constants.Applications.Content || CurrentApp == Constants.Applications.Media) + { + CheckPathAndPermissions( + ParentIdAsInt.Value, + CurrentApp == Constants.Applications.Content ? UmbracoObjectTypes.Document : UmbracoObjectTypes.Media, + ActionSort.Instance); + } + } + base.OnInit(e); } @@ -50,23 +73,22 @@ namespace umbraco.cms.presentation var app = Request.GetItemAsString("app"); var icon = "../images/umbraco/doc.gif"; - - int parentId; - if (int.TryParse(Request.GetItemAsString("ID"), out parentId)) + + if (ParentIdAsInt.HasValue) { if (app == Constants.Applications.Media) { icon = "../images/umbraco/mediaPhoto.gif"; var mediaService = ApplicationContext.Current.Services.MediaService; - if (parentId == -1) + if (ParentIdAsInt.Value == -1) { foreach (var child in mediaService.GetRootMedia().ToList().OrderBy(x => x.SortOrder)) _nodes.Add(CreateNode(child.Id.ToInvariantString(), child.SortOrder, child.Name, child.CreateDate, icon)); } else { - var children = mediaService.GetChildren(parentId); + var children = mediaService.GetChildren(ParentIdAsInt.Value); foreach (var child in children.OrderBy(x => x.SortOrder)) _nodes.Add(CreateNode(child.Id.ToInvariantString(), child.SortOrder, child.Name, child.CreateDate, icon)); } @@ -76,14 +98,14 @@ namespace umbraco.cms.presentation { var contentService = ApplicationContext.Current.Services.ContentService; - if (parentId == -1) + if (ParentIdAsInt.Value == -1) { foreach (var child in contentService.GetRootContent().ToList().OrderBy(x => x.SortOrder)) _nodes.Add(CreateNode(child.Id.ToInvariantString(), child.SortOrder, child.Name, child.CreateDate, icon)); } else { - var children = contentService.GetChildren(parentId); + var children = contentService.GetChildren(ParentIdAsInt.Value); foreach (var child in children) _nodes.Add(CreateNode(child.Id.ToInvariantString(), child.SortOrder, child.Name, child.CreateDate, icon)); } @@ -100,7 +122,7 @@ namespace umbraco.cms.presentation HideDateColumn = true; - var stylesheetName = Request.GetItemAsString("ID"); + var stylesheetName = ParentIdAsString; if (stylesheetName.IsNullOrWhiteSpace())throw new NullReferenceException("No Id passed in to editor"); var stylesheet = Services.FileService.GetStylesheetByName(stylesheetName.EnsureEndsWith(".css")); if (stylesheet == null) throw new InvalidOperationException("No stylesheet found by name " + stylesheetName); diff --git a/src/umbraco.businesslogic/BasePages/UmbracoEnsuredPage.cs b/src/umbraco.businesslogic/BasePages/UmbracoEnsuredPage.cs index 58362d50f2..36a0f63f36 100644 --- a/src/umbraco.businesslogic/BasePages/UmbracoEnsuredPage.cs +++ b/src/umbraco.businesslogic/BasePages/UmbracoEnsuredPage.cs @@ -7,6 +7,8 @@ using Umbraco.Core.IO; using Umbraco.Core.Logging; using umbraco.BusinessLogic; using umbraco.businesslogic.Exceptions; +using umbraco.interfaces; +using Umbraco.Core.Models; using Umbraco.Core.Security; namespace umbraco.BasePages @@ -16,7 +18,41 @@ namespace umbraco.BasePages ///
[Obsolete("This class has been superceded by Umbraco.Web.UI.Pages.UmbracoEnsuredPage")] public class UmbracoEnsuredPage : BasePage - { + { + /// + /// Performs an authorization check for the user against the requested entity/path and permission set, this is only relevant to content and media + /// + /// + /// + /// + protected void CheckPathAndPermissions(int entityId, UmbracoObjectTypes objectType, IAction actionToCheck) + { + if (objectType == UmbracoObjectTypes.Document || objectType == UmbracoObjectTypes.Media) + { + //check path access + + var entity = entityId == Constants.System.Root + ? UmbracoEntity.Root + : Services.EntityService.Get( + entityId, + objectType); + var hasAccess = CurrentUser.UserEntity.HasPathAccess( + entity, + Services.EntityService, + objectType == UmbracoObjectTypes.Document ? Constants.System.RecycleBinContent : Constants.System.RecycleBinMedia); + if (hasAccess == false) + throw new UserAuthorizationException(string.Format("The current user doesn't have access to the path '{0}'", entity.Path)); + + //only documents have action permissions + if (objectType == UmbracoObjectTypes.Document) + { + var allowedActions = ActionsResolver.Current.FromActionSymbols(CurrentUser.UserEntity.GetPermissions(entity.Path, Services.UserService)).ToArray(); + if (allowedActions.Contains(actionToCheck) == false) + throw new UserAuthorizationException(string.Format("The current user doesn't have permission to {0} on the path '{1}'", actionToCheck.Alias, entity.Path)); + } + } + } + /// /// Checks if the page exists outside of the /umbraco route, in which case the request will not have been authenticated for the back office /// so we'll force authentication. diff --git a/src/umbraco.cms/Actions/Action.cs b/src/umbraco.cms/Actions/Action.cs index 81c78ade1b..c7a9a6242b 100644 --- a/src/umbraco.cms/Actions/Action.cs +++ b/src/umbraco.cms/Actions/Action.cs @@ -128,30 +128,20 @@ namespace umbraco.BusinessLogic.Actions /// /// /// returns a list of actions that have an associated letter found in the action string list + [Obsolete("Use ActionsResolver.Current.FromActionSymbols instead")] public static List FromString(string actions) { - List list = new List(); - foreach (char c in actions.ToCharArray()) - { - IAction action = ActionsResolver.Current.Actions.ToList().Find( - delegate(IAction a) - { - return a.Letter == c; - } - ); - if (action != null) - list.Add(action); - } - return list; + return ActionsResolver.Current.FromActionSymbols(actions.ToCharArray().Select(x => x.ToString())).ToList(); } /// /// Returns the string representation of the actions that make up the actions collection /// /// + [Obsolete("Use ActionsResolver.Current.ToActionSymbols instead")] public static string ToString(List actions) { - string[] strMenu = Array.ConvertAll(actions.ToArray(), delegate(IAction a) { return (a.Letter.ToString(CultureInfo.InvariantCulture)); }); + string[] strMenu = Array.ConvertAll(actions.ToArray(), a => (a.Letter.ToString(CultureInfo.InvariantCulture))); return string.Join("", strMenu); } @@ -161,12 +151,7 @@ namespace umbraco.BusinessLogic.Actions /// public static List GetPermissionAssignable() { - return ActionsResolver.Current.Actions.ToList().FindAll( - delegate(IAction a) - { - return (a.CanBePermissionAssigned); - } - ); + return ActionsResolver.Current.Actions.ToList().FindAll(a => (a.CanBePermissionAssigned)); } ///