Moved More files to infrastructure/abstractions

This commit is contained in:
Bjarke Berg
2020-02-13 11:21:20 +01:00
parent a69b985002
commit b57a7690f5
44 changed files with 211 additions and 225 deletions

View File

@@ -19,6 +19,21 @@
public const string PreviewCookieName = "UMB_PREVIEW";
public const string InstallerCookieName = "umb_installId";
/// <summary>
/// The cookie name that is used to store the validation value
/// </summary>
public const string CsrfValidationCookieName = "UMB-XSRF-V";
/// <summary>
/// The cookie name that is set for angular to use to pass in to the header value for "X-UMB-XSRF-TOKEN"
/// </summary>
public const string AngularCookieName = "UMB-XSRF-TOKEN";
/// <summary>
/// The header name that angular uses to pass in the token to validate the cookie
/// </summary>
public const string AngularHeadername = "X-UMB-XSRF-TOKEN";
}
}
}

View File

@@ -0,0 +1,7 @@
namespace Umbraco.Core.Cookie
{
public interface ICookieManager
{
void ExpireCookie(string angularCookieName);
}
}

View File

@@ -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; }

View File

@@ -1,5 +1,4 @@
using System;
namespace Umbraco.Web.PublishedCache
{
public class UmbracoContextPublishedSnapshotAccessor : IPublishedSnapshotAccessor

View File

@@ -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
/// <summary>
/// Gets the url of the content item.
/// </summary>
/// <remarks>
/// <para>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.</para>
/// <para>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.</para>
/// </remarks>
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
}
}

View File

@@ -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
{

View File

@@ -20,9 +20,8 @@ namespace Umbraco.Web
/// <summary>
/// Initializes a new instance of the <see cref="UmbracoContextReference"/> class.
/// </summary>
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
/// <summary>
/// Gets the <see cref="UmbracoContext"/>.
/// </summary>
public IUmbracoContext UmbracoContext { get; }
public IUmbracoContext UmbracoContext => _umbracoContextAccessor.UmbracoContext;
/// <summary>
/// Gets a value indicating whether the reference is a root reference.

View File

@@ -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
/// <summary>
/// Extension methods for <see cref="DistributedCache"/>.
/// </summary>
internal static class DistributedCacheExtensions
public static class DistributedCacheExtensions
{
#region PublicAccessCache

View File

@@ -0,0 +1,26 @@
using Umbraco.Core;
using Umbraco.Core.Cookie;
using Umbraco.Core.Migrations;
namespace Umbraco.Web.Migrations.PostMigrations
{
/// <summary>
/// Clears Csrf tokens.
/// </summary>
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);
}
}
}

View File

@@ -0,0 +1,12 @@
namespace Umbraco.Core.Migrations.PostMigrations
{
/// <summary>
/// Implements <see cref="IPublishedSnapshotRebuilder"/> in Umbraco.Core (doing nothing).
/// </summary>
public class NoopPublishedSnapshotRebuilder : IPublishedSnapshotRebuilder
{
/// <inheritdoc />
public void Rebuild()
{ }
}
}

View File

@@ -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
{
/// <summary>
/// Implements <see cref="IPublishedSnapshotRebuilder"/> in Umbraco.Core (doing nothing).
/// Implements <see cref="IPublishedSnapshotRebuilder"/> in Umbraco.Web (rebuilding).
/// </summary>
public class PublishedSnapshotRebuilder : IPublishedSnapshotRebuilder
{
private readonly IPublishedSnapshotService _publishedSnapshotService;
private readonly DistributedCache _distributedCache;
/// <summary>
/// Initializes a new instance of the <see cref="PublishedSnapshotRebuilder"/> class.
/// </summary>
public PublishedSnapshotRebuilder(IPublishedSnapshotService publishedSnapshotService, DistributedCache distributedCache)
{
_publishedSnapshotService = publishedSnapshotService;
_distributedCache = distributedCache;
}
/// <inheritdoc />
public void Rebuild()
{ }
{
_publishedSnapshotService.Rebuild();
_distributedCache.RefreshAllPublishedSnapshot();
}
}
}

View File

@@ -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<IEntityService> _entityService;
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
private readonly IIOHelper _ioHelper;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
public MultiUrlPickerPropertyEditor(ILogger logger, Lazy<IEntityService> entityService, IPublishedSnapshotAccessor publishedSnapshotAccessor, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, IIOHelper ioHelper, IShortStringHelper shortStringHelper)
public MultiUrlPickerPropertyEditor(ILogger logger, Lazy<IEntityService> 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);
}
}

View File

@@ -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; }

View File

@@ -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

View File

@@ -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)

View File

@@ -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<string> PropertiesToExclude = new List<string>
{
@@ -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))
{

View File

@@ -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<Link>();
var dtos = JsonConvert.DeserializeObject<IEnumerable<MultiUrlPickerValueEditor.LinkDto>>(inter.ToString());
var dtos = _jsonSerializer.Deserialize<IEnumerable<MultiUrlPickerValueEditor.LinkDto>>(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(

View File

@@ -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

View File

@@ -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<IPublishedModelFactory, NoopPublishedModelFactory>();
// by default, register a noop rebuilder
composition.RegisterUnique<IPublishedSnapshotRebuilder, PublishedSnapshotRebuilder>();
composition.RegisterUnique<IPublishedSnapshotRebuilder, NoopPublishedSnapshotRebuilder>();
composition.SetCultureDictionaryFactory<DefaultCultureDictionaryFactory>();
composition.Register(f => f.GetInstance<ICultureDictionaryFactory>().CreateDictionary(), Lifetime.Singleton);
// register the published snapshot accessor - the "current" published snapshot is in the umbraco context
composition.RegisterUnique<IPublishedSnapshotAccessor, UmbracoContextPublishedSnapshotAccessor>();
}
}
}

View File

@@ -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;

View File

@@ -154,6 +154,7 @@ namespace Umbraco.Web.Cache
private void PublicAccessService_Saved(IPublicAccessService sender, SaveEventArgs<PublicAccessEntry> e)
{
_distributedCache.RefreshPublicAccess();
}

View File

@@ -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<BackOfficeTourFile> 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;

View File

@@ -1,21 +0,0 @@
using System.Web;
using Umbraco.Core.Migrations;
using Umbraco.Web.WebApi.Filters;
namespace Umbraco.Web.Migrations.PostMigrations
{
/// <summary>
/// Clears Csrf tokens.
/// </summary>
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);
}
}
}

View File

@@ -1,31 +0,0 @@
using Umbraco.Core.Migrations.PostMigrations;
using Umbraco.Web.Cache;
using Umbraco.Web.PublishedCache;
namespace Umbraco.Web.Migrations.PostMigrations
{
/// <summary>
/// Implements <see cref="IPublishedSnapshotRebuilder"/> in Umbraco.Web (rebuilding).
/// </summary>
public class PublishedSnapshotRebuilder : IPublishedSnapshotRebuilder
{
private readonly IPublishedSnapshotService _publishedSnapshotService;
private readonly DistributedCache _distributedCache;
/// <summary>
/// Initializes a new instance of the <see cref="PublishedSnapshotRebuilder"/> class.
/// </summary>
public PublishedSnapshotRebuilder(IPublishedSnapshotService publishedSnapshotService, DistributedCache distributedCache)
{
_publishedSnapshotService = publishedSnapshotService;
_distributedCache = distributedCache;
}
/// <inheritdoc />
public void Rebuild()
{
_publishedSnapshotService.Rebuild();
_distributedCache.RefreshAllPublishedSnapshot();
}
}
}

View File

@@ -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;

View File

@@ -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<IContentTypeComposition, ContentTypeBasic>(contentType);

View File

@@ -44,7 +44,7 @@ namespace Umbraco.Web.Mvc
headers.Add(new KeyValuePair<string, List<string>>(key, new List<string> { 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<string, IEnumerable<string>>(x.Key, x.Value)).ToArray(),
cookie == null ? "" : cookie.Value,

View File

@@ -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);
}
}
}

View File

@@ -75,7 +75,7 @@ namespace Umbraco.Web.PropertyEditors
/// <summary>
/// A custom value editor to ensure that macro syntax is parsed when being persisted and formatted correctly for display in the editor
/// </summary>
internal class RichTextPropertyValueEditor : DataValueEditor, IDataValueReference
public class RichTextPropertyValueEditor : DataValueEditor, IDataValueReference
{
private IUmbracoContextAccessor _umbracoContextAccessor;
private readonly HtmlImageSourceParser _imageSourceParser;

View File

@@ -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));
}
}
}

View File

@@ -284,7 +284,7 @@ namespace Umbraco.Web
{
return parentNodes.DescendantsOrSelf<T>(VariationContextAccessor, culture);
}
public static IEnumerable<IPublishedContent> Descendants(this IPublishedContent content, string culture = null)
{
return content.Descendants(VariationContextAccessor, culture);
@@ -713,24 +713,12 @@ namespace Umbraco.Web
/// </remarks>
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

View File

@@ -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<IFilePermissionHelper, FilePermissionHelper>(Lifetime.Singleton);
composition.RegisterUnique<IHttpContextAccessor, AspNetHttpContextAccessor>(); // required for hybrid accessors
composition.RegisterUnique<ICookieManager, AspNetCookieManager>();
composition.ComposeWebMappingProfiles();
@@ -102,9 +104,6 @@ namespace Umbraco.Web.Runtime
// is per-request so only one wrapper is created per request
composition.Register<HttpContextBase>(factory => factory.GetInstance<IHttpContextAccessor>().HttpContext, Lifetime.Request);
// register the published snapshot accessor - the "current" published snapshot is in the umbraco context
composition.RegisterUnique<IPublishedSnapshotAccessor, UmbracoContextPublishedSnapshotAccessor>();
// 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

View File

@@ -168,7 +168,6 @@
<Compile Include="Logging\WebProfilerProvider.cs" />
<Compile Include="Macros\IMacroRenderer.cs" />
<Compile Include="Macros\PublishedContentHashtableConverter.cs" />
<Compile Include="Migrations\PostMigrations\PublishedSnapshotRebuilder.cs" />
<Compile Include="Models\ContentEditing\UserInvite.cs" />
<Compile Include="Models\Identity\BackOfficeIdentityUser.cs" />
<Compile Include="Models\Identity\IdentityMapDefinition.cs" />
@@ -200,6 +199,7 @@
<Compile Include="Mvc\SurfaceControllerTypeCollectionBuilder.cs" />
<Compile Include="Mvc\ValidateUmbracoFormRouteStringAttribute.cs" />
<Compile Include="Net\AspNetBackOfficeInfo.cs" />
<Compile Include="Net\AspNetCookieManager.cs" />
<Compile Include="Net\AspNetHttpContextAccessor.cs" />
<Compile Include="Net\AspNetIpResolver.cs" />
<Compile Include="Net\AspNetPasswordHasher.cs" />
@@ -207,7 +207,8 @@
<Compile Include="Profiling\WebProfilingController.cs" />
<Compile Include="PropertyEditors\GridPropertyEditor.cs" />
<Compile Include="PropertyEditors\RichTextEditorPastedImages.cs" />
<Compile Include="PublishedCache\UmbracoContextPublishedSnapshotAccessor.cs" />
<Compile Include="PropertyEditors\RichTextPropertyEditor.cs" />
<Compile Include="PropertyEditors\ValueConverters\RteMacroRenderingValueConverter.cs" />
<Compile Include="RoutableDocumentFilter.cs" />
<Compile Include="Routing\DefaultMediaUrlProvider.cs" />
<Compile Include="Routing\IMediaUrlProvider.cs" />
@@ -235,22 +236,15 @@
<Compile Include="Security\UserAwarePasswordHasher.cs" />
<Compile Include="Search\UmbracoTreeSearcherFields.cs" />
<Compile Include="StringExtensions.cs" />
<Compile Include="Templates\HtmlLocalLinkParser.cs" />
<Compile Include="Templates\HtmlImageSourceParser.cs" />
<Compile Include="Templates\HtmlUrlParser.cs" />
<Compile Include="Trees\TreeCollectionBuilder.cs" />
<Compile Include="Trees\TreeNode.cs" />
<Compile Include="UmbracoContext.cs" />
<Compile Include="UmbracoContextFactory.cs" />
<Compile Include="UmbracoContextReference.cs" />
<Compile Include="Mvc\UmbracoVirtualNodeByUdiRouteHandler.cs" />
<Compile Include="UmbracoDbProviderFactoryCreator.cs" />
<Compile Include="ViewDataExtensions.cs" />
<Compile Include="WebApi\Filters\AdminUsersAuthorizeAttribute.cs" />
<Compile Include="WebApi\Filters\OnlyLocalRequestsAttribute.cs" />
<Compile Include="PropertyEditors\MultiUrlPickerPropertyEditor.cs" />
<Compile Include="PropertyEditors\MultiUrlPickerValueEditor.cs" />
<Compile Include="PropertyEditors\ValueConverters\MultiUrlPickerValueConverter.cs" />
<Compile Include="Templates\ITemplateRenderer.cs" />
<Compile Include="PropertyEditors\GridPropertyIndexValueFactory.cs" />
<Compile Include="Routing\RedirectTrackingComposer.cs" />
@@ -344,14 +338,6 @@
<Compile Include="Mvc\FilteredControllerFactoryCollectionBuilder.cs" />
<Compile Include="Mvc\SurfaceControllerTypeCollection.cs" />
<Compile Include="PropertyEditors\NestedContentController.cs" />
<Compile Include="PropertyEditors\NestedContentPropertyEditor.cs" />
<Compile Include="PropertyEditors\ValueConverters\NestedContentManyValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\NestedContentValueConverterBase.cs" />
<Compile Include="PropertyEditors\ValueConverters\NestedContentSingleValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\MediaPickerValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\MemberPickerValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\MultiNodeTreePickerValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\ContentPickerValueConverter.cs" />
<Compile Include="PublishedElementExtensions.cs" />
<Compile Include="PublishedModels\DummyClassSoThatPublishedModelsNamespaceExists.cs" />
<Compile Include="Routing\ContentFinderByUrl.cs" />
@@ -429,7 +415,6 @@
<Compile Include="Mvc\ProfilingViewEngine.cs" />
<Compile Include="BatchedDatabaseServerMessenger.cs" />
<Compile Include="CacheHelperExtensions.cs" />
<Compile Include="Cache\DistributedCacheExtensions.cs" />
<Compile Include="Editors\AuthenticationController.cs" />
<Compile Include="Controllers\UmbProfileController.cs" />
<Compile Include="Editors\ContentController.cs" />
@@ -505,7 +490,6 @@
<Compile Include="Security\AuthenticationManagerExtensions.cs" />
<Compile Include="Security\BackOfficeCookieManager.cs" />
<Compile Include="Security\UmbracoBackOfficeCookieAuthOptions.cs" />
<Compile Include="Migrations\PostMigrations\ClearCsrfCookies.cs" />
<Compile Include="TagQuery.cs" />
<Compile Include="Trees\DataTypeTreeController.cs" />
<Compile Include="Trees\FileSystemTreeController.cs" />
@@ -541,8 +525,6 @@
<Compile Include="Controllers\UmbRegisterController.cs" />
<Compile Include="Models\ProfileModel.cs" />
<Compile Include="Models\LoginStatusModel.cs" />
<Compile Include="PropertyEditors\ValueConverters\MarkdownEditorValueConverter.cs" />
<Compile Include="PropertyEditors\ValueConverters\TextStringValueConverter.cs" />
<Compile Include="PublishedPropertyExtension.cs" />
<Compile Include="Mvc\MergeParentContextViewDataAttribute.cs" />
<Compile Include="Mvc\ViewDataDictionaryExtensions.cs" />
@@ -554,7 +536,6 @@
<Compile Include="Editors\UmbracoAuthorizedJsonController.cs" />
<Compile Include="HttpCookieExtensions.cs" />
<Compile Include="FormDataCollectionExtensions.cs" />
<Compile Include="PropertyEditors\RichTextPropertyEditor.cs" />
<Compile Include="Trees\MediaTreeController.cs" />
<Compile Include="Trees\ContentTreeControllerBase.cs" />
<Compile Include="Models\Trees\TreeRootNode.cs" />
@@ -652,7 +633,6 @@
<Compile Include="Mvc\PluginControllerAttribute.cs" />
<Compile Include="Mvc\PluginControllerMetadata.cs" />
<Compile Include="Mvc\UmbracoPageResult.cs" />
<Compile Include="PropertyEditors\ValueConverters\RteMacroRenderingValueConverter.cs" />
<Compile Include="RouteCollectionExtensions.cs" />
<Compile Include="Routing\AliasUrlProvider.cs" />
<Compile Include="Routing\ContentFinderByConfigured404.cs" />

View File

@@ -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)

View File

@@ -14,21 +14,6 @@ namespace Umbraco.Web.WebApi.Filters
/// </summary>
public static class AngularAntiForgeryHelper
{
/// <summary>
/// The cookie name that is used to store the validation value
/// </summary>
public const string CsrfValidationCookieName = "UMB-XSRF-V";
/// <summary>
/// The cookie name that is set for angular to use to pass in to the header value for "X-UMB-XSRF-TOKEN"
/// </summary>
public const string AngularCookieName = "UMB-XSRF-TOKEN";
/// <summary>
/// The header name that angular uses to pass in the token to validate the cookie
/// </summary>
public const string AngularHeadername = "X-UMB-XSRF-TOKEN";
/// <summary>
/// Returns 2 tokens - one for the cookie value and one that angular should set as the header value
/// </summary>
@@ -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
/// <returns></returns>
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(),

View File

@@ -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,

View File

@@ -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,