diff --git a/src/Umbraco.Core/Security/UmbracoBackOfficeIdentity.cs b/src/Umbraco.Core/Security/UmbracoBackOfficeIdentity.cs
index 3223e37faf..67cff98ac4 100644
--- a/src/Umbraco.Core/Security/UmbracoBackOfficeIdentity.cs
+++ b/src/Umbraco.Core/Security/UmbracoBackOfficeIdentity.cs
@@ -47,7 +47,7 @@ namespace Umbraco.Core.Security
}
}
- public int Id
+ public object Id
{
get
{
@@ -65,6 +65,15 @@ namespace Umbraco.Core.Security
}
}
+ public string Culture
+ {
+ get
+ {
+ EnsureDeserialized();
+ return DeserializedData.Culture;
+ }
+ }
+
//public int SessionTimeout
//{
// get
diff --git a/src/Umbraco.Core/Security/UserData.cs b/src/Umbraco.Core/Security/UserData.cs
index 61d337d813..163bc91108 100644
--- a/src/Umbraco.Core/Security/UserData.cs
+++ b/src/Umbraco.Core/Security/UserData.cs
@@ -15,7 +15,7 @@ namespace Umbraco.Core.Security
}
[DataMember(Name = "id")]
- public int Id { get; set; }
+ public object Id { get; set; }
[DataMember(Name = "roles")]
public string[] Roles { get; set; }
@@ -36,5 +36,8 @@ namespace Umbraco.Core.Security
[DataMember(Name = "allowedApps")]
public string[] AllowedApplications { get; set; }
+
+ [DataMember(Name = "culture")]
+ public string Culture { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Tests/PublishedCache/PublishedContentCacheTests.cs b/src/Umbraco.Tests/PublishedCache/PublishedContentCacheTests.cs
index d1abe13d54..b0b03c5a78 100644
--- a/src/Umbraco.Tests/PublishedCache/PublishedContentCacheTests.cs
+++ b/src/Umbraco.Tests/PublishedCache/PublishedContentCacheTests.cs
@@ -10,6 +10,7 @@ using Umbraco.Web;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.PublishedCache.XmlPublishedCache;
using Umbraco.Web.Routing;
+using Umbraco.Web.Security;
using umbraco.BusinessLogic;
namespace Umbraco.Tests.PublishedCache
@@ -92,7 +93,8 @@ namespace Umbraco.Tests.PublishedCache
_umbracoContext = new UmbracoContext(
_httpContextFactory.HttpContext,
ApplicationContext.Current,
- new PublishedCaches(cache, new PublishedMediaCache()));
+ new PublishedCaches(cache, new PublishedMediaCache()),
+ new WebSecurity(_httpContextFactory.HttpContext, ApplicationContext.Current));
_cache = _umbracoContext.ContentCache;
}
diff --git a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs
index 6e55342833..7db1a236f6 100644
--- a/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs
+++ b/src/Umbraco.Tests/TestHelpers/BaseDatabaseFactoryTest.cs
@@ -24,6 +24,7 @@ using Umbraco.Web;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.PublishedCache.XmlPublishedCache;
using Umbraco.Web.Routing;
+using Umbraco.Web.Security;
using umbraco.BusinessLogic;
namespace Umbraco.Tests.TestHelpers
@@ -284,10 +285,12 @@ namespace Umbraco.Tests.TestHelpers
PublishedContentCache.UnitTesting = true;
+ var httpContext = GetHttpContextFactory(url, routeData).HttpContext;
var ctx = new UmbracoContext(
- GetHttpContextFactory(url, routeData).HttpContext,
+ httpContext,
ApplicationContext,
- new PublishedCaches(cache, new PublishedMediaCache()));
+ new PublishedCaches(cache, new PublishedMediaCache()),
+ new WebSecurity(httpContext, ApplicationContext));
if (setSingleton)
{
diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/WebSecurity.cs
index ab7286dec1..3cc853dfe0 100644
--- a/src/Umbraco.Web/Security/WebSecurity.cs
+++ b/src/Umbraco.Web/Security/WebSecurity.cs
@@ -6,13 +6,16 @@ using System.Web.Security;
using Newtonsoft.Json.Linq;
using Umbraco.Core;
using Umbraco.Core.Cache;
-using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
+using Umbraco.Core.Models.Membership;
using Umbraco.Core.Security;
-using umbraco.BusinessLogic;
+using umbraco;
using umbraco.DataLayer;
using umbraco.businesslogic.Exceptions;
-using umbraco.cms.businesslogic.member;
+using GlobalSettings = Umbraco.Core.Configuration.GlobalSettings;
+using Member = umbraco.cms.businesslogic.member.Member;
+using UmbracoSettings = Umbraco.Core.Configuration.UmbracoSettings;
+using User = umbraco.BusinessLogic.User;
namespace Umbraco.Web.Security
{
@@ -22,10 +25,12 @@ namespace Umbraco.Web.Security
public class WebSecurity : DisposableObject
{
private HttpContextBase _httpContext;
+ private ApplicationContext _applicationContext;
- public WebSecurity(HttpContextBase httpContext)
+ public WebSecurity(HttpContextBase httpContext, ApplicationContext applicationContext)
{
_httpContext = httpContext;
+ _applicationContext = applicationContext;
//This ensures the dispose method is called when the request terminates, though
// we also ensure this happens in the Umbraco module because the UmbracoContext is added to the
// http context items.
@@ -133,24 +138,25 @@ namespace Umbraco.Web.Security
/// The user Id
public void PerformLogin(int userId)
{
- var user = User.GetUser(userId);
+ var user = _applicationContext.Services.UserService.GetUserById(userId);
PerformLogin(user);
}
- internal void PerformLogin(User user)
+ internal void PerformLogin(IUser user)
{
_httpContext.CreateUmbracoAuthTicket(new UserData
{
Id = user.Id,
- AllowedApplications = user.GetApplications().Select(x => x.alias).ToArray(),
+ AllowedApplications = user.AllowedSections.ToArray(),
RealName = user.Name,
//currently we only have one user type!
Roles = new[] { user.UserType.Alias },
- StartContentNode = user.StartNodeId,
+ StartContentNode = user.StartContentId,
StartMediaNode = user.StartMediaId,
- Username = user.LoginName
+ Username = user.Username,
+ Culture = ui.Culture(user.Language)
});
-
+
LogHelper.Info("User Id: {0} logged in", () => user.Id);
}
@@ -244,7 +250,7 @@ namespace Umbraco.Web.Security
var identity = _httpContext.GetCurrentIdentity();
if (identity == null)
return -1;
- return identity.Id;
+ return (int)identity.Id;
}
///
@@ -364,6 +370,7 @@ namespace Umbraco.Web.Security
protected override void DisposeResources()
{
_httpContext = null;
+ _applicationContext = null;
}
}
}
diff --git a/src/Umbraco.Web/Standalone/StandaloneBootManager.cs b/src/Umbraco.Web/Standalone/StandaloneBootManager.cs
index cf2e8f7c11..a6ca751142 100644
--- a/src/Umbraco.Web/Standalone/StandaloneBootManager.cs
+++ b/src/Umbraco.Web/Standalone/StandaloneBootManager.cs
@@ -6,6 +6,7 @@ using Umbraco.Core;
using Umbraco.Core.ObjectResolution;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
+using Umbraco.Web.Security;
using umbraco.interfaces;
namespace Umbraco.Web.Standalone
@@ -79,7 +80,10 @@ namespace Umbraco.Web.Standalone
base.FreezeResolution();
var httpContext = new StandaloneHttpContext();
- UmbracoContext.EnsureContext(httpContext, ApplicationContext.Current);
+ UmbracoContext.EnsureContext(
+ httpContext,
+ ApplicationContext.Current,
+ new WebSecurity(httpContext, ApplicationContext.Current));
}
}
}
diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs
index e3756ae26e..6135082c81 100644
--- a/src/Umbraco.Web/UmbracoContext.cs
+++ b/src/Umbraco.Web/UmbracoContext.cs
@@ -46,6 +46,7 @@ namespace Umbraco.Web
///
///
///
+ ///
///
/// The Singleton context object
///
@@ -55,9 +56,34 @@ namespace Umbraco.Web
/// during the startup process as well.
/// See: http://issues.umbraco.org/issue/U4-1890, http://issues.umbraco.org/issue/U4-1717
///
- public static UmbracoContext EnsureContext(HttpContextBase httpContext, ApplicationContext applicationContext)
+ public static UmbracoContext EnsureContext(
+ HttpContextBase httpContext,
+ ApplicationContext applicationContext,
+ WebSecurity webSecurity)
{
- return EnsureContext(httpContext, applicationContext, false);
+ return EnsureContext(httpContext, applicationContext, webSecurity, false);
+ }
+
+ ///
+ /// This is a helper method which is called to ensure that the singleton context is created and the nice url and routing
+ /// context is created and assigned.
+ ///
+ ///
+ ///
+ ///
+ /// The Singleton context object
+ ///
+ ///
+ /// This is created in order to standardize the creation of the singleton. Normally it is created during a request
+ /// in the UmbracoModule, however this module does not execute during application startup so we need to ensure it
+ /// during the startup process as well.
+ /// See: http://issues.umbraco.org/issue/U4-1890, http://issues.umbraco.org/issue/U4-1717
+ ///
+ public static UmbracoContext EnsureContext(
+ HttpContextBase httpContext,
+ ApplicationContext applicationContext)
+ {
+ return EnsureContext(httpContext, applicationContext, new WebSecurity(httpContext, applicationContext), false);
}
///
@@ -80,7 +106,40 @@ namespace Umbraco.Web
/// during the startup process as well.
/// See: http://issues.umbraco.org/issue/U4-1890, http://issues.umbraco.org/issue/U4-1717
///
- public static UmbracoContext EnsureContext(HttpContextBase httpContext, ApplicationContext applicationContext, bool replaceContext)
+ public static UmbracoContext EnsureContext(
+ HttpContextBase httpContext,
+ ApplicationContext applicationContext,
+ bool replaceContext)
+ {
+ return EnsureContext(httpContext, applicationContext, new WebSecurity(httpContext, applicationContext), replaceContext);
+ }
+
+ ///
+ /// This is a helper method which is called to ensure that the singleton context is created and the nice url and routing
+ /// context is created and assigned.
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// if set to true will replace the current singleton with a new one, this is generally only ever used because
+ /// during application startup the base url domain will not be available so after app startup we'll replace the current
+ /// context with a new one in which we can access the httpcontext.Request object.
+ ///
+ ///
+ /// The Singleton context object
+ ///
+ ///
+ /// This is created in order to standardize the creation of the singleton. Normally it is created during a request
+ /// in the UmbracoModule, however this module does not execute during application startup so we need to ensure it
+ /// during the startup process as well.
+ /// See: http://issues.umbraco.org/issue/U4-1890, http://issues.umbraco.org/issue/U4-1717
+ ///
+ public static UmbracoContext EnsureContext(
+ HttpContextBase httpContext,
+ ApplicationContext applicationContext,
+ WebSecurity webSecurity,
+ bool replaceContext)
{
if (UmbracoContext.Current != null)
{
@@ -92,7 +151,8 @@ namespace Umbraco.Web
var umbracoContext = new UmbracoContext(
httpContext,
applicationContext,
- PublishedCachesResolver.Current.Caches);
+ PublishedCachesResolver.Current.Caches,
+ webSecurity);
// create the nice urls provider
// there's one per request because there are some behavior parameters that can be changed
@@ -121,11 +181,13 @@ namespace Umbraco.Web
///
///
/// The published caches.
+ ///
/// An optional value overriding detection of preview mode.
internal UmbracoContext(
HttpContextBase httpContext,
ApplicationContext applicationContext,
IPublishedCaches publishedCaches,
+ WebSecurity webSecurity,
bool? preview = null)
{
//This ensures the dispose method is called when the request terminates, though
@@ -141,7 +203,7 @@ namespace Umbraco.Web
HttpContext = httpContext;
Application = applicationContext;
- Security = new WebSecurity(HttpContext);
+ Security = webSecurity;
ContentCache = publishedCaches.CreateContextualContentCache(this);
MediaCache = publishedCaches.CreateContextualMediaCache(this);
@@ -374,10 +436,11 @@ namespace Umbraco.Web
protected override void DisposeResources()
{
- Security.Dispose();
+ Security.DisposeIfDisposable();
Security = null;
_previewContent = null;
_umbracoContext = null;
+ //ensure not to dispose this!
Application = null;
ContentCache = null;
MediaCache = null;
diff --git a/src/Umbraco.Web/UmbracoModule.cs b/src/Umbraco.Web/UmbracoModule.cs
index f7df4bab03..a8fdb04479 100644
--- a/src/Umbraco.Web/UmbracoModule.cs
+++ b/src/Umbraco.Web/UmbracoModule.cs
@@ -61,7 +61,11 @@ namespace Umbraco.Web
// create the UmbracoContext singleton, one per request, and assign
// NOTE: we assign 'true' to ensure the context is replaced if it is already set (i.e. during app startup)
- UmbracoContext.EnsureContext(httpContext, ApplicationContext.Current, true);
+ UmbracoContext.EnsureContext(
+ httpContext,
+ ApplicationContext.Current,
+ new WebSecurity(httpContext, ApplicationContext.Current),
+ true);
}
///
@@ -173,6 +177,11 @@ namespace Umbraco.Web
}
app.Context.User = principal;
Thread.CurrentPrincipal = principal;
+
+ //This is a back office request, we will also set the culture/ui culture
+ Thread.CurrentThread.CurrentCulture =
+ Thread.CurrentThread.CurrentUICulture =
+ new System.Globalization.CultureInfo(identity.Culture);
}
}
diff --git a/src/Umbraco.Web/WebApi/Binders/ContentItemBaseBinder.cs b/src/Umbraco.Web/WebApi/Binders/ContentItemBaseBinder.cs
index 9c0c589b79..f0b805ae22 100644
--- a/src/Umbraco.Web/WebApi/Binders/ContentItemBaseBinder.cs
+++ b/src/Umbraco.Web/WebApi/Binders/ContentItemBaseBinder.cs
@@ -18,6 +18,7 @@ using Newtonsoft.Json.Serialization;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Web.Models.ContentEditing;
+using Umbraco.Web.Security;
using Umbraco.Web.WebApi.Filters;
using IModelBinder = System.Web.Http.ModelBinding.IModelBinder;
using ModelBindingContext = System.Web.Http.ModelBinding.ModelBindingContext;
@@ -90,7 +91,11 @@ namespace Umbraco.Web.WebApi.Binders
var request = actionContext.Request;
//IMPORTANT!!! We need to ensure the umbraco context here because this is running in an async thread
- UmbracoContext.EnsureContext(request.Properties["MS_HttpContext"] as HttpContextBase, ApplicationContext.Current);
+ var httpContext = (HttpContextBase) request.Properties["MS_HttpContext"];
+ UmbracoContext.EnsureContext(
+ httpContext,
+ ApplicationContext.Current,
+ new WebSecurity(httpContext, ApplicationContext.Current));
var content = request.Content;
diff --git a/src/Umbraco.Web/WebApi/UmbracoApiController.cs b/src/Umbraco.Web/WebApi/UmbracoApiController.cs
index 5fbb2942c5..152fd89cfc 100644
--- a/src/Umbraco.Web/WebApi/UmbracoApiController.cs
+++ b/src/Umbraco.Web/WebApi/UmbracoApiController.cs
@@ -44,6 +44,11 @@ namespace Umbraco.Web.WebApi
return new Attempt(true, httpContext);
}
}
+ if (HttpContext.Current != null)
+ {
+ return new Attempt(true, new HttpContextWrapper(HttpContext.Current));
+ }
+
return Attempt.False;
}
diff --git a/src/Umbraco.Web/WebBootManager.cs b/src/Umbraco.Web/WebBootManager.cs
index 13074a7065..280f0969e2 100644
--- a/src/Umbraco.Web/WebBootManager.cs
+++ b/src/Umbraco.Web/WebBootManager.cs
@@ -25,6 +25,7 @@ using Umbraco.Web.Mvc;
using Umbraco.Web.PropertyEditors;
using Umbraco.Web.PublishedCache;
using Umbraco.Web.Routing;
+using Umbraco.Web.Security;
using Umbraco.Web.WebApi;
using umbraco.BusinessLogic;
using umbraco.businesslogic;
@@ -98,7 +99,11 @@ namespace Umbraco.Web
//before we do anything, we'll ensure the umbraco context
//see: http://issues.umbraco.org/issue/U4-1717
- UmbracoContext.EnsureContext(new HttpContextWrapper(UmbracoApplication.Context), ApplicationContext);
+ var httpContext = new HttpContextWrapper(UmbracoApplication.Context);
+ UmbracoContext.EnsureContext(
+ httpContext,
+ ApplicationContext,
+ new WebSecurity(httpContext, ApplicationContext));
}
///
diff --git a/src/umbraco.businesslogic/BasePages/BasePage.cs b/src/umbraco.businesslogic/BasePages/BasePage.cs
index b226176ae6..0512319bdb 100644
--- a/src/umbraco.businesslogic/BasePages/BasePage.cs
+++ b/src/umbraco.businesslogic/BasePages/BasePage.cs
@@ -184,7 +184,7 @@ namespace umbraco.BasePages
var identity = HttpContext.Current.GetCurrentIdentity();
if (identity == null)
return -1;
- return identity.Id;
+ return (int)identity.Id;
}
// Added by NH to use with webservices authentications
diff --git a/src/umbraco.businesslogic/ui.cs b/src/umbraco.businesslogic/ui.cs
index 6eb950495e..fd5fe6ae99 100644
--- a/src/umbraco.businesslogic/ui.cs
+++ b/src/umbraco.businesslogic/ui.cs
@@ -28,7 +28,12 @@ namespace umbraco
///
public static string Culture(User u)
{
- var langFile = getLanguageFile(u.Language);
+ return Culture(u.Language);
+ }
+
+ internal static string Culture(string userLanguage)
+ {
+ var langFile = getLanguageFile(userLanguage);
try
{
return langFile.SelectSingleNode("/language").Attributes.GetNamedItem("culture").Value;