From b57a7690f573de5763d8cdb367bac3a40bf09feb Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 13 Feb 2020 11:21:20 +0100 Subject: [PATCH] Moved More files to infrastructure/abstractions --- src/Umbraco.Abstractions/Constants-Web.cs | 15 ++++++ .../Cookie/ICookieManager.cs | 7 +++ .../Models/ContentEditing/LinkDisplay.cs | 2 +- ...UmbracoContextPublishedSnapshotAccessor.cs | 1 - .../PublishedContentExtensions.cs | 36 +++++++++++++ .../Templates/HtmlImageSourceParser.cs | 0 .../Templates/HtmlLocalLinkParser.cs | 3 -- .../Templates/HtmlUrlParser.cs | 0 .../UmbracoContextReference.cs | 5 +- .../Cache/DistributedCacheExtensions.cs | 5 +- .../PostMigrations/ClearCsrfCookies.cs | 26 +++++++++ .../NoopPublishedSnapshotRebuilder.cs | 12 +++++ .../PublishedSnapshotRebuilder.cs | 25 +++++++-- .../MultiUrlPickerPropertyEditor.cs | 7 +-- .../MultiUrlPickerValueEditor.cs | 13 ++--- .../NestedContentPropertyEditor.cs | 5 +- .../ContentPickerValueConverter.cs | 0 .../MediaPickerValueConverter.cs | 0 .../MemberPickerValueConverter.cs | 8 +-- .../MultiNodeTreePickerValueConverter.cs | 9 ++-- .../MultiUrlPickerValueConverter.cs | 13 +++-- .../NestedContentManyValueConverter.cs | 0 .../NestedContentSingleValueConverter.cs | 0 .../NestedContentValueConverterBase.cs | 0 .../TextStringValueConverter.cs | 1 - .../Runtime/CoreInitialComposer.cs | 6 ++- .../ContentTypeServiceVariantsTests.cs | 1 + .../Cache/DistributedCacheBinder_Handlers.cs | 1 + src/Umbraco.Web/Editors/TourController.cs | 8 ++- .../PostMigrations/ClearCsrfCookies.cs | 21 -------- .../PublishedSnapshotRebuilder.cs | 31 ----------- src/Umbraco.Web/Models/LoginStatusModel.cs | 1 - .../Models/Mapping/CommonMapper.cs | 12 +++-- ...dateMvcAngularAntiForgeryTokenAttribute.cs | 2 +- src/Umbraco.Web/Net/AspNetCookieManager.cs | 19 +++++++ .../PropertyEditors/RichTextPropertyEditor.cs | 2 +- .../MarkdownEditorValueConverter.cs | 53 ------------------- src/Umbraco.Web/PublishedContentExtensions.cs | 18 ++----- src/Umbraco.Web/Runtime/WebInitialComposer.cs | 5 +- src/Umbraco.Web/Umbraco.Web.csproj | 26 ++------- src/Umbraco.Web/UmbracoContextFactory.cs | 4 +- .../Filters/AngularAntiForgeryHelper.cs | 21 ++------ .../ClearAngularAntiForgeryTokenAttribute.cs | 4 +- .../SetAngularAntiForgeryTokensAttribute.cs | 8 +-- 44 files changed, 211 insertions(+), 225 deletions(-) create mode 100644 src/Umbraco.Abstractions/Cookie/ICookieManager.cs rename src/{Umbraco.Web => Umbraco.Abstractions}/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs (99%) rename src/{Umbraco.Web => Umbraco.Abstractions}/Templates/HtmlImageSourceParser.cs (100%) rename src/{Umbraco.Web => Umbraco.Abstractions}/Templates/HtmlLocalLinkParser.cs (97%) rename src/{Umbraco.Web => Umbraco.Abstractions}/Templates/HtmlUrlParser.cs (100%) rename src/{Umbraco.Web => Umbraco.Abstractions}/UmbracoContextReference.cs (88%) rename src/{Umbraco.Web => Umbraco.Infrastructure}/Cache/DistributedCacheExtensions.cs (98%) create mode 100644 src/Umbraco.Infrastructure/Migrations/PostMigrations/ClearCsrfCookies.cs create mode 100644 src/Umbraco.Infrastructure/Migrations/PostMigrations/NoopPublishedSnapshotRebuilder.cs rename src/{Umbraco.Web => Umbraco.Infrastructure}/PropertyEditors/MultiUrlPickerPropertyEditor.cs (87%) rename src/{Umbraco.Web => Umbraco.Infrastructure}/PropertyEditors/MultiUrlPickerValueEditor.cs (93%) rename src/{Umbraco.Web => Umbraco.Infrastructure}/PropertyEditors/NestedContentPropertyEditor.cs (99%) rename src/{Umbraco.Web => Umbraco.Infrastructure}/PropertyEditors/ValueConverters/ContentPickerValueConverter.cs (100%) rename src/{Umbraco.Web => Umbraco.Infrastructure}/PropertyEditors/ValueConverters/MediaPickerValueConverter.cs (100%) rename src/{Umbraco.Web => Umbraco.Infrastructure}/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs (90%) rename src/{Umbraco.Web => Umbraco.Infrastructure}/PropertyEditors/ValueConverters/MultiNodeTreePickerValueConverter.cs (96%) rename src/{Umbraco.Web => Umbraco.Infrastructure}/PropertyEditors/ValueConverters/MultiUrlPickerValueConverter.cs (85%) rename src/{Umbraco.Web => Umbraco.Infrastructure}/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs (100%) rename src/{Umbraco.Web => Umbraco.Infrastructure}/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs (100%) rename src/{Umbraco.Web => Umbraco.Infrastructure}/PropertyEditors/ValueConverters/NestedContentValueConverterBase.cs (100%) rename src/{Umbraco.Web => Umbraco.Infrastructure}/PropertyEditors/ValueConverters/TextStringValueConverter.cs (98%) delete mode 100644 src/Umbraco.Web/Migrations/PostMigrations/ClearCsrfCookies.cs delete mode 100644 src/Umbraco.Web/Migrations/PostMigrations/PublishedSnapshotRebuilder.cs create mode 100644 src/Umbraco.Web/Net/AspNetCookieManager.cs delete mode 100644 src/Umbraco.Web/PropertyEditors/ValueConverters/MarkdownEditorValueConverter.cs diff --git a/src/Umbraco.Abstractions/Constants-Web.cs b/src/Umbraco.Abstractions/Constants-Web.cs index 64216ba571..a1e138116d 100644 --- a/src/Umbraco.Abstractions/Constants-Web.cs +++ b/src/Umbraco.Abstractions/Constants-Web.cs @@ -19,6 +19,21 @@ public const string PreviewCookieName = "UMB_PREVIEW"; public const string InstallerCookieName = "umb_installId"; + + /// + /// The cookie name that is used to store the validation value + /// + public const string CsrfValidationCookieName = "UMB-XSRF-V"; + + /// + /// The cookie name that is set for angular to use to pass in to the header value for "X-UMB-XSRF-TOKEN" + /// + public const string AngularCookieName = "UMB-XSRF-TOKEN"; + + /// + /// The header name that angular uses to pass in the token to validate the cookie + /// + public const string AngularHeadername = "X-UMB-XSRF-TOKEN"; } } } diff --git a/src/Umbraco.Abstractions/Cookie/ICookieManager.cs b/src/Umbraco.Abstractions/Cookie/ICookieManager.cs new file mode 100644 index 0000000000..4822d8ce74 --- /dev/null +++ b/src/Umbraco.Abstractions/Cookie/ICookieManager.cs @@ -0,0 +1,7 @@ +namespace Umbraco.Core.Cookie +{ + public interface ICookieManager + { + void ExpireCookie(string angularCookieName); + } +} diff --git a/src/Umbraco.Abstractions/Models/ContentEditing/LinkDisplay.cs b/src/Umbraco.Abstractions/Models/ContentEditing/LinkDisplay.cs index 650b7b8db5..5b6379288f 100644 --- a/src/Umbraco.Abstractions/Models/ContentEditing/LinkDisplay.cs +++ b/src/Umbraco.Abstractions/Models/ContentEditing/LinkDisplay.cs @@ -4,7 +4,7 @@ using Umbraco.Core; namespace Umbraco.Web.Models.ContentEditing { [DataContract(Name = "link", Namespace = "")] - internal class LinkDisplay + public class LinkDisplay { [DataMember(Name = "icon")] public string Icon { get; set; } diff --git a/src/Umbraco.Web/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs b/src/Umbraco.Abstractions/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs similarity index 99% rename from src/Umbraco.Web/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs rename to src/Umbraco.Abstractions/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs index 76936dd2cb..7e0ebc6f13 100644 --- a/src/Umbraco.Web/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs +++ b/src/Umbraco.Abstractions/PublishedCache/UmbracoContextPublishedSnapshotAccessor.cs @@ -1,5 +1,4 @@ using System; - namespace Umbraco.Web.PublishedCache { public class UmbracoContextPublishedSnapshotAccessor : IPublishedSnapshotAccessor diff --git a/src/Umbraco.Abstractions/PublishedContentExtensions.cs b/src/Umbraco.Abstractions/PublishedContentExtensions.cs index aa432459dd..6132659977 100644 --- a/src/Umbraco.Abstractions/PublishedContentExtensions.cs +++ b/src/Umbraco.Abstractions/PublishedContentExtensions.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using System.Linq; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; +using Umbraco.Web; using Umbraco.Web.PublishedCache; +using Umbraco.Web.Routing; namespace Umbraco.Core { @@ -1075,5 +1077,39 @@ namespace Umbraco.Core } #endregion + + #region Url + + /// + /// Gets the url of the content item. + /// + /// + /// If the content item is a document, then this method returns the url of the + /// document. If it is a media, then this methods return the media url for the + /// 'umbracoFile' property. Use the MediaUrl() method to get the media url for other + /// properties. + /// The value of this property is contextual. It depends on the 'current' request uri, + /// if any. In addition, when the content type is multi-lingual, this is the url for the + /// specified culture. Otherwise, it is the invariant url. + /// + public static string Url(this IPublishedContent content, IPublishedUrlProvider publishedUrlProvider, string culture = null, UrlMode mode = UrlMode.Default) + { + if (publishedUrlProvider == null) + throw new InvalidOperationException("Cannot resolve a Url when Current.UmbracoContext.UrlProvider is null."); + + switch (content.ContentType.ItemType) + { + case PublishedItemType.Content: + return publishedUrlProvider.GetUrl(content, mode, culture); + + case PublishedItemType.Media: + return publishedUrlProvider.GetMediaUrl(content, mode, culture, Constants.Conventions.Media.File); + + default: + throw new NotSupportedException(); + } + } + + #endregion } } diff --git a/src/Umbraco.Web/Templates/HtmlImageSourceParser.cs b/src/Umbraco.Abstractions/Templates/HtmlImageSourceParser.cs similarity index 100% rename from src/Umbraco.Web/Templates/HtmlImageSourceParser.cs rename to src/Umbraco.Abstractions/Templates/HtmlImageSourceParser.cs diff --git a/src/Umbraco.Web/Templates/HtmlLocalLinkParser.cs b/src/Umbraco.Abstractions/Templates/HtmlLocalLinkParser.cs similarity index 97% rename from src/Umbraco.Web/Templates/HtmlLocalLinkParser.cs rename to src/Umbraco.Abstractions/Templates/HtmlLocalLinkParser.cs index ef89088a7a..fd9177569a 100644 --- a/src/Umbraco.Web/Templates/HtmlLocalLinkParser.cs +++ b/src/Umbraco.Abstractions/Templates/HtmlLocalLinkParser.cs @@ -2,9 +2,6 @@ using System.Collections.Generic; using System.Text.RegularExpressions; using Umbraco.Core; -using Umbraco.Core.Logging; -using Umbraco.Web.PublishedCache; -using Umbraco.Web.Routing; namespace Umbraco.Web.Templates { diff --git a/src/Umbraco.Web/Templates/HtmlUrlParser.cs b/src/Umbraco.Abstractions/Templates/HtmlUrlParser.cs similarity index 100% rename from src/Umbraco.Web/Templates/HtmlUrlParser.cs rename to src/Umbraco.Abstractions/Templates/HtmlUrlParser.cs diff --git a/src/Umbraco.Web/UmbracoContextReference.cs b/src/Umbraco.Abstractions/UmbracoContextReference.cs similarity index 88% rename from src/Umbraco.Web/UmbracoContextReference.cs rename to src/Umbraco.Abstractions/UmbracoContextReference.cs index 740f972bbf..b282932d9f 100644 --- a/src/Umbraco.Web/UmbracoContextReference.cs +++ b/src/Umbraco.Abstractions/UmbracoContextReference.cs @@ -20,9 +20,8 @@ namespace Umbraco.Web /// /// Initializes a new instance of the class. /// - internal UmbracoContextReference(IUmbracoContext umbracoContext, bool isRoot, IUmbracoContextAccessor umbracoContextAccessor) + internal UmbracoContextReference(bool isRoot, IUmbracoContextAccessor umbracoContextAccessor) { - UmbracoContext = umbracoContext; IsRoot = isRoot; _umbracoContextAccessor = umbracoContextAccessor; @@ -31,7 +30,7 @@ namespace Umbraco.Web /// /// Gets the . /// - public IUmbracoContext UmbracoContext { get; } + public IUmbracoContext UmbracoContext => _umbracoContextAccessor.UmbracoContext; /// /// Gets a value indicating whether the reference is a root reference. diff --git a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs b/src/Umbraco.Infrastructure/Cache/DistributedCacheExtensions.cs similarity index 98% rename from src/Umbraco.Web/Cache/DistributedCacheExtensions.cs rename to src/Umbraco.Infrastructure/Cache/DistributedCacheExtensions.cs index 1c3b6a1dcc..7cfac1b9a0 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs +++ b/src/Umbraco.Infrastructure/Cache/DistributedCacheExtensions.cs @@ -1,8 +1,5 @@ using System.Linq; -using NPoco.Expressions; -using Umbraco.Core.Cache; using Umbraco.Core.Models; -using Umbraco.Core.Serialization; using Umbraco.Core.Services.Changes; namespace Umbraco.Web.Cache @@ -10,7 +7,7 @@ namespace Umbraco.Web.Cache /// /// Extension methods for . /// - internal static class DistributedCacheExtensions + public static class DistributedCacheExtensions { #region PublicAccessCache diff --git a/src/Umbraco.Infrastructure/Migrations/PostMigrations/ClearCsrfCookies.cs b/src/Umbraco.Infrastructure/Migrations/PostMigrations/ClearCsrfCookies.cs new file mode 100644 index 0000000000..ab9c946e05 --- /dev/null +++ b/src/Umbraco.Infrastructure/Migrations/PostMigrations/ClearCsrfCookies.cs @@ -0,0 +1,26 @@ +using Umbraco.Core; +using Umbraco.Core.Cookie; +using Umbraco.Core.Migrations; + + +namespace Umbraco.Web.Migrations.PostMigrations +{ + /// + /// Clears Csrf tokens. + /// + public class ClearCsrfCookies : IMigration + { + private readonly ICookieManager _cookieManager; + + public ClearCsrfCookies(ICookieManager cookieManager) + { + _cookieManager = cookieManager; + } + + public void Migrate() + { + _cookieManager.ExpireCookie(Constants.Web.AngularCookieName); + _cookieManager.ExpireCookie(Constants.Web.CsrfValidationCookieName); + } + } +} diff --git a/src/Umbraco.Infrastructure/Migrations/PostMigrations/NoopPublishedSnapshotRebuilder.cs b/src/Umbraco.Infrastructure/Migrations/PostMigrations/NoopPublishedSnapshotRebuilder.cs new file mode 100644 index 0000000000..cf53f161a4 --- /dev/null +++ b/src/Umbraco.Infrastructure/Migrations/PostMigrations/NoopPublishedSnapshotRebuilder.cs @@ -0,0 +1,12 @@ +namespace Umbraco.Core.Migrations.PostMigrations +{ + /// + /// Implements in Umbraco.Core (doing nothing). + /// + public class NoopPublishedSnapshotRebuilder : IPublishedSnapshotRebuilder + { + /// + public void Rebuild() + { } + } +} diff --git a/src/Umbraco.Infrastructure/Migrations/PostMigrations/PublishedSnapshotRebuilder.cs b/src/Umbraco.Infrastructure/Migrations/PostMigrations/PublishedSnapshotRebuilder.cs index acc943b297..764e46af5d 100644 --- a/src/Umbraco.Infrastructure/Migrations/PostMigrations/PublishedSnapshotRebuilder.cs +++ b/src/Umbraco.Infrastructure/Migrations/PostMigrations/PublishedSnapshotRebuilder.cs @@ -1,12 +1,31 @@ -namespace Umbraco.Core.Migrations.PostMigrations +using Umbraco.Core.Migrations.PostMigrations; +using Umbraco.Web.Cache; +using Umbraco.Web.PublishedCache; + +namespace Umbraco.Web.Migrations.PostMigrations { /// - /// Implements in Umbraco.Core (doing nothing). + /// Implements in Umbraco.Web (rebuilding). /// public class PublishedSnapshotRebuilder : IPublishedSnapshotRebuilder { + private readonly IPublishedSnapshotService _publishedSnapshotService; + private readonly DistributedCache _distributedCache; + + /// + /// Initializes a new instance of the class. + /// + public PublishedSnapshotRebuilder(IPublishedSnapshotService publishedSnapshotService, DistributedCache distributedCache) + { + _publishedSnapshotService = publishedSnapshotService; + _distributedCache = distributedCache; + } + /// public void Rebuild() - { } + { + _publishedSnapshotService.Rebuild(); + _distributedCache.RefreshAllPublishedSnapshot(); + } } } diff --git a/src/Umbraco.Web/PropertyEditors/MultiUrlPickerPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerPropertyEditor.cs similarity index 87% rename from src/Umbraco.Web/PropertyEditors/MultiUrlPickerPropertyEditor.cs rename to src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerPropertyEditor.cs index 1501abc071..203003548f 100644 --- a/src/Umbraco.Web/PropertyEditors/MultiUrlPickerPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerPropertyEditor.cs @@ -1,6 +1,5 @@ using System; using Umbraco.Core; -using Umbraco.Web.Composing; using Umbraco.Core.IO; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Logging; @@ -23,17 +22,19 @@ namespace Umbraco.Web.PropertyEditors private readonly Lazy _entityService; private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; private readonly IIOHelper _ioHelper; + private readonly IUmbracoContextAccessor _umbracoContextAccessor; - public MultiUrlPickerPropertyEditor(ILogger logger, Lazy entityService, IPublishedSnapshotAccessor publishedSnapshotAccessor, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IIOHelper ioHelper, IShortStringHelper shortStringHelper) + public MultiUrlPickerPropertyEditor(ILogger logger, Lazy entityService, IPublishedSnapshotAccessor publishedSnapshotAccessor, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IIOHelper ioHelper, IShortStringHelper shortStringHelper, IUmbracoContextAccessor umbracoContextAccessor) : base(logger, dataTypeService, localizationService, localizedTextService, shortStringHelper, EditorType.PropertyValue) { _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); _publishedSnapshotAccessor = publishedSnapshotAccessor ?? throw new ArgumentNullException(nameof(publishedSnapshotAccessor)); _ioHelper = ioHelper; + _umbracoContextAccessor = umbracoContextAccessor; } protected override IConfigurationEditor CreateConfigurationEditor() => new MultiUrlPickerConfigurationEditor(_ioHelper); - protected override IDataValueEditor CreateValueEditor() => new MultiUrlPickerValueEditor(_entityService.Value, _publishedSnapshotAccessor, Logger, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, Attribute); + protected override IDataValueEditor CreateValueEditor() => new MultiUrlPickerValueEditor(_entityService.Value, _publishedSnapshotAccessor, Logger, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper, Attribute, _umbracoContextAccessor); } } diff --git a/src/Umbraco.Web/PropertyEditors/MultiUrlPickerValueEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerValueEditor.cs similarity index 93% rename from src/Umbraco.Web/PropertyEditors/MultiUrlPickerValueEditor.cs rename to src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerValueEditor.cs index ab0f927f47..f34a6a0139 100644 --- a/src/Umbraco.Web/PropertyEditors/MultiUrlPickerValueEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/MultiUrlPickerValueEditor.cs @@ -11,24 +11,25 @@ using Umbraco.Core.Models.Entities; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Core.Strings; -using Umbraco.Web.Composing; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.PublishedCache; - +using Umbraco.Core; namespace Umbraco.Web.PropertyEditors { public class MultiUrlPickerValueEditor : DataValueEditor, IDataValueReference { private readonly IEntityService _entityService; private readonly ILogger _logger; + private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; - public MultiUrlPickerValueEditor(IEntityService entityService, IPublishedSnapshotAccessor publishedSnapshotAccessor, ILogger logger, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, DataEditorAttribute attribute) + public MultiUrlPickerValueEditor(IEntityService entityService, IPublishedSnapshotAccessor publishedSnapshotAccessor, ILogger logger, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, DataEditorAttribute attribute, IUmbracoContextAccessor umbracoContextAccessor) : base(dataTypeService, localizationService, localizedTextService, shortStringHelper, attribute) { _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); _publishedSnapshotAccessor = publishedSnapshotAccessor ?? throw new ArgumentNullException(nameof(publishedSnapshotAccessor)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); } public override object ToEditor(IProperty property, string culture = null, string segment = null) @@ -84,7 +85,7 @@ namespace Umbraco.Web.PropertyEditors icon = documentEntity.ContentTypeIcon; published = culture == null ? documentEntity.Published : documentEntity.PublishedCultures.Contains(culture); udi = new GuidUdi(Constants.UdiEntityType.Document, documentEntity.Key); - url = _publishedSnapshotAccessor.PublishedSnapshot.Content.GetById(entity.Key)?.Url() ?? "#"; + url = _publishedSnapshotAccessor.PublishedSnapshot.Content.GetById(entity.Key)?.Url(_umbracoContextAccessor.UmbracoContext.UrlProvider) ?? "#"; trashed = documentEntity.Trashed; } else if(entity is IContentEntitySlim contentEntity) @@ -92,7 +93,7 @@ namespace Umbraco.Web.PropertyEditors icon = contentEntity.ContentTypeIcon; published = !contentEntity.Trashed; udi = new GuidUdi(Constants.UdiEntityType.Media, contentEntity.Key); - url = _publishedSnapshotAccessor.PublishedSnapshot.Media.GetById(entity.Key)?.Url() ?? "#"; + url = _publishedSnapshotAccessor.PublishedSnapshot.Media.GetById(entity.Key)?.Url(_umbracoContextAccessor.UmbracoContext.UrlProvider) ?? "#"; trashed = contentEntity.Trashed; } else @@ -160,7 +161,7 @@ namespace Umbraco.Web.PropertyEditors } [DataContract] - internal class LinkDto + public class LinkDto { [DataMember(Name = "name")] public string Name { get; set; } diff --git a/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs similarity index 99% rename from src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs rename to src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs index f55e792189..70490af1a3 100644 --- a/src/Umbraco.Web/PropertyEditors/NestedContentPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs @@ -6,7 +6,6 @@ using System.Text.RegularExpressions; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core; -using Umbraco.Web.Composing; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -316,14 +315,14 @@ namespace Umbraco.Web.PropertyEditors ? $"'{row.PropType.Name}' cannot be null" : row.PropType.MandatoryMessage; validationResults.Add(new ValidationResult($"Item {(row.RowIndex + 1)}: {message}", new[] { row.PropKey })); - } + } else if (row.JsonRowValue[row.PropKey].ToString().IsNullOrWhiteSpace() || (row.JsonRowValue[row.PropKey].Type == JTokenType.Array && !row.JsonRowValue[row.PropKey].HasValues)) { var message = string.IsNullOrWhiteSpace(row.PropType.MandatoryMessage) ? $"'{row.PropType.Name}' cannot be empty" : row.PropType.MandatoryMessage; validationResults.Add(new ValidationResult($"Item {(row.RowIndex + 1)}: {message}", new[] { row.PropKey })); - } + } } // Check regex diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/ContentPickerValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/ContentPickerValueConverter.cs similarity index 100% rename from src/Umbraco.Web/PropertyEditors/ValueConverters/ContentPickerValueConverter.cs rename to src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/ContentPickerValueConverter.cs diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/MediaPickerValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MediaPickerValueConverter.cs similarity index 100% rename from src/Umbraco.Web/PropertyEditors/ValueConverters/MediaPickerValueConverter.cs rename to src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MediaPickerValueConverter.cs diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs similarity index 90% rename from src/Umbraco.Web/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs rename to src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs index cd69fd9de6..19cca866df 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs @@ -2,9 +2,7 @@ using Umbraco.Core; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; -using Umbraco.Web.Composing; using Umbraco.Web.PublishedCache; -using Umbraco.Web.Security; namespace Umbraco.Web.PropertyEditors.ValueConverters { @@ -12,10 +10,12 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters public class MemberPickerValueConverter : PropertyValueConverterBase { private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; + private readonly IUmbracoContextAccessor _umbracoContextAccessor; - public MemberPickerValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor) + public MemberPickerValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor, IUmbracoContextAccessor umbracoContextAccessor) { _publishedSnapshotAccessor = publishedSnapshotAccessor ?? throw new ArgumentNullException(nameof(publishedSnapshotAccessor)); + _umbracoContextAccessor = umbracoContextAccessor; } public override bool IsConverter(IPublishedPropertyType propertyType) @@ -45,7 +45,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters if (source == null) return null; - if (Current.UmbracoContext != null) + if (_umbracoContextAccessor.UmbracoContext != null) { IPublishedContent member; if (source is int id) diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/MultiNodeTreePickerValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MultiNodeTreePickerValueConverter.cs similarity index 96% rename from src/Umbraco.Web/PropertyEditors/ValueConverters/MultiNodeTreePickerValueConverter.cs rename to src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MultiNodeTreePickerValueConverter.cs index 46ebbd0abb..e35205b704 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/MultiNodeTreePickerValueConverter.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MultiNodeTreePickerValueConverter.cs @@ -3,13 +3,10 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using Umbraco.Core; -using Umbraco.Core.Cache; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; -using Umbraco.Core.Services; -using Umbraco.Web.Composing; using Umbraco.Web.PublishedCache; namespace Umbraco.Web.PropertyEditors.ValueConverters @@ -22,6 +19,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters public class MultiNodeTreePickerValueConverter : PropertyValueConverterBase { private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; + private readonly IUmbracoContextAccessor _umbracoContextAccessor; private static readonly List PropertiesToExclude = new List { @@ -29,9 +27,10 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters Constants.Conventions.Content.Redirect.ToLower(CultureInfo.InvariantCulture) }; - public MultiNodeTreePickerValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor) + public MultiNodeTreePickerValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor, IUmbracoContextAccessor umbracoContextAccessor) { _publishedSnapshotAccessor = publishedSnapshotAccessor ?? throw new ArgumentNullException(nameof(publishedSnapshotAccessor)); + _umbracoContextAccessor = umbracoContextAccessor; } public override bool IsConverter(IPublishedPropertyType propertyType) @@ -70,7 +69,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters } // TODO: Inject an UmbracoHelper and create a GetUmbracoHelper method based on either injected or singleton - if (Current.UmbracoContext != null) + if (_umbracoContextAccessor.UmbracoContext != null) { if (propertyType.EditorAlias.Equals(Constants.PropertyEditors.Aliases.MultiNodeTreePicker)) { diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/MultiUrlPickerValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MultiUrlPickerValueConverter.cs similarity index 85% rename from src/Umbraco.Web/PropertyEditors/ValueConverters/MultiUrlPickerValueConverter.cs rename to src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MultiUrlPickerValueConverter.cs index 2ceac6cfa8..c5b7e48057 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/MultiUrlPickerValueConverter.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MultiUrlPickerValueConverter.cs @@ -1,5 +1,3 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; @@ -7,6 +5,7 @@ using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Serialization; using Umbraco.Web.Models; using Umbraco.Web.PublishedCache; @@ -16,11 +15,15 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters { private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; private readonly IProfilingLogger _proflog; + private readonly IJsonSerializer _jsonSerializer; + private readonly IUmbracoContextAccessor _umbracoContextAccessor; - public MultiUrlPickerValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor, IProfilingLogger proflog) + public MultiUrlPickerValueConverter(IPublishedSnapshotAccessor publishedSnapshotAccessor, IProfilingLogger proflog, IJsonSerializer jsonSerializer, IUmbracoContextAccessor umbracoContextAccessor) { _publishedSnapshotAccessor = publishedSnapshotAccessor ?? throw new ArgumentNullException(nameof(publishedSnapshotAccessor)); _proflog = proflog ?? throw new ArgumentNullException(nameof(proflog)); + _jsonSerializer = jsonSerializer; + _umbracoContextAccessor = umbracoContextAccessor; } public override bool IsConverter(IPublishedPropertyType propertyType) => Constants.PropertyEditors.Aliases.MultiUrlPicker.Equals(propertyType.EditorAlias); @@ -48,7 +51,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters } var links = new List(); - var dtos = JsonConvert.DeserializeObject>(inter.ToString()); + var dtos = _jsonSerializer.Deserialize>(inter.ToString()); foreach (var dto in dtos) { @@ -69,7 +72,7 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters { continue; } - url = content.Url(); + url = content.Url(_umbracoContextAccessor.UmbracoContext.UrlProvider); } links.Add( diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs similarity index 100% rename from src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs rename to src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs similarity index 100% rename from src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs rename to src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentValueConverterBase.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentValueConverterBase.cs similarity index 100% rename from src/Umbraco.Web/PropertyEditors/ValueConverters/NestedContentValueConverterBase.cs rename to src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentValueConverterBase.cs diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/TextStringValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/TextStringValueConverter.cs similarity index 98% rename from src/Umbraco.Web/PropertyEditors/ValueConverters/TextStringValueConverter.cs rename to src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/TextStringValueConverter.cs index 939a658407..93d670601e 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/TextStringValueConverter.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/TextStringValueConverter.cs @@ -3,7 +3,6 @@ using System.Linq; using Umbraco.Core; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; -using Umbraco.Web.Composing; using Umbraco.Web.Templates; namespace Umbraco.Web.PropertyEditors.ValueConverters diff --git a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs index dbecd56d18..e22041a682 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs @@ -20,6 +20,7 @@ using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Core.Sync; +using Umbraco.Web.PublishedCache; using IntegerValidator = Umbraco.Core.PropertyEditors.Validators.IntegerValidator; namespace Umbraco.Core.Runtime @@ -133,10 +134,13 @@ namespace Umbraco.Core.Runtime composition.RegisterUnique(); // by default, register a noop rebuilder - composition.RegisterUnique(); + composition.RegisterUnique(); composition.SetCultureDictionaryFactory(); composition.Register(f => f.GetInstance().CreateDictionary(), Lifetime.Singleton); + + // register the published snapshot accessor - the "current" published snapshot is in the umbraco context + composition.RegisterUnique(); } } } diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs index 8653aa3c58..2c22b98262 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs @@ -20,6 +20,7 @@ using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Core.Sync; using Umbraco.Tests.Strings; +using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; using Umbraco.Web.PublishedCache; diff --git a/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs b/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs index 0fbd3a2e6b..b9de06c2d3 100644 --- a/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs +++ b/src/Umbraco.Web/Cache/DistributedCacheBinder_Handlers.cs @@ -154,6 +154,7 @@ namespace Umbraco.Web.Cache private void PublicAccessService_Saved(IPublicAccessService sender, SaveEventArgs e) { + _distributedCache.RefreshPublicAccess(); } diff --git a/src/Umbraco.Web/Editors/TourController.cs b/src/Umbraco.Web/Editors/TourController.cs index aafce5dc01..97553b5143 100644 --- a/src/Umbraco.Web/Editors/TourController.cs +++ b/src/Umbraco.Web/Editors/TourController.cs @@ -10,6 +10,7 @@ using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Mapping; +using Umbraco.Core.Models.Identity; using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -25,6 +26,7 @@ namespace Umbraco.Web.Editors private readonly TourFilterCollection _filters; private readonly IUmbracoSettingsSection _umbracoSettingsSection; private readonly IIOHelper _ioHelper; + private readonly ICurrentUserAccessor _currentUserAccessor; public TourController( IGlobalSettings globalSettings, @@ -39,12 +41,14 @@ namespace Umbraco.Web.Editors UmbracoMapper umbracoMapper, TourFilterCollection filters, IUmbracoSettingsSection umbracoSettingsSection, - IIOHelper ioHelper) + IIOHelper ioHelper, + ICurrentUserAccessor currentUserAccessor) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper, shortStringHelper, umbracoMapper) { _filters = filters; _umbracoSettingsSection = umbracoSettingsSection ?? throw new ArgumentNullException(nameof(umbracoSettingsSection)); _ioHelper = ioHelper; + _currentUserAccessor = currentUserAccessor; } public IEnumerable GetTours() @@ -54,7 +58,7 @@ namespace Umbraco.Web.Editors if (_umbracoSettingsSection.BackOffice.Tours.EnableTours == false) return result; - var user = Composing.Current.UmbracoContext.Security.CurrentUser; + var user = _currentUserAccessor.TryGetCurrentUser(); if (user == null) return result; diff --git a/src/Umbraco.Web/Migrations/PostMigrations/ClearCsrfCookies.cs b/src/Umbraco.Web/Migrations/PostMigrations/ClearCsrfCookies.cs deleted file mode 100644 index 2267f775be..0000000000 --- a/src/Umbraco.Web/Migrations/PostMigrations/ClearCsrfCookies.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Web; -using Umbraco.Core.Migrations; -using Umbraco.Web.WebApi.Filters; - -namespace Umbraco.Web.Migrations.PostMigrations -{ - /// - /// Clears Csrf tokens. - /// - public class ClearCsrfCookies : IMigration - { - public void Migrate() - { - if (HttpContext.Current == null) return; - - var http = new HttpContextWrapper(HttpContext.Current); - http.ExpireCookie(AngularAntiForgeryHelper.AngularCookieName); - http.ExpireCookie(AngularAntiForgeryHelper.CsrfValidationCookieName); - } - } -} diff --git a/src/Umbraco.Web/Migrations/PostMigrations/PublishedSnapshotRebuilder.cs b/src/Umbraco.Web/Migrations/PostMigrations/PublishedSnapshotRebuilder.cs deleted file mode 100644 index 764e46af5d..0000000000 --- a/src/Umbraco.Web/Migrations/PostMigrations/PublishedSnapshotRebuilder.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Umbraco.Core.Migrations.PostMigrations; -using Umbraco.Web.Cache; -using Umbraco.Web.PublishedCache; - -namespace Umbraco.Web.Migrations.PostMigrations -{ - /// - /// Implements in Umbraco.Web (rebuilding). - /// - public class PublishedSnapshotRebuilder : IPublishedSnapshotRebuilder - { - private readonly IPublishedSnapshotService _publishedSnapshotService; - private readonly DistributedCache _distributedCache; - - /// - /// Initializes a new instance of the class. - /// - public PublishedSnapshotRebuilder(IPublishedSnapshotService publishedSnapshotService, DistributedCache distributedCache) - { - _publishedSnapshotService = publishedSnapshotService; - _distributedCache = distributedCache; - } - - /// - public void Rebuild() - { - _publishedSnapshotService.Rebuild(); - _distributedCache.RefreshAllPublishedSnapshot(); - } - } -} diff --git a/src/Umbraco.Web/Models/LoginStatusModel.cs b/src/Umbraco.Web/Models/LoginStatusModel.cs index d253a364ae..e20c7f0a0b 100644 --- a/src/Umbraco.Web/Models/LoginStatusModel.cs +++ b/src/Umbraco.Web/Models/LoginStatusModel.cs @@ -1,6 +1,5 @@ using System.ComponentModel.DataAnnotations; using Umbraco.Core; -using Umbraco.Core.Composing; using Umbraco.Web.Security; using Current = Umbraco.Web.Composing.Current; diff --git a/src/Umbraco.Web/Models/Mapping/CommonMapper.cs b/src/Umbraco.Web/Models/Mapping/CommonMapper.cs index ed047d2ad8..f8b99a444c 100644 --- a/src/Umbraco.Web/Models/Mapping/CommonMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/CommonMapper.cs @@ -7,6 +7,7 @@ using Umbraco.Core; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Models.ContentEditing; +using Umbraco.Core.Models.Identity; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; using Umbraco.Web.ContentApps; @@ -24,9 +25,10 @@ namespace Umbraco.Web.Models.Mapping private readonly ContentAppFactoryCollection _contentAppDefinitions; private readonly ILocalizedTextService _localizedTextService; private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ICurrentUserAccessor _currentUserAccessor; public CommonMapper(IUserService userService, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, IUmbracoContextAccessor umbracoContextAccessor, - ContentAppFactoryCollection contentAppDefinitions, ILocalizedTextService localizedTextService, IHttpContextAccessor httpContextAccessor) + ContentAppFactoryCollection contentAppDefinitions, ILocalizedTextService localizedTextService, IHttpContextAccessor httpContextAccessor, ICurrentUserAccessor currentUserAccessor) { _userService = userService; _contentTypeBaseServiceProvider = contentTypeBaseServiceProvider; @@ -34,6 +36,7 @@ namespace Umbraco.Web.Models.Mapping _contentAppDefinitions = contentAppDefinitions; _localizedTextService = localizedTextService; _httpContextAccessor = httpContextAccessor; + _currentUserAccessor = currentUserAccessor; } public UserProfile GetOwner(IContentBase source, MapperContext context) @@ -50,10 +53,9 @@ namespace Umbraco.Web.Models.Mapping public ContentTypeBasic GetContentType(IContentBase source, MapperContext context) { - // TODO: We can resolve the UmbracoContext from the IValueResolver options! - // OMG - if (HttpContext.Current != null && Composing.Current.UmbracoContext != null && Composing.Current.UmbracoContext.Security.CurrentUser != null - && Composing.Current.UmbracoContext.Security.CurrentUser.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings))) + + var user = _currentUserAccessor.TryGetCurrentUser(); + if (user?.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings)) ?? false) { var contentType = _contentTypeBaseServiceProvider.GetContentTypeOf(source); var contentTypeBasic = context.Map(contentType); diff --git a/src/Umbraco.Web/Mvc/ValidateMvcAngularAntiForgeryTokenAttribute.cs b/src/Umbraco.Web/Mvc/ValidateMvcAngularAntiForgeryTokenAttribute.cs index 0803941a70..484ee70ff7 100644 --- a/src/Umbraco.Web/Mvc/ValidateMvcAngularAntiForgeryTokenAttribute.cs +++ b/src/Umbraco.Web/Mvc/ValidateMvcAngularAntiForgeryTokenAttribute.cs @@ -44,7 +44,7 @@ namespace Umbraco.Web.Mvc headers.Add(new KeyValuePair>(key, new List { filterContext.HttpContext.Request.Headers[key] })); } } - var cookie = filterContext.HttpContext.Request.Cookies[AngularAntiForgeryHelper.CsrfValidationCookieName]; + var cookie = filterContext.HttpContext.Request.Cookies[Core.Constants.Web.CsrfValidationCookieName]; if (AngularAntiForgeryHelper.ValidateHeaders( headers.Select(x => new KeyValuePair>(x.Key, x.Value)).ToArray(), cookie == null ? "" : cookie.Value, diff --git a/src/Umbraco.Web/Net/AspNetCookieManager.cs b/src/Umbraco.Web/Net/AspNetCookieManager.cs new file mode 100644 index 0000000000..2b5318110d --- /dev/null +++ b/src/Umbraco.Web/Net/AspNetCookieManager.cs @@ -0,0 +1,19 @@ +using Umbraco.Core.Cookie; + +namespace Umbraco.Web +{ + public class AspNetCookieManager : ICookieManager + { + private readonly IHttpContextAccessor _httpContextAccessor; + + public AspNetCookieManager(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + } + + public void ExpireCookie(string cookieName) + { + _httpContextAccessor.HttpContext?.ExpireCookie(cookieName); + } + } +} diff --git a/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs index da3342a682..766a811fb1 100644 --- a/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/RichTextPropertyEditor.cs @@ -75,7 +75,7 @@ namespace Umbraco.Web.PropertyEditors /// /// A custom value editor to ensure that macro syntax is parsed when being persisted and formatted correctly for display in the editor /// - internal class RichTextPropertyValueEditor : DataValueEditor, IDataValueReference + public class RichTextPropertyValueEditor : DataValueEditor, IDataValueReference { private IUmbracoContextAccessor _umbracoContextAccessor; private readonly HtmlImageSourceParser _imageSourceParser; diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/MarkdownEditorValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/MarkdownEditorValueConverter.cs deleted file mode 100644 index c62a79d283..0000000000 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/MarkdownEditorValueConverter.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.Web; -using HeyRed.MarkdownSharp; -using Umbraco.Core; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.PropertyEditors; -using Umbraco.Web.Composing; -using Umbraco.Web.Templates; - -namespace Umbraco.Web.PropertyEditors.ValueConverters -{ - [DefaultPropertyValueConverter] - public class MarkdownEditorValueConverter : PropertyValueConverterBase - { - private readonly HtmlLocalLinkParser _localLinkParser; - private readonly HtmlUrlParser _urlParser; - - public MarkdownEditorValueConverter(HtmlLocalLinkParser localLinkParser, HtmlUrlParser urlParser) - { - _localLinkParser = localLinkParser; - _urlParser = urlParser; - } - - public override bool IsConverter(IPublishedPropertyType propertyType) - => Constants.PropertyEditors.Aliases.MarkdownEditor == propertyType.EditorAlias; - - public override Type GetPropertyValueType(IPublishedPropertyType propertyType) - => typeof (IHtmlString); - - public override PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) - => PropertyCacheLevel.Snapshot; - - public override object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview) - { - if (source == null) return null; - var sourceString = source.ToString(); - - // ensures string is parsed for {localLink} and urls are resolved correctly - sourceString = _localLinkParser.EnsureInternalLinks(sourceString, preview); - sourceString = _urlParser.EnsureUrls(sourceString); - - return sourceString; - } - - public override object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview) - { - // convert markup to HTML for frontend rendering. - // source should come from ConvertSource and be a string (or null) already - var mark = new Markdown(); - return new HtmlString(inter == null ? string.Empty : mark.Transform((string)inter)); - } - } -} diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index 9d026fb50a..0d60ed5914 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -284,7 +284,7 @@ namespace Umbraco.Web { return parentNodes.DescendantsOrSelf(VariationContextAccessor, culture); } - + public static IEnumerable Descendants(this IPublishedContent content, string culture = null) { return content.Descendants(VariationContextAccessor, culture); @@ -713,24 +713,12 @@ namespace Umbraco.Web /// public static string Url(this IPublishedContent content, string culture = null, UrlMode mode = UrlMode.Default) { - var umbracoContext = Composing.Current.UmbracoContext; + var umbracoContext = Current.UmbracoContext; if (umbracoContext == null) throw new InvalidOperationException("Cannot resolve a Url when Current.UmbracoContext is null."); - if (umbracoContext.UrlProvider == null) - throw new InvalidOperationException("Cannot resolve a Url when Current.UmbracoContext.UrlProvider is null."); - switch (content.ContentType.ItemType) - { - case PublishedItemType.Content: - return umbracoContext.UrlProvider.GetUrl(content, mode, culture); - - case PublishedItemType.Media: - return umbracoContext.UrlProvider.GetMediaUrl(content, mode, culture, Constants.Conventions.Media.File); - - default: - throw new NotSupportedException(); - } + return content.Url(Current.UmbracoContext.UrlProvider, culture, mode); } #endregion diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs index 7bb54fa5b0..1e3b269e1d 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs @@ -6,6 +6,7 @@ using Microsoft.AspNet.SignalR; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; +using Umbraco.Core.Cookie; using Umbraco.Core.Dashboards; using Umbraco.Core.Dictionary; using Umbraco.Core.Events; @@ -71,6 +72,7 @@ namespace Umbraco.Web.Runtime composition.Register(Lifetime.Singleton); composition.RegisterUnique(); // required for hybrid accessors + composition.RegisterUnique(); composition.ComposeWebMappingProfiles(); @@ -102,9 +104,6 @@ namespace Umbraco.Web.Runtime // is per-request so only one wrapper is created per request composition.Register(factory => factory.GetInstance().HttpContext, Lifetime.Request); - // register the published snapshot accessor - the "current" published snapshot is in the umbraco context - composition.RegisterUnique(); - // we should stop injecting UmbracoContext and always inject IUmbracoContextAccessor, however at the moment // there are tons of places (controllers...) which require UmbracoContext in their ctor - so let's register // a way to inject the UmbracoContext - DO NOT register this as Lifetime.Request since LI will dispose the context diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 69b9e182c7..a129e1f4c1 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -168,7 +168,6 @@ - @@ -200,6 +199,7 @@ + @@ -207,7 +207,8 @@ - + + @@ -235,22 +236,15 @@ - - - - - - - @@ -344,14 +338,6 @@ - - - - - - - - @@ -429,7 +415,6 @@ - @@ -505,7 +490,6 @@ - @@ -541,8 +525,6 @@ - - @@ -554,7 +536,6 @@ - @@ -652,7 +633,6 @@ - diff --git a/src/Umbraco.Web/UmbracoContextFactory.cs b/src/Umbraco.Web/UmbracoContextFactory.cs index 50d450112e..268048edd3 100644 --- a/src/Umbraco.Web/UmbracoContextFactory.cs +++ b/src/Umbraco.Web/UmbracoContextFactory.cs @@ -77,7 +77,7 @@ namespace Umbraco.Web { var currentUmbracoContext = _umbracoContextAccessor.UmbracoContext; if (currentUmbracoContext != null) - return new UmbracoContextReference(currentUmbracoContext, false, _umbracoContextAccessor); + return new UmbracoContextReference(false, _umbracoContextAccessor); httpContext = EnsureHttpContext(httpContext); @@ -85,7 +85,7 @@ namespace Umbraco.Web var umbracoContext = CreateUmbracoContext(httpContext); _umbracoContextAccessor.UmbracoContext = umbracoContext; - return new UmbracoContextReference(umbracoContext, true, _umbracoContextAccessor); + return new UmbracoContextReference(true, _umbracoContextAccessor); } public static HttpContextBase EnsureHttpContext(HttpContextBase httpContext = null) diff --git a/src/Umbraco.Web/WebApi/Filters/AngularAntiForgeryHelper.cs b/src/Umbraco.Web/WebApi/Filters/AngularAntiForgeryHelper.cs index a0bbeac851..a15014d4e5 100644 --- a/src/Umbraco.Web/WebApi/Filters/AngularAntiForgeryHelper.cs +++ b/src/Umbraco.Web/WebApi/Filters/AngularAntiForgeryHelper.cs @@ -14,21 +14,6 @@ namespace Umbraco.Web.WebApi.Filters /// public static class AngularAntiForgeryHelper { - /// - /// The cookie name that is used to store the validation value - /// - public const string CsrfValidationCookieName = "UMB-XSRF-V"; - - /// - /// The cookie name that is set for angular to use to pass in to the header value for "X-UMB-XSRF-TOKEN" - /// - public const string AngularCookieName = "UMB-XSRF-TOKEN"; - - /// - /// The header name that angular uses to pass in the token to validate the cookie - /// - public const string AngularHeadername = "X-UMB-XSRF-TOKEN"; - /// /// Returns 2 tokens - one for the cookie value and one that angular should set as the header value /// @@ -72,14 +57,14 @@ namespace Umbraco.Web.WebApi.Filters { failedReason = ""; - if (requestHeaders.Any(z => z.Key.InvariantEquals(AngularHeadername)) == false) + if (requestHeaders.Any(z => z.Key.InvariantEquals(Constants.Web.AngularHeadername)) == false) { failedReason = "Missing token"; return false; } var headerToken = requestHeaders - .Where(z => z.Key.InvariantEquals(AngularHeadername)) + .Where(z => z.Key.InvariantEquals(Constants.Web.AngularHeadername)) .Select(z => z.Value) .SelectMany(z => z) .FirstOrDefault(); @@ -108,7 +93,7 @@ namespace Umbraco.Web.WebApi.Filters /// public static bool ValidateHeaders(HttpRequestHeaders requestHeaders, out string failedReason) { - var cookieToken = requestHeaders.GetCookieValue(CsrfValidationCookieName); + var cookieToken = requestHeaders.GetCookieValue(Constants.Web.CsrfValidationCookieName); return ValidateHeaders( requestHeaders.ToDictionary(x => x.Key, x => x.Value).ToArray(), diff --git a/src/Umbraco.Web/WebApi/Filters/ClearAngularAntiForgeryTokenAttribute.cs b/src/Umbraco.Web/WebApi/Filters/ClearAngularAntiForgeryTokenAttribute.cs index 613cc36af3..2aa2f1c52f 100644 --- a/src/Umbraco.Web/WebApi/Filters/ClearAngularAntiForgeryTokenAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/ClearAngularAntiForgeryTokenAttribute.cs @@ -16,14 +16,14 @@ namespace Umbraco.Web.WebApi.Filters if (context.Response.IsSuccessStatusCode == false) return; //remove the cookies - var angularCookie = new CookieHeaderValue(AngularAntiForgeryHelper.AngularCookieName, "null") + var angularCookie = new CookieHeaderValue(Core.Constants.Web.AngularCookieName, "null") { Expires = DateTime.Now.AddYears(-1), //must be js readable HttpOnly = false, Path = "/" }; - var validationCookie = new CookieHeaderValue(AngularAntiForgeryHelper.CsrfValidationCookieName, "null") + var validationCookie = new CookieHeaderValue(Core.Constants.Web.CsrfValidationCookieName, "null") { Expires = DateTime.Now.AddYears(-1), HttpOnly = true, diff --git a/src/Umbraco.Web/WebApi/Filters/SetAngularAntiForgeryTokensAttribute.cs b/src/Umbraco.Web/WebApi/Filters/SetAngularAntiForgeryTokensAttribute.cs index 91633ffaf3..dadf2367b6 100644 --- a/src/Umbraco.Web/WebApi/Filters/SetAngularAntiForgeryTokensAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/SetAngularAntiForgeryTokensAttribute.cs @@ -21,8 +21,8 @@ namespace Umbraco.Web.WebApi.Filters if (context.Response.StatusCode != HttpStatusCode.OK) return; //don't need to set the cookie if they already exist and they are valid - if (context.Request.Headers.GetCookies(AngularAntiForgeryHelper.AngularCookieName).Any() - && context.Request.Headers.GetCookies(AngularAntiForgeryHelper.CsrfValidationCookieName).Any()) + if (context.Request.Headers.GetCookies(Constants.Web.AngularCookieName).Any() + && context.Request.Headers.GetCookies(Constants.Web.CsrfValidationCookieName).Any()) { //if they are not valid for some strange reason - we need to continue setting valid ones string failedReason; @@ -38,7 +38,7 @@ namespace Umbraco.Web.WebApi.Filters //We need to set 2 cookies: one is the cookie value that angular will use to set a header value on each request, // the 2nd is the validation value generated by the anti-forgery helper that we use to validate the header token against. - var angularCookie = new CookieHeaderValue(AngularAntiForgeryHelper.AngularCookieName, headerToken) + var angularCookie = new CookieHeaderValue(Constants.Web.AngularCookieName, headerToken) { Path = "/", //must be js readable @@ -46,7 +46,7 @@ namespace Umbraco.Web.WebApi.Filters Secure = Current.Configs.Global().UseHttps }; - var validationCookie = new CookieHeaderValue(AngularAntiForgeryHelper.CsrfValidationCookieName, cookieToken) + var validationCookie = new CookieHeaderValue(Constants.Web.CsrfValidationCookieName, cookieToken) { Path = "/", HttpOnly = true,