Isolated more web usages - Membership and Request stuff

- Moved a few more files
This commit is contained in:
Bjarke Berg
2020-02-28 11:15:25 +01:00
parent dc36fa1290
commit 7daee53c64
26 changed files with 369 additions and 174 deletions

View File

@@ -0,0 +1,24 @@
using Umbraco.Core.Request;
namespace Umbraco.Web.AspNet
{
public class AspNetRequestAccessor : IRequestAccessor
{
private readonly IHttpContextAccessor _httpContextAccessor;
public AspNetRequestAccessor(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public string GetRequestValue(string name)
{
return _httpContextAccessor.GetRequiredHttpContext().Request[name];
}
public string GetQueryStringValue(string name)
{
return _httpContextAccessor.GetRequiredHttpContext().Request.QueryString[name];
}
}
}

View File

@@ -1,11 +0,0 @@
using System.Web;
using Umbraco.Core;
using Umbraco.Net;
namespace Umbraco.Web
{
internal class AspNetSessionIdResolver : ISessionIdResolver
{
public string SessionId => HttpContext.Current?.Session?.SessionID;
}
}

View File

@@ -0,0 +1,26 @@
using System.Web;
using Umbraco.Core.Session;
using Umbraco.Net;
namespace Umbraco.Web.AspNet
{
public class AspNetSessionManager: ISessionManager, ISessionIdResolver
{
public AspNetSessionManager()
{
}
public object GetSessionValue(string sessionName)
{
return HttpContext.Current.Session[sessionName];
}
public void SetSessionValue(string sessionName, object value)
{
HttpContext.Current.Session[sessionName] = value;
}
public string SessionId => HttpContext.Current?.Session?.SessionID;
}
}

49
src/Umbraco.Web/Macros/MacroRenderer.cs Executable file → Normal file
View File

@@ -1,5 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -12,10 +11,11 @@ using Umbraco.Core.Events;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Macros;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Request;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
using Umbraco.Web.Security;
using Umbraco.Core.Session;
namespace Umbraco.Web.Macros
{
@@ -29,10 +29,23 @@ namespace Umbraco.Web.Macros
private readonly IMacroService _macroService;
private readonly IIOHelper _ioHelper;
private readonly ICookieManager _cookieManager;
private readonly IUserService _userService;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IMemberUserKeyProvider _memberUserKeyProvider;
private readonly ISessionManager _sessionManager;
private readonly IRequestAccessor _requestAccessor;
public MacroRenderer(IProfilingLogger plogger, IUmbracoContextAccessor umbracoContextAccessor, IContentSection contentSection, ILocalizedTextService textService, AppCaches appCaches, IMacroService macroService, IUserService userService, IHttpContextAccessor httpContextAccessor, IIOHelper ioHelper, ICookieManager cookieManager)
public MacroRenderer(
IProfilingLogger plogger,
IUmbracoContextAccessor umbracoContextAccessor,
IContentSection contentSection,
ILocalizedTextService textService,
AppCaches appCaches,
IMacroService macroService,
IIOHelper ioHelper,
ICookieManager cookieManager,
IMemberUserKeyProvider memberUserKeyProvider,
ISessionManager sessionManager,
IRequestAccessor requestAccessor)
{
_plogger = plogger ?? throw new ArgumentNullException(nameof(plogger));
_umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor));
@@ -42,8 +55,9 @@ namespace Umbraco.Web.Macros
_macroService = macroService ?? throw new ArgumentNullException(nameof(macroService));
_ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper));
_cookieManager = cookieManager;
_userService = userService ?? throw new ArgumentNullException(nameof(userService));
_httpContextAccessor = httpContextAccessor;
_memberUserKeyProvider = memberUserKeyProvider;
_sessionManager = sessionManager;
_requestAccessor = requestAccessor;
}
#region MacroContent cache
@@ -63,12 +77,9 @@ namespace Umbraco.Web.Macros
{
object key = 0;
if (_httpContextAccessor.HttpContext?.User?.Identity?.IsAuthenticated ?? false)
if (_umbracoContextAccessor.UmbracoContext.Security.IsAuthenticated())
{
//ugh, membershipproviders :(
var provider = MembershipProviderExtensions.GetMembersMembershipProvider();
var member = MembershipProviderExtensions.GetCurrentUser(provider);
key = member?.ProviderUserKey ?? 0;
key = _memberUserKeyProvider.GetMemberProviderUserKey() ?? 0;
}
id.AppendFormat("m{0}-", key);
@@ -127,10 +138,8 @@ namespace Umbraco.Web.Macros
// do not cache if it should cache by member and there's not member
if (model.CacheByMember)
{
var provider = MembershipProviderExtensions.GetMembersMembershipProvider();
var member = MembershipProviderExtensions.GetCurrentUser(provider);
var key = member?.ProviderUserKey;
if (key == null) return;
var key = _memberUserKeyProvider.GetMemberProviderUserKey();
if (key is null) return;
}
// remember when we cache the content
@@ -364,8 +373,6 @@ namespace Umbraco.Web.Macros
return attributeValue;
}
var context = _httpContextAccessor.HttpContext;
foreach (var token in tokens)
{
var isToken = token.Length > 4 && token[0] == '[' && token[token.Length - 1] == ']' && validTypes.Contains(token[1]);
@@ -383,10 +390,10 @@ namespace Umbraco.Web.Macros
switch (type)
{
case '@':
attributeValue = context?.Request[name];
attributeValue = _requestAccessor.GetRequestValue(name);
break;
case '%':
attributeValue = context?.Session[name]?.ToString();
attributeValue = _sessionManager.GetSessionValue(name)?.ToString();
if (string.IsNullOrEmpty(attributeValue))
attributeValue = _cookieManager.GetCookieValue(name);
break;

View File

@@ -0,0 +1,17 @@
using Umbraco.Core.Security;
using Umbraco.Web.Security;
namespace Umbraco.Web.Macros
{
internal class MemberUserKeyProvider : IMemberUserKeyProvider
{
public object GetMemberProviderUserKey()
{
//ugh, membershipproviders :(
var provider = MembershipProviderExtensions.GetMembersMembershipProvider();
var member = MembershipProviderExtensions.GetCurrentUser(provider);
return member?.ProviderUserKey;
}
}
}

View File

@@ -1,83 +0,0 @@
using Umbraco.Core.Logging;
using Umbraco.Core;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Models.PublishedContent;
using System.Globalization;
namespace Umbraco.Web.Routing
{
/// <summary>
/// Provides an implementation of <see cref="IContentFinder"/> that handles page identifiers.
/// </summary>
/// <remarks>
/// <para>Handles <c>/1234</c> where <c>1234</c> is the identified of a document.</para>
/// </remarks>
public class ContentFinderByIdPath : IContentFinder
{
private readonly ILogger _logger;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IWebRoutingSection _webRoutingSection;
public ContentFinderByIdPath(IWebRoutingSection webRoutingSection, ILogger logger, IHttpContextAccessor httpContextAccessor)
{
_webRoutingSection = webRoutingSection ?? throw new System.ArgumentNullException(nameof(webRoutingSection));
_logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
_httpContextAccessor = httpContextAccessor;
}
/// <summary>
/// Tries to find and assign an Umbraco document to a <c>PublishedRequest</c>.
/// </summary>
/// <param name="frequest">The <c>PublishedRequest</c>.</param>
/// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
public bool TryFindContent(IPublishedRequest frequest)
{
if (frequest.UmbracoContext != null && frequest.UmbracoContext.InPreviewMode == false
&& _webRoutingSection.DisableFindContentByIdPath)
return false;
IPublishedContent node = null;
var path = frequest.Uri.GetAbsolutePathDecoded();
var nodeId = -1;
if (path != "/") // no id if "/"
{
var noSlashPath = path.Substring(1);
if (int.TryParse(noSlashPath, out nodeId) == false)
nodeId = -1;
if (nodeId > 0)
{
_logger.Debug<ContentFinderByIdPath>("Id={NodeId}", nodeId);
node = frequest.UmbracoContext.Content.GetById(nodeId);
if (node != null)
{
var httpContext = _httpContextAccessor.GetRequiredHttpContext();
//if we have a node, check if we have a culture in the query string
if (httpContext.Request.QueryString.ContainsKey("culture"))
{
//we're assuming it will match a culture, if an invalid one is passed in, an exception will throw (there is no TryGetCultureInfo method), i think this is ok though
frequest.Culture = CultureInfo.GetCultureInfo(httpContext.Request.QueryString["culture"]);
}
frequest.PublishedContent = node;
_logger.Debug<ContentFinderByIdPath>("Found node with id={PublishedContentId}", frequest.PublishedContent.Id);
}
else
{
nodeId = -1; // trigger message below
}
}
}
if (nodeId == -1)
_logger.Debug<ContentFinderByIdPath>("Not a node id");
return node != null;
}
}
}

View File

@@ -1,35 +0,0 @@
namespace Umbraco.Web.Routing
{
/// <summary>
/// This looks up a document by checking for the umbPageId of a request/query string
/// </summary>
/// <remarks>
/// This is used by library.RenderTemplate and also some of the macro rendering functionality like in
/// macroResultWrapper.aspx
/// </remarks>
public class ContentFinderByPageIdQuery : IContentFinder
{
private readonly IHttpContextAccessor _httpContextAccessor;
public ContentFinderByPageIdQuery(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public bool TryFindContent(IPublishedRequest frequest)
{
int pageId;
if (int.TryParse(_httpContextAccessor.GetRequiredHttpContext().Request["umbPageID"], out pageId))
{
var doc = frequest.UmbracoContext.Content.GetById(pageId);
if (doc != null)
{
frequest.PublishedContent = doc;
return true;
}
}
return false;
}
}
}

View File

@@ -1,772 +0,0 @@
using System;
using System.Linq;
using System.Threading;
using System.Globalization;
using System.IO;
using Umbraco.Core;
using Umbraco.Web.Composing;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Services;
using Umbraco.Web.Macros;
using Umbraco.Web.Security;
namespace Umbraco.Web.Routing
{
/// <summary>
/// Provides the default <see cref="IPublishedRouter"/> implementation.
/// </summary>
public class PublishedRouter : IPublishedRouter
{
private readonly IWebRoutingSection _webRoutingSection;
private readonly ContentFinderCollection _contentFinders;
private readonly IContentLastChanceFinder _contentLastChanceFinder;
private readonly ServiceContext _services;
private readonly IProfilingLogger _profilingLogger;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly ILogger _logger;
private readonly IUmbracoSettingsSection _umbracoSettingsSection;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IPublishedUrlProvider _publishedUrlProvider;
/// <summary>
/// Initializes a new instance of the <see cref="PublishedRouter"/> class.
/// </summary>
public PublishedRouter(
IWebRoutingSection webRoutingSection,
ContentFinderCollection contentFinders,
IContentLastChanceFinder contentLastChanceFinder,
IVariationContextAccessor variationContextAccessor,
ServiceContext services,
IProfilingLogger proflog,
IUmbracoSettingsSection umbracoSettingsSection,
IHttpContextAccessor httpContextAccessor,
IPublishedUrlProvider publishedUrlProvider)
{
_webRoutingSection = webRoutingSection ?? throw new ArgumentNullException(nameof(webRoutingSection));
_contentFinders = contentFinders ?? throw new ArgumentNullException(nameof(contentFinders));
_contentLastChanceFinder = contentLastChanceFinder ?? throw new ArgumentNullException(nameof(contentLastChanceFinder));
_services = services ?? throw new ArgumentNullException(nameof(services));
_profilingLogger = proflog ?? throw new ArgumentNullException(nameof(proflog));
_variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor));
_logger = proflog;
_umbracoSettingsSection = umbracoSettingsSection ?? throw new ArgumentNullException(nameof(umbracoSettingsSection));
_httpContextAccessor = httpContextAccessor;
_publishedUrlProvider = publishedUrlProvider;
}
/// <inheritdoc />
public IPublishedRequest CreateRequest(IUmbracoContext umbracoContext, Uri uri = null)
{
return new PublishedRequest(this, umbracoContext, _umbracoSettingsSection, uri ?? umbracoContext.CleanedUmbracoUrl);
}
#region Request
/// <inheritdoc />
public bool TryRouteRequest(IPublishedRequest request)
{
// disabled - is it going to change the routing?
//_pcr.OnPreparing();
FindDomain(request);
if (request.IsRedirect) return false;
if (request.HasPublishedContent) return true;
FindPublishedContent(request);
if (request.IsRedirect) return false;
// don't handle anything - we just want to ensure that we find the content
//HandlePublishedContent();
//FindTemplate();
//FollowExternalRedirect();
//HandleWildcardDomains();
// disabled - we just want to ensure that we find the content
//_pcr.OnPrepared();
return request.HasPublishedContent;
}
private void SetVariationContext(string culture)
{
var variationContext = _variationContextAccessor.VariationContext;
if (variationContext != null && variationContext.Culture == culture) return;
_variationContextAccessor.VariationContext = new VariationContext(culture);
}
/// <inheritdoc />
public bool PrepareRequest(IPublishedRequest request)
{
// note - at that point the original legacy module did something do handle IIS custom 404 errors
// ie pages looking like /anything.aspx?404;/path/to/document - I guess the reason was to support
// "directory urls" without having to do wildcard mapping to ASP.NET on old IIS. This is a pain
// to maintain and probably not used anymore - removed as of 06/2012. @zpqrtbnk.
//
// to trigger Umbraco's not-found, one should configure IIS and/or ASP.NET custom 404 errors
// so that they point to a non-existing page eg /redirect-404.aspx
// TODO: SD: We need more information on this for when we release 4.10.0 as I'm not sure what this means.
// trigger the Preparing event - at that point anything can still be changed
// the idea is that it is possible to change the uri
//
request.OnPreparing();
//find domain
FindDomain(request);
// if request has been flagged to redirect then return
// whoever called us is in charge of actually redirecting
if (request.IsRedirect)
{
return false;
}
// set the culture on the thread - once, so it's set when running document lookups
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = request.Culture;
SetVariationContext(request.Culture.Name);
//find the published content if it's not assigned. This could be manually assigned with a custom route handler, or
// with something like EnsurePublishedContentRequestAttribute or UmbracoVirtualNodeRouteHandler. Those in turn call this method
// to setup the rest of the pipeline but we don't want to run the finders since there's one assigned.
if (request.PublishedContent == null)
{
// find the document & template
FindPublishedContentAndTemplate(request);
}
// handle wildcard domains
HandleWildcardDomains(request);
// set the culture on the thread -- again, 'cos it might have changed due to a finder or wildcard domain
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = request.Culture;
SetVariationContext(request.Culture.Name);
// trigger the Prepared event - at that point it is still possible to change about anything
// even though the request might be flagged for redirection - we'll redirect _after_ the event
//
// also, OnPrepared() will make the PublishedRequest readonly, so nothing can change
//
request.OnPrepared();
// we don't take care of anything so if the content has changed, it's up to the user
// to find out the appropriate template
//complete the PCR and assign the remaining values
return ConfigureRequest(request);
}
/// <summary>
/// Called by PrepareRequest once everything has been discovered, resolved and assigned to the PCR. This method
/// finalizes the PCR with the values assigned.
/// </summary>
/// <returns>
/// Returns false if the request was not successfully configured
/// </returns>
/// <remarks>
/// This method logic has been put into it's own method in case developers have created a custom PCR or are assigning their own values
/// but need to finalize it themselves.
/// </remarks>
public bool ConfigureRequest(IPublishedRequest frequest)
{
if (frequest.HasPublishedContent == false)
{
return false;
}
// set the culture on the thread -- again, 'cos it might have changed in the event handler
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture = frequest.Culture;
SetVariationContext(frequest.Culture.Name);
// if request has been flagged to redirect, or has no content to display,
// then return - whoever called us is in charge of actually redirecting
if (frequest.IsRedirect || frequest.HasPublishedContent == false)
{
return false;
}
// we may be 404 _and_ have a content
// can't go beyond that point without a PublishedContent to render
// it's ok not to have a template, in order to give MVC a chance to hijack routes
return true;
}
/// <inheritdoc />
public void UpdateRequestToNotFound(IPublishedRequest request)
{
// clear content
var content = request.PublishedContent;
request.PublishedContent = null;
HandlePublishedContent(request); // will go 404
FindTemplate(request);
// if request has been flagged to redirect then return
// whoever called us is in charge of redirecting
if (request.IsRedirect)
return;
if (request.HasPublishedContent == false)
{
// means the engine could not find a proper document to handle 404
// restore the saved content so we know it exists
request.PublishedContent = content;
return;
}
if (request.HasTemplate == false)
{
// means we may have a document, but we have no template
// at that point there isn't much we can do and there is no point returning
// to Mvc since Mvc can't do much either
return;
}
}
#endregion
#region Domain
/// <summary>
/// Finds the site root (if any) matching the http request, and updates the PublishedRequest accordingly.
/// </summary>
/// <returns>A value indicating whether a domain was found.</returns>
internal bool FindDomain(IPublishedRequest request)
{
const string tracePrefix = "FindDomain: ";
// note - we are not handling schemes nor ports here.
_logger.Debug<PublishedRouter>("{TracePrefix}Uri={RequestUri}", tracePrefix, request.Uri);
var domainsCache = request.UmbracoContext.PublishedSnapshot.Domains;
var domains = domainsCache.GetAll(includeWildcards: false).ToList();
// determines whether a domain corresponds to a published document, since some
// domains may exist but on a document that has been unpublished - as a whole - or
// that is not published for the domain's culture - in which case the domain does
// not apply
bool IsPublishedContentDomain(Domain domain)
{
// just get it from content cache - optimize there, not here
var domainDocument = request.UmbracoContext.PublishedSnapshot.Content.GetById(domain.ContentId);
// not published - at all
if (domainDocument == null)
return false;
// invariant - always published
if (!domainDocument.ContentType.VariesByCulture())
return true;
// variant, ensure that the culture corresponding to the domain's language is published
return domainDocument.Cultures.ContainsKey(domain.Culture.Name);
}
domains = domains.Where(IsPublishedContentDomain).ToList();
var defaultCulture = domainsCache.DefaultCulture;
// try to find a domain matching the current request
var domainAndUri = DomainUtilities.SelectDomain(domains, request.Uri, defaultCulture: defaultCulture);
// handle domain - always has a contentId and a culture
if (domainAndUri != null)
{
// matching an existing domain
_logger.Debug<PublishedRouter>("{TracePrefix}Matches domain={Domain}, rootId={RootContentId}, culture={Culture}", tracePrefix, domainAndUri.Name, domainAndUri.ContentId, domainAndUri.Culture);
request.Domain = domainAndUri;
request.Culture = domainAndUri.Culture;
// canonical? not implemented at the moment
// if (...)
// {
// _pcr.RedirectUrl = "...";
// return true;
// }
}
else
{
// not matching any existing domain
_logger.Debug<PublishedRouter>("{TracePrefix}Matches no domain", tracePrefix);
request.Culture = defaultCulture == null ? CultureInfo.CurrentUICulture : new CultureInfo(defaultCulture);
}
_logger.Debug<PublishedRouter>("{TracePrefix}Culture={CultureName}", tracePrefix, request.Culture.Name);
return request.Domain != null;
}
/// <summary>
/// Looks for wildcard domains in the path and updates <c>Culture</c> accordingly.
/// </summary>
internal void HandleWildcardDomains(IPublishedRequest request)
{
const string tracePrefix = "HandleWildcardDomains: ";
if (request.HasPublishedContent == false)
return;
var nodePath = request.PublishedContent.Path;
_logger.Debug<PublishedRouter>("{TracePrefix}Path={NodePath}", tracePrefix, nodePath);
var rootNodeId = request.HasDomain ? request.Domain.ContentId : (int?)null;
var domain = DomainUtilities.FindWildcardDomainInPath(request.UmbracoContext.PublishedSnapshot.Domains.GetAll(true), nodePath, rootNodeId);
// always has a contentId and a culture
if (domain != null)
{
request.Culture = domain.Culture;
_logger.Debug<PublishedRouter>("{TracePrefix}Got domain on node {DomainContentId}, set culture to {CultureName}", tracePrefix, domain.ContentId, request.Culture.Name);
}
else
{
_logger.Debug<PublishedRouter>("{TracePrefix}No match.", tracePrefix);
}
}
#endregion
#region Rendering engine
internal bool FindTemplateRenderingEngineInDirectory(DirectoryInfo directory, string alias, string[] extensions)
{
if (directory == null || directory.Exists == false)
return false;
var pos = alias.IndexOf('/');
if (pos > 0)
{
// recurse
var subdir = directory.GetDirectories(alias.Substring(0, pos)).FirstOrDefault();
alias = alias.Substring(pos + 1);
return subdir != null && FindTemplateRenderingEngineInDirectory(subdir, alias, extensions);
}
// look here
return directory.GetFiles().Any(f => extensions.Any(e => f.Name.InvariantEquals(alias + e)));
}
#endregion
#region Document and template
/// <inheritdoc />
public ITemplate GetTemplate(string alias)
{
return _services.FileService.GetTemplate(alias);
}
/// <summary>
/// Finds the Umbraco document (if any) matching the request, and updates the PublishedRequest accordingly.
/// </summary>
/// <returns>A value indicating whether a document and template were found.</returns>
private void FindPublishedContentAndTemplate(IPublishedRequest request)
{
_logger.Debug<PublishedRouter>("FindPublishedContentAndTemplate: Path={UriAbsolutePath}", request.Uri.AbsolutePath);
// run the document finders
FindPublishedContent(request);
// if request has been flagged to redirect then return
// whoever called us is in charge of actually redirecting
// -- do not process anything any further --
if (request.IsRedirect)
return;
// not handling umbracoRedirect here but after LookupDocument2
// so internal redirect, 404, etc has precedence over redirect
// handle not-found, redirects, access...
HandlePublishedContent(request);
// find a template
FindTemplate(request);
// handle umbracoRedirect
FollowExternalRedirect(request);
}
/// <summary>
/// Tries to find the document matching the request, by running the IPublishedContentFinder instances.
/// </summary>
/// <exception cref="InvalidOperationException">There is no finder collection.</exception>
internal void FindPublishedContent(IPublishedRequest request)
{
const string tracePrefix = "FindPublishedContent: ";
// look for the document
// the first successful finder, if any, will set this.PublishedContent, and may also set this.Template
// some finders may implement caching
using (_profilingLogger.DebugDuration<PublishedRouter>(
$"{tracePrefix}Begin finders",
$"{tracePrefix}End finders, {(request.HasPublishedContent ? "a document was found" : "no document was found")}"))
{
//iterate but return on first one that finds it
var found = _contentFinders.Any(finder =>
{
_logger.Debug<PublishedRouter>("Finder {ContentFinderType}", finder.GetType().FullName);
return finder.TryFindContent(request);
});
}
// indicate that the published content (if any) we have at the moment is the
// one that was found by the standard finders before anything else took place.
request.SetIsInitialPublishedContent();
}
/// <summary>
/// Handles the published content (if any).
/// </summary>
/// <remarks>
/// Handles "not found", internal redirects, access validation...
/// things that must be handled in one place because they can create loops
/// </remarks>
private void HandlePublishedContent(IPublishedRequest request)
{
// because these might loop, we have to have some sort of infinite loop detection
int i = 0, j = 0;
const int maxLoop = 8;
do
{
_logger.Debug<PublishedRouter>("HandlePublishedContent: Loop {LoopCounter}", i);
// handle not found
if (request.HasPublishedContent == false)
{
request.Is404 = true;
_logger.Debug<PublishedRouter>("HandlePublishedContent: No document, try last chance lookup");
// if it fails then give up, there isn't much more that we can do
if (_contentLastChanceFinder.TryFindContent(request) == false)
{
_logger.Debug<PublishedRouter>("HandlePublishedContent: Failed to find a document, give up");
break;
}
_logger.Debug<PublishedRouter>("HandlePublishedContent: Found a document");
}
// follow internal redirects as long as it's not running out of control ie infinite loop of some sort
j = 0;
while (FollowInternalRedirects(request) && j++ < maxLoop)
{ }
if (j == maxLoop) // we're running out of control
break;
// ensure access
if (request.HasPublishedContent)
EnsurePublishedContentAccess(request);
// loop while we don't have page, ie the redirect or access
// got us to nowhere and now we need to run the notFoundLookup again
// as long as it's not running out of control ie infinite loop of some sort
} while (request.HasPublishedContent == false && i++ < maxLoop);
if (i == maxLoop || j == maxLoop)
{
_logger.Debug<PublishedRouter>("HandlePublishedContent: Looks like we are running into an infinite loop, abort");
request.PublishedContent = null;
}
_logger.Debug<PublishedRouter>("HandlePublishedContent: End");
}
/// <summary>
/// Follows internal redirections through the <c>umbracoInternalRedirectId</c> document property.
/// </summary>
/// <returns>A value indicating whether redirection took place and led to a new published document.</returns>
/// <remarks>
/// <para>Redirecting to a different site root and/or culture will not pick the new site root nor the new culture.</para>
/// <para>As per legacy, if the redirect does not work, we just ignore it.</para>
/// </remarks>
private bool FollowInternalRedirects(IPublishedRequest request)
{
if (request.PublishedContent == null)
throw new InvalidOperationException("There is no PublishedContent.");
// don't try to find a redirect if the property doesn't exist
if (request.PublishedContent.HasProperty(Constants.Conventions.Content.InternalRedirectId) == false)
return false;
var redirect = false;
var valid = false;
IPublishedContent internalRedirectNode = null;
var internalRedirectId = request.PublishedContent.Value(Constants.Conventions.Content.InternalRedirectId, defaultValue: -1);
if (internalRedirectId > 0)
{
// try and get the redirect node from a legacy integer ID
valid = true;
internalRedirectNode = request.UmbracoContext.Content.GetById(internalRedirectId);
}
else
{
var udiInternalRedirectId = request.PublishedContent.Value<GuidUdi>(Constants.Conventions.Content.InternalRedirectId);
if (udiInternalRedirectId != null)
{
// try and get the redirect node from a UDI Guid
valid = true;
internalRedirectNode = request.UmbracoContext.Content.GetById(udiInternalRedirectId.Guid);
}
}
if (valid == false)
{
// bad redirect - log and display the current page (legacy behavior)
_logger.Debug<PublishedRouter>("FollowInternalRedirects: Failed to redirect to id={InternalRedirectId}: value is not an int nor a GuidUdi.",
request.PublishedContent.GetProperty(Constants.Conventions.Content.InternalRedirectId).GetSourceValue());
}
if (internalRedirectNode == null)
{
_logger.Debug<PublishedRouter>("FollowInternalRedirects: Failed to redirect to id={InternalRedirectId}: no such published document.",
request.PublishedContent.GetProperty(Constants.Conventions.Content.InternalRedirectId).GetSourceValue());
}
else if (internalRedirectId == request.PublishedContent.Id)
{
// redirect to self
_logger.Debug<PublishedRouter>("FollowInternalRedirects: Redirecting to self, ignore");
}
else
{
request.SetInternalRedirectPublishedContent(internalRedirectNode); // don't use .PublishedContent here
redirect = true;
_logger.Debug<PublishedRouter>("FollowInternalRedirects: Redirecting to id={InternalRedirectId}", internalRedirectId);
}
return redirect;
}
/// <summary>
/// Ensures that access to current node is permitted.
/// </summary>
/// <remarks>Redirecting to a different site root and/or culture will not pick the new site root nor the new culture.</remarks>
private void EnsurePublishedContentAccess(IPublishedRequest request)
{
if (request.PublishedContent == null)
throw new InvalidOperationException("There is no PublishedContent.");
var path = request.PublishedContent.Path;
var publicAccessAttempt = _services.PublicAccessService.IsProtected(path);
if (publicAccessAttempt)
{
_logger.Debug<PublishedRouter>("EnsurePublishedContentAccess: Page is protected, check for access");
var membershipHelper = Current.Factory.GetInstance<MembershipHelper>();
if (membershipHelper.IsLoggedIn() == false)
{
_logger.Debug<PublishedRouter>("EnsurePublishedContentAccess: Not logged in, redirect to login page");
var loginPageId = publicAccessAttempt.Result.LoginNodeId;
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, membershipHelper.GetCurrentUserRoles()) == false)
{
_logger.Debug<PublishedRouter>("EnsurePublishedContentAccess: Current member has not access, redirect to error page");
var errorPageId = publicAccessAttempt.Result.NoAccessNodeId;
if (errorPageId != request.PublishedContent.Id)
request.PublishedContent = request.UmbracoContext.PublishedSnapshot.Content.GetById(errorPageId);
}
else
{
// grab the current member
var member = membershipHelper.GetCurrentMember();
// if the member has the "approved" and/or "locked out" properties, make sure they're correctly set before allowing access
var memberIsActive = true;
if (member != null)
{
if (member.HasProperty(Constants.Conventions.Member.IsApproved) == false)
memberIsActive = member.Value<bool>(Constants.Conventions.Member.IsApproved);
if (member.HasProperty(Constants.Conventions.Member.IsLockedOut) == false)
memberIsActive = member.Value<bool>(Constants.Conventions.Member.IsLockedOut) == false;
}
if (memberIsActive == false)
{
_logger.Debug<PublishedRouter>(
"Current member is either unapproved or locked out, redirect to error page");
var errorPageId = publicAccessAttempt.Result.NoAccessNodeId;
if (errorPageId != request.PublishedContent.Id)
request.PublishedContent =
request.UmbracoContext.PublishedSnapshot.Content.GetById(errorPageId);
}
else
{
_logger.Debug<PublishedRouter>("Current member has access");
}
}
}
else
{
_logger.Debug<PublishedRouter>("EnsurePublishedContentAccess: Page is not protected");
}
}
/// <summary>
/// Finds a template for the current node, if any.
/// </summary>
private void FindTemplate(IPublishedRequest request)
{
// NOTE: at the moment there is only 1 way to find a template, and then ppl must
// use the Prepared event to change the template if they wish. Should we also
// implement an ITemplateFinder logic?
if (request.PublishedContent == null)
{
request.TemplateModel = null;
return;
}
// read the alternate template alias, from querystring, form, cookie or server vars,
// only if the published content is the initial once, else the alternate template
// does not apply
// + optionally, apply the alternate template on internal redirects
var useAltTemplate = request.IsInitialPublishedContent
|| (_webRoutingSection.InternalRedirectPreservesTemplate && request.IsInternalRedirectPublishedContent);
var altTemplate = useAltTemplate
? _httpContextAccessor.GetRequiredHttpContext().Request[Constants.Conventions.Url.AltTemplate]
: null;
if (string.IsNullOrWhiteSpace(altTemplate))
{
// we don't have an alternate template specified. use the current one if there's one already,
// which can happen if a content lookup also set the template (LookupByNiceUrlAndTemplate...),
// else lookup the template id on the document then lookup the template with that id.
if (request.HasTemplate)
{
_logger.Debug<IPublishedRequest>("FindTemplate: Has a template already, and no alternate template.");
return;
}
// TODO: When we remove the need for a database for templates, then this id should be irrelevant,
// not sure how were going to do this nicely.
// TODO: We need to limit altTemplate to only allow templates that are assigned to the current document type!
// if the template isn't assigned to the document type we should log a warning and return 404
var templateId = request.PublishedContent.TemplateId;
request.TemplateModel = GetTemplateModel(templateId);
}
else
{
// we have an alternate template specified. lookup the template with that alias
// this means the we override any template that a content lookup might have set
// so /path/to/page/template1?altTemplate=template2 will use template2
// ignore if the alias does not match - just trace
if (request.HasTemplate)
_logger.Debug<PublishedRouter>("FindTemplate: Has a template already, but also an alternative template.");
_logger.Debug<PublishedRouter>("FindTemplate: Look for alternative template alias={AltTemplate}", altTemplate);
// IsAllowedTemplate deals both with DisableAlternativeTemplates and ValidateAlternativeTemplates settings
if (request.PublishedContent.IsAllowedTemplate(altTemplate))
{
// allowed, use
var template = _services.FileService.GetTemplate(altTemplate);
if (template != null)
{
request.TemplateModel = template;
_logger.Debug<PublishedRouter>("FindTemplate: Got alternative template id={TemplateId} alias={TemplateAlias}", template.Id, template.Alias);
}
else
{
_logger.Debug<PublishedRouter>("FindTemplate: The alternative template with alias={AltTemplate} does not exist, ignoring.", altTemplate);
}
}
else
{
_logger.Warn<PublishedRouter>("FindTemplate: Alternative template {TemplateAlias} is not allowed on node {NodeId}, ignoring.", altTemplate, request.PublishedContent.Id);
// no allowed, back to default
var templateId = request.PublishedContent.TemplateId;
request.TemplateModel = GetTemplateModel(templateId);
}
}
if (request.HasTemplate == false)
{
_logger.Debug<PublishedRouter>("FindTemplate: No template was found.");
// initial idea was: if we're not already 404 and UmbracoSettings.HandleMissingTemplateAs404 is true
// then reset _pcr.Document to null to force a 404.
//
// but: because we want to let MVC hijack routes even though no template is defined, we decide that
// a missing template is OK but the request will then be forwarded to MVC, which will need to take
// care of everything.
//
// so, don't set _pcr.Document to null here
}
else
{
_logger.Debug<PublishedRouter>("FindTemplate: Running with template id={TemplateId} alias={TemplateAlias}", request.TemplateModel.Id, request.TemplateModel.Alias);
}
}
private ITemplate GetTemplateModel(int? templateId)
{
if (templateId.HasValue == false || templateId.Value == default)
{
_logger.Debug<PublishedRouter>("GetTemplateModel: No template.");
return null;
}
_logger.Debug<PublishedRouter>("GetTemplateModel: Get template id={TemplateId}", templateId);
if (templateId == null)
throw new InvalidOperationException("The template is not set, the page cannot render.");
var template = _services.FileService.GetTemplate(templateId.Value);
if (template == null)
throw new InvalidOperationException("The template with Id " + templateId + " does not exist, the page cannot render.");
_logger.Debug<PublishedRouter>("GetTemplateModel: Got template id={TemplateId} alias={TemplateAlias}", template.Id, template.Alias);
return template;
}
/// <summary>
/// Follows external redirection through <c>umbracoRedirect</c> document property.
/// </summary>
/// <remarks>As per legacy, if the redirect does not work, we just ignore it.</remarks>
private void FollowExternalRedirect(IPublishedRequest request)
{
if (request.HasPublishedContent == false) return;
// don't try to find a redirect if the property doesn't exist
if (request.PublishedContent.HasProperty(Constants.Conventions.Content.Redirect) == false)
return;
var redirectId = request.PublishedContent.Value(Constants.Conventions.Content.Redirect, defaultValue: -1);
var redirectUrl = "#";
if (redirectId > 0)
{
redirectUrl = _publishedUrlProvider.GetUrl(redirectId);
}
else
{
// might be a UDI instead of an int Id
var redirectUdi = request.PublishedContent.Value<GuidUdi>(Constants.Conventions.Content.Redirect);
if (redirectUdi != null)
redirectUrl = _publishedUrlProvider.GetUrl(redirectUdi.Guid);
}
if (redirectUrl != "#")
request.SetRedirect(redirectUrl);
}
#endregion
}
}

View File

@@ -1,163 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;
using Umbraco.Web.PublishedCache;
namespace Umbraco.Web.Routing
{
/// Implements an Application Event Handler for managing redirect urls tracking.
/// <para>when content is renamed or moved, we want to create a permanent 301 redirect from it's old url</para>
/// <para>
/// not managing domains because we don't know how to do it - changing domains => must create a higher level
/// strategy using rewriting rules probably
/// </para>
/// <para>recycle bin = moving to and from does nothing: to = the node is gone, where would we redirect? from = same</para>
public sealed class RedirectTrackingComponent : IComponent
{
private const string _eventStateKey = "Umbraco.Web.Redirects.RedirectTrackingEventHandler";
private readonly IUmbracoSettingsSection _umbracoSettings;
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
private readonly IRedirectUrlService _redirectUrlService;
public RedirectTrackingComponent(IUmbracoSettingsSection umbracoSettings, IPublishedSnapshotAccessor publishedSnapshotAccessor, IRedirectUrlService redirectUrlService)
{
_umbracoSettings = umbracoSettings;
_publishedSnapshotAccessor = publishedSnapshotAccessor;
_redirectUrlService = redirectUrlService;
}
public void Initialize()
{
// don't let the event handlers kick in if Redirect Tracking is turned off in the config
if (_umbracoSettings.WebRouting.DisableRedirectUrlTracking) return;
ContentService.Publishing += ContentService_Publishing;
ContentService.Published += ContentService_Published;
ContentService.Moving += ContentService_Moving;
ContentService.Moved += ContentService_Moved;
// kill all redirects once a content is deleted
//ContentService.Deleted += ContentService_Deleted;
// BUT, doing it here would prevent content deletion due to FK
// so the rows are actually deleted by the ContentRepository (see GetDeleteClauses)
// rolled back items have to be published, so publishing will take care of that
}
public void Terminate()
{ }
private void ContentService_Publishing(IContentService sender, PublishEventArgs<IContent> args)
{
var oldRoutes = GetOldRoutes(args.EventState);
foreach (var entity in args.PublishedEntities)
{
StoreOldRoute(entity, oldRoutes);
}
}
private void ContentService_Published(IContentService sender, ContentPublishedEventArgs args)
{
var oldRoutes = GetOldRoutes(args.EventState);
CreateRedirects(oldRoutes);
}
private void ContentService_Moving(IContentService sender, MoveEventArgs<IContent> args)
{
var oldRoutes = GetOldRoutes(args.EventState);
foreach (var info in args.MoveInfoCollection)
{
StoreOldRoute(info.Entity, oldRoutes);
}
}
private void ContentService_Moved(IContentService sender, MoveEventArgs<IContent> args)
{
var oldRoutes = GetOldRoutes(args.EventState);
CreateRedirects(oldRoutes);
}
private OldRoutesDictionary GetOldRoutes(IDictionary<string, object> eventState)
{
if (! eventState.ContainsKey(_eventStateKey))
{
eventState[_eventStateKey] = new OldRoutesDictionary();
}
return eventState[_eventStateKey] as OldRoutesDictionary;
}
private void StoreOldRoute(IContent entity, OldRoutesDictionary oldRoutes)
{
var contentCache = _publishedSnapshotAccessor.PublishedSnapshot.Content;
var entityContent = contentCache.GetById(entity.Id);
if (entityContent == null) return;
// get the default affected cultures by going up the tree until we find the first culture variant entity (default to no cultures)
var defaultCultures = entityContent.AncestorsOrSelf()?.FirstOrDefault(a => a.Cultures.Any())?.Cultures.Keys.ToArray()
?? new[] { (string)null };
foreach (var x in entityContent.DescendantsOrSelf())
{
// if this entity defines specific cultures, use those instead of the default ones
var cultures = x.Cultures.Any() ? x.Cultures.Keys : defaultCultures;
foreach (var culture in cultures)
{
var route = contentCache.GetRouteById(x.Id, culture);
if (IsNotRoute(route)) continue;
oldRoutes[new ContentIdAndCulture(x.Id, culture)] = new ContentKeyAndOldRoute(x.Key, route);
}
}
}
private void CreateRedirects(OldRoutesDictionary oldRoutes)
{
var contentCache = _publishedSnapshotAccessor.PublishedSnapshot.Content;
foreach (var oldRoute in oldRoutes)
{
var newRoute = contentCache.GetRouteById(oldRoute.Key.ContentId, oldRoute.Key.Culture);
if (IsNotRoute(newRoute) || oldRoute.Value.OldRoute == newRoute) continue;
_redirectUrlService.Register(oldRoute.Value.OldRoute, oldRoute.Value.ContentKey, oldRoute.Key.Culture);
}
}
private static bool IsNotRoute(string route)
{
// null if content not found
// err/- if collision or anomaly or ...
return route == null || route.StartsWith("err/");
}
private class ContentIdAndCulture : Tuple<int, string>
{
public ContentIdAndCulture(int contentId, string culture) : base(contentId, culture)
{
}
public int ContentId => Item1;
public string Culture => Item2;
}
private class ContentKeyAndOldRoute : Tuple<Guid, string>
{
public ContentKeyAndOldRoute(Guid contentKey, string oldRoute) : base(contentKey, oldRoute)
{
}
public Guid ContentKey => Item1;
public string OldRoute => Item2;
}
private class OldRoutesDictionary : Dictionary<ContentIdAndCulture, ContentKeyAndOldRoute>
{ }
}
}

View File

@@ -1,17 +0,0 @@
using Umbraco.Core;
using Umbraco.Core.Composing;
namespace Umbraco.Web.Routing
{
/// <summary>
/// Implements an Application Event Handler for managing redirect urls tracking.
/// </summary>
/// <remarks>
/// <para>when content is renamed or moved, we want to create a permanent 301 redirect from it's old url</para>
/// <para>not managing domains because we don't know how to do it - changing domains => must create a higher level strategy using rewriting rules probably</para>
/// <para>recycle bin = moving to and from does nothing: to = the node is gone, where would we redirect? from = same</para>
/// </remarks>
[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
public class RedirectTrackingComposer : ComponentComposer<RedirectTrackingComponent>, ICoreComposer
{ }
}

View File

@@ -1,5 +1,4 @@
using System.Linq;
using System.Web;
using System.Web.Security;
using Examine;
using Microsoft.AspNet.SignalR;
@@ -7,13 +6,11 @@ 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;
using Umbraco.Core.Hosting;
using Umbraco.Core.Install;
using Umbraco.Core.Migrations.PostMigrations;
using Umbraco.Core.Models.Identity;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PropertyEditors.ValueConverters;
using Umbraco.Core.Runtime;
@@ -49,6 +46,9 @@ using Current = Umbraco.Web.Composing.Current;
using Umbraco.Web.PropertyEditors;
using Umbraco.Examine;
using Umbraco.Core.Models;
using Umbraco.Core.Request;
using Umbraco.Core.Session;
using Umbraco.Web.AspNet;
using Umbraco.Web.Models;
namespace Umbraco.Web.Runtime
@@ -64,7 +64,14 @@ namespace Umbraco.Web.Runtime
composition.Register<UmbracoInjectedModule>();
composition.Register<IIpResolver, AspNetIpResolver>();
composition.Register<ISessionIdResolver, AspNetSessionIdResolver>();
composition.Register<AspNetSessionManager>(Lifetime.Singleton);
composition.Register<ISessionIdResolver>(factory => factory.GetInstance<AspNetSessionManager>(), Lifetime.Singleton);
composition.Register<ISessionManager>(factory => factory.GetInstance<AspNetSessionManager>(), Lifetime.Singleton);
composition.Register<IRequestAccessor, AspNetRequestAccessor>();
composition.Register<IHostingEnvironment, AspNetHostingEnvironment>();
composition.Register<IBackOfficeInfo, AspNetBackOfficeInfo>();
composition.Register<IPasswordHasher, AspNetPasswordHasher>();
@@ -73,6 +80,7 @@ namespace Umbraco.Web.Runtime
composition.RegisterUnique<IHttpContextAccessor, AspNetHttpContextAccessor>(); // required for hybrid accessors
composition.RegisterUnique<ICookieManager, AspNetCookieManager>();
composition.ComposeWebMappingProfiles();
//register the install components
@@ -85,6 +93,8 @@ namespace Umbraco.Web.Runtime
composition.Register(factory => Roles.Enabled ? Roles.Provider : new MembersRoleProvider(factory.GetInstance<IMemberService>()));
composition.Register<MembershipHelper>(Lifetime.Request);
composition.Register<IPublishedMemberCache>(factory => factory.GetInstance<IUmbracoContext>().PublishedSnapshot.Members);
composition.RegisterUnique<IMemberUserKeyProvider, MemberUserKeyProvider>();
composition.RegisterUnique<IPublicAccessChecker, PublicAccessChecker>();
// register accessors for cultures
composition.RegisterUnique<IDefaultCultureAccessor, DefaultCultureAccessor>();
@@ -115,6 +125,7 @@ namespace Umbraco.Web.Runtime
composition.RegisterUnique<ITemplateRenderer, TemplateRenderer>();
composition.RegisterUnique<IMacroRenderer, MacroRenderer>();
composition.RegisterUnique<IUmbracoComponentRenderer, UmbracoComponentRenderer>();
composition.RegisterUnique<HtmlLocalLinkParser>();
@@ -125,6 +136,7 @@ namespace Umbraco.Web.Runtime
// register the umbraco helper - this is Transient! very important!
// also, if not level.Run, we cannot really use the helper (during upgrade...)
// so inject a "void" helper (not exactly pretty but...)
if (composition.RuntimeState.Level == RuntimeLevel.Run)
if (composition.RuntimeState.Level == RuntimeLevel.Run)
composition.Register<UmbracoHelper>(factory =>
{

View File

@@ -0,0 +1,54 @@
using System;
using Umbraco.Core;
using Umbraco.Core.Services;
namespace Umbraco.Web.Security
{
public class PublicAccessChecker : IPublicAccessChecker
{
//TODO: This is lazy to avoid circular dependency. We don't care right now because all membership is going to be changed.
private readonly Lazy<MembershipHelper> _membershipHelper;
private readonly IPublicAccessService _publicAccessService;
private readonly IContentService _contentService;
public PublicAccessChecker(Lazy<MembershipHelper> membershipHelper, IPublicAccessService publicAccessService, IContentService contentService)
{
_membershipHelper = membershipHelper;
_publicAccessService = publicAccessService;
_contentService = contentService;
}
public PublicAccessStatus HasMemberAccessToContent(int publishedContentId)
{
var membershipHelper = _membershipHelper.Value;
if (membershipHelper.IsLoggedIn() == false)
{
return PublicAccessStatus.NotLoggedIn;
}
var username = membershipHelper.CurrentUserName;
var userRoles = membershipHelper.GetCurrentUserRoles();
if (_publicAccessService.HasAccess(publishedContentId, _contentService, username, userRoles) == false)
{
return PublicAccessStatus.AccessDenied;
}
var member = membershipHelper.GetCurrentMember();
if (member.HasProperty(Constants.Conventions.Member.IsApproved) == false)
{
return PublicAccessStatus.NotApproved;
}
if (member.HasProperty(Constants.Conventions.Member.IsLockedOut) &&
member.Value<bool>(Constants.Conventions.Member.IsApproved))
{
return PublicAccessStatus.LockedOut;
}
return PublicAccessStatus.AccessAccepted;
}
}
}

View File

@@ -134,6 +134,8 @@
<Compile Include="AppBuilderExtensions.cs" />
<Compile Include="AreaRegistrationContextExtensions.cs" />
<Compile Include="AspNet\AspNetHostingEnvironment.cs" />
<Compile Include="AspNet\AspNetRequestAccessor.cs" />
<Compile Include="AspNet\AspNetSessionManager.cs" />
<Compile Include="AspNet\FrameworkMarchal.cs" />
<Compile Include="Cache\WebCachingAppCache.cs" />
<Compile Include="Compose\AuditEventsComponent.cs" />
@@ -166,6 +168,8 @@
<Compile Include="Logging\WebProfilerComponent.cs" />
<Compile Include="Logging\WebProfilerComposer.cs" />
<Compile Include="Logging\WebProfilerProvider.cs" />
<Compile Include="Macros\MacroRenderer.cs" />
<Compile Include="Macros\MemberUserKeyProvider.cs" />
<Compile Include="Models\Identity\BackOfficeIdentityUser.cs" />
<Compile Include="Models\Identity\IdentityMapDefinition.cs" />
<Compile Include="Models\Identity\IdentityUser.cs" />
@@ -185,7 +189,6 @@
<Compile Include="AspNet\AspNetHttpContextAccessor.cs" />
<Compile Include="AspNet\AspNetIpResolver.cs" />
<Compile Include="AspNet\AspNetPasswordHasher.cs" />
<Compile Include="AspNet\AspNetSessionIdResolver.cs" />
<Compile Include="Profiling\WebProfilingController.cs" />
<Compile Include="RoutableDocumentFilter.cs" />
<Compile Include="Runtime\AspNetUmbracoBootPermissionChecker.cs" />
@@ -200,6 +203,7 @@
<Compile Include="Security\MembershipProviderBase.cs" />
<Compile Include="Security\MembershipProviderExtensions.cs" />
<Compile Include="Security\PasswordSecurity.cs" />
<Compile Include="Security\PublicAccessChecker.cs" />
<Compile Include="Security\UmbracoBackOfficeIdentity.cs" />
<Compile Include="Security\UmbracoEmailMessage.cs" />
<Compile Include="Security\UmbracoMembershipProviderBase.cs" />
@@ -214,7 +218,6 @@
<Compile Include="ViewDataExtensions.cs" />
<Compile Include="WebApi\Filters\AdminUsersAuthorizeAttribute.cs" />
<Compile Include="WebApi\Filters\OnlyLocalRequestsAttribute.cs" />
<Compile Include="Routing\RedirectTrackingComposer.cs" />
<Compile Include="Runtime\WebInitialComposer.cs" />
<Compile Include="Security\ActiveDirectoryBackOfficeUserPasswordChecker.cs" />
<Compile Include="Security\BackOfficeClaimsIdentityFactory.cs" />
@@ -274,7 +277,6 @@
<Compile Include="Editors\MemberGroupController.cs" />
<Compile Include="Composing\CompositionExtensions\Controllers.cs" />
<Compile Include="HealthCheck\HealthCheckController.cs" />
<Compile Include="Macros\MacroRenderer.cs" />
<Compile Include="HtmlHelperBackOfficeExtensions.cs" />
<Compile Include="Composing\ModuleInjector.cs" />
<Compile Include="Mvc\FilteredControllerFactoryCollection.cs" />
@@ -323,7 +325,6 @@
<Compile Include="Mvc\UmbracoRequireHttpsAttribute.cs" />
<Compile Include="Mvc\ValidateMvcAngularAntiForgeryTokenAttribute.cs" />
<Compile Include="OwinMiddlewareConfiguredEventArgs.cs" />
<Compile Include="Routing\RedirectTrackingComponent.cs" />
<Compile Include="Editors\RedirectUrlManagementController.cs" />
<Compile Include="DefaultEventMessagesFactory.cs" />
<Compile Include="Security\ExternalSignInAutoLinkOptions.cs" />
@@ -529,8 +530,6 @@
<Compile Include="Mvc\PluginControllerMetadata.cs" />
<Compile Include="Mvc\UmbracoPageResult.cs" />
<Compile Include="RouteCollectionExtensions.cs" />
<Compile Include="Routing\ContentFinderByPageIdQuery.cs" />
<Compile Include="Routing\PublishedRouter.cs" />
<Compile Include="Compose\DatabaseServerRegistrarAndMessengerComponent.cs" />
<Compile Include="Templates\TemplateRenderer.cs" />
<Compile Include="Trees\PartialViewMacrosTreeController.cs" />
@@ -556,7 +555,6 @@
<Compile Include="WebApi\Filters\UmbracoUserTimeoutFilterAttribute.cs" />
<Compile Include="Runtime\WebRuntime.cs" />
<Compile Include="Mvc\ControllerExtensions.cs" />
<Compile Include="Routing\ContentFinderByIdPath.cs" />
<Compile Include="TypeLoaderExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>

View File

@@ -11,6 +11,7 @@ using Umbraco.Core.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Logging.Serilog;
using Umbraco.Web.AspNet;
using Umbraco.Web.Hosting;
using Current = Umbraco.Web.Composing.Current;
@@ -39,7 +40,7 @@ namespace Umbraco.Web
var ioHelper = new IOHelper(hostingEnvironment);
var configs = configFactory.Create(ioHelper);
var logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment, new AspNetSessionIdResolver(), () => _factory?.GetInstance<IRequestCache>(), coreDebug, ioHelper, new FrameworkMarchal());
var logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment, new AspNetSessionManager(), () => _factory?.GetInstance<IRequestCache>(), coreDebug, ioHelper, new FrameworkMarchal());
var backOfficeInfo = new AspNetBackOfficeInfo(configs.Global(), ioHelper, configs.Settings(), logger);
var profiler = new LogProfiler(logger);
Umbraco.Composing.Current.Initialize(logger, configs, ioHelper, hostingEnvironment, backOfficeInfo, profiler);