From 73bc5c6ec92d208f7c992c0ba4c90600b3d72e1a Mon Sep 17 00:00:00 2001 From: Claus Date: Wed, 9 Aug 2017 15:29:12 +0200 Subject: [PATCH] changes needed for blueprints to differentiate them from content items. --- src/Umbraco.Core/Models/Content.cs | 5 +- src/Umbraco.Core/Models/IContent.cs | 8 +-- src/Umbraco.Core/Services/ContentService.cs | 40 +++++++------ src/Umbraco.Core/UdiEntityType.cs | 2 + src/Umbraco.Web/Editors/ContentController.cs | 56 +++++++++---------- .../ContentEditing/ContentItemDisplay.cs | 12 +--- .../Models/Mapping/ContentModelMapper.cs | 7 +-- 7 files changed, 59 insertions(+), 71 deletions(-) diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index d7db11dc3b..ef16a78248 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -1,8 +1,5 @@ using System; -using System.Collections; -using System.Collections.Generic; using System.ComponentModel; -using System.Linq; using System.Reflection; using System.Runtime.Serialization; @@ -333,7 +330,7 @@ namespace Umbraco.Core.Models //turn off change tracking clone.DisableChangeTracking(); //need to manually clone this since it's not settable - clone._contentType = (IContentType)ContentType.DeepClone(); + clone._contentType = (IContentType)ContentType.DeepClone(); //this shouldn't really be needed since we're not tracking clone.ResetDirtyProperties(false); //re-enable tracking diff --git a/src/Umbraco.Core/Models/IContent.cs b/src/Umbraco.Core/Models/IContent.cs index 3c92b17ae6..3d385f1b36 100644 --- a/src/Umbraco.Core/Models/IContent.cs +++ b/src/Umbraco.Core/Models/IContent.cs @@ -1,7 +1,5 @@ using System; using System.ComponentModel; -using System.Diagnostics; -using Umbraco.Core.Persistence.Mappers; namespace Umbraco.Core.Models { @@ -84,11 +82,11 @@ namespace Umbraco.Core.Models /// /// Gets the unique identifier of the published version, if any. /// - Guid PublishedVersionGuid { get; } - + Guid PublishedVersionGuid { get; } + /// /// Gets a value indicating whether the content item is a blueprint. - /// + /// bool IsBlueprint { get; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 60788eb958..1ba94105f5 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -13,13 +13,11 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; - using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.UnitOfWork; using Umbraco.Core.Publishing; -using Umbraco.Core.Scoping; namespace Umbraco.Core.Services { @@ -1161,7 +1159,7 @@ namespace Umbraco.Core.Services using (var uow = UowProvider.GetUnitOfWork(readOnly: true)) { var repository = RepositoryFactory.CreateContentBlueprintRepository(uow); - var blueprint = repository.Get(id); + var blueprint = repository.Get(id); if (blueprint != null) ((Content) blueprint).IsBlueprint = true; return blueprint; @@ -1178,12 +1176,12 @@ namespace Umbraco.Core.Services var a = _idkMap.GetIdForKey(id, UmbracoObjectTypes.DocumentBlueprint); return a.Success ? GetBlueprintById(a.Result) : null; } - + public void SaveBlueprint(IContent content, int userId = 0) - { - //always ensure the blueprint is at the root + { + //always ensure the blueprint is at the root if (content.ParentId != -1) - content.ParentId = -1; + content.ParentId = -1; ((Content) content).IsBlueprint = true; @@ -1204,8 +1202,8 @@ namespace Umbraco.Core.Services } content.WriterId = userId; - repository.AddOrUpdate(content); - + repository.AddOrUpdate(content); + uow.Events.Dispatch(SavedBlueprint, this, new SaveEventArgs(content), "SavedBlueprint"); uow.Commit(); @@ -1220,7 +1218,7 @@ namespace Umbraco.Core.Services using (var uow = UowProvider.GetUnitOfWork()) { var repository = RepositoryFactory.CreateContentBlueprintRepository(uow); - repository.Delete(content); + repository.Delete(content); uow.Events.Dispatch(DeletedBlueprint, this, new DeleteEventArgs(content), "DeletedBlueprint"); uow.Commit(); } @@ -1236,8 +1234,8 @@ namespace Umbraco.Core.Services content.Path = string.Concat(content.ParentId.ToString(), ",", content.Id); content.CreatorId = userId; - content.WriterId = userId; - + content.WriterId = userId; + foreach (var property in blueprint.Properties) content.SetValue(property.Alias, property.Value); @@ -1683,21 +1681,21 @@ namespace Umbraco.Core.Services // Update the create author and last edit author copy.CreatorId = userId; copy.WriterId = userId; - + //get the current permissions, if there are any explicit ones they need to be copied var currentPermissions = GetPermissionsForEntity(content); - currentPermissions.RemoveWhere(p => p.IsDefaultPermissions); + currentPermissions.RemoveWhere(p => p.IsDefaultPermissions); repository.AddOrUpdate(copy); - repository.AddOrUpdatePreviewXml(copy, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c)); - + repository.AddOrUpdatePreviewXml(copy, c => _entitySerializer.Serialize(this, _dataTypeService, _userService, c)); + //add permissions if (currentPermissions.Count > 0) { var permissionSet = new ContentPermissionSet(copy, currentPermissions); - repository.AddOrUpdatePermissions(permissionSet); - } - + repository.AddOrUpdatePermissions(permissionSet); + } + uow.Commit(); // todo - this should flush, not commit //Special case for the associated tags @@ -2641,12 +2639,12 @@ namespace Umbraco.Core.Services /// Occurs after the Recycle Bin has been Emptied /// public static event TypedEventHandler EmptiedRecycleBin; - + /// /// Occurs after a blueprint has been saved. /// public static event TypedEventHandler> SavedBlueprint; - + /// /// Occurs after a blueprint has been deleted. /// diff --git a/src/Umbraco.Core/UdiEntityType.cs b/src/Umbraco.Core/UdiEntityType.cs index 30c9f5513a..fcaf718813 100644 --- a/src/Umbraco.Core/UdiEntityType.cs +++ b/src/Umbraco.Core/UdiEntityType.cs @@ -44,6 +44,8 @@ namespace Umbraco.Core [UdiType(UdiType.GuidUdi)] public const string DocumentTypeContainer = "document-type-container"; [UdiType(UdiType.GuidUdi)] + public const string DocumentTypeBluePrints = "document-type-blueprints"; + [UdiType(UdiType.GuidUdi)] public const string MediaType = "media-type"; [UdiType(UdiType.GuidUdi)] public const string MediaTypeContainer = "media-type-container"; diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 838e5db493..c8e598016a 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -9,7 +9,6 @@ using System.Web.Http; using System.Web.Http.Controllers; using System.Web.Http.ModelBinding; using AutoMapper; -using umbraco.BusinessLogic.Actions; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -81,8 +80,8 @@ namespace Umbraco.Web.Editors { var foundContent = Services.ContentService.GetByIds(ids); return foundContent.Select(Mapper.Map); - } - + } + /// /// Updates the permissions for a content item for a particular user group /// @@ -95,16 +94,16 @@ namespace Umbraco.Web.Editors public IEnumerable PostSaveUserGroupPermissions(UserGroupPermissionsSave saveModel) { if (saveModel.ContentId <= 0) throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); - + var content = Services.ContentService.GetById(saveModel.ContentId); if (content == null) throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); - + //current permissions explicitly assigned to this content item var contentPermissions = Services.ContentService.GetPermissionsForEntity(content) - .ToDictionary(x => x.UserGroupId, x => x); + .ToDictionary(x => x.UserGroupId, x => x); + + var allUserGroups = Services.UserService.GetAllUserGroups().ToArray(); - var allUserGroups = Services.UserService.GetAllUserGroups().ToArray(); - //loop through each user group foreach (var userGroup in allUserGroups) { @@ -114,8 +113,8 @@ namespace Umbraco.Web.Editors { //create a string collection of the assigned letters var groupPermissionCodes = groupPermissions.ToArray(); - - //check if there are no permissions assigned for this group save model, if that is the case we want to reset the permissions + + //check if there are no permissions assigned for this group save model, if that is the case we want to reset the permissions //for this group/node which will go back to the defaults if (groupPermissionCodes.Length == 0) { @@ -141,8 +140,8 @@ namespace Umbraco.Web.Editors } return GetDetailedPermissions(content, allUserGroups); - } - + } + /// /// Returns the user group permissions for user groups assigned to this node /// @@ -166,10 +165,10 @@ namespace Umbraco.Web.Editors private IEnumerable GetDetailedPermissions(IContent content, IEnumerable allUserGroups) { //get all user groups and map their default permissions to the AssignedUserGroupPermissions model. - //we do this because not all groups will have true assigned permissions for this node so if they don't have assigned permissions, we need to show the defaults. + //we do this because not all groups will have true assigned permissions for this node so if they don't have assigned permissions, we need to show the defaults. + + var defaultPermissionsByGroup = Mapper.Map>(allUserGroups).ToArray(); - var defaultPermissionsByGroup = Mapper.Map>(allUserGroups).ToArray(); - var defaultPermissionsAsDictionary = defaultPermissionsByGroup .ToDictionary(x => Convert.ToInt32(x.Id), x => x); @@ -180,9 +179,9 @@ namespace Umbraco.Web.Editors foreach (var assignedGroupPermission in assignedPermissionsByGroup) { var defaultUserGroupPermissions = defaultPermissionsAsDictionary[assignedGroupPermission.UserGroupId]; - + //clone the default permissions model to the assigned ones - defaultUserGroupPermissions.AssignedPermissions = AssignedUserGroupPermissions.ClonePermissions(defaultUserGroupPermissions.DefaultPermissions); + defaultUserGroupPermissions.AssignedPermissions = AssignedUserGroupPermissions.ClonePermissions(defaultUserGroupPermissions.DefaultPermissions); //since there is custom permissions assigned to this node for this group, we need to clear all of the default permissions //and we'll re-check it if it's one of the explicitly assigned ones @@ -192,10 +191,10 @@ namespace Umbraco.Web.Editors permission.Checked = assignedGroupPermission.AssignedPermissions.Contains(permission.PermissionCode, StringComparer.InvariantCulture); } - } - + } + return defaultPermissionsByGroup; - } + } /// /// Returns an item to be used to display the recycle bin for content @@ -243,6 +242,7 @@ namespace Umbraco.Web.Editors content.Path = string.Format("-1,{0},{1}", persistedContent.ContentTypeId, content.Id); content.AllowedActions = new[] {"A"}; + content.IsBlueprint = true; var excludeProps = new[] {"_umb_urls", "_umb_releasedate", "_umb_expiredate", "_umb_template"}; var propsTab = content.Tabs.Last(); @@ -428,7 +428,7 @@ namespace Umbraco.Web.Editors return Services.UserService .GetPermissions(Security.CurrentUser, nodeIds) .ToDictionary(x => x.EntityId, x => x.AssignedPermissions); - } + } /// /// Checks a nodes permission for the current user @@ -501,7 +501,7 @@ namespace Umbraco.Web.Editors var contentItemDisplay = PostSaveInternal(contentItem, content => { - EnsureUniqueName(content.Name, content, "Name"); + EnsureUniqueName(content.Name, content, "Name"); Services.ContentService.SaveBlueprint(contentItem.PersistedContent, Security.CurrentUser.Id); //we need to reuse the underlying logic so return the result that it wants @@ -522,7 +522,7 @@ namespace Umbraco.Web.Editors [ModelBinder(typeof(ContentItemBinder))] ContentItemSave contentItem) { - return PostSaveInternal(contentItem, + return PostSaveInternal(contentItem, content => Services.ContentService.WithResult().Save(contentItem.PersistedContent, Security.CurrentUser.Id)); } @@ -643,7 +643,7 @@ namespace Umbraco.Web.Editors display.PersistedContent = contentItem.PersistedContent; return display; - } + } /// /// Publishes a document with a given ID @@ -689,7 +689,7 @@ namespace Umbraco.Web.Editors return HandleContentNotFound(id, false); } - Services.ContentService.DeleteBlueprint(found); + Services.ContentService.DeleteBlueprint(found); return Request.CreateResponse(HttpStatusCode.OK); } @@ -1080,8 +1080,8 @@ namespace Umbraco.Web.Editors { return true; } - - //get the implicit/inherited permissions for the user for this path, + + //get the implicit/inherited permissions for the user for this path, //if there is no content item for this id, than just use the id as the path (i.e. -1 or -20) var path = contentItem != null ? contentItem.Path : nodeId.ToString(); var permission = userService.GetPermissionsForPath(user, path); @@ -1089,7 +1089,7 @@ namespace Umbraco.Web.Editors var allowed = true; foreach (var p in permissionsToCheck) { - if (permission == null + if (permission == null || permission.GetAllPermissions().Contains(p.ToString(CultureInfo.InvariantCulture)) == false) { allowed = false; diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs index c416f30a48..5d424e4dd3 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentItemDisplay.cs @@ -1,15 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Net.Http.Formatting; using System.Runtime.Serialization; -using System.Web.Http; -using System.Web.Http.ModelBinding; -using Umbraco.Core; using Umbraco.Core.Models; -using Umbraco.Core.Models.Validation; -using Umbraco.Web.Models.Trees; -using Umbraco.Web.Trees; namespace Umbraco.Web.Models.ContentEditing { @@ -57,6 +49,8 @@ namespace Umbraco.Web.Models.ContentEditing /// [DataMember(Name = "allowedActions")] public IEnumerable AllowedActions { get; set; } - + + [DataMember(Name = "isBlueprint")] + public bool IsBlueprint { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs index 3b55def135..1809bffd3d 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs @@ -4,7 +4,6 @@ using System.Globalization; using System.Linq; using System.Web; using System.Web.Mvc; -using System.Web.Routing; using AutoMapper; using Umbraco.Core; using Umbraco.Core.Models; @@ -28,7 +27,7 @@ namespace Umbraco.Web.Models.Mapping //FROM IContent TO ContentItemDisplay config.CreateMap() - .ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Document, content.Key))) + .ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(content.IsBlueprint ? Constants.UdiEntityType.DocumentBluePrint : Constants.UdiEntityType.Document, content.Key))) .ForMember(display => display.Owner, expression => expression.ResolveUsing(new OwnerResolver())) .ForMember(display => display.Updater, expression => expression.ResolveUsing(new CreatorResolver())) .ForMember(display => display.Icon, expression => expression.MapFrom(content => content.ContentType.Icon)) @@ -59,7 +58,7 @@ namespace Umbraco.Web.Models.Mapping //FROM IContent TO ContentItemBasic config.CreateMap>() - .ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Document, content.Key))) + .ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(content.IsBlueprint ? Constants.UdiEntityType.DocumentBluePrint : Constants.UdiEntityType.Document, content.Key))) .ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver())) .ForMember(dto => dto.Updater, expression => expression.ResolveUsing(new CreatorResolver())) .ForMember(dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon)) @@ -70,7 +69,7 @@ namespace Umbraco.Web.Models.Mapping //FROM IContent TO ContentItemDto config.CreateMap>() - .ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Document, content.Key))) + .ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(content.IsBlueprint ? Constants.UdiEntityType.DocumentBluePrint : Constants.UdiEntityType.Document, content.Key))) .ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver())) .ForMember(dto => dto.HasPublishedVersion, expression => expression.MapFrom(content => content.HasPublishedVersion)) .ForMember(dto => dto.Updater, expression => expression.Ignore())