Merge branch 'temp8' into temp8-oembed-collection

This commit is contained in:
Stephan
2019-02-01 17:44:53 +01:00
119 changed files with 1428 additions and 756 deletions

View File

@@ -1,15 +1,22 @@
using Umbraco.Core.Configuration;
using System.Collections.Generic;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models;
using Umbraco.Web.Features;
namespace Umbraco.Web.Editors
{
public class BackOfficePreviewModel : BackOfficeModel
{
public BackOfficePreviewModel(UmbracoFeatures features, IGlobalSettings globalSettings) : base(features, globalSettings)
private readonly UmbracoFeatures _features;
public IEnumerable<ILanguage> Languages { get; }
public BackOfficePreviewModel(UmbracoFeatures features, IGlobalSettings globalSettings, IEnumerable<ILanguage> languages) : base(features, globalSettings)
{
_features = features;
Languages = languages;
}
public bool DisableDevicePreview => Features.Disabled.DisableDevicePreview;
public string PreviewExtendedHeaderView => Features.Enabled.PreviewExtendedView;
public bool DisableDevicePreview => _features.Disabled.DisableDevicePreview;
public string PreviewExtendedHeaderView => _features.Enabled.PreviewExtendedView;
}
}

View File

@@ -259,7 +259,7 @@ namespace Umbraco.Web.Editors
},
{
"tagsDataBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<TagsDataController>(
controller => controller.GetTags("", ""))
controller => controller.GetTags("", "", null))
},
{
"examineMgmtBaseUrl", _urlHelper.GetUmbracoApiServiceBaseUrl<ExamineManagementController>(

View File

@@ -1838,8 +1838,10 @@ namespace Umbraco.Web.Editors
throw new HttpResponseException(HttpStatusCode.NotFound);
}
var contentTypeService = Services.ContentTypeBaseServices.For(parent);
var parentContentType = contentTypeService.Get(parent.ContentTypeId);
//check if the item is allowed under this one
if (parent.ContentType.AllowedContentTypes.Select(x => x.Id).ToArray()
if (parentContentType.AllowedContentTypes.Select(x => x.Id).ToArray()
.Any(x => x.Value == toMove.ContentType.Id) == false)
{
throw new HttpResponseException(

View File

@@ -214,7 +214,7 @@ namespace Umbraco.Web.Editors
? Request.CreateResponse(HttpStatusCode.OK, result.Result) //return the id
: Request.CreateNotificationValidationErrorResponse(result.Exception.Message);
}
public CreatedContentTypeCollectionResult PostCreateCollection(int parentId, string collectionName, bool collectionCreateTemplate, string collectionItemName, bool collectionItemCreateTemplate, string collectionIcon, string collectionItemIcon)
{
// create item doctype
@@ -222,7 +222,7 @@ namespace Umbraco.Web.Editors
itemDocType.Name = collectionItemName;
itemDocType.Alias = collectionItemName.ToSafeAlias(true);
itemDocType.Icon = collectionItemIcon;
// create item doctype template
if (collectionItemCreateTemplate)
{
@@ -243,7 +243,7 @@ namespace Umbraco.Web.Editors
{
new ContentTypeSort(itemDocType.Id, 0)
};
// create collection doctype template
if (collectionCreateTemplate)
{
@@ -403,7 +403,9 @@ namespace Umbraco.Web.Editors
return Enumerable.Empty<ContentTypeBasic>();
}
var ids = contentItem.ContentType.AllowedContentTypes.Select(x => x.Id.Value).ToArray();
var contentTypeService = Services.ContentTypeBaseServices.For(contentItem);
var contentType = contentTypeService.Get(contentItem.ContentTypeId);
var ids = contentType.AllowedContentTypes.Select(x => x.Id.Value).ToArray();
if (ids.Any() == false) return Enumerable.Empty<ContentTypeBasic>();
@@ -497,7 +499,7 @@ namespace Umbraco.Web.Editors
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
var dataInstaller = new PackageDataInstallation(Logger, Services.FileService, Services.MacroService, Services.LocalizationService,
Services.DataTypeService, Services.EntityService, Services.ContentTypeService, Services.ContentService, _propertyEditors);
@@ -543,7 +545,7 @@ namespace Umbraco.Web.Editors
}
var model = new ContentTypeImportModel();
var file = result.FileData[0];
var fileName = file.Headers.ContentDisposition.FileName.Trim('\"');
var ext = fileName.Substring(fileName.LastIndexOf('.') + 1).ToLower();
@@ -577,6 +579,6 @@ namespace Umbraco.Web.Editors
}
}
}

View File

@@ -43,12 +43,16 @@ namespace Umbraco.Web.Editors
public class EntityController : UmbracoAuthorizedJsonController
{
private readonly ITreeService _treeService;
private readonly UmbracoTreeSearcher _treeSearcher;
private readonly SearchableTreeCollection _searchableTreeCollection;
public EntityController(IGlobalSettings globalSettings, UmbracoContext umbracoContext, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState,
ITreeService treeService)
ITreeService treeService, SearchableTreeCollection searchableTreeCollection, UmbracoTreeSearcher treeSearcher)
: base(globalSettings, umbracoContext, sqlContext, services, appCaches, logger, runtimeState)
{
_treeService = treeService;
_searchableTreeCollection = searchableTreeCollection;
_treeSearcher = treeSearcher;
}
/// <summary>
@@ -69,15 +73,6 @@ namespace Umbraco.Web.Editors
}
}
private readonly UmbracoTreeSearcher _treeSearcher;
private readonly SearchableTreeCollection _searchableTreeCollection;
public EntityController(SearchableTreeCollection searchableTreeCollection, UmbracoTreeSearcher treeSearcher)
{
_searchableTreeCollection = searchableTreeCollection;
_treeSearcher = treeSearcher;
}
/// <summary>
/// Returns an Umbraco alias given a string
/// </summary>

View File

@@ -47,9 +47,10 @@ namespace Umbraco.Web.Editors
[MediaControllerControllerConfiguration]
public class MediaController : ContentControllerBase
{
public MediaController(PropertyEditorCollection propertyEditors)
public MediaController(PropertyEditorCollection propertyEditors, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider)
{
_propertyEditors = propertyEditors ?? throw new ArgumentNullException(nameof(propertyEditors));
_contentTypeBaseServiceProvider = contentTypeBaseServiceProvider;
}
/// <summary>
@@ -233,6 +234,7 @@ namespace Umbraco.Web.Editors
private int[] _userStartNodes;
private readonly PropertyEditorCollection _propertyEditors;
private readonly IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider;
protected int[] UserStartNodes
{
@@ -292,7 +294,7 @@ namespace Umbraco.Web.Editors
else
{
//better to not use this without paging where possible, currently only the sort dialog does
children = Services.MediaService.GetPagedChildren(id, 0, int.MaxValue, out var total).ToList();
children = Services.MediaService.GetPagedChildren(id,0, int.MaxValue, out var total).ToList();
totalChildren = children.Count;
}
@@ -724,7 +726,7 @@ namespace Umbraco.Web.Editors
if (fs == null) throw new InvalidOperationException("Could not acquire file stream");
using (fs)
{
f.SetValue(Constants.Conventions.Media.File, fileName, fs);
f.SetValue(_contentTypeBaseServiceProvider, Constants.Conventions.Media.File,fileName, fs);
}
var saveResult = mediaService.Save(f, Security.CurrentUser.Id);

View File

@@ -592,11 +592,6 @@ namespace Umbraco.Web.Editors
if (builtInAliases.Contains(p.Alias) == false && valueMapped != null)
{
p.SetValue(valueMapped.GetValue());
// FIXME: /task - ok, I give up, at that point tags are dead here, until we figure it out
// p.TagChanges.Behavior = valueMapped.TagChanges.Behavior;
// p.TagChanges.Enable = valueMapped.TagChanges.Enable;
// p.TagChanges.Tags = valueMapped.TagChanges.Tags;
}
}
}

View File

@@ -1,9 +1,11 @@
using System;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.UI;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Services;
using Umbraco.Web.Composing;
using Umbraco.Web.Features;
using Umbraco.Web.JavaScript;
@@ -21,20 +23,29 @@ namespace Umbraco.Web.Editors
private readonly IGlobalSettings _globalSettings;
private readonly IPublishedSnapshotService _publishedSnapshotService;
private readonly UmbracoContext _umbracoContext;
private readonly ILocalizationService _localizationService;
public PreviewController(UmbracoFeatures features, IGlobalSettings globalSettings, IPublishedSnapshotService publishedSnapshotService, UmbracoContext umbracoContext)
public PreviewController(
UmbracoFeatures features,
IGlobalSettings globalSettings,
IPublishedSnapshotService publishedSnapshotService,
UmbracoContext umbracoContext,
ILocalizationService localizationService)
{
_features = features;
_globalSettings = globalSettings;
_publishedSnapshotService = publishedSnapshotService;
_umbracoContext = umbracoContext;
_localizationService = localizationService;
}
[UmbracoAuthorize(redirectToUmbracoLogin: true)]
[DisableBrowserCache]
public ActionResult Index()
{
var model = new BackOfficePreviewModel(_features, _globalSettings);
var availableLanguages = _localizationService.GetAllLanguages();
var model = new BackOfficePreviewModel(_features, _globalSettings, availableLanguages);
if (model.PreviewExtendedHeaderView.IsNullOrWhiteSpace() == false)
{

View File

@@ -102,7 +102,7 @@ namespace Umbraco.Web.Macros
Elements.Add("path", path);
Elements.Add("splitpath", path.Split(','));
}
/// <summary>
/// Puts the properties of the node into the elements table
/// </summary>
@@ -202,7 +202,8 @@ namespace Umbraco.Web.Macros
CreatorName = _inner.GetCreatorProfile().Name;
WriterName = _inner.GetWriterProfile().Name;
ContentType = Current.PublishedContentTypeFactory.CreateContentType(_inner.ContentType);
var contentTypeService = Current.Services.ContentTypeBaseServices.For(_inner);
ContentType = Current.PublishedContentTypeFactory.CreateContentType(contentTypeService.Get(_inner.ContentTypeId));
_properties = ContentType.PropertyTypes
.Select(x =>

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Umbraco.Core;
@@ -22,6 +23,7 @@ namespace Umbraco.Web.Models.Mapping
IUserService userService,
IContentService contentService,
IContentTypeService contentTypeService,
IContentTypeBaseServiceProvider contentTypeBaseServiceProvider,
ILocalizationService localizationService)
{
// create, capture, cache
@@ -29,7 +31,8 @@ namespace Umbraco.Web.Models.Mapping
var creatorResolver = new CreatorResolver(userService);
var actionButtonsResolver = new ActionButtonsResolver(userService, contentService);
var childOfListViewResolver = new ContentChildOfListViewResolver(contentService, contentTypeService);
var contentTypeBasicResolver = new ContentTypeBasicResolver<IContent, ContentItemDisplay>();
var contentTypeBasicResolver = new ContentTypeBasicResolver<IContent, ContentItemDisplay>(contentTypeBaseServiceProvider);
var allowedTemplatesResolver = new AllowedTemplatesResolver(contentTypeService);
var defaultTemplateResolver = new DefaultTemplateResolver();
var variantResolver = new ContentVariantResolver(localizationService);
var schedPublishReleaseDateResolver = new ScheduledPublishDateResolver(ContentScheduleAction.Release);
@@ -57,10 +60,7 @@ namespace Umbraco.Web.Models.Mapping
.ForMember(dest => dest.Notifications, opt => opt.Ignore())
.ForMember(dest => dest.Errors, opt => opt.Ignore())
.ForMember(dest => dest.DocumentType, opt => opt.ResolveUsing(contentTypeBasicResolver))
.ForMember(dest => dest.AllowedTemplates, opt =>
opt.MapFrom(content => content.ContentType.AllowedTemplates
.Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false)
.ToDictionary(t => t.Alias, t => t.Name)))
.ForMember(dest => dest.AllowedTemplates, opt => opt.ResolveUsing(allowedTemplatesResolver))
.ForMember(dest => dest.AllowedActions, opt => opt.ResolveUsing(src => actionButtonsResolver.Resolve(src)))
.ForMember(dest => dest.AdditionalData, opt => opt.Ignore());
@@ -141,5 +141,26 @@ namespace Umbraco.Web.Models.Mapping
return source.CultureInfos.TryGetValue(culture, out var name) && !name.Name.IsNullOrWhiteSpace() ? name.Name : $"(({source.Name}))";
}
}
private class AllowedTemplatesResolver : IValueResolver<IContent, ContentItemDisplay, IDictionary<string, string>>
{
private readonly IContentTypeService _contentTypeService;
public AllowedTemplatesResolver(IContentTypeService contentTypeService)
{
_contentTypeService = contentTypeService;
}
public IDictionary<string, string> Resolve(IContent source, ContentItemDisplay destination, IDictionary<string, string> destMember, ResolutionContext context)
{
var contentType = _contentTypeService.Get(source.ContentTypeId);
return contentType.AllowedTemplates
.Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false)
.ToDictionary(t => t.Alias, t => t.Name);
}
}
}
}

View File

@@ -4,6 +4,7 @@ using System.Web;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.Models.ContentEditing;
namespace Umbraco.Web.Models.Mapping
@@ -15,6 +16,13 @@ namespace Umbraco.Web.Models.Mapping
internal class ContentTypeBasicResolver<TSource, TDestination> : IValueResolver<TSource, TDestination, ContentTypeBasic>
where TSource : IContentBase
{
private readonly IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider;
public ContentTypeBasicResolver(IContentTypeBaseServiceProvider contentTypeBaseServiceProvider)
{
_contentTypeBaseServiceProvider = contentTypeBaseServiceProvider;
}
public ContentTypeBasic Resolve(TSource source, TDestination destination, ContentTypeBasic destMember, ResolutionContext context)
{
// TODO: We can resolve the UmbracoContext from the IValueResolver options!
@@ -22,13 +30,9 @@ namespace Umbraco.Web.Models.Mapping
if (HttpContext.Current != null && UmbracoContext.Current != null && UmbracoContext.Current.Security.CurrentUser != null
&& UmbracoContext.Current.Security.CurrentUser.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings)))
{
ContentTypeBasic contentTypeBasic;
if (source is IContent content)
contentTypeBasic = Mapper.Map<IContentType, ContentTypeBasic>(content.ContentType);
else if (source is IMedia media)
contentTypeBasic = Mapper.Map<IMediaType, ContentTypeBasic>(media.ContentType);
else
throw new NotSupportedException($"Expected TSource to be IContent or IMedia, got {typeof(TSource).Name}.");
var contentTypeService = _contentTypeBaseServiceProvider.For(source);
var contentType = contentTypeService.Get(source.ContentTypeId);
var contentTypeBasic = Mapper.Map<IContentTypeComposition, ContentTypeBasic>(contentType);
return contentTypeBasic;
}

View File

@@ -134,6 +134,10 @@ namespace Umbraco.Web.Models.Mapping
});
CreateMap<IContentTypeComposition, ContentTypeBasic>()
.ForMember(dest => dest.Udi, opt => opt.MapFrom(source => Udi.Create(Constants.UdiEntityType.MemberType, source.Key)))
.ForMember(dest => dest.Blueprints, opt => opt.Ignore())
.ForMember(dest => dest.AdditionalData, opt => opt.Ignore());
CreateMap<IMemberType, ContentTypeBasic>()
.ForMember(dest => dest.Udi, opt => opt.MapFrom(source => Udi.Create(Constants.UdiEntityType.MemberType, source.Key)))
.ForMember(dest => dest.Blueprints, opt => opt.Ignore())

View File

@@ -11,7 +11,7 @@ namespace Umbraco.Web.Models.Mapping
internal class ContentUrlResolver : IValueResolver<IContent, ContentItemDisplay, UrlInfo[]>
{
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly PublishedRouter _publishedRouter;
private readonly IPublishedRouter _publishedRouter;
private readonly ILocalizationService _localizationService;
private readonly ILocalizedTextService _textService;
private readonly IContentService _contentService;
@@ -19,7 +19,7 @@ namespace Umbraco.Web.Models.Mapping
public ContentUrlResolver(
IUmbracoContextAccessor umbracoContextAccessor,
PublishedRouter publishedRouter,
IPublishedRouter publishedRouter,
ILocalizationService localizationService,
ILocalizedTextService textService,
IContentService contentService,

View File

@@ -16,8 +16,7 @@ namespace Umbraco.Web.Models.Mapping
/// </summary>
internal class MediaMapperProfile : Profile
{
public MediaMapperProfile(
TabsAndPropertiesResolver<IMedia, MediaItemDisplay> tabsAndPropertiesResolver,
public MediaMapperProfile(TabsAndPropertiesResolver<IMedia, MediaItemDisplay> tabsAndPropertiesResolver,
ContentTreeNodeUrlResolver<IMedia, MediaTreeController> contentTreeNodeUrlResolver,
MediaAppResolver mediaAppResolver,
IUserService userService,
@@ -25,12 +24,13 @@ namespace Umbraco.Web.Models.Mapping
IDataTypeService dataTypeService,
IMediaService mediaService,
IMediaTypeService mediaTypeService,
ILogger logger)
ILogger logger,
IContentTypeBaseServiceProvider contentTypeBaseServiceProvider)
{
// create, capture, cache
var mediaOwnerResolver = new OwnerResolver<IMedia>(userService);
var childOfListViewResolver = new MediaChildOfListViewResolver(mediaService, mediaTypeService);
var mediaTypeBasicResolver = new ContentTypeBasicResolver<IMedia, MediaItemDisplay>();
var mediaTypeBasicResolver = new ContentTypeBasicResolver<IMedia, MediaItemDisplay>(contentTypeBaseServiceProvider);
//FROM IMedia TO MediaItemDisplay
CreateMap<IMedia, MediaItemDisplay>()

View File

@@ -33,8 +33,7 @@ namespace Umbraco.Web.Mvc
/// <param name="contentId"></param>
public EnsurePublishedContentRequestAttribute(UmbracoContext umbracoContext, int contentId)
{
if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext));
_umbracoContext = umbracoContext;
_umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext));
_contentId = contentId;
}
@@ -63,8 +62,7 @@ namespace Umbraco.Web.Mvc
/// <param name="dataTokenName"></param>
public EnsurePublishedContentRequestAttribute(UmbracoContext umbracoContext, string dataTokenName)
{
if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext));
_umbracoContext = umbracoContext;
_umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext));
_dataTokenName = dataTokenName;
}
@@ -74,7 +72,7 @@ namespace Umbraco.Web.Mvc
protected UmbracoContext UmbracoContext => _umbracoContext ?? (_umbracoContext = UmbracoContext.Current);
// TODO: try lazy property injection?
private PublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance<PublishedRouter>();
private IPublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance<IPublishedRouter>();
/// <summary>
/// Exposes an UmbracoHelper

View File

@@ -377,7 +377,7 @@ namespace Umbraco.Web.Mvc
if ((request.HasTemplate == false && Features.Disabled.DisableTemplates == false)
&& routeDef.HasHijackedRoute == false)
{
request.UpdateOnMissingTemplate(); // request will go 404
request.UpdateToNotFound(); // request will go 404
// HandleHttpResponseStatus returns a value indicating that the request should
// not be processed any further, eg because it has been redirect. then, exit.

View File

@@ -217,7 +217,7 @@ namespace Umbraco.Web.Mvc
markupToInject =
string.Format(Current.Configs.Settings().Content.PreviewBadge,
IOHelper.ResolveUrl(SystemDirectories.Umbraco),
Server.UrlEncode(UmbracoContext.Current.HttpContext.Request.Path));
Server.UrlEncode(UmbracoContext.Current.HttpContext.Request.Url?.PathAndQuery));
}
else
{

View File

@@ -12,7 +12,7 @@ namespace Umbraco.Web.Mvc
public abstract class UmbracoVirtualNodeRouteHandler : IRouteHandler
{
// TODO: try lazy property injection?
private PublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance<PublishedRouter>();
private IPublishedRouter PublishedRouter => Current.Factory.GetInstance<IPublishedRouter>();
/// <summary>
/// Returns the UmbracoContext for this route handler

View File

@@ -1,4 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi;
@@ -15,10 +17,28 @@ namespace Umbraco.Web.PropertyEditors
[PluginController("UmbracoApi")]
public class TagsDataController : UmbracoAuthorizedApiController
{
public IEnumerable<TagModel> GetTags(string tagGroup, string culture)
/// <summary>
/// Returns all tags matching tagGroup, culture and an optional query
/// </summary>
/// <param name="tagGroup"></param>
/// <param name="culture"></param>
/// <param name="query"></param>
/// <returns></returns>
public IEnumerable<TagModel> GetTags(string tagGroup, string culture, string query = null)
{
if (culture == string.Empty) culture = null;
return Umbraco.TagQuery.GetAllTags(tagGroup, culture);
var result = Umbraco.TagQuery.GetAllTags(tagGroup, culture);
if (!query.IsNullOrWhiteSpace())
{
//TODO: add the query to TagQuery + the tag service, this is ugly but all we can do for now.
//currently we are post filtering this :( but works for now
result = result.Where(x => x.Text.InvariantContains(query));
}
return result.OrderBy(x => x.Text);
}
}
}

View File

@@ -41,6 +41,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
private readonly IMemberRepository _memberRepository;
private readonly IGlobalSettings _globalSettings;
private readonly ISiteDomainHelper _siteDomainHelper;
private readonly IContentTypeBaseServiceProvider _contentTypeBaseServiceProvider;
private readonly IEntityXmlSerializer _entitySerializer;
private readonly IDefaultCultureAccessor _defaultCultureAccessor;
@@ -84,7 +85,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
IUmbracoContextAccessor umbracoContextAccessor, ILogger logger, IScopeProvider scopeProvider,
IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository,
IDefaultCultureAccessor defaultCultureAccessor,
IDataSource dataSource, IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper,
IDataSource dataSource, IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider,
IEntityXmlSerializer entitySerializer)
: base(publishedSnapshotAccessor, variationContextAccessor)
{
@@ -103,6 +104,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
_defaultCultureAccessor = defaultCultureAccessor;
_globalSettings = globalSettings;
_siteDomainHelper = siteDomainHelper;
_contentTypeBaseServiceProvider = contentTypeBaseServiceProvider;
// we need an Xml serializer here so that the member cache can support XPath,
// for members this is done by navigating the serialized-to-xml member
@@ -1202,7 +1204,9 @@ namespace Umbraco.Web.PublishedCache.NuCache
var cultureData = new Dictionary<string, CultureVariation>();
// sanitize - names should be ok but ... never knows
if (content.GetContentType().VariesByCulture())
var contentTypeService = _contentTypeBaseServiceProvider.For(content);
var contentType = contentTypeService.Get(content.ContentTypeId);
if (contentType.VariesByCulture())
{
var infos = content is IContent document
? (published

View File

@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Models;
namespace Umbraco.Web.Routing
{
/// <summary>
/// Routes requests.
/// </summary>
public interface IPublishedRouter
{
// TODO: consider this and RenderRouteHandler - move some code around?
/// <summary>
/// Creates a published request.
/// </summary>
/// <param name="umbracoContext">The current Umbraco context.</param>
/// <param name="uri">The (optional) request Uri.</param>
/// <returns>A published request.</returns>
PublishedRequest CreateRequest(UmbracoContext umbracoContext, Uri uri = null);
/// <summary>
/// Prepares a request for rendering.
/// </summary>
/// <param name="request">The request.</param>
/// <returns>A value indicating whether the request was successfully prepared and can be rendered.</returns>
bool PrepareRequest(PublishedRequest request);
/// <summary>
/// Tries to route a request.
/// </summary>
/// <param name="request">The request.</param>
/// <returns>A value indicating whether the request can be routed to a document.</returns>
bool TryRouteRequest(PublishedRequest request);
/// <summary>
/// Gets a template.
/// </summary>
/// <param name="alias">The template alias</param>
/// <returns>The template.</returns>
ITemplate GetTemplate(string alias);
/// <summary>
/// Updates the request to "not found".
/// </summary>
/// <param name="request">The request.</param>
/// <remarks>
/// <para>This method is invoked when the pipeline decides it cannot render
/// the request, for whatever reason, and wants to force it to be re-routed
/// and rendered as if no document were found (404).</para>
/// </remarks>
void UpdateRequestToNotFound(PublishedRequest request);
}
}

View File

@@ -17,7 +17,7 @@ namespace Umbraco.Web.Routing
/// </summary>
public class PublishedRequest
{
private readonly PublishedRouter _publishedRouter;
private readonly IPublishedRouter _publishedRouter;
private bool _readonly; // after prepared
private bool _readonlyUri; // after preparing
@@ -35,7 +35,7 @@ namespace Umbraco.Web.Routing
/// <param name="publishedRouter">The published router.</param>
/// <param name="umbracoContext">The Umbraco context.</param>
/// <param name="uri">The request <c>Uri</c>.</param>
internal PublishedRequest(PublishedRouter publishedRouter, UmbracoContext umbracoContext, Uri uri = null)
internal PublishedRequest(IPublishedRouter publishedRouter, UmbracoContext umbracoContext, Uri uri = null)
{
UmbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext));
_publishedRouter = publishedRouter ?? throw new ArgumentNullException(nameof(publishedRouter));
@@ -291,11 +291,11 @@ namespace Umbraco.Web.Routing
/// </summary>
public bool HasTemplate => TemplateModel != null;
internal void UpdateOnMissingTemplate()
internal void UpdateToNotFound()
{
var __readonly = _readonly;
_readonly = false;
_publishedRouter.UpdateRequestOnMissingTemplate(this);
_publishedRouter.UpdateRequestToNotFound(this);
_readonly = __readonly;
}

View File

@@ -6,6 +6,7 @@ using System.Globalization;
using System.IO;
using System.Web.Security;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
@@ -18,8 +19,10 @@ using Umbraco.Web.Security;
namespace Umbraco.Web.Routing
{
// TODO: making sense to have an interface?
public class PublishedRouter
/// <summary>
/// Provides the default <see cref="IPublishedRouter"/> implementation.
/// </summary>
public class PublishedRouter : IPublishedRouter
{
private readonly IWebRoutingSection _webRoutingSection;
private readonly ContentFinderCollection _contentFinders;
@@ -47,15 +50,9 @@ namespace Umbraco.Web.Routing
_profilingLogger = proflog ?? throw new ArgumentNullException(nameof(proflog));
_variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor));
_logger = proflog;
GetRolesForLogin = s => Roles.Provider.GetRolesForUser(s);
}
// TODO: in 7.7 this is cached in the PublishedContentRequest, which ... makes little sense
// killing it entirely, if we need cache, just implement it properly !!
// this is all so weird
public Func<string, IEnumerable<string>> GetRolesForLogin { get; }
/// <inheritdoc />
public PublishedRequest CreateRequest(UmbracoContext umbracoContext, Uri uri = null)
{
return new PublishedRequest(this, umbracoContext, uri ?? umbracoContext.CleanedUmbracoUrl);
@@ -63,10 +60,8 @@ namespace Umbraco.Web.Routing
#region Request
/// <summary>
/// Tries to route the request.
/// </summary>
internal bool TryRouteRequest(PublishedRequest request)
/// <inheritdoc />
public bool TryRouteRequest(PublishedRequest request)
{
// disabled - is it going to change the routing?
//_pcr.OnPreparing();
@@ -96,12 +91,7 @@ namespace Umbraco.Web.Routing
_variationContextAccessor.VariationContext = new VariationContext(culture);
}
/// <summary>
/// Prepares the request.
/// </summary>
/// <returns>
/// Returns false if the request was not successfully prepared
/// </returns>
/// <inheritdoc />
public bool PrepareRequest(PublishedRequest request)
{
// note - at that point the original legacy module did something do handle IIS custom 404 errors
@@ -213,11 +203,8 @@ namespace Umbraco.Web.Routing
return true;
}
/// <summary>
/// Updates the request when there is no template to render the content.
/// </summary>
/// <remarks>This is called from Mvc when there's a document to render but no template.</remarks>
public void UpdateRequestOnMissingTemplate(PublishedRequest request)
/// <inheritdoc />
public void UpdateRequestToNotFound(PublishedRequest request)
{
// clear content
var content = request.PublishedContent;
@@ -386,11 +373,7 @@ namespace Umbraco.Web.Routing
#region Document and template
/// <summary>
/// Gets a template.
/// </summary>
/// <param name="alias">The template alias</param>
/// <returns>The template.</returns>
/// <inheritdoc />
public ITemplate GetTemplate(string alias)
{
return _services.FileService.GetTemplate(alias);
@@ -607,7 +590,7 @@ namespace Umbraco.Web.Routing
if (loginPageId != request.PublishedContent.Id)
request.PublishedContent = request.UmbracoContext.PublishedSnapshot.Content.GetById(loginPageId);
}
else if (_services.PublicAccessService.HasAccess(request.PublishedContent.Id, _services.ContentService, membershipHelper.CurrentUserName, GetRolesForLogin(membershipHelper.CurrentUserName)) == false)
else if (_services.PublicAccessService.HasAccess(request.PublishedContent.Id, _services.ContentService, membershipHelper.CurrentUserName, membershipHelper.GetCurrentUserRoles()) == false)
{
_logger.Debug<PublishedRouter>("EnsurePublishedContentAccess: Current member has not access, redirect to error page");
var errorPageId = publicAccessAttempt.Result.NoAccessNodeId;

View File

@@ -18,7 +18,7 @@ namespace Umbraco.Web.Routing
/// <para>Contains all the Urls that we can figure out (based upon domains, etc).</para>
/// </remarks>
public static IEnumerable<UrlInfo> GetContentUrls(this IContent content,
PublishedRouter publishedRouter,
IPublishedRouter publishedRouter,
UmbracoContext umbracoContext,
ILocalizationService localizationService,
ILocalizedTextService textService,
@@ -92,7 +92,7 @@ namespace Umbraco.Web.Routing
/// <returns></returns>
private static IEnumerable<UrlInfo> GetContentUrlsByCulture(IContent content,
IEnumerable<string> cultures,
PublishedRouter publishedRouter,
IPublishedRouter publishedRouter,
UmbracoContext umbracoContext,
IContentService contentService,
ILocalizedTextService textService,
@@ -161,7 +161,7 @@ namespace Umbraco.Web.Routing
return UrlInfo.Message(textService.Localize("content/parentCultureNotPublished", new[] {parent.Name}), culture);
}
private static bool DetectCollision(IContent content, string url, string culture, UmbracoContext umbracoContext, PublishedRouter publishedRouter, ILocalizedTextService textService, out UrlInfo urlInfo)
private static bool DetectCollision(IContent content, string url, string culture, UmbracoContext umbracoContext, IPublishedRouter publishedRouter, ILocalizedTextService textService, out UrlInfo urlInfo)
{
// test for collisions on the 'main' url
var uri = new Uri(url.TrimEnd('/'), UriKind.RelativeOrAbsolute);

View File

@@ -248,7 +248,7 @@ namespace Umbraco.Web.Runtime
XmlFileMapper.FileMapDefaultFolder = SystemDirectories.TempData.EnsureEndsWith('/') + "ClientDependency";
BaseCompositeFileProcessingProvider.UrlTypeDefault = CompositeUrlType.Base64QueryStrings;
// Now we need to detect if we are running umbracoLocalTempStorage as EnvironmentTemp and in that case we want to change the CDF file
// Now we need to detect if we are running 'Umbraco.Core.LocalTempStorage' as EnvironmentTemp and in that case we want to change the CDF file
// location to be there
if (globalSettings.LocalTempStorageLocation == LocalTempStorage.EnvironmentTemp)
{

View File

@@ -179,7 +179,7 @@ namespace Umbraco.Web.Runtime
composition.RegisterAuto(typeof(UmbracoViewPage<>));
// register published router
composition.RegisterUnique<PublishedRouter>();
composition.RegisterUnique<IPublishedRouter, PublishedRouter>();
composition.Register(_ => Current.Configs.Settings().WebRouting);
// register preview SignalR hub

View File

@@ -13,6 +13,7 @@ namespace Umbraco.Web.Security
{
get
{
// TODO: Verify this AppSetting key is used in .NET Framework & canot be changed to Umbraco.Core. prefix
return ConfigurationManager.AppSettings["ActiveDirectoryDomain"];
}
}

View File

@@ -31,7 +31,6 @@ namespace Umbraco.Web.Security
private readonly IMemberTypeService _memberTypeService;
private readonly IUserService _userService;
private readonly IPublicAccessService _publicAccessService;
private readonly PublishedRouter _publishedRouter;
private readonly AppCaches _appCaches;
private readonly ILogger _logger;
@@ -46,7 +45,6 @@ namespace Umbraco.Web.Security
IMemberTypeService memberTypeService,
IUserService userService,
IPublicAccessService publicAccessService,
PublishedRouter publishedRouter,
AppCaches appCaches,
ILogger logger
)
@@ -57,7 +55,6 @@ namespace Umbraco.Web.Security
_memberTypeService = memberTypeService;
_userService = userService;
_publicAccessService = publicAccessService;
_publishedRouter = publishedRouter;
_appCaches = appCaches;
_logger = logger;
@@ -116,7 +113,7 @@ namespace Umbraco.Web.Security
{
return UmbracoContext.PublishedRequest == null
? _publicAccessService.HasAccess(path, CurrentUserName, roleProvider.GetRolesForUser)
: _publicAccessService.HasAccess(path, CurrentUserName, _publishedRouter.GetRolesForLogin);
: _publicAccessService.HasAccess(path, CurrentUserName, GetUserRoles);
}
/// <summary>
@@ -514,6 +511,24 @@ namespace Umbraco.Web.Security
}
#endregion
/// <summary>
/// Gets the current user's roles.
/// </summary>
/// <remarks>Roles are cached per user name, at request level.</remarks>
public IEnumerable<string> GetCurrentUserRoles()
=> GetUserRoles(CurrentUserName);
/// <summary>
/// Gets a user's roles.
/// </summary>
/// <remarks>Roles are cached per user name, at request level.</remarks>
public IEnumerable<string> GetUserRoles(string userName)
{
// optimize by caching per-request (v7 cached per PublishedRequest, in PublishedRouter)
var key = "Umbraco.Web.Security.MembershipHelper__Roles__" + userName;
return _appCaches.RequestCache.GetCacheItem(key, () => Roles.Provider.GetRolesForUser(userName));
}
/// <summary>
/// Returns the login status model of the currently logged in member, if no member is logged in it returns null;
/// </summary>
@@ -618,7 +633,7 @@ namespace Umbraco.Web.Security
var provider = _membershipProvider;
string username;
if (provider.IsUmbracoMembershipProvider())
{
var member = GetCurrentPersistedMember();
@@ -626,7 +641,7 @@ namespace Umbraco.Web.Security
if (member == null)
return false;
username = member.Username;
// If types defined, check member is of one of those types
var allowTypesList = allowTypes as IList<string> ?? allowTypes.ToList();
if (allowTypesList.Any(allowType => allowType != string.Empty))

View File

@@ -36,7 +36,7 @@ namespace Umbraco.Web.Templates
}
private IFileService FileService => Current.Services.FileService; // TODO: inject
private PublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance<PublishedRouter>(); // TODO: inject
private IPublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance<IPublishedRouter>(); // TODO: inject
/// <summary>

View File

@@ -200,6 +200,7 @@
<Compile Include="Models\ContentEditing\MacroDisplay.cs" />
<Compile Include="Models\ContentEditing\MacroParameterDisplay.cs" />
<Compile Include="Models\TemplateQuery\QueryConditionExtensions.cs" />
<Compile Include="Routing\IPublishedRouter.cs" />
<Compile Include="Services\DashboardService.cs" />
<Compile Include="Services\IDashboardService.cs" />
<Compile Include="Models\Link.cs" />

View File

@@ -45,7 +45,7 @@ namespace Umbraco.Web
private readonly UrlProviderCollection _urlProviders;
private readonly IRuntimeState _runtime;
private readonly ILogger _logger;
private readonly PublishedRouter _publishedRouter;
private readonly IPublishedRouter _publishedRouter;
private readonly IVariationContextAccessor _variationContextAccessor;
public UmbracoInjectedModule(
@@ -56,7 +56,7 @@ namespace Umbraco.Web
UrlProviderCollection urlProviders,
IRuntimeState runtime,
ILogger logger,
PublishedRouter publishedRouter,
IPublishedRouter publishedRouter,
IVariationContextAccessor variationContextAccessor)
{
_combinedRouteCollection = new Lazy<RouteCollection>(CreateRouteCollection);