diff --git a/build/Build.bat b/build/Build.bat index af15cd5f07..ead7df0abc 100644 --- a/build/Build.bat +++ b/build/Build.bat @@ -1,5 +1,5 @@ @ECHO OFF -SET release=7.0.1 +SET release=7.0.2 SET comment= SET version=%release% diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs index 86b2f17836..f4517608a4 100644 --- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs +++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs @@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration { public class UmbracoVersion { - private static readonly Version Version = new Version("7.0.1"); + private static readonly Version Version = new Version("7.0.2"); /// /// Gets the current version of Umbraco. diff --git a/src/Umbraco.Core/Services/IMemberService.cs b/src/Umbraco.Core/Services/IMemberService.cs index 44fce3eba2..e394c3bffd 100644 --- a/src/Umbraco.Core/Services/IMemberService.cs +++ b/src/Umbraco.Core/Services/IMemberService.cs @@ -8,7 +8,7 @@ namespace Umbraco.Core.Services /// /// Defines the MemberService, which is an easy access to operations involving (umbraco) members. /// - internal interface IMemberService : IMembershipMemberService + public interface IMemberService : IMembershipMemberService { /// /// Checks if a member with the id exists diff --git a/src/Umbraco.Core/Services/IMembershipMemberService.cs b/src/Umbraco.Core/Services/IMembershipMemberService.cs index 18edae2bea..f309eea445 100644 --- a/src/Umbraco.Core/Services/IMembershipMemberService.cs +++ b/src/Umbraco.Core/Services/IMembershipMemberService.cs @@ -10,7 +10,7 @@ namespace Umbraco.Core.Services /// /// Idea is to have this is an isolated interface so that it can be easily 'replaced' in the membership provider impl. /// - internal interface IMembershipMemberService : IService + public interface IMembershipMemberService : IService { /// /// Checks if a member with the username exists diff --git a/src/Umbraco.Core/Services/MemberService.cs b/src/Umbraco.Core/Services/MemberService.cs index 7dcbbe2ff6..c9734d09bd 100644 --- a/src/Umbraco.Core/Services/MemberService.cs +++ b/src/Umbraco.Core/Services/MemberService.cs @@ -18,24 +18,24 @@ namespace Umbraco.Core.Services /// /// Represents the MemberService. /// - internal class MemberService : IMemberService + public class MemberService : IMemberService { private readonly RepositoryFactory _repositoryFactory; private readonly IDatabaseUnitOfWorkProvider _uowProvider; private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(); - public MemberService(RepositoryFactory repositoryFactory) + internal MemberService(RepositoryFactory repositoryFactory) : this(new PetaPocoUnitOfWorkProvider(), repositoryFactory) { } - public MemberService(IDatabaseUnitOfWorkProvider provider) + internal MemberService(IDatabaseUnitOfWorkProvider provider) : this(provider, new RepositoryFactory()) { } - public MemberService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory) + internal MemberService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory) { _repositoryFactory = repositoryFactory; _uowProvider = provider; diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 475ac6824c..4debbc8f57 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -132,7 +132,8 @@ namespace Umbraco.Web.Editors /// /// Gets an entity by a xpath or css-like query /// - /// + /// + /// /// /// public EntityBasic GetByQuery(string query, int rootNodeId, UmbracoEntityTypes type) @@ -143,15 +144,28 @@ namespace Umbraco.Web.Editors // query = css2xpath.Converter.CSSToXPath(query, ""); - if(rootNodeId < 0){ - var nodes = global::umbraco.library.GetXmlNodeByXPath(query); - var node = uQuery.GetNodesByXPath(query).FirstOrDefault(); + if(rootNodeId < 0) + { + var node = Umbraco.TypedContentSingleAtXPath(query); if(node == null) return null; return GetById(node.Id, UmbracoEntityTypes.Document); - }else{ + } + else + { + //SD: This should be done using UmbracoHelper + + //var node = Umbraco.TypedContent(rootNodeId); + //if (node != null) + //{ + // //TODO: Build an Xpath query based on this node ID and the rest of the query + // // var subQuery = [@id=rootNodeId]/query + // // and then get that node with: + // // var result = Umbraco.TypedContentSingleAtXPath(subQuery); + //} + var node = global::umbraco.library.GetXmlNodeById(rootNodeId.ToString()); if (node.MoveNext()) { diff --git a/src/Umbraco.Web/HttpCookieExtensions.cs b/src/Umbraco.Web/HttpCookieExtensions.cs index 8a17d440c4..dc6d087fb3 100644 --- a/src/Umbraco.Web/HttpCookieExtensions.cs +++ b/src/Umbraco.Web/HttpCookieExtensions.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Web; @@ -14,6 +15,30 @@ namespace Umbraco.Web /// internal static class HttpCookieExtensions { + /// + /// Removes the cookie from the request and the response if it exists + /// + /// + /// + public static void ExpireCookie(this HttpContextBase http, string cookieName) + { + //remove from the request + http.Request.Cookies.Remove(cookieName); + + //expire from the response + var angularCookie = http.Response.Cookies[cookieName]; + if (angularCookie != null) + { + //this will expire immediately and be removed from the browser + angularCookie.Expires = DateTime.Now.AddYears(-1); + } + else + { + //ensure there's def an expired cookie + http.Response.Cookies.Add(new HttpCookie(cookieName) { Expires = DateTime.Now.AddYears(-1) }); + } + } + public static string GetPreviewCookieValue(this HttpRequestMessage request) { var cookie = request.Headers.GetCookies(Constants.Web.PreviewCookieName).FirstOrDefault(); diff --git a/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs b/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs new file mode 100644 index 0000000000..8e76053a09 --- /dev/null +++ b/src/Umbraco.Web/Strategies/Migrations/ClearCsrfCookiesAfterUpgrade.cs @@ -0,0 +1,28 @@ +using System.Web; +using Umbraco.Core.Persistence.Migrations; +using Umbraco.Web.WebApi.Filters; +using umbraco.interfaces; + +namespace Umbraco.Web.Strategies.Migrations +{ + /// + /// After upgrade we clear out the csrf tokens + /// + public class ClearCsrfCookiesAfterUpgrade : IApplicationStartupHandler + { + public ClearCsrfCookiesAfterUpgrade() + { + MigrationRunner.Migrated += MigrationRunner_Migrated; + } + + void MigrationRunner_Migrated(MigrationRunner sender, Core.Events.MigrationEventArgs e) + { + if (HttpContext.Current == null) return; + + var http = new HttpContextWrapper(HttpContext.Current); + + http.ExpireCookie(AngularAntiForgeryHelper.AngularCookieName); + http.ExpireCookie(AngularAntiForgeryHelper.CsrfValidationCookieName); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 7e1d051c5f..fa5cb23dac 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -405,6 +405,7 @@ + diff --git a/src/Umbraco.Web/WebApi/Filters/SetAngularAntiForgeryTokensAttribute.cs b/src/Umbraco.Web/WebApi/Filters/SetAngularAntiForgeryTokensAttribute.cs index 9ea42f8a39..a0ed584ef8 100644 --- a/src/Umbraco.Web/WebApi/Filters/SetAngularAntiForgeryTokensAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/SetAngularAntiForgeryTokensAttribute.cs @@ -1,4 +1,5 @@ using System.Linq; +using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Web.Helpers; @@ -16,11 +17,19 @@ namespace Umbraco.Web.WebApi.Filters { if (context.Response == null) return; - //don't need to set the cookie if they already exist + //DO not set the token cookies if the request has failed!! + if (context.Response.StatusCode != HttpStatusCode.OK) return; + + //don't need to set the cookie if they already exist and they are valid if (context.Request.Headers.GetCookies(AngularAntiForgeryHelper.AngularCookieName).Any() && context.Request.Headers.GetCookies(AngularAntiForgeryHelper.CsrfValidationCookieName).Any()) { - return; + //if they are not valid for some strange reason - we need to continue setting valid ones + string failedReason; + if (AngularAntiForgeryHelper.ValidateHeaders(context.Request.Headers, out failedReason)) + { + return; + } } string cookieToken, headerToken;