From 296c24f829b3b15e823f5290c0babf71df84f4f4 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Thu, 4 Apr 2013 02:11:31 +0600 Subject: [PATCH] Fixes: #U4-2042 - ensures users cannot continue to user the back office after they've been disabled and ensures that the user context cache is cleared when users are saved which will work in LB environments. Changes more HttpRuntime.Cache dependencies to ApplicationContext.Current.ApplicationCache. --- src/Umbraco.Core/Cache/CacheKeys.cs | 2 + src/Umbraco.Web/Cache/UserCacheRefresher.cs | 7 ++- src/Umbraco.Web/Security/WebSecurity.cs | 60 ++++++------------- src/Umbraco.Web/Umbraco.Web.csproj | 4 +- .../developer/Cache/viewCacheItem.aspx.cs | 27 +-------- .../developer/DataTypes/editDatatype.aspx.cs | 4 +- .../BasePages/BasePage.cs | 55 ++++++----------- src/umbraco.businesslogic/User.cs | 3 + 8 files changed, 54 insertions(+), 108 deletions(-) diff --git a/src/Umbraco.Core/Cache/CacheKeys.cs b/src/Umbraco.Core/Cache/CacheKeys.cs index b022fbbe2e..18019b005d 100644 --- a/src/Umbraco.Core/Cache/CacheKeys.cs +++ b/src/Umbraco.Core/Cache/CacheKeys.cs @@ -23,6 +23,8 @@ namespace Umbraco.Core.Cache public const string TemplateFrontEndCacheKey = "template"; public const string TemplateBusinessLogicCacheKey = "UmbracoTemplateCache"; + public const string UserContextCacheKey = "UmbracoUserContext"; + public const string UserContextTimeoutCacheKey = "UmbracoUserContextTimeout"; public const string UserCacheKey = "UmbracoUser"; public const string ContentTypeCacheKey = "UmbracoContentType"; diff --git a/src/Umbraco.Web/Cache/UserCacheRefresher.cs b/src/Umbraco.Web/Cache/UserCacheRefresher.cs index 0525d34fa4..0e4e32bc48 100644 --- a/src/Umbraco.Web/Cache/UserCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/UserCacheRefresher.cs @@ -28,6 +28,7 @@ namespace Umbraco.Web.Cache public override void RefreshAll() { ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch(CacheKeys.UserCacheKey); + ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch(CacheKeys.UserContextCacheKey); } public override void Refresh(int id) @@ -37,7 +38,11 @@ namespace Umbraco.Web.Cache public override void Remove(int id) { - ApplicationContext.Current.ApplicationCache.ClearCacheItem(string.Format("{0}{1}", CacheKeys.UserCacheKey, id)); + ApplicationContext.Current.ApplicationCache.ClearCacheItem(string.Format("{0}{1}", CacheKeys.UserCacheKey, id)); + + //we need to clear all UserContextCacheKey since we cannot invalidate based on ID since the cache is done so based + //on the current contextId stored in the database + ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch(CacheKeys.UserContextCacheKey); } } diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/WebSecurity.cs index dac7d3a461..3d5905f2f4 100644 --- a/src/Umbraco.Web/Security/WebSecurity.cs +++ b/src/Umbraco.Web/Security/WebSecurity.cs @@ -5,8 +5,8 @@ using System.Text; using System.Web; using System.Web.Security; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Logging; -using Umbraco.Web.UI.Pages; using umbraco; using umbraco.BusinessLogic; using umbraco.DataLayer; @@ -164,26 +164,10 @@ namespace Umbraco.Web.Security internal static long GetTimeout(string umbracoUserContextId) { - //TODO: Clean this up! We should be using the CacheHelper (ApplicationContext.Current.ApplicationCache) - // for all things cache related - - if (HttpRuntime.Cache["UmbracoUserContextTimeout" + umbracoUserContextId] == null) - { - HttpRuntime.Cache.Insert( - "UmbracoUserContextTimeout" + umbracoUserContextId, - GetTimeout(true), - null, - DateTime.Now.AddMinutes(UmbracoTimeOutInMinutes / 10), System.Web.Caching.Cache.NoSlidingExpiration); - - - } - - var timeout = HttpRuntime.Cache["UmbracoUserContextTimeout" + umbracoUserContextId]; - if (timeout != null) - return (long)timeout; - - return 0; - + return ApplicationContext.Current.ApplicationCache.GetCacheItem( + CacheKeys.UserContextTimeoutCacheKey + umbracoUserContextId, + new TimeSpan(0, UmbracoTimeOutInMinutes / 10, 0), + () => GetTimeout(true)); } internal static long GetTimeout(bool byPassCache) @@ -208,28 +192,22 @@ namespace Umbraco.Web.Security /// public static int GetUserId(string umbracoUserContextId) { - try - { - //TODO: Clean this up! We should be using the CacheHelper (ApplicationContext.Current.ApplicationCache) - // for all things cache related - - if (HttpRuntime.Cache["UmbracoUserContext" + umbracoUserContextId] == null) - { - HttpRuntime.Cache.Insert( - "UmbracoUserContext" + umbracoUserContextId, - SqlHelper.ExecuteScalar("select userID from umbracoUserLogins where contextID = @contextId", - SqlHelper.CreateParameter("@contextId", new Guid(umbracoUserContextId)) - ), - null, - System.Web.Caching.Cache.NoAbsoluteExpiration, - new TimeSpan(0, (int)(UmbracoTimeOutInMinutes / 10), 0)); - } - return (int)HttpRuntime.Cache["UmbracoUserContext" + umbracoUserContextId]; - } - catch + //need to parse to guid + Guid gid; + if (!Guid.TryParse(umbracoUserContextId, out gid)) { return -1; } + + var id = ApplicationContext.Current.ApplicationCache.GetCacheItem( + CacheKeys.UserContextCacheKey + umbracoUserContextId, + new TimeSpan(0, UmbracoTimeOutInMinutes/10, 0), + () => SqlHelper.ExecuteScalar( + "select userID from umbracoUserLogins where contextID = @contextId", + SqlHelper.CreateParameter("@contextId", gid))); + if (id == null) + return -1; + return id.Value; } /// @@ -248,7 +226,7 @@ namespace Umbraco.Web.Security { return true; } - var user = global::umbraco.BusinessLogic.User.GetUser(uid); + var user = User.GetUser(uid); LogHelper.Info(typeof(WebSecurity), "User {0} (Id:{1}) logged out", () => user.Name, () => user.Id); } return false; diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 220ea707f1..ad5099541e 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -340,6 +340,7 @@ + AssignDomain2.aspx @@ -424,7 +425,6 @@ - @@ -466,7 +466,7 @@ ASPXCodeBehind - + ASPXCodeBehind diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Cache/viewCacheItem.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Cache/viewCacheItem.aspx.cs index 4d06f91d79..a78a8d24da 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Cache/viewCacheItem.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/Cache/viewCacheItem.aspx.cs @@ -12,37 +12,16 @@ namespace umbraco.cms.presentation.developer public viewCacheItem() { CurrentApp = BusinessLogic.DefaultApps.developer.ToString(); - } + protected void Page_Load(object sender, EventArgs e) { - // Put user code to initialize the page here Panel1.Text = ui.Text("viewCacheItem"); - string cacheKey = Request.QueryString["key"]; + var cacheKey = Request.QueryString["key"]; LabelCacheAlias.Text = cacheKey; - object cacheItem = HttpRuntime.Cache[cacheKey]; + var cacheItem = ApplicationContext.ApplicationCache.GetCacheItem(cacheKey); LabelCacheValue.Text = cacheItem != null ? cacheItem.ToString() : "Cache item isn't in cache anymore!"; } - #region Web Form Designer generated code - - protected override void OnInit(EventArgs e) - { - // - // CODEGEN: This call is required by the ASP.NET Web Form Designer. - // - InitializeComponent(); - base.OnInit(e); - } - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - } - - #endregion } } \ No newline at end of file diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/DataTypes/editDatatype.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/DataTypes/editDatatype.aspx.cs index 7c1e8a5de1..7e22296ed9 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/developer/DataTypes/editDatatype.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/developer/DataTypes/editDatatype.aspx.cs @@ -102,9 +102,7 @@ namespace umbraco.cms.presentation.developer dt.DataType = f.DataType(new Guid(ddlRenderControl.SelectedValue)); dt.Save(); - System.Web.HttpRuntime.Cache.Remove(string.Format("UmbracoDataTypeDefinition{0}", dt.UniqueId)); - - ClientTools.ShowSpeechBubble(BasePages.BasePage.speechBubbleIcon.save, ui.Text("speechBubbles", "dataTypeSaved", null), ""); + ClientTools.ShowSpeechBubble(speechBubbleIcon.save, ui.Text("speechBubbles", "dataTypeSaved", null), ""); ClientTools.SyncTree(dt.Path, true); } diff --git a/src/umbraco.businesslogic/BasePages/BasePage.cs b/src/umbraco.businesslogic/BasePages/BasePage.cs index a527e52c33..ef86c3a702 100644 --- a/src/umbraco.businesslogic/BasePages/BasePage.cs +++ b/src/umbraco.businesslogic/BasePages/BasePage.cs @@ -6,6 +6,7 @@ using System.Web.Mvc; using System.Web.Routing; using System.Web.Security; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Services; using umbraco.BusinessLogic; @@ -167,29 +168,22 @@ namespace umbraco.BasePages [Obsolete("Use Umbraco.Web.Security.WebSecurity.GetUserId instead")] public static int GetUserId(string umbracoUserContextID) { - try - { - if (System.Web.HttpRuntime.Cache["UmbracoUserContext" + umbracoUserContextID] == null) - { - System.Web.HttpRuntime.Cache.Insert( - "UmbracoUserContext" + umbracoUserContextID, - SqlHelper.ExecuteScalar("select userID from umbracoUserLogins where contextID = @contextId", - SqlHelper.CreateParameter("@contextId", new Guid(umbracoUserContextID)) - ), - null, - System.Web.Caching.Cache.NoAbsoluteExpiration, - new TimeSpan(0, (int) (UmbracoTimeOutInMinutes/10), 0)); - - - } - - return (int)System.Web.HttpRuntime.Cache["UmbracoUserContext" + umbracoUserContextID]; - - } - catch + //need to parse to guid + Guid gid; + if (!Guid.TryParse(umbracoUserContextID, out gid)) { return -1; } + + var id = ApplicationContext.Current.ApplicationCache.GetCacheItem( + CacheKeys.UserContextCacheKey + umbracoUserContextID, + new TimeSpan(0, UmbracoTimeOutInMinutes / 10, 0), + () => SqlHelper.ExecuteScalar( + "select userID from umbracoUserLogins where contextID = @contextId", + SqlHelper.CreateParameter("@contextId", gid))); + if (id == null) + return -1; + return id.Value; } @@ -219,23 +213,10 @@ namespace umbraco.BasePages private static long GetTimeout(string umbracoUserContextID) { - if (System.Web.HttpRuntime.Cache["UmbracoUserContextTimeout" + umbracoUserContextID] == null) - { - System.Web.HttpRuntime.Cache.Insert( - "UmbracoUserContextTimeout" + umbracoUserContextID, - GetTimeout(true), - null, - DateTime.Now.AddMinutes(UmbracoTimeOutInMinutes / 10), System.Web.Caching.Cache.NoSlidingExpiration); - - - } - - object timeout = HttpRuntime.Cache["UmbracoUserContextTimeout" + umbracoUserContextID]; - if (timeout != null) - return (long)timeout; - - return 0; - + return ApplicationContext.Current.ApplicationCache.GetCacheItem( + CacheKeys.UserContextTimeoutCacheKey + umbracoUserContextID, + new TimeSpan(0, UmbracoTimeOutInMinutes / 10, 0), + () => GetTimeout(true)); } [Obsolete("Use Umbraco.Web.Security.WebSecurity.GetTimeout instead")] diff --git a/src/umbraco.businesslogic/User.cs b/src/umbraco.businesslogic/User.cs index 6987be7123..ae5c0202ab 100644 --- a/src/umbraco.businesslogic/User.cs +++ b/src/umbraco.businesslogic/User.cs @@ -647,6 +647,9 @@ namespace umbraco.BusinessLogic OnDisabling(EventArgs.Empty); //change disabled and userLogin (prefix with yyyyMMdd_ ) this.Disabled = true; + //MUST clear out the umbraco logins otherwise if they are still logged in they can still do stuff: + //http://issues.umbraco.org/issue/U4-2042 + SqlHelper.ExecuteNonQuery("delete from umbracoUserLogins where userID = @id", SqlHelper.CreateParameter("@id", Id)); //can't rename if it's going to take up too many chars if (this.LoginName.Length + 9 <= 125) {