Got the user timeout counter all working nicely with minimal server queries, now to show the login dialog when timeout is close or finished.

This commit is contained in:
Shannon
2013-10-16 11:31:35 +11:00
parent 7c881a29ae
commit 7a3e9facd0
5 changed files with 84 additions and 20 deletions

View File

@@ -177,8 +177,21 @@ namespace Umbraco.Core
public static MethodInfo GetMethodInfo<T1, T2>(Expression<Func<T1, T2>> fromExpression)
{
if (fromExpression == null) return null;
var body = fromExpression.Body as MethodCallExpression;
return body != null ? body.Method : null;
MethodCallExpression me;
switch (fromExpression.Body.NodeType)
{
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
var ue = fromExpression.Body as UnaryExpression;
me = ((ue != null) ? ue.Operand : null) as MethodCallExpression;
break;
default:
me = fromExpression.Body as MethodCallExpression;
break;
}
return me != null ? me.Method : null;
}
/// <summary>

View File

@@ -11,12 +11,9 @@ angular.module('umbraco.security.interceptor', ['umbraco.security.retryQueue'])
//expires. Then we'll update the user in the user service accordingly.
var headers = originalResponse.headers();
if (headers["x-umb-user-seconds"]) {
var asNumber = parseFloat(headers["x-umb-user-seconds"]);
if (!isNaN(asNumber)) {
// We must use $injector to get the $http service to prevent circular dependency
var userService = $injector.get('userService');
userService.setUserTimeout(asNumber);
}
// We must use $injector to get the $http service to prevent circular dependency
var userService = $injector.get('userService');
userService.setUserTimeout(headers["x-umb-user-seconds"]);
}
return promise;

View File

@@ -4,6 +4,9 @@ angular.module('umbraco.services')
var currentUser = null;
var lastUserId = null;
var loginDialog = null;
//this tracks the last date/time that the user's remainingAuthSeconds was updated from the server
// this is used so that we know when to go and get the user's remaining seconds directly.
var lastServerTimeoutSet = null;
// Redirect to the given url (defaults to '/')
function redirect(url) {
@@ -44,19 +47,55 @@ angular.module('umbraco.services')
throw "The user object is invalid, the remainingAuthSeconds is required.";
}
currentUser = usr;
lastServerTimeoutSet = new Date();
//start the timer
setCurrentUserTimeout(usr);
countdownUserTimeout();
}
function setCurrentUserTimeout() {
/**
Method to count down the current user's timeout seconds,
this will continually count down their current remaining seconds every 2 seconds until
there are no more seconds remaining.
*/
function countdownUserTimeout() {
$timeout(function () {
if (currentUser) {
currentUser.remainingAuthSeconds -= 1;
if (currentUser.remainingAuthSeconds > 0) {
//recurse!
setCurrentUserTimeout();
//if there are remaining seconds, recurse!
if (currentUser.remainingAuthSeconds > 0) {
//we need to check when the last time the timeout was set from the server, if
// it has been more than 30 seconds then we'll manually go and retreive it from the
// server - this helps to keep our local countdown in check with the true timeout.
if (lastServerTimeoutSet != null) {
var now = new Date();
var seconds = (now.getTime() - lastServerTimeoutSet.getTime()) / 1000;
if (seconds > 30) {
//first we'll set the lastServerTimeoutSet to null - this is so we don't get back in to this loop while we
// wait for a response from the server otherwise we'll be making double/triple/etc... calls while we wait.
lastServerTimeoutSet = null;
//now go get it from the server
authResource.getRemainingTimeoutSeconds().then(function (result) {
setUserTimeoutInternal(result);
});
}
}
//recurse the countdown!
countdownUserTimeout();
}
}
}, 1000);//every second
}, 2000);//every 2 seconds
}
/** Called to update the current user's timeout */
function setUserTimeoutInternal(newTimeout) {
var asNumber = parseFloat(newTimeout);
if (!isNaN(asNumber) && currentUser && angular.isNumber(asNumber)) {
currentUser.remainingAuthSeconds = newTimeout;
lastServerTimeoutSet = new Date();
}
}
// Register a handler for when an item is added to the retry queue
@@ -157,10 +196,9 @@ angular.module('umbraco.services')
return deferred.promise;
},
/** Called whenever a server request is made that contains a x-umb-user-seconds response header for which we can update the user's remaining timeout seconds */
setUserTimeout: function(newTimeout) {
if (currentUser && angular.isNumber(newTimeout)) {
currentUser.remainingAuthSeconds = newTimeout;
}
setUserTimeoutInternal(newTimeout);
}
};

View File

@@ -175,9 +175,9 @@ namespace Umbraco.Web
if (ShouldAuthenticateRequest(req, UmbracoContext.Current.OriginalRequestUrl))
{
var ticket = http.GetUmbracoAuthTicket();
//if there was a ticket, it's not expired, its renewable - or it should not be renewed
//if there was a ticket, it's not expired, - it should not be renewed or its renewable
if (ticket != null && ticket.Expired == false
&& (http.RenewUmbracoAuthTicket() || ShouldIgnoreTicketRenew(UmbracoContext.Current.OriginalRequestUrl, http)))
&& (ShouldIgnoreTicketRenew(UmbracoContext.Current.OriginalRequestUrl, http) || http.RenewUmbracoAuthTicket()))
{
try
{
@@ -270,7 +270,7 @@ namespace Umbraco.Web
if (IgnoreTicketRenewUrls.Any() == false)
{
var urlHelper = new UrlHelper(new RequestContext(httpContext, new RouteData()));
var checkSessionUrl = urlHelper.GetUmbracoApiServiceBaseUrl<AuthenticationController>(controller => controller.GetRemainingTimeoutSeconds());
var checkSessionUrl = urlHelper.GetUmbracoApiService<AuthenticationController>(controller => controller.GetRemainingTimeoutSeconds());
IgnoreTicketRenewUrls.Add(checkSessionUrl);
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Management.Instrumentation;
using System.Web.Mvc;
using Umbraco.Core;
using Umbraco.Web.Mvc;
@@ -55,9 +56,24 @@ namespace Umbraco.Web
where T : UmbracoApiController
{
var method = Umbraco.Core.ExpressionHelper.GetMethodInfo(methodSelector);
if (method == null)
{
throw new MissingMethodException("Could not find the method " + methodSelector + " on type " + typeof(T) + " or the result ");
}
return url.GetUmbracoApiService<T>(method.Name).TrimEnd(method.Name);
}
public static string GetUmbracoApiService<T>(this UrlHelper url, Expression<Func<T, object>> methodSelector)
where T : UmbracoApiController
{
var method = Umbraco.Core.ExpressionHelper.GetMethodInfo(methodSelector);
if (method == null)
{
throw new MissingMethodException("Could not find the method " + methodSelector + " on type " + typeof(T) + " or the result ");
}
return url.GetUmbracoApiService<T>(method.Name);
}
/// <summary>
/// Return the Url for a Web Api service
/// </summary>