Compare commits

...

21 Commits

Author SHA1 Message Date
Shannon Deminick 686f6752f3 Merge pull request #5951 from umbraco/v7/hotfix/5921-preview-failing
https://github.com/umbraco/Umbraco-CMS/issues/5921 - AB#1794 - Remove…
2019-07-23 16:58:13 +10:00
Shannon Deminick 23ccdeb2cf Merge pull request #5868 from umbraco/v7/hotfix/5835-AB#1693-add-null-checks-when-using-dataTypeId
Added null checks when *.dataTypeId is used
2019-07-22 13:44:05 +10:00
Shannon 6148ce4e52 oops no es6 support in 7.x 2019-07-22 13:41:26 +10:00
Shannon 06850ed25c Merge branch 'v7/7.15' into v7/hotfix/5835-AB#1693-add-null-checks-when-using-dataTypeId 2019-07-22 13:40:35 +10:00
Shannon 0320a56cb5 Fixes up dataTypeId var declarations 2019-07-22 13:27:51 +10:00
Bjarke Berg cd27bb210f https://github.com/umbraco/Umbraco-CMS/issues/5921 - AB#1794 - Remove trashed nodes from sql when building xml for previews 2019-07-19 11:25:33 +02:00
Bjarke Berg 67f680a675 Revert "https://github.com/umbraco/Umbraco-CMS/issues/5921 - AB#1794 - Remove trashed nodes from sql when building xml for previews"
This reverts commit 47c3e3a7
2019-07-19 11:24:01 +02:00
Bjarke Berg 47c3e3a79f https://github.com/umbraco/Umbraco-CMS/issues/5921 - AB#1794 - Remove trashed nodes from sql when building xml for previews 2019-07-19 11:20:31 +02:00
Shannon f3bfc1ffb2 Puts back UmbracoAntiForgeryAdditionalDataProvider for backwards compat reasons but it is not used 2019-07-18 16:18:11 +10:00
Shannon 89cd655df2 Merge remote-tracking branch 'origin/v7/bugfix/build-without-vs2017' into v7/7.15 2019-07-17 21:48:21 +10:00
Shannon 14c4c4815d bumps version 2019-07-17 21:35:43 +10:00
Shannon bfb69a34ef re-adds back in the serialization overloads for the custom exception, re-adds detailed error messages, adds more documentation. Adds unit tests. 2019-07-17 21:15:18 +10:00
Shannon d52420183e Cherry picks ValidateUmbracoFormRouteStringAttribute implementation and fixes up some logic 2019-07-16 23:03:26 +10:00
skttl 2aaca865e7 changes innerjoin to left join, to allow folders in sql query 2019-07-16 07:26:26 +02:00
Bjarke Berg 59bf24c461 Added null checks when *.dataTypeId is used 2019-07-12 11:22:31 +02:00
Bjarke Berg 2748c3635d Merge pull request #5863 from umbraco/v7/bugfix/5822-entityservice-overloads
Fixes Change to Entity Service GetByKey isn't breaking in 7.15 #5822
2019-07-12 09:29:45 +02:00
Shannon 2252db0d55 Fixes 5822 by reinstating optional method overloads of loadBaseType 2019-07-12 13:40:21 +10:00
Claus df896af476 adding build targets package. 2019-07-10 12:58:15 +02:00
Claus 4b605b2580 Merge pull request #5799 from kjac/v7-fix-save-member
V7: Can't save members without resetting their password
2019-07-08 09:28:46 +02:00
Kenn Jacobsen 80d7f1b2c9 Make it possible to save a member without resetting the password 2019-07-07 11:36:26 +02:00
Sebastiaan Janssen 5ada85df29 Provide the correct assembly redirects 2019-07-05 12:11:03 +02:00
39 changed files with 1740 additions and 1622 deletions
+9 -9
View File
@@ -346,7 +346,7 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.4.9.5" newVersion="1.4.9.5" />
<bindingRedirect oldVersion="0.0.0.0-1.8.8.0" newVersion="1.8.8.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
@@ -358,11 +358,11 @@
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" />
@@ -370,27 +370,27 @@
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
</dependentAssembly>
<dependentAssembly xdt:Transform="Insert">
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral"/>
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.15.0")]
[assembly: AssemblyInformationalVersion("7.15.0")]
[assembly: AssemblyFileVersion("7.15.1")]
[assembly: AssemblyInformationalVersion("7.15.1")]
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.15.0");
private static readonly Version Version = new Version("7.15.1");
/// <summary>
/// Gets the current version of Umbraco.
File diff suppressed because it is too large Load Diff
@@ -370,7 +370,7 @@ namespace Umbraco.Core.Persistence.Repositories
if (isMedia)
{
entitySql.InnerJoin("cmsMedia media").On("media.nodeId = umbracoNode.id");
entitySql.LeftJoin("cmsMedia media").On("media.nodeId = umbracoNode.id");
}
entitySql.LeftJoin("cmsContentType contenttype").On("contenttype.nodeId = content.contentType");
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using Umbraco.Core.CodeAnnotations;
@@ -717,5 +718,32 @@ namespace Umbraco.Core.Services
}
return node.NodeId;
}
#region Obsolete - only here for compat
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IUmbracoEntity GetByKey(Guid key, bool loadBaseType = true) => GetByKey(key);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IUmbracoEntity Get(int id, bool loadBaseType = true) => Get(id);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IUmbracoEntity GetByKey(Guid key, UmbracoObjectTypes umbracoObjectType, bool loadBaseType = true) => GetByKey(key, umbracoObjectType);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IUmbracoEntity GetByKey<T>(Guid key, bool loadBaseType = true) where T : IUmbracoEntity => GetByKey<T>(key);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IUmbracoEntity Get(int id, UmbracoObjectTypes umbracoObjectType, bool loadBaseType = true) => Get(id, umbracoObjectType);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IUmbracoEntity Get<T>(int id, bool loadBaseType = true) where T : IUmbracoEntity => Get<T>(id);
#endregion
}
}
+25 -1
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
@@ -55,6 +56,10 @@ namespace Umbraco.Core.Services
/// <returns>An <see cref="IUmbracoEntity"/></returns>
IUmbracoEntity GetByKey(Guid key);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
IUmbracoEntity GetByKey(Guid key, bool loadBaseType = true);
/// <summary>
/// Gets an UmbracoEntity by its Id, and optionally loads the complete object graph.
/// </summary>
@@ -62,9 +67,13 @@ namespace Umbraco.Core.Services
/// By default this will load the base type <see cref="IUmbracoEntity"/> with a minimum set of properties.
/// </returns>
/// <param name="id">Id of the object to retrieve</param>
/// <returns>An <see cref="IUmbracoEntity"/></returns>
/// <returns>An <see cref="IUmbracoEntity"/></returns>
IUmbracoEntity Get(int id);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
IUmbracoEntity Get(int id, bool loadBaseType = true);
/// <summary>
/// Gets an UmbracoEntity by its Id and UmbracoObjectType, and optionally loads the complete object graph.
/// </summary>
@@ -76,6 +85,14 @@ namespace Umbraco.Core.Services
/// <returns>An <see cref="IUmbracoEntity"/></returns>
IUmbracoEntity GetByKey(Guid key, UmbracoObjectTypes umbracoObjectType);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
IUmbracoEntity GetByKey(Guid key, UmbracoObjectTypes umbracoObjectType, bool loadBaseType = true);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
IUmbracoEntity GetByKey<T>(Guid key, bool loadBaseType = true) where T : IUmbracoEntity;
/// <summary>
/// Gets an UmbracoEntity by its Id and UmbracoObjectType, and optionally loads the complete object graph.
/// </summary>
@@ -87,6 +104,9 @@ namespace Umbraco.Core.Services
/// <returns>An <see cref="IUmbracoEntity"/></returns>
IUmbracoEntity Get(int id, UmbracoObjectTypes umbracoObjectType);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
IUmbracoEntity Get(int id, UmbracoObjectTypes umbracoObjectType, bool loadBaseType = true);
/// <summary>
/// Gets an UmbracoEntity by its Id and specified Type. Optionally loads the complete object graph.
@@ -99,6 +119,10 @@ namespace Umbraco.Core.Services
/// <returns>An <see cref="IUmbracoEntity"/></returns>
IUmbracoEntity Get<T>(int id) where T : IUmbracoEntity;
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
IUmbracoEntity Get<T>(int id, bool loadBaseType = true) where T : IUmbracoEntity;
/// <summary>
/// Gets the parent of entity by its id
/// </summary>
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
@@ -145,6 +146,10 @@ namespace Umbraco.Core.Services
/// <returns>An <see cref="IUmbracoEntity"/></returns>
IUmbracoEntity GetChildEntityFromRelation(IRelation relation);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
IUmbracoEntity GetChildEntityFromRelation(IRelation relation, bool loadBaseType = false);
/// <summary>
/// Gets the Parent object from a Relation as an <see cref="IUmbracoEntity"/>
/// </summary>
@@ -152,6 +157,10 @@ namespace Umbraco.Core.Services
/// <returns>An <see cref="IUmbracoEntity"/></returns>
IUmbracoEntity GetParentEntityFromRelation(IRelation relation);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
IUmbracoEntity GetParentEntityFromRelation(IRelation relation, bool loadBaseType = false);
/// <summary>
/// Gets the Parent and Child objects from a Relation as a <see cref="Tuple"/>"/> with <see cref="IUmbracoEntity"/>.
/// </summary>
@@ -159,6 +168,10 @@ namespace Umbraco.Core.Services
/// <returns>Returns a Tuple with Parent (item1) and Child (item2)</returns>
Tuple<IUmbracoEntity, IUmbracoEntity> GetEntitiesFromRelation(IRelation relation);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
Tuple<IUmbracoEntity, IUmbracoEntity> GetEntitiesFromRelation(IRelation relation, bool loadBaseType = false);
/// <summary>
/// Gets the Child objects from a list of Relations as a list of <see cref="IUmbracoEntity"/> objects.
/// </summary>
@@ -166,6 +179,10 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/></returns>
IEnumerable<IUmbracoEntity> GetChildEntitiesFromRelations(IEnumerable<IRelation> relations);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
IEnumerable<IUmbracoEntity> GetChildEntitiesFromRelations(IEnumerable<IRelation> relations, bool loadBaseType = false);
/// <summary>
/// Gets the Parent objects from a list of Relations as a list of <see cref="IUmbracoEntity"/> objects.
/// </summary>
@@ -173,6 +190,10 @@ namespace Umbraco.Core.Services
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/></returns>
IEnumerable<IUmbracoEntity> GetParentEntitiesFromRelations(IEnumerable<IRelation> relations);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
IEnumerable<IUmbracoEntity> GetParentEntitiesFromRelations(IEnumerable<IRelation> relations, bool loadBaseType = false);
/// <summary>
/// Gets the Parent and Child objects from a list of Relations as a list of <see cref="IUmbracoEntity"/> objects.
/// </summary>
@@ -181,6 +202,12 @@ namespace Umbraco.Core.Services
IEnumerable<Tuple<IUmbracoEntity, IUmbracoEntity>> GetEntitiesFromRelations(
IEnumerable<IRelation> relations);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
IEnumerable<Tuple<IUmbracoEntity, IUmbracoEntity>> GetEntitiesFromRelations(
IEnumerable<IRelation> relations,
bool loadBaseType = false);
/// <summary>
/// Relates two objects by their entity Ids.
/// </summary>
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
@@ -736,5 +737,31 @@ namespace Umbraco.Core.Services
/// </summary>
public static event TypedEventHandler<IRelationService, SaveEventArgs<IRelationType>> SavedRelationType;
#endregion
#region Obsolete - only here for compat
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IUmbracoEntity GetChildEntityFromRelation(IRelation relation, bool loadBaseType = false) => GetChildEntityFromRelation(relation);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IUmbracoEntity GetParentEntityFromRelation(IRelation relation, bool loadBaseType = false) => GetParentEntityFromRelation(relation);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
public Tuple<IUmbracoEntity, IUmbracoEntity> GetEntitiesFromRelation(IRelation relation, bool loadBaseType = false) => GetEntitiesFromRelation(relation);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<IUmbracoEntity> GetChildEntitiesFromRelations(IEnumerable<IRelation> relations, bool loadBaseType = false) => GetChildEntitiesFromRelations(relations);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<IUmbracoEntity> GetParentEntitiesFromRelations(IEnumerable<IRelation> relations, bool loadBaseType = false) => GetParentEntitiesFromRelations(relations);
[Obsolete("Use the overload that doesn't specify loadBaseType instead, loadBaseType will not affect any results")]
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<Tuple<IUmbracoEntity, IUmbracoEntity>> GetEntitiesFromRelations(IEnumerable<IRelation> relations, bool loadBaseType = false) => GetEntitiesFromRelations(relations);
#endregion
}
}
@@ -1,157 +0,0 @@
using System.Collections.Specialized;
using System.Web;
using System.Web.Helpers;
using Moq;
using Newtonsoft.Json;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web.Mvc;
using Umbraco.Web.Security;
namespace Umbraco.Tests.Security
{
[TestFixture]
public class UmbracoAntiForgeryAdditionalDataProviderTests
{
[Test]
public void Test_Wrapped_Non_BeginUmbracoForm()
{
var wrapped = Mock.Of<IAntiForgeryAdditionalDataProvider>(x => x.GetAdditionalData(It.IsAny<HttpContextBase>()) == "custom");
var provider = new UmbracoAntiForgeryAdditionalDataProvider(wrapped);
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
var data = provider.GetAdditionalData(httpContextFactory.HttpContext);
Assert.IsTrue(data.DetectIsJson());
var json = JsonConvert.DeserializeObject<UmbracoAntiForgeryAdditionalDataProvider.AdditionalData>(data);
Assert.AreEqual(null, json.Ufprt);
Assert.IsTrue(json.Stamp != default);
Assert.AreEqual("custom", json.WrappedValue);
}
[Test]
public void Null_Wrapped_Non_BeginUmbracoForm()
{
var provider = new UmbracoAntiForgeryAdditionalDataProvider(null);
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
var data = provider.GetAdditionalData(httpContextFactory.HttpContext);
Assert.IsTrue(data.DetectIsJson());
var json = JsonConvert.DeserializeObject<UmbracoAntiForgeryAdditionalDataProvider.AdditionalData>(data);
Assert.AreEqual(null, json.Ufprt);
Assert.IsTrue(json.Stamp != default);
Assert.AreEqual("default", json.WrappedValue);
}
[Test]
public void Validate_Non_Json()
{
var provider = new UmbracoAntiForgeryAdditionalDataProvider(null);
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
var isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "hello");
Assert.IsFalse(isValid);
}
[Test]
public void Validate_Invalid_Json()
{
var provider = new UmbracoAntiForgeryAdditionalDataProvider(null);
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
var isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '0'}");
Assert.IsFalse(isValid);
isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': ''}");
Assert.IsFalse(isValid);
isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'hello': 'world'}");
Assert.IsFalse(isValid);
}
[Test]
public void Validate_No_Request_Ufprt()
{
var provider = new UmbracoAntiForgeryAdditionalDataProvider(null);
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
//there is a ufprt in the additional data, but not in the request
var isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '636970328040070330', 'WrappedValue': 'default', 'Ufprt': 'ASBVDFDFDFDF'}");
Assert.IsFalse(isValid);
}
[Test]
public void Validate_No_AdditionalData_Ufprt()
{
var provider = new UmbracoAntiForgeryAdditionalDataProvider(null);
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
var requestMock = Mock.Get(httpContextFactory.HttpContext.Request);
requestMock.SetupGet(x => x["ufprt"]).Returns("ABCDEFG");
//there is a ufprt in the additional data, but not in the request
var isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '636970328040070330', 'WrappedValue': 'default', 'Ufprt': ''}");
Assert.IsFalse(isValid);
}
[Test]
public void Validate_No_AdditionalData_Or_Request_Ufprt()
{
var provider = new UmbracoAntiForgeryAdditionalDataProvider(null);
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
//there is a ufprt in the additional data, but not in the request
var isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '636970328040070330', 'WrappedValue': 'default', 'Ufprt': ''}");
Assert.IsTrue(isValid);
}
[Test]
public void Validate_Request_And_AdditionalData_Ufprt()
{
var provider = new UmbracoAntiForgeryAdditionalDataProvider(null);
var routeParams1 = $"{RenderRouteHandler.ReservedAdditionalKeys.Controller}={HttpUtility.UrlEncode("Test")}&{RenderRouteHandler.ReservedAdditionalKeys.Action}={HttpUtility.UrlEncode("Index")}&{RenderRouteHandler.ReservedAdditionalKeys.Area}=Umbraco";
var routeParams2 = $"{RenderRouteHandler.ReservedAdditionalKeys.Controller}={HttpUtility.UrlEncode("Test")}&{RenderRouteHandler.ReservedAdditionalKeys.Action}={HttpUtility.UrlEncode("Index")}&{RenderRouteHandler.ReservedAdditionalKeys.Area}=Umbraco";
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
var requestMock = Mock.Get(httpContextFactory.HttpContext.Request);
requestMock.SetupGet(x => x["ufprt"]).Returns(routeParams1.EncryptWithMachineKey());
var isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '636970328040070330', 'WrappedValue': 'default', 'Ufprt': '" + routeParams2.EncryptWithMachineKey() + "'}");
Assert.IsTrue(isValid);
routeParams2 = $"{RenderRouteHandler.ReservedAdditionalKeys.Controller}={HttpUtility.UrlEncode("Invalid")}&{RenderRouteHandler.ReservedAdditionalKeys.Action}={HttpUtility.UrlEncode("Index")}&{RenderRouteHandler.ReservedAdditionalKeys.Area}=Umbraco";
isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '636970328040070330', 'WrappedValue': 'default', 'Ufprt': '" + routeParams2.EncryptWithMachineKey() + "'}");
Assert.IsFalse(isValid);
}
[Test]
public void Validate_Wrapped_Request_And_AdditionalData_Ufprt()
{
var wrapped = Mock.Of<IAntiForgeryAdditionalDataProvider>(x => x.ValidateAdditionalData(It.IsAny<HttpContextBase>(), "custom") == true);
var provider = new UmbracoAntiForgeryAdditionalDataProvider(wrapped);
var routeParams1 = $"{RenderRouteHandler.ReservedAdditionalKeys.Controller}={HttpUtility.UrlEncode("Test")}&{RenderRouteHandler.ReservedAdditionalKeys.Action}={HttpUtility.UrlEncode("Index")}&{RenderRouteHandler.ReservedAdditionalKeys.Area}=Umbraco";
var routeParams2 = $"{RenderRouteHandler.ReservedAdditionalKeys.Controller}={HttpUtility.UrlEncode("Test")}&{RenderRouteHandler.ReservedAdditionalKeys.Action}={HttpUtility.UrlEncode("Index")}&{RenderRouteHandler.ReservedAdditionalKeys.Area}=Umbraco";
var httpContextFactory = new FakeHttpContextFactory("/hello/world");
var requestMock = Mock.Get(httpContextFactory.HttpContext.Request);
requestMock.SetupGet(x => x["ufprt"]).Returns(routeParams1.EncryptWithMachineKey());
var isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '636970328040070330', 'WrappedValue': 'default', 'Ufprt': '" + routeParams2.EncryptWithMachineKey() + "'}");
Assert.IsFalse(isValid);
isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '636970328040070330', 'WrappedValue': 'custom', 'Ufprt': '" + routeParams2.EncryptWithMachineKey() + "'}");
Assert.IsTrue(isValid);
routeParams2 = $"{RenderRouteHandler.ReservedAdditionalKeys.Controller}={HttpUtility.UrlEncode("Invalid")}&{RenderRouteHandler.ReservedAdditionalKeys.Action}={HttpUtility.UrlEncode("Index")}&{RenderRouteHandler.ReservedAdditionalKeys.Area}=Umbraco";
isValid = provider.ValidateAdditionalData(httpContextFactory.HttpContext, "{'Stamp': '636970328040070330', 'WrappedValue': 'default', 'Ufprt': '" + routeParams2.EncryptWithMachineKey() + "'}");
Assert.IsFalse(isValid);
}
}
}
+1 -1
View File
@@ -197,7 +197,6 @@
<Compile Include="Packaging\PackageExtractionTests.cs" />
<Compile Include="Persistence\Repositories\SimilarNodeNameTests.cs" />
<Compile Include="PublishedContent\StronglyTypedModels\Home.cs" />
<Compile Include="Security\UmbracoAntiForgeryAdditionalDataProviderTests.cs" />
<Compile Include="Services\AuditServiceTests.cs" />
<Compile Include="Services\ConsentServiceTests.cs" />
<Compile Include="Services\MemberGroupServiceTests.cs" />
@@ -399,6 +398,7 @@
<Compile Include="Models\ContentExtensionsTests.cs" />
<Compile Include="Models\UserExtensionsTests.cs" />
<Compile Include="Web\Mvc\MergeParentContextViewDataAttributeTests.cs" />
<Compile Include="Web\Mvc\ValidateUmbracoFormRouteStringAttributeTests.cs" />
<Compile Include="Web\Mvc\ViewDataDictionaryExtensionTests.cs" />
<Compile Include="Persistence\PetaPocoExtensionsTest.cs" />
<Compile Include="Persistence\Querying\ContentTypeSqlMappingTests.cs" />
@@ -4,7 +4,8 @@ using Umbraco.Web;
namespace Umbraco.Tests.Web.Mvc
{
[TestFixture]
[TestFixture]
public class HtmlHelperExtensionMethodsTests
{
[SetUp]
@@ -0,0 +1,37 @@
using NUnit.Framework;
using Umbraco.Web;
using Umbraco.Web.Mvc;
namespace Umbraco.Tests.Web.Mvc
{
[TestFixture]
public class ValidateUmbracoFormRouteStringAttributeTests
{
[Test]
public void Validate_Route_String()
{
var attribute = new ValidateUmbracoFormRouteStringAttribute();
Assert.Throws<HttpUmbracoFormRouteStringException>(() => attribute.ValidateRouteString(null, null, null, null));
const string ControllerName = "Test";
const string ControllerAction = "Index";
const string Area = "MyArea";
var validUfprt = UmbracoHelper.CreateEncryptedRouteString(ControllerName, ControllerAction, Area);
var invalidUfprt = validUfprt + "z";
Assert.Throws<HttpUmbracoFormRouteStringException>(() => attribute.ValidateRouteString(invalidUfprt, null, null, null));
Assert.Throws<HttpUmbracoFormRouteStringException>(() => attribute.ValidateRouteString(validUfprt, ControllerName, ControllerAction, "doesntMatch"));
Assert.Throws<HttpUmbracoFormRouteStringException>(() => attribute.ValidateRouteString(validUfprt, ControllerName, ControllerAction, null));
Assert.Throws<HttpUmbracoFormRouteStringException>(() => attribute.ValidateRouteString(validUfprt, ControllerName, "doesntMatch", Area));
Assert.Throws<HttpUmbracoFormRouteStringException>(() => attribute.ValidateRouteString(validUfprt, ControllerName, null, Area));
Assert.Throws<HttpUmbracoFormRouteStringException>(() => attribute.ValidateRouteString(validUfprt, "doesntMatch", ControllerAction, Area));
Assert.Throws<HttpUmbracoFormRouteStringException>(() => attribute.ValidateRouteString(validUfprt, null, ControllerAction, Area));
Assert.DoesNotThrow(() => attribute.ValidateRouteString(validUfprt, ControllerName, ControllerAction, Area));
Assert.DoesNotThrow(() => attribute.ValidateRouteString(validUfprt, ControllerName.ToLowerInvariant(), ControllerAction.ToLowerInvariant(), Area.ToLowerInvariant()));
}
}
}
@@ -409,7 +409,8 @@ function entityResource($q, $http, umbRequestHelper) {
pageNumber: 100,
filter: '',
orderDirection: "Ascending",
orderBy: "SortOrder"
orderBy: "SortOrder",
dataTypeId: null
};
if (options === undefined) {
options = {};
@@ -426,6 +427,7 @@ function entityResource($q, $http, umbRequestHelper) {
options.orderDirection = "Descending";
}
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
@@ -14,7 +14,7 @@ angular.module("umbraco").controller("Umbraco.Dialogs.LinkPickerController",
searchFromId: null,
searchFromName: null,
showSearch: false,
dataTypeId: $scope.model.dataTypeId,
dataTypeId: ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null,
results: [],
selectedSearchResults: []
}
@@ -12,17 +12,22 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
$scope.model.title = localizationService.localize("defaultdialogs_selectLink");
}
var dataTypeId = null;
if(dialogOptions && dialogOptions.dataTypeId){
dataTypeId = dialogOptions.dataTypeId;
}
$scope.dialogTreeEventHandler = $({});
$scope.model.target = {};
$scope.searchInfo = {
searchFromId: null,
searchFromName: null,
showSearch: false,
dataTypeId: dialogOptions.dataTypeId,
dataTypeId: dataTypeId,
results: [],
selectedSearchResults: []
};
$scope.customTreeParams = dialogOptions.dataTypeId ? "dataTypeId=" + dialogOptions.dataTypeId : "";
$scope.customTreeParams = dataTypeId !== null ? "dataTypeId=" + dataTypeId : "";
$scope.showTarget = $scope.model.hideTarget !== true;
if (dialogOptions.currentTarget) {
@@ -115,12 +120,13 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController",
startNodeId = -1;
startNodeIsVirtual = true;
}
$scope.mediaPickerOverlay = {
view: "mediapicker",
startNodeId: startNodeId,
startNodeIsVirtual: startNodeIsVirtual,
show: true,
dataTypeId: dialogOptions.dataTypeId,
dataTypeId: dataTypeId,
submit: function (model) {
var media = model.selectedImages[0];
@@ -44,13 +44,17 @@ angular.module("umbraco")
$scope.acceptedMediatypes = types;
});
var dataTypeId = null;
if($scope.model && $scope.model.dataTypeId) {
dataTypeId = $scope.model.dataTypeId;
}
$scope.searchOptions = {
pageNumber: 1,
pageSize: 100,
totalItems: 0,
totalPages: 0,
filter: '',
dataTypeId: $scope.model.dataTypeId
dataTypeId: dataTypeId
};
//preload selected item
@@ -157,7 +161,8 @@ angular.module("umbraco")
}
if (folder.id > 0) {
entityResource.getAncestors(folder.id, "media", { dataTypeId: $scope.model.dataTypeId })
entityResource.getAncestors(folder.id, "media", { dataTypeId: dataTypeId })
.then(function (anc) {
$scope.path = _.filter(anc,
function (f) {
@@ -309,6 +314,7 @@ angular.module("umbraco")
if ($scope.searchOptions.filter) {
searchMedia();
} else {
// reset pagination
$scope.searchOptions = {
pageNumber: 1,
@@ -316,7 +322,7 @@ angular.module("umbraco")
totalItems: 0,
totalPages: 0,
filter: '',
dataTypeId: $scope.model.dataTypeId
dataTypeId: dataTypeId
};
getChildren($scope.currentFolder.id);
}
@@ -4,6 +4,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController",
var tree = null;
var dialogOptions = $scope.model;
$scope.treeReady = false;
$scope.dialogTreeEventHandler = $({});
$scope.section = dialogOptions.section;
@@ -16,7 +17,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController",
searchFromId: dialogOptions.startNodeId,
searchFromName: null,
showSearch: false,
dataTypeId: dialogOptions.dataTypeId,
dataTypeId: (dialogOptions && dialogOptions.dataTypeId) ? dialogOptions.dataTypeId : null,
results: [],
selectedSearchResults: []
}
@@ -133,7 +133,7 @@ function MemberEditController($scope, $routeParams, $location, $q, $window, appS
//anytime a user is changing a member's password without the oldPassword, we are in effect resetting it so we need to set that flag here
var passwordProp = _.find(contentEditingHelper.getAllProps($scope.content), function (e) { return e.alias === '_umb_password' });
if (!passwordProp.value.reset) {
if (passwordProp && passwordProp.value && !passwordProp.value.reset) {
//so if the admin is not explicitly resetting the password, flag it for resetting if a new password is being entered
passwordProp.value.reset = !passwordProp.value.oldPassword && passwordProp.config.allowManuallyChangingPassword;
}
@@ -68,11 +68,11 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
showPathOnHover: false,
dataTypeId: null,
maxNumber: 1,
minNumber : 0,
minNumber: 0,
startNode: {
query: "",
type: "content",
id: $scope.model.config.startNodeId ? $scope.model.config.startNodeId : -1 // get start node for simple Content Picker
id: $scope.model.config.startNodeId ? $scope.model.config.startNodeId : -1 // get start node for simple Content Picker
}
};
@@ -104,8 +104,8 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
var entityType = $scope.model.config.startNode.type === "member"
? "Member"
: $scope.model.config.startNode.type === "media"
? "Media"
: "Document";
? "Media"
: "Document";
$scope.allowOpenButton = entityType === "Document";
$scope.allowEditButton = entityType === "Document";
$scope.allowRemoveButton = true;
@@ -144,7 +144,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
dialogOptions.filterCssClass = "not-allowed";
var currFilter = dialogOptions.filter;
//now change the filter to be a method
dialogOptions.filter = function(i) {
dialogOptions.filter = function (i) {
//filter out the list view nodes
if (i.metaData.isContainer) {
return true;
@@ -179,29 +179,30 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
}
//dialog
$scope.openContentPicker = function() {
$scope.contentPickerOverlay = dialogOptions;
$scope.contentPickerOverlay.view = "treepicker";
$scope.contentPickerOverlay.show = true;
$scope.contentPickerOverlay.dataTypeId = $scope.model.dataTypeId;
$scope.openContentPicker = function () {
$scope.contentPickerOverlay = dialogOptions;
$scope.contentPickerOverlay.view = "treepicker";
$scope.contentPickerOverlay.show = true;
$scope.contentPickerOverlay.dataTypeId = ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null;
$scope.contentPickerOverlay.submit = function(model) {
$scope.contentPickerOverlay.submit = function (model) {
if (angular.isArray(model.selection)) {
_.each(model.selection, function (item, i) {
$scope.add(item);
});
angularHelper.getCurrentForm($scope).$setDirty();
}
if (angular.isArray(model.selection)) {
_.each(model.selection, function (item, i) {
$scope.add(item);
});
angularHelper.getCurrentForm($scope).$setDirty();
}
$scope.contentPickerOverlay.show = false;
$scope.contentPickerOverlay = null;
}
$scope.contentPickerOverlay.show = false;
$scope.contentPickerOverlay = null;
}
$scope.contentPickerOverlay.close = function(oldModel) {
$scope.contentPickerOverlay.show = false;
$scope.contentPickerOverlay = null;
}
$scope.contentPickerOverlay.close = function (oldModel) {
$scope.contentPickerOverlay.show = false;
$scope.contentPickerOverlay = null;
}
};
@@ -241,13 +242,13 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
$scope.renderModel = [];
};
$scope.openMiniEditor = function(node) {
miniEditorHelper.launchMiniEditor(node).then(function(updatedNode){
$scope.openMiniEditor = function (node) {
miniEditorHelper.launchMiniEditor(node).then(function (updatedNode) {
// update the node
node.name = updatedNode.name;
node.published = updatedNode.hasPublishedVersion;
if(entityType !== "Member") {
entityResource.getUrl(updatedNode.id, entityType).then(function(data){
if (entityType !== "Member") {
entityResource.getUrl(updatedNode.id, entityType).then(function (data) {
node.url = data;
});
}
@@ -256,7 +257,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
//when the scope is destroyed we need to unsubscribe
$scope.$on('$destroy', function () {
if(unsubscribe) {
if (unsubscribe) {
unsubscribe();
}
});
@@ -265,12 +266,12 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
//load current data if anything selected
if (modelIds.length > 0) {
entityResource.getByIds(modelIds, entityType).then(function(data) {
entityResource.getByIds(modelIds, entityType).then(function (data) {
_.each(modelIds,
function(id, i) {
function (id, i) {
var entity = _.find(data,
function(d) {
function (d) {
return $scope.model.config.idType === "udi" ? (d.udi == id) : (d.id == id);
});
@@ -294,10 +295,10 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
function setEntityUrl(entity) {
// get url for content and media items
if(entityType !== "Member") {
entityResource.getUrl(entity.id, entityType).then(function(data){
if (entityType !== "Member") {
entityResource.getUrl(entity.id, entityType).then(function (data) {
// update url
angular.forEach($scope.renderModel, function(item){
angular.forEach($scope.renderModel, function (item) {
if (item.id === entity.id) {
if (entity.trashed) {
item.url = localizationService.dictionary.general_recycleBin;
@@ -319,7 +320,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
function addSelectedItem(item) {
// set icon
if(item.icon) {
if (item.icon) {
item.icon = iconHelper.convertFromLegacyIcon(item.icon);
}
@@ -354,7 +355,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
function setSortingState(items) {
// disable sorting if the list only consist of one item
if(items.length > 1) {
if (items.length > 1) {
$scope.sortableOptions.disabled = false;
} else {
$scope.sortableOptions.disabled = true;
@@ -16,12 +16,13 @@ angular.module("umbraco")
}
$scope.setImage = function(){
$scope.mediaPickerOverlay = {};
$scope.mediaPickerOverlay.view = "mediapicker";
$scope.mediaPickerOverlay.startNodeId = $scope.model.config && $scope.model.config.startNodeId ? $scope.model.config.startNodeId : undefined;
$scope.mediaPickerOverlay.startNodeIsVirtual = $scope.mediaPickerOverlay.startNodeId ? $scope.model.config.startNodeIsVirtual : undefined;
$scope.mediaPickerOverlay.dataTypeId = $scope.model.dataTypeId;
$scope.mediaPickerOverlay.cropSize = $scope.control.editor.config && $scope.control.editor.config.size ? $scope.control.editor.config.size : undefined;
$scope.mediaPickerOverlay.startNodeId = $scope.model.config && $scope.model.config.startNodeId ? $scope.model.config.startNodeId : null;
$scope.mediaPickerOverlay.startNodeIsVirtual = $scope.mediaPickerOverlay.startNodeId ? $scope.model.config.startNodeIsVirtual : null;
$scope.mediaPickerOverlay.dataTypeId = ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null;
$scope.mediaPickerOverlay.cropSize = $scope.control.editor.config && $scope.control.editor.config.size ? $scope.control.editor.config.size : null;
$scope.mediaPickerOverlay.showDetails = true;
$scope.mediaPickerOverlay.disableFolderSelect = true;
$scope.mediaPickerOverlay.onlyImages = true;
@@ -10,14 +10,17 @@
vm.openMacroPicker = openMacroPicker;
vm.openEmbed = openEmbed;
var dataTypeId = ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null;
function openLinkPicker(editor, currentTarget, anchorElement) {
entityResource.getAnchors(JSON.stringify($scope.model.value)).then(function(anchorValues) {
vm.linkPickerOverlay = {
view: "linkpicker",
currentTarget: currentTarget,
anchors: anchorValues,
dataTypeId: $scope.model.dataTypeId,
dataTypeId: dataTypeId,
ignoreUserStartNodes : $scope.model.config.ignoreUserStartNodes,
show: true,
submit: function(model) {
@@ -46,7 +49,7 @@
showDetails: true,
startNodeId: startNodeId,
startNodeIsVirtual: startNodeIsVirtual,
dataTypeId: $scope.model.dataTypeId,
dataTypeId: dataTypeId,
view: "mediapicker",
show: true,
submit: function(model) {
@@ -107,13 +107,13 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
};
$scope.add = function() {
$scope.mediaPickerOverlay = {
view: "mediapicker",
title: "Select media",
startNodeId: $scope.model.config.startNodeId,
startNodeIsVirtual: $scope.model.config.startNodeIsVirtual,
dataTypeId: $scope.model.dataTypeId,
dataTypeId: ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null,
multiPicker: multiPicker,
onlyImages: onlyImages,
disableFolderSelect: disableFolderSelect,
@@ -71,7 +71,7 @@ function multiUrlPickerController($scope, angularHelper, localizationService, en
$scope.linkPickerOverlay = {
view: "linkpicker",
currentTarget: target,
dataTypeId: $scope.model.dataTypeId,
dataTypeId: ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null,
ignoreUserStartNodes : $scope.model.config.ignoreUserStartNodes,
show: true,
submit: function (model) {
@@ -18,14 +18,17 @@
$scope.currentEditLink = null;
$scope.hasError = false;
var dataTypeId = ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null;
$scope.internal = function($event) {
$scope.currentEditLink = null;
$scope.contentPickerOverlay = {};
$scope.contentPickerOverlay.view = "contentpicker";
$scope.contentPickerOverlay.multiPicker = false;
$scope.contentPickerOverlay.show = true;
$scope.contentPickerOverlay.dataTypeId = $scope.model.dataTypeId;
$scope.contentPickerOverlay.dataTypeId = dataTypeId;
$scope.contentPickerOverlay.idType = $scope.model.config.idType ? $scope.model.config.idType : "int";
$scope.contentPickerOverlay.submit = function(model) {
@@ -45,13 +48,14 @@
};
$scope.selectInternal = function ($event, link) {
$scope.currentEditLink = link;
$scope.contentPickerOverlay = {};
$scope.contentPickerOverlay.view = "contentpicker";
$scope.contentPickerOverlay.multiPicker = false;
$scope.contentPickerOverlay.show = true;
$scope.contentPickerOverlay.dataTypeId = $scope.model.dataTypeId;
$scope.contentPickerOverlay.dataTypeId = dataTypeId;
$scope.contentPickerOverlay.idType = $scope.model.config.idType ? $scope.model.config.idType : "int";
$scope.contentPickerOverlay.submit = function(model) {
@@ -52,6 +52,8 @@ angular.module("umbraco")
editorConfig.maxImageSize = tinyMceService.defaultPrevalues().maxImageSize;
}
var dataTypeId = ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null;
//queue file loading
if (typeof tinymce === "undefined") { // Don't reload tinymce if already loaded
await.push(assetsService.loadJs("lib/tinymce/tinymce.min.js", $scope));
@@ -272,11 +274,12 @@ angular.module("umbraco")
tinyMceService.createLinkPicker(editor, $scope, function(currentTarget, anchorElement) {
entityResource.getAnchors($scope.model.value).then(function(anchorValues){
$scope.linkPickerOverlay = {
view: "linkpicker",
currentTarget: currentTarget,
anchors: anchorValues,
dataTypeId: $scope.model.dataTypeId,
dataTypeId: dataTypeId,
ignoreUserStartNodes: $scope.model.config.ignoreUserStartNodes,
show: true,
submit: function(model) {
@@ -300,7 +303,7 @@ angular.module("umbraco")
startNodeId = -1;
startNodeIsVirtual = true;
}
$scope.mediaPickerOverlay = {
currentTarget: currentTarget,
onlyImages: true,
@@ -308,7 +311,7 @@ angular.module("umbraco")
disableFolderSelect: true,
startNodeId: startNodeId,
startNodeIsVirtual: startNodeIsVirtual,
dataTypeId: $scope.model.dataTypeId,
dataTypeId: dataTypeId,
view: "mediapicker",
show: true,
submit: function(model) {
+4 -2
View File
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
<Import Project="..\packages\MSBuild.Microsoft.VisualStudio.Web.targets.14.0.0.3\build\MSBuild.Microsoft.VisualStudio.Web.targets.props" Condition="Exists('..\packages\MSBuild.Microsoft.VisualStudio.Web.targets.14.0.0.3\build\MSBuild.Microsoft.VisualStudio.Web.targets.props')" />
<Import Project="..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" />
<Import Project="..\packages\Microsoft.Net.Compilers.1.3.2\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.1.3.2\build\Microsoft.Net.Compilers.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
@@ -1027,9 +1028,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>7150</DevelopmentServerPort>
<DevelopmentServerPort>7151</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:7150</IISUrl>
<IISUrl>http://localhost:7151</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
@@ -1088,5 +1089,6 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.Net.Compilers.1.3.2\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Net.Compilers.1.3.2\build\Microsoft.Net.Compilers.props'))" />
<Error Condition="!Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.2.0.1\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props'))" />
<Error Condition="!Exists('..\packages\MSBuild.Microsoft.VisualStudio.Web.targets.14.0.0.3\build\MSBuild.Microsoft.VisualStudio.Web.targets.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSBuild.Microsoft.VisualStudio.Web.targets.14.0.0.3\build\MSBuild.Microsoft.VisualStudio.Web.targets.props'))" />
</Target>
</Project>
+1
View File
@@ -32,6 +32,7 @@
<package id="Microsoft.Owin.Security.OAuth" version="4.0.1" targetFramework="net452" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
<package id="MiniProfiler" version="2.1.0" targetFramework="net45" />
<package id="MSBuild.Microsoft.VisualStudio.Web.targets" version="14.0.0.3" targetFramework="net452" />
<package id="MySql.Data" version="6.9.9" targetFramework="net45" />
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net452" />
<package id="Owin" version="1.0" targetFramework="net45" />
@@ -12,6 +12,7 @@ namespace Umbraco.Web.Controllers
{
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateUmbracoFormRouteString]
public ActionResult HandleLogin([Bind(Prefix = "loginModel")]LoginModel model)
{
if (ModelState.IsValid == false)
@@ -13,6 +13,7 @@ namespace Umbraco.Web.Controllers
{
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateUmbracoFormRouteString]
public ActionResult HandleLogout([Bind(Prefix = "logoutModel")]PostRedirectModel model)
{
if (ModelState.IsValid == false)
@@ -16,6 +16,7 @@ namespace Umbraco.Web.Controllers
{
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateUmbracoFormRouteString]
public ActionResult HandleUpdateProfile([Bind(Prefix = "profileModel")] ProfileModel model)
{
var provider = global::Umbraco.Core.Security.MembershipProviderExtensions.GetMembersMembershipProvider();
@@ -11,6 +11,7 @@ namespace Umbraco.Web.Controllers
{
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateUmbracoFormRouteString]
public ActionResult HandleRegisterMember([Bind(Prefix = "registerModel")]RegisterModel model)
{
if (ModelState.IsValid == false)
@@ -293,13 +293,6 @@ namespace Umbraco.Web
_controllerName = controllerName;
_encryptedString = UmbracoHelper.CreateEncryptedRouteString(controllerName, controllerAction, area, additionalRouteVals);
//For UmbracoForm's we want to add our routing string to the httpcontext items in the case where anti-forgery tokens are used.
//In which case our custom UmbracoAntiForgeryAdditionalDataProvider will kick in and validate the values in the request against
//the values that will be appended to the token. This essentially means that when anti-forgery tokens are used with UmbracoForm's forms,
//that each token is unique to the controller/action/area instead of the default ASP.Net implementation which is that the token is unique
//per user.
_viewContext.HttpContext.Items["ufprt"] = _encryptedString;
}
@@ -0,0 +1,41 @@
using System;
using System.Net;
using System.Runtime.Serialization;
using System.Web;
namespace Umbraco.Web.Mvc
{
/// <summary>
/// Exception that occurs when an Umbraco form route string is invalid
/// </summary>
/// <seealso cref="System.Web.HttpException" />
[Serializable]
public sealed class HttpUmbracoFormRouteStringException : HttpException
{
/// Initializes a new instance of the <see cref="HttpUmbracoFormRouteStringException" /> class.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that holds the contextual information about the source or destination.</param>
private HttpUmbracoFormRouteStringException(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="HttpUmbracoFormRouteStringException" /> class.
/// </summary>
/// <param name="message">The error message displayed to the client when the exception is thrown.</param>
public HttpUmbracoFormRouteStringException(string message)
: base(message)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="HttpUmbracoFormRouteStringException" /> class.
/// </summary>
/// <param name="message">The error message displayed to the client when the exception is thrown.</param>
/// <param name="innerException">The <see cref="P:System.Exception.InnerException" />, if any, that threw the current exception.</param>
public HttpUmbracoFormRouteStringException(string message, Exception innerException)
: base(message, innerException)
{ }
}
}
@@ -0,0 +1,62 @@
using System;
using System.Net;
using System.Net.Http;
using System.Web.Mvc;
using Umbraco.Core;
namespace Umbraco.Web.Mvc
{
/// <summary>
/// Attribute used to check that the request contains a valid Umbraco form request string.
/// </summary>
/// <seealso cref="System.Web.Mvc.FilterAttribute" />
/// <seealso cref="System.Web.Mvc.IAuthorizationFilter" />
/// <remarks>
/// Applying this attribute/filter to a <see cref="SurfaceController"/> or SurfaceController Action will ensure that the Action can only be executed
/// when it is routed to from within Umbraco, typically when rendering a form with BegingUmbracoForm. It will mean that the natural MVC route for this Action
/// will fail with a <see cref="HttpUmbracoFormRouteStringException"/>.
/// </remarks>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class ValidateUmbracoFormRouteStringAttribute : FilterAttribute, IAuthorizationFilter
{
/// <summary>
/// Called when authorization is required.
/// </summary>
/// <param name="filterContext">The filter context.</param>
/// <exception cref="ArgumentNullException">filterContext</exception>
/// <exception cref="Umbraco.Web.Mvc.HttpUmbracoFormRouteStringException">The required request field \"ufprt\" is not present.
/// or
/// The Umbraco form request route string could not be decrypted.
/// or
/// The provided Umbraco form request route string was meant for a different controller and action.</exception>
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
throw new ArgumentNullException(nameof(filterContext));
var ufprt = filterContext.HttpContext.Request["ufprt"];
ValidateRouteString(ufprt, filterContext.ActionDescriptor?.ControllerDescriptor.ControllerName, filterContext.ActionDescriptor?.ActionName, filterContext.RouteData?.DataTokens["area"]?.ToString());
}
public void ValidateRouteString(string ufprt, string currentController, string currentAction, string currentArea)
{
if (ufprt.IsNullOrWhiteSpace())
{
throw new HttpUmbracoFormRouteStringException("The required request field \"ufprt\" is not present.");
}
if (!UmbracoHelper.DecryptAndValidateEncryptedRouteString(ufprt, out var additionalDataParts))
{
throw new HttpUmbracoFormRouteStringException("The Umbraco form request route string could not be decrypted.");
}
if (!additionalDataParts[RenderRouteHandler.ReservedAdditionalKeys.Controller].InvariantEquals(currentController) ||
!additionalDataParts[RenderRouteHandler.ReservedAdditionalKeys.Action].InvariantEquals(currentAction) ||
(!additionalDataParts[RenderRouteHandler.ReservedAdditionalKeys.Area].IsNullOrWhiteSpace() && !additionalDataParts[RenderRouteHandler.ReservedAdditionalKeys.Area].InvariantEquals(currentArea)))
{
throw new HttpUmbracoFormRouteStringException("The provided Umbraco form request route string was meant for a different controller and action.");
}
}
}
}
@@ -4,12 +4,12 @@ using Umbraco.Core;
using System.Web.Helpers;
using System.Web;
using Newtonsoft.Json;
using System.ComponentModel;
namespace Umbraco.Web.Security
{
/// <summary>
/// A custom <see cref="IAntiForgeryAdditionalDataProvider"/> to create a unique antiforgery token/validator per form created with BeginUmbracoForm
/// </summary>
[Obsolete("This is no longer used and will be removed from the codebase in future versions")]
[EditorBrowsable(EditorBrowsableState.Never)]
public class UmbracoAntiForgeryAdditionalDataProvider : IAntiForgeryAdditionalDataProvider
{
private readonly IAntiForgeryAdditionalDataProvider _defaultProvider;
+3 -1
View File
@@ -307,7 +307,8 @@
<Compile Include="Cache\TemplateCacheRefresher.cs" />
<Compile Include="Cache\UnpublishedPageCacheRefresher.cs" />
<Compile Include="Cache\UserCacheRefresher.cs" />
<Compile Include="Security\UmbracoAntiForgeryAdditionalDataProvider.cs" />
<Compile Include="Mvc\HttpUmbracoFormRouteStringException.cs" />
<Compile Include="Mvc\ValidateUmbracoFormRouteStringAttribute.cs" />
<Compile Include="Editors\PreviewController.cs" />
<Compile Include="Editors\BackOfficeAssetsController.cs" />
<Compile Include="Features\DisabledFeatures.cs" />
@@ -340,6 +341,7 @@
<Compile Include="Models\Mapping\MemberTreeNodeUrlResolver.cs" />
<Compile Include="Models\Trees\ExportMember.cs" />
<Compile Include="PropertyEditors\DropdownFlexiblePropertyEditor.cs" />
<Compile Include="Security\UmbracoAntiForgeryAdditionalDataProvider.cs" />
<Compile Include="TourFilterResolver.cs" />
<Compile Include="Editors\UserEditorAuthorizationHelper.cs" />
<Compile Include="Editors\UserGroupAuthorizationAttribute.cs" />
+1 -1
View File
@@ -1656,7 +1656,7 @@ namespace Umbraco.Web
{
decryptedString = ufprt.DecryptWithMachineKey();
}
catch (FormatException)
catch (Exception ex) when (ex is FormatException || ex is ArgumentException)
{
LogHelper.Warn<UmbracoHelper>("A value was detected in the ufprt parameter but Umbraco could not decrypt the string");
parts = null;
-2
View File
@@ -190,8 +190,6 @@ namespace Umbraco.Web
base.Complete(afterComplete);
AntiForgeryConfig.AdditionalDataProvider = new UmbracoAntiForgeryAdditionalDataProvider(AntiForgeryConfig.AdditionalDataProvider);
//Now, startup all of our legacy startup handler
ApplicationEventsResolver.Current.InstantiateLegacyStartupHandlers();