From 37171d96bc65fbe8d2ce5cf89c0236e802b2880e Mon Sep 17 00:00:00 2001 From: Stephan Date: Wed, 13 Sep 2017 17:35:20 +0200 Subject: [PATCH] Port 7.7 - WIP --- .../Publishing/ScheduledPublisher.cs | 89 +++++ src/Umbraco.Core/Umbraco.Core.csproj | 1 + .../Cache/DataTypeCacheRefresher.cs | 13 +- src/Umbraco.Web/Editors/ContentController.cs | 1 - .../Editors/CurrentUserController.cs | 9 +- src/Umbraco.Web/Editors/EntityController.cs | 28 +- .../HtmlHelperBackOfficeExtensions.cs | 22 +- .../InstallSteps/ConfigureMachineKey.cs | 24 +- .../Models/DetachedPublishedProperty.cs | 36 +- .../UserGroupDefaultPermissionsResolver.cs | 1 + src/Umbraco.Web/Models/RelatedLink.cs | 2 +- .../Routing/RedirectTrackingEventHandler.cs | 327 ------------------ .../Scheduling/HealthCheckNotifier.cs | 51 +-- .../Scheduling/ScheduledPublishing.cs | 43 +-- .../Scheduling/SchedulerComponent.cs | 113 ++++-- .../Search/SearchableTreeCollection.cs | 2 +- .../Search/SearchableTreeResolver.cs | 51 --- src/Umbraco.Web/Security/WebSecurity.cs | 1 + .../Trees/ContentBlueprintTreeController.cs | 46 +-- .../Trees/ContentTreeController.cs | 2 +- .../Trees/LegacyBaseTreeAttribute.cs | 31 -- .../Trees/PackagesTreeController.cs | 1 - .../Trees/TemplatesTreeController.cs | 1 + src/Umbraco.Web/Trees/UserTreeController.cs | 14 - src/Umbraco.Web/Umbraco.Web.csproj | 91 +---- 25 files changed, 295 insertions(+), 705 deletions(-) create mode 100644 src/Umbraco.Core/Publishing/ScheduledPublisher.cs delete mode 100644 src/Umbraco.Web/Routing/RedirectTrackingEventHandler.cs delete mode 100644 src/Umbraco.Web/Search/SearchableTreeResolver.cs delete mode 100644 src/Umbraco.Web/Trees/LegacyBaseTreeAttribute.cs diff --git a/src/Umbraco.Core/Publishing/ScheduledPublisher.cs b/src/Umbraco.Core/Publishing/ScheduledPublisher.cs new file mode 100644 index 0000000000..acc21c6c95 --- /dev/null +++ b/src/Umbraco.Core/Publishing/ScheduledPublisher.cs @@ -0,0 +1,89 @@ +using System; +using System.Linq; +using Umbraco.Core.Logging; +using Umbraco.Core.Models; +using Umbraco.Core.Services; + +namespace Umbraco.Core.Publishing +{ + /// + /// Used to perform scheduled publishing/unpublishing + /// + internal class ScheduledPublisher + { + private readonly IContentService _contentService; + private readonly ILogger _logger; + + public ScheduledPublisher(IContentService contentService, ILogger logger) + { + _contentService = contentService; + _logger = logger; + } + + /// + /// Processes scheduled operations + /// + /// + /// Returns the number of items successfully completed + /// + public int CheckPendingAndProcess() + { + var counter = 0; + var contentForRelease = _contentService.GetContentForRelease().ToArray(); + if (contentForRelease.Length > 0) + _logger.Debug($"There's {contentForRelease.Length} item(s) of content to be published"); + foreach (var d in contentForRelease) + { + try + { + d.ReleaseDate = null; + var result = _contentService.SaveAndPublishWithStatus(d, d.GetWriterProfile().Id); + _logger.Debug($"Result of publish attempt: {result.Result.StatusType}"); + if (result.Success == false) + { + if (result.Exception != null) + { + _logger.Error("Could not published the document (" + d.Id + ") based on it's scheduled release, status result: " + result.Result.StatusType, result.Exception); + } + else + { + _logger.Warn("Could not published the document (" + d.Id + ") based on it's scheduled release. Status result: " + result.Result.StatusType); + } + } + else + { + counter++; + } + } + catch (Exception ee) + { + _logger.Error($"Error publishing node {d.Id}", ee); + throw; + } + } + + var contentForExpiration = _contentService.GetContentForExpiration().ToArray(); + if (contentForExpiration.Length > 0) + _logger.Debug($"There's {contentForExpiration.Length} item(s) of content to be unpublished"); + foreach (var d in contentForExpiration) + { + try + { + d.ExpireDate = null; + var result = _contentService.UnPublish(d, d.GetWriterProfile().Id); + if (result) + { + counter++; + } + } + catch (Exception ee) + { + _logger.Error($"Error unpublishing node {d.Id}", ee); + throw; + } + } + + return counter; + } + } +} diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index e2095c737b..8da2b86518 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -1264,6 +1264,7 @@ + diff --git a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs index 748e90469d..794a3d4d66 100644 --- a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs @@ -3,6 +3,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors.ValueConverters; using Umbraco.Core.Services; +using Umbraco.Web.PropertyEditors; using Umbraco.Web.PropertyEditors.ValueConverters; using Umbraco.Web.PublishedCache; @@ -50,15 +51,13 @@ namespace Umbraco.Web.Cache var dataTypeCache = CacheHelper.IsolatedRuntimeCache.GetCache(); - //clears the prevalue cache - if (dataTypeCache) - foreach (var payload in payloads) - dataTypeCache.Result.ClearCacheByKeySearch(CacheKeys.DataTypePreValuesCacheKey + "_" + payload.Id); - foreach (var payload in payloads) - { + { + if (dataTypeCache) + dataTypeCache.Result.ClearCacheByKeySearch(CacheKeys.DataTypePreValuesCacheKey + "_" + payload.Id); + _idkMap.ClearCache(payload.Id); -#error also nested content see 7.7 + NestedContentHelper.ClearCache(payload.Id); // fixme refactor nested content } // fixme - not sure I like these? diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index a7adf07049..ef61c17c57 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; diff --git a/src/Umbraco.Web/Editors/CurrentUserController.cs b/src/Umbraco.Web/Editors/CurrentUserController.cs index 1dc431b069..f97f389c9d 100644 --- a/src/Umbraco.Web/Editors/CurrentUserController.cs +++ b/src/Umbraco.Web/Editors/CurrentUserController.cs @@ -1,6 +1,8 @@ -using System.Collections.Generic; +using System.Net.Http; +using System.Threading.Tasks; using System.Web.Http; -using Umbraco.Core.Services; +using AutoMapper; +using Umbraco.Core.Composing; using Umbraco.Core.Services; using Umbraco.Web.Models; using Umbraco.Web.Models.ContentEditing; @@ -8,7 +10,6 @@ using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; using Umbraco.Core.Security; using Umbraco.Web.WebApi.Filters; -using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Editors @@ -66,7 +67,7 @@ namespace Umbraco.Web.Editors public async Task PostSetAvatar() { //borrow the logic from the user controller - return await UsersController.PostSetAvatarInternal(Request, Services.UserService, ApplicationContext.ApplicationCache.StaticCache, Security.GetUserId()); + return await UsersController.PostSetAvatarInternal(Request, Services.UserService, Current.ApplicationCache.StaticCache, Security.GetUserId()); } /// diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index f5f18e995e..ce8fd3341f 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -1,10 +1,7 @@ using System; -using System.Collections; using System.Collections.Generic; using System.ComponentModel; -using System.Globalization; using System.Net; -using System.Text; using System.Web.Http; using AutoMapper; using Umbraco.Core; @@ -16,8 +13,6 @@ using System.Net.Http; using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models; using Constants = Umbraco.Core.Constants; -using Examine; -using System.Text.RegularExpressions; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using System.Web.Http.Controllers; using Umbraco.Core.Xml; @@ -36,7 +31,6 @@ namespace Umbraco.Web.Editors [PluginController("UmbracoApi")] public class EntityController : UmbracoAuthorizedJsonController { - /// /// Configures this controller with a custom action selector /// @@ -56,6 +50,12 @@ namespace Umbraco.Web.Editors } private readonly UmbracoTreeSearcher _treeSearcher = new UmbracoTreeSearcher(); + private readonly SearchableTreeCollection _searchableTreeCollection; + + public EntityController(SearchableTreeCollection searchableTreeCollection) + { + _searchableTreeCollection = searchableTreeCollection; + } /// /// Returns an Umbraco alias given a string @@ -65,7 +65,7 @@ namespace Umbraco.Web.Editors /// public dynamic GetSafeAlias(string value, bool camelCase = true) { - var returnValue = (string.IsNullOrWhiteSpace(value)) ? string.Empty : value.ToSafeAlias(camelCase); + var returnValue = string.IsNullOrWhiteSpace(value) ? string.Empty : value.ToSafeAlias(camelCase); dynamic returnObj = new System.Dynamic.ExpandoObject(); returnObj.alias = returnValue; returnObj.original = value; @@ -107,7 +107,7 @@ namespace Umbraco.Web.Editors /// /// The reason a user is allowed to search individual entity types that they are not allowed to edit is because those search /// methods might be used in things like pickers in the content editor. - /// + /// [HttpGet] public IDictionary SearchAll(string query) { @@ -115,17 +115,17 @@ namespace Umbraco.Web.Editors if (string.IsNullOrEmpty(query)) return result; - + var allowedSections = Security.CurrentUser.AllowedSections.ToArray(); - var searchableTrees = SearchableTreeResolver.Current.GetSearchableTrees(); - + var searchableTrees = _searchableTreeCollection.AsReadOnlyDictionary(); + foreach (var searchableTree in searchableTrees) { if (allowedSections.Contains(searchableTree.Value.AppAlias)) { var tree = Services.ApplicationTreeService.GetByAlias(searchableTree.Key); if (tree == null) continue; //shouldn't occur - #error why cannot we use a collectino? + var searchableTreeAttribute = searchableTree.Value.SearchableTree.GetType().GetCustomAttribute(false); var treeAttribute = tree.GetTreeAttribute(); @@ -140,7 +140,7 @@ namespace Umbraco.Web.Editors JsFormatterMethod = searchableTreeAttribute == null ? "" : searchableTreeAttribute.MethodName }; } - } + } return result; } @@ -616,7 +616,7 @@ namespace Umbraco.Web.Editors return _treeSearcher.ExamineSearch(Umbraco, query, entityType, 200, 0, out total, searchFrom); } - + private IEnumerable GetResultForChildren(int id, UmbracoEntityTypes entityType) diff --git a/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs b/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs index 50fe829e1a..fe835e950c 100644 --- a/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs +++ b/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs @@ -1,40 +1,28 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; +using System.Collections.Generic; using System.Linq; using System.Text; using System.Web; using System.Web.Mvc; -using ClientDependency.Core.Config; using Microsoft.Owin.Security; using Newtonsoft.Json; -using Umbraco.Core; -using Umbraco.Core.Configuration; +using Umbraco.Core.Composing; using Umbraco.Web.Editors; using Umbraco.Web.Models; namespace Umbraco.Web { - using Umbraco.Core.Configuration; + using Core.Configuration; /// /// HtmlHelper extensions for the back office /// public static class HtmlHelperBackOfficeExtensions { - [Obsolete("Use the overload with all required parameters instead")] - [EditorBrowsable(EditorBrowsableState.Never)] - public static IHtmlString BareMinimumServerVariablesScript(this HtmlHelper html, UrlHelper uri, string externalLoginsUrl) - { - return html.BareMinimumServerVariablesScript(uri, ApplicationContext.Current, externalLoginsUrl); - } - /// /// Outputs a script tag containing the bare minimum (non secure) server vars for use with the angular app /// /// /// - /// /// /// The post url used to sign in with external logins - this can change depending on for what service the external login is service. /// Example: normal back office login or authenticating upgrade login @@ -44,9 +32,9 @@ namespace Umbraco.Web /// These are the bare minimal server variables that are required for the application to start without being authenticated, /// we will load the rest of the server vars after the user is authenticated. /// - public static IHtmlString BareMinimumServerVariablesScript(this HtmlHelper html, UrlHelper uri, ApplicationContext appCtx, string externalLoginsUrl) + public static IHtmlString BareMinimumServerVariablesScript(this HtmlHelper html, UrlHelper uri, string externalLoginsUrl) { - var serverVars = new BackOfficeServerVariables(uri, appCtx, UmbracoConfig.For.UmbracoSettings()); + var serverVars = new BackOfficeServerVariables(uri, Current.RuntimeState); var minVars = serverVars.BareMinimumServerVariables(); var str = @"