using System; using System.Collections.Generic; using System.Linq; using System.Net.Http.Formatting; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; using Umbraco.Web.Trees.Menu; using umbraco; using umbraco.BusinessLogic.Actions; namespace Umbraco.Web.Trees { public abstract class ContentTreeControllerBase : TreeApiController { /// /// Returns the /// protected abstract int RecycleBinId { get; } /// /// Returns true if the recycle bin has items in it /// protected abstract bool RecycleBinSmells { get; } protected abstract TreeNodeCollection PerformGetTreeNodes(string id, FormDataCollection queryStrings); protected abstract MenuItemCollection PerformGetMenuForNode(string id, FormDataCollection queryStrings); protected abstract UmbracoObjectTypes UmbracoObjectType { get; } protected IEnumerable GetChildEntities(string id) { int iid; if (int.TryParse(id, out iid) == false) { throw new InvalidCastException("The id for the media tree must be an integer"); } //if a request is made for the root node data but the user's start node is not the default, then // we need to return their start node data if (iid == Constants.System.Root && UmbracoUser.StartNodeId != Constants.System.Root) { return Services.EntityService.GetChildren(UmbracoUser.StartNodeId, UmbracoObjectType).ToArray(); } return Services.EntityService.GetChildren(iid, UmbracoObjectType).ToArray(); } /// /// This will automatically check if the recycle bin needs to be rendered (i.e. its the first level) /// and will automatically append it to the result of GetChildNodes. /// /// /// /// protected sealed override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) { if (id == Constants.System.Root.ToInvariantString()) { //we need to append the recycle bin to the end var nodes = PerformGetTreeNodes(id, queryStrings); nodes.Add(CreateTreeNode( Constants.System.RecycleBinContent.ToInvariantString(), queryStrings, ui.GetText("general", "recycleBin"), "icon-trash", RecycleBinSmells, queryStrings.GetValue("application") + TreeAlias.EnsureStartsWith('/') + "/recyclebin")); return nodes; } return PerformGetTreeNodes(id, queryStrings); } /// /// Checks if the menu requested is for the recycle bin and renders that, otherwise renders the result of PerformGetMenuForNode /// /// /// /// protected sealed override MenuItemCollection GetMenuForNode(string id, FormDataCollection queryStrings) { if (RecycleBinId.ToInvariantString() == id) { var menu = new MenuItemCollection(); menu.AddMenuItem(); menu.AddMenuItem(true); return menu; } return PerformGetMenuForNode(id, queryStrings); } /// /// Based on the allowed actions, this will filter the ones that the current user is allowed /// /// /// /// protected MenuItemCollection GetUserAllowedMenuItems(IEnumerable allMenuItems, IEnumerable userAllowedMenuItems) { var userAllowedActions = userAllowedMenuItems.Where(x => x.Action != null).Select(x => x.Action).ToArray(); return new MenuItemCollection(allMenuItems.Where( a => (a.Action == null || a.Action.CanBePermissionAssigned == false || (a.Action.CanBePermissionAssigned && userAllowedActions.Contains(a.Action))))); } internal MenuItemCollection GetUserMenuItemsForNode(IUmbracoEntity dd) { var actions = global::umbraco.BusinessLogic.Actions.Action.FromString(UmbracoUser.GetPermissions(dd.Path)); // A user is allowed to delete their own stuff if (dd.CreatorId == UmbracoUser.Id && actions.Contains(ActionDelete.Instance) == false) actions.Add(ActionDelete.Instance); return new MenuItemCollection(actions.Select(x => new MenuItem(x))); } /// /// Determins if the user has access to view the node/document /// /// The Document to check permissions against /// A list of MenuItems that the user has permissions to execute on the current document /// By default the user must have Browse permissions to see the node in the Content tree /// internal bool CanUserAccessNode(IUmbracoEntity doc, IEnumerable allowedUserOptions) { return allowedUserOptions.Select(x => x.Action).OfType().Any(); } } }