From c2660af60dc3b14bc5bf56f68c68cc36b6506338 Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Thu, 15 Nov 2018 11:45:11 -0500 Subject: [PATCH] stop various async background requests from bumping the session expiry if a user has an active session that just sits on the dashboard or job list, websocket messages that come in (for e.g., job status changes) will trigger AJAX requests for more data; this process causes a user with an idle login to continue to generate API requests, which in turn ticks their expiry timer. As a result, users with active sessions sitting on these two (popular) pages will never be automatically logged out via SESSION_MAX_AGE. this change introduces a special header that the UI can use to signify that a request shouldn't bump the expiry timer --- awx/main/middleware.py | 3 ++- awx/ui/client/features/jobs/jobsList.controller.js | 2 +- awx/ui/client/features/templates/templatesList.controller.js | 2 +- awx/ui/client/lib/models/Base.js | 5 +++-- .../dashboard/graphs/job-status/job-status-graph.service.js | 1 + awx/ui/client/src/home/home.controller.js | 2 ++ 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/awx/main/middleware.py b/awx/main/middleware.py index 1005e9982f..f97b5bfc0f 100644 --- a/awx/main/middleware.py +++ b/awx/main/middleware.py @@ -126,8 +126,9 @@ class SessionTimeoutMiddleware(object): """ def process_response(self, request, response): + should_skip = 'HTTP_X_WS_SESSION_QUIET' in request.META req_session = getattr(request, 'session', None) - if req_session and not req_session.is_empty(): + if req_session and not req_session.is_empty() and should_skip is False: expiry = int(settings.SESSION_COOKIE_AGE) request.session.set_expiry(expiry) response['Session-Timeout'] = expiry diff --git a/awx/ui/client/features/jobs/jobsList.controller.js b/awx/ui/client/features/jobs/jobsList.controller.js index 1a1943c6c4..a398a03818 100644 --- a/awx/ui/client/features/jobs/jobsList.controller.js +++ b/awx/ui/client/features/jobs/jobsList.controller.js @@ -207,7 +207,7 @@ function ListJobsController ( }; function refreshJobs () { - qs.search(SearchBasePath, $state.params.job_search) + qs.search(SearchBasePath, $state.params.job_search, { 'X-WS-Session-Quiet': true }) .then(({ data }) => { vm.jobs = data.results; vm.job_dataset = data; diff --git a/awx/ui/client/features/templates/templatesList.controller.js b/awx/ui/client/features/templates/templatesList.controller.js index 7bf634b1db..d1a88dcda6 100644 --- a/awx/ui/client/features/templates/templatesList.controller.js +++ b/awx/ui/client/features/templates/templatesList.controller.js @@ -199,7 +199,7 @@ function ListTemplatesController( function refreshTemplates() { Wait('start'); let path = GetBasePath('unified_job_templates'); - qs.search(path, $state.params.template_search) + qs.search(path, $state.params.template_search, { 'X-WS-Session-Quiet': true }) .then(function(searchResponse) { vm.dataset = searchResponse.data; vm.templates = vm.dataset.results; diff --git a/awx/ui/client/lib/models/Base.js b/awx/ui/client/lib/models/Base.js index a7cc321806..1eaa60de87 100644 --- a/awx/ui/client/lib/models/Base.js +++ b/awx/ui/client/lib/models/Base.js @@ -62,10 +62,11 @@ function requestWithCache (config) { * @yields {boolean} - Indicating a match has been found. If so, the results * are set on the model. */ -function search (params = {}, config = {}) { +function search (params = {}, config = {}, headers = {}) { const req = { method: 'GET', - url: this.path + url: this.path, + headers }; if (typeof params === 'string') { diff --git a/awx/ui/client/src/home/dashboard/graphs/job-status/job-status-graph.service.js b/awx/ui/client/src/home/dashboard/graphs/job-status/job-status-graph.service.js index 0e6a3b4dda..c040e1f71b 100644 --- a/awx/ui/client/src/home/dashboard/graphs/job-status/job-status-graph.service.js +++ b/awx/ui/client/src/home/dashboard/graphs/job-status/job-status-graph.service.js @@ -36,6 +36,7 @@ function JobStatusGraphData(Rest, getBasePath, processErrors, $rootScope, $q) { return; } url = dash_path + 'graphs/jobs/?period='+period+'&job_type='+jobType; + Rest.setHeader({'X-WS-Session-Quiet': true}); Rest.setUrl(url); var result = Rest.get() .catch(function(response) { diff --git a/awx/ui/client/src/home/home.controller.js b/awx/ui/client/src/home/home.controller.js index 17b6d4e314..80fdb3b0a1 100644 --- a/awx/ui/client/src/home/home.controller.js +++ b/awx/ui/client/src/home/home.controller.js @@ -87,6 +87,7 @@ export default ['$scope', '$rootScope','Wait', ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get dashboard: ' + status }); }); Rest.setUrl(GetBasePath("unified_jobs") + "?order_by=-finished&page_size=5&finished__isnull=false&type=workflow_job,job"); + Rest.setHeader({'X-WS-Session-Quiet': true}); Rest.get() .then(({data}) => { data = data.results; @@ -119,6 +120,7 @@ export default ['$scope', '$rootScope','Wait', }); Rest.setUrl(GetBasePath("unified_jobs") + "?order_by=-finished&page_size=5&finished__isnull=false&type=workflow_job,job"); + Rest.setHeader({'X-WS-Session-Quiet': true}); Rest.get() .then(({data}) => { $scope.dashboardJobsListData = data.results;