diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IWebRoutingSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IWebRoutingSection.cs index aedfac7aa5..c59d63d42e 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/IWebRoutingSection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IWebRoutingSection.cs @@ -8,7 +8,7 @@ bool DisableAlternativeTemplates { get; } - bool DisableNotPermittedAlternativeTemplates { get; } + bool ValidateAlternativeTemplates { get; } bool DisableFindContentByIdPath { get; } diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/WebRoutingElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/WebRoutingElement.cs index 35348b0338..ed133e5f61 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/WebRoutingElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/WebRoutingElement.cs @@ -23,11 +23,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings get { return (bool) base["disableAlternativeTemplates"]; } } - [ConfigurationProperty("disableNotPermittedAlternativeTemplates", DefaultValue = "false")] - public bool DisableNotPermittedAlternativeTemplates + [ConfigurationProperty("validateAlternativeTemplates", DefaultValue = "false")] + public bool ValidateAlternativeTemplates { - get { return (bool)base["disableNotPermittedAlternativeTemplates"]; } + get { return (bool)base["validateAlternativeTemplates"]; } } + [ConfigurationProperty("disableFindContentByIdPath", DefaultValue = "false")] public bool DisableFindContentByIdPath { diff --git a/src/Umbraco.Core/Models/ContentType.cs b/src/Umbraco.Core/Models/ContentType.cs index d05fc74ac8..5849fcda04 100644 --- a/src/Umbraco.Core/Models/ContentType.cs +++ b/src/Umbraco.Core/Models/ContentType.cs @@ -105,8 +105,8 @@ namespace Umbraco.Core.Models /// True if AllowedTemplates contains the templateId else False public bool IsAllowedTemplate(int templateId) { - var allowedTemplates = AllowedContentTypes ?? new ContentTypeSort[0]; - return allowedTemplates.Any(t => t.Id.Value == templateId); + var allowedTemplates = AllowedTemplates ?? new ITemplate[0]; + return allowedTemplates.Any(t => t.Id == templateId); } /// @@ -116,7 +116,7 @@ namespace Umbraco.Core.Models /// True if AllowedTemplates contains the templateAlias else False public bool IsAllowedTemplate(string templateAlias) { - var allowedTemplates = AllowedContentTypes ?? new ContentTypeSort[0]; + var allowedTemplates = AllowedTemplates ?? new ITemplate[0]; return allowedTemplates.Any(t => t.Alias.Equals(templateAlias, StringComparison.InvariantCultureIgnoreCase)); } diff --git a/src/Umbraco.Tests/Configurations/UmbracoSettings/WebRoutingElementDefaultTests.cs b/src/Umbraco.Tests/Configurations/UmbracoSettings/WebRoutingElementDefaultTests.cs index eb27126e57..4c77fff5bc 100644 --- a/src/Umbraco.Tests/Configurations/UmbracoSettings/WebRoutingElementDefaultTests.cs +++ b/src/Umbraco.Tests/Configurations/UmbracoSettings/WebRoutingElementDefaultTests.cs @@ -24,9 +24,9 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings } [Test] - public void DisableNotPermittedAlternativeTemplates() + public void ValidateAlternativeTemplates() { - Assert.IsTrue(SettingsSection.WebRouting.DisableNotPermittedAlternativeTemplates == false); + Assert.IsTrue(SettingsSection.WebRouting.ValidateAlternativeTemplates == false); } [Test] diff --git a/src/Umbraco.Web.UI/config/umbracoSettings.config b/src/Umbraco.Web.UI/config/umbracoSettings.config index 0d0ad45d83..522da20c9c 100644 --- a/src/Umbraco.Web.UI/config/umbracoSettings.config +++ b/src/Umbraco.Web.UI/config/umbracoSettings.config @@ -302,9 +302,12 @@ will make Umbraco render the content on the current page with the template you requested, for example: http://mysite.com/about-us/?altTemplate=Home and http://mysite.com/about-us/Home would render the "About Us" page with a template with the alias Home. Setting this setting to true stops that behavior - @disableNotPermittedAlternativeTemplates - Similar to @disableAlternativeTemplates; setting this settings prevents alternative templates which have not been - permitted for the document type. Setting will not have any effect if disableNotPermittedAlternativeTemplates is set. + @validateAlternativeTemplates + By default you can add a altTemplate querystring or append a template name to the current URL which + will make Umbraco render the content on the current page with the template you requested, for example: + http://mysite.com/about-us/?altTemplate=Home and http://mysite.com/about-us/Home would render the + "About Us" page with a template with the alias Home. Setting this setting to true will ensure that + only templates that have been permitted on the document type will be allowed @disableFindContentByIdPath By default you can call any content Id in the url and show the content with that id, for example: http://mysite.com/1092 or http://mysite.com/1092.aspx would render the content with id 1092. Setting @@ -316,7 +319,7 @@ --> diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index 5caa08729a..189dda4934 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -12,6 +12,7 @@ using Umbraco.Web.Models; using Umbraco.Core; using Umbraco.Web.Routing; using ContentType = umbraco.cms.businesslogic.ContentType; +using Umbraco.Core.Configuration; namespace Umbraco.Web { @@ -114,6 +115,44 @@ namespace Umbraco.Web return template == null ? string.Empty : template.Alias; } + public static bool IsTemplateAllowed(this IPublishedContent content, int templateId) + { + if (UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates == true) + return content.TemplateId == templateId; + + if (content.TemplateId != templateId && UmbracoConfig.For.UmbracoSettings().WebRouting.ValidateAlternativeTemplates == true) + { + var publishedContentContentType = ApplicationContext.Current.Services.ContentTypeService.GetContentType(content.ContentType.Id); + if (publishedContentContentType == null) + throw new NullReferenceException("No content type returned for published content (contentType='" + content.ContentType.Id + "')"); + + return publishedContentContentType.IsAllowedTemplate(templateId); + } + + return true; + } + public static bool IsTemplateAllowed(this IPublishedContent content, string templateAlias) + { + var contentTemplateAlias = content.GetTemplateAlias(); + //I assume it is enough to compare aliases, as you can not have different templates with the same alias + var matchingAlias = contentTemplateAlias.Equals(templateAlias, StringComparison.InvariantCultureIgnoreCase); + + if (UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates == true) + return matchingAlias; + + if (matchingAlias == false && UmbracoConfig.For.UmbracoSettings().WebRouting.ValidateAlternativeTemplates == true) + { + var publishedContentContentType = ApplicationContext.Current.Services.ContentTypeService.GetContentType(content.ContentType.Id); + if (publishedContentContentType == null) + throw new NullReferenceException("No content type returned for published content (contentType='" + content.ContentType.Id + "')"); + + //This doesn't appear to be working because new templates aren't in AllowedTemplates + return publishedContentContentType.IsAllowedTemplate(templateAlias); + } + + return true; + } + #endregion #region IsComposedOf diff --git a/src/Umbraco.Web/Routing/ContentFinderByNiceUrlAndTemplate.cs b/src/Umbraco.Web/Routing/ContentFinderByNiceUrlAndTemplate.cs index 570f0d00c5..50696f6867 100644 --- a/src/Umbraco.Web/Routing/ContentFinderByNiceUrlAndTemplate.cs +++ b/src/Umbraco.Web/Routing/ContentFinderByNiceUrlAndTemplate.cs @@ -44,36 +44,15 @@ namespace Umbraco.Web.Routing var route = docRequest.HasDomain ? (docRequest.Domain.RootNodeId.ToString() + path) : path; node = FindContent(docRequest, route); - if (UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates == false && node != null) + if (node.IsTemplateAllowed(template.Id)) { - if (UmbracoConfig.For.UmbracoSettings().WebRouting.DisableNotPermittedAlternativeTemplates == true) - { - var publishedContentContentType = ApplicationContext.Current.Services.ContentTypeService.GetContentType(node.DocumentTypeId); - if (publishedContentContentType == null) - { - LogHelper.Warn("Content type ({1}) of published content({2}) can't be fetched ={1} alias=\"{2}\"", () => tracePrefix, () => node.Id, () => node.DocumentTypeId); - } - else - { - var isAllowedTemplate = publishedContentContentType.IsAllowedTemplate(template.Id); - if (isAllowedTemplate == false) - { - //If it is not allowed then default to as if no altTemplate had been supplied - LogHelper.Warn("{0}Content type '{1}' requested altTemplate of '{2}' but this is not an allowed template", () => tracePrefix, () => node.DocumentTypeAlias, () => template.Alias); - - docRequest.PublishedContent = null; - node = null; - } - else - { - docRequest.TemplateModel = template; - } - } - } - else - { - docRequest.TemplateModel = template; - } + docRequest.TemplateModel = template; + } + else + { + LogHelper.Warn("Configuration settings prevent template \"{0}\" from showing for node \"{1}\"", () => templateAlias, () => node.Id); + docRequest.PublishedContent = null; + node = null; } } else diff --git a/src/Umbraco.Web/Routing/PublishedContentRequestEngine.cs b/src/Umbraco.Web/Routing/PublishedContentRequestEngine.cs index 3acabdcbec..796ef9c1ce 100644 --- a/src/Umbraco.Web/Routing/PublishedContentRequestEngine.cs +++ b/src/Umbraco.Web/Routing/PublishedContentRequestEngine.cs @@ -607,9 +607,8 @@ namespace Umbraco.Web.Routing // only if the published content is the initial once, else the alternate template // does not apply // + optionnally, apply the alternate template on internal redirects - var useAltTemplate = _webRoutingSection.DisableAlternativeTemplates == false - && (_pcr.IsInitialPublishedContent - || (_webRoutingSection.InternalRedirectPreservesTemplate && _pcr.IsInternalRedirectPublishedContent)); + var useAltTemplate = _pcr.IsInitialPublishedContent + || (_webRoutingSection.InternalRedirectPreservesTemplate && _pcr.IsInternalRedirectPublishedContent); string altTemplate = useAltTemplate ? _routingContext.UmbracoContext.HttpContext.Request[Constants.Conventions.Url.AltTemplate] : null; @@ -648,33 +647,18 @@ namespace Umbraco.Web.Routing ProfilingLogger.Logger.Debug("{0}Has a template already, but also an alternate template.", () => tracePrefix); ProfilingLogger.Logger.Debug("{0}Look for alternate template alias=\"{1}\"", () => tracePrefix, () => altTemplate); - var template = ApplicationContext.Current.Services.FileService.GetTemplate(altTemplate); - if (template != null) + if (_pcr.PublishedContent.IsTemplateAllowed(altTemplate)) { - if (UmbracoConfig.For.UmbracoSettings().WebRouting.DisableNotPermittedAlternativeTemplates) - { - var publishedContentContentType = ApplicationContext.Current.Services.ContentTypeService.GetContentType(_pcr.PublishedContent.DocumentTypeId); - if (publishedContentContentType == null) - { - ProfilingLogger.Logger.Warn("{0}Content type ({1}) of published content({2}) can't be fetched ={1} alias=\"{2}\"", () => tracePrefix, () => _pcr.PublishedContent.Id, () => _pcr.PublishedContent.DocumentTypeId); - } - else - { - var isAllowedTemplate = publishedContentContentType.IsAllowedTemplate(template.Id); - if(isAllowedTemplate == false) - { - //If it is not allowed then default to as if no altTemplate had been supplied - ProfilingLogger.Logger.Warn("{0}Content type '{1}' requested altTemplate of '{2}' but this is not an allowed template", () => tracePrefix, () => _pcr.PublishedContent.DocumentTypeAlias, () => altTemplate); - template = GetTemplateModel(_pcr.PublishedContent.TemplateId); - } - } - } - _pcr.TemplateModel = template; - ProfilingLogger.Logger.Debug("{0}Got template id={1} alias=\"{2}\"", () => tracePrefix, () => template.Id, () => template.Alias); + var template = ApplicationContext.Current.Services.FileService.GetTemplate(altTemplate); + if (template != null) + _pcr.TemplateModel = template; + else + ProfilingLogger.Logger.Debug("{0}The template with alias=\"{1}\" does not exist, ignoring.", () => tracePrefix, () => altTemplate); } else { - ProfilingLogger.Logger.Debug("{0}The template with alias=\"{1}\" does not exist, ignoring.", () => tracePrefix, () => altTemplate); + LogHelper.Warn("{0}Configuration settings prevent template \"{1}\" from showing for node \"{2}\"", () => tracePrefix, () => altTemplate, () => _pcr.PublishedContent.Id); + _pcr.TemplateModel = GetTemplateModel(_pcr.PublishedContent.TemplateId); } } diff --git a/src/Umbraco.Web/Templates/TemplateRenderer.cs b/src/Umbraco.Web/Templates/TemplateRenderer.cs index a409e2da2b..2eb00a9c75 100644 --- a/src/Umbraco.Web/Templates/TemplateRenderer.cs +++ b/src/Umbraco.Web/Templates/TemplateRenderer.cs @@ -77,38 +77,16 @@ namespace Umbraco.Web.Templates { contentRequest.Culture = _umbracoContext.PublishedContentRequest.Culture; } - - //set the doc that was found by id - contentRequest.PublishedContent = doc; - //set the template, either based on the AltTemplate found or the standard template of the doc - if (UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates || AltTemplate.HasValue == false) - { - contentRequest.TemplateModel = _umbracoContext.Application.Services.FileService.GetTemplate(doc.TemplateId); - } - else - { - var template = _umbracoContext.Application.Services.FileService.GetTemplate(AltTemplate.Value); - if (UmbracoConfig.For.UmbracoSettings().WebRouting.DisableNotPermittedAlternativeTemplates == false) - { - contentRequest.TemplateModel = template; - } - else - { - //Check if we're allowed to show the selected template - var publishedContentContentType = ApplicationContext.Current.Services.ContentTypeService.GetContentType(contentRequest.PublishedContent.DocumentTypeId); - if (publishedContentContentType != null) - { - var isAllowedTemplate = publishedContentContentType.IsAllowedTemplate(template.Id); - if (isAllowedTemplate == true) - { - contentRequest.TemplateModel = template; - } - } - } - } - //if there is not template then exit - if (!contentRequest.HasTemplate) + //set the doc that was found by id + contentRequest.PublishedContent = doc; + //set the template, either based on the AltTemplate found or the standard template of the doc + contentRequest.TemplateModel = UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates || AltTemplate.HasValue == false + ? _umbracoContext.Application.Services.FileService.GetTemplate(doc.TemplateId) + : _umbracoContext.Application.Services.FileService.GetTemplate(AltTemplate.Value); + + //if there is not template then exit + if (!contentRequest.HasTemplate) { if (!AltTemplate.HasValue) { diff --git a/src/Umbraco.Web/umbraco.presentation/NotFoundHandlers.cs b/src/Umbraco.Web/umbraco.presentation/NotFoundHandlers.cs index de8483b4d0..27e62888d4 100644 --- a/src/Umbraco.Web/umbraco.presentation/NotFoundHandlers.cs +++ b/src/Umbraco.Web/umbraco.presentation/NotFoundHandlers.cs @@ -281,20 +281,7 @@ namespace umbraco { { _redirectID = int.Parse(urlNode.Attributes.GetNamedItem("id").Value); - var altTemplateAllowed = UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates == false; - - //Query: Is it worth the overhead of the DB request here? The usage of AltTemplate is checked later. - if (altTemplateAllowed && UmbracoConfig.For.UmbracoSettings().WebRouting.DisableNotPermittedAlternativeTemplates == true) - { - var nodeTypeAlias = urlNode.Attributes.GetNamedItem("nodeTypeAlias").Value; - var publishedContentContentType = ApplicationContext.Current.Services.ContentTypeService.GetContentType(nodeTypeAlias); - if (publishedContentContentType != null) - { - altTemplateAllowed = publishedContentContentType.IsAllowedTemplate(templateAlias); - } - } - - if (altTemplateAllowed) + if (UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates == false) { HttpContext.Current.Items[Constants.Conventions.Url.AltTemplate] = templateAlias; HttpContext.Current.Trace.Write("umbraco.altTemplateHandler", diff --git a/src/Umbraco.Web/umbraco.presentation/page.cs b/src/Umbraco.Web/umbraco.presentation/page.cs index 2172be88e5..ed4254198e 100644 --- a/src/Umbraco.Web/umbraco.presentation/page.cs +++ b/src/Umbraco.Web/umbraco.presentation/page.cs @@ -152,42 +152,28 @@ namespace umbraco public page(XmlNode node) { populatePageData(node); - - if (UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates == false) - { - var templateSet = false; - // Check for alternative template - if (HttpContext.Current.Items[Constants.Conventions.Url.AltTemplate] != null && - HttpContext.Current.Items[Constants.Conventions.Url.AltTemplate].ToString() != String.Empty) - { - _template = - umbraco.cms.businesslogic.template.Template.GetTemplateIdFromAlias( - HttpContext.Current.Items[Constants.Conventions.Url.AltTemplate].ToString()); - templateSet = true; - } - else if (helper.Request(Constants.Conventions.Url.AltTemplate) != String.Empty) - { - _template = - umbraco.cms.businesslogic.template.Template.GetTemplateIdFromAlias( - helper.Request(Constants.Conventions.Url.AltTemplate).ToLower()); - templateSet = true; - } - if (templateSet == true && UmbracoConfig.For.UmbracoSettings().WebRouting.DisableNotPermittedAlternativeTemplates == true) + if (UmbracoConfig.For.UmbracoSettings().WebRouting.DisableAlternativeTemplates == false) + { + // Check for alternative template + if (HttpContext.Current.Items[Constants.Conventions.Url.AltTemplate] != null && + HttpContext.Current.Items[Constants.Conventions.Url.AltTemplate].ToString() != String.Empty) { - var publishedContentContentType = ApplicationContext.Current.Services.ContentTypeService.GetContentType(_nodeTypeAlias); - if (publishedContentContentType != null && publishedContentContentType.IsAllowedTemplate(_template)) - { - _elements.Add("template", _template.ToString()); - } + _template = + umbraco.cms.businesslogic.template.Template.GetTemplateIdFromAlias( + HttpContext.Current.Items[Constants.Conventions.Url.AltTemplate].ToString()); + _elements.Add("template", _template.ToString()); } - else if(templateSet == true) + else if (helper.Request(Constants.Conventions.Url.AltTemplate) != String.Empty) { + _template = + umbraco.cms.businesslogic.template.Template.GetTemplateIdFromAlias( + helper.Request(Constants.Conventions.Url.AltTemplate).ToLower()); _elements.Add("template", _template.ToString()); } } - if (_template == 0) + if (_template == 0) { try {