From cdb757503e57e2a5d6ff56c80723a226df8278de Mon Sep 17 00:00:00 2001 From: Matthew Jones Date: Mon, 27 Feb 2017 21:17:51 -0500 Subject: [PATCH 01/16] Bump version for 3.1.1 release --- awx/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/__init__.py b/awx/__init__.py index f5457b5caa..48f9219933 100644 --- a/awx/__init__.py +++ b/awx/__init__.py @@ -5,7 +5,7 @@ import os import sys import warnings -__version__ = '3.1.0' +__version__ = '3.1.1' __all__ = ['__version__'] From 9cbf9a5c47bdcc43fdb5195f7774d3c81b285180 Mon Sep 17 00:00:00 2001 From: jaredevantabor Date: Mon, 27 Feb 2017 18:52:45 -0800 Subject: [PATCH 02/16] host event stdout changes --- .../job-results/host-event/host-event-modal.partial.html | 2 +- .../client/src/job-results/host-event/host-event.block.less | 5 ++++- .../src/job-results/host-event/host-event.controller.js | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/awx/ui/client/src/job-results/host-event/host-event-modal.partial.html b/awx/ui/client/src/job-results/host-event/host-event-modal.partial.html index cf9dc67ac4..96676dc56a 100644 --- a/awx/ui/client/src/job-results/host-event/host-event-modal.partial.html +++ b/awx/ui/client/src/job-results/host-event/host-event-modal.partial.html @@ -33,7 +33,7 @@
MODULE - {{module_name}} + {{module_name}}
diff --git a/awx/ui/client/src/job-results/host-event/host-event.block.less b/awx/ui/client/src/job-results/host-event/host-event.block.less index e5797643b3..84fb77c1f6 100644 --- a/awx/ui/client/src/job-results/host-event/host-event.block.less +++ b/awx/ui/client/src/job-results/host-event/host-event.block.less @@ -126,6 +126,9 @@ max-width: 13em; flex: 0 1 13em; } +.HostEvent-field--monospaceContent{ + font-family: monospace; +} .HostEvent-details--left, .HostEvent-details--right{ flex: 1 1 47%; } @@ -175,7 +178,7 @@ border-right: 1px solid #ccc; border-bottom-left-radius: 5px; color: #999; - font-family: monospace; + font-family: Monaco, Menlo, Consolas, "Courier New", monospace; position: fixed; padding: 4px 3px 0 5px; text-align: right; diff --git a/awx/ui/client/src/job-results/host-event/host-event.controller.js b/awx/ui/client/src/job-results/host-event/host-event.controller.js index 6015dd3a63..398ae70ab4 100644 --- a/awx/ui/client/src/job-results/host-event/host-event.controller.js +++ b/awx/ui/client/src/job-results/host-event/host-event.controller.js @@ -52,9 +52,9 @@ // grab standard out & standard error if present from the host // event's "res" object, for things like Ansible modules try{ - $scope.module_name = hostEvent.event_data.res.invocation.module_name || hostEvent.event_data.task_action || "No result found"; - $scope.stdout = hostEvent.event_data.res.stdout; - $scope.stderr = hostEvent.event_data.res.stderr; + $scope.module_name = hostEvent.event_data.task_action || "No result found"; + $scope.stdout = hostEvent.event_data.res.stdout ? hostEvent.event_data.res.stdout : hostEvent.event_data.res.stdout === "" ? " " : undefined; + $scope.stderr = hostEvent.event_data.res.stderr ? hostEvent.event_data.res.stderr : hostEvent.event_data.res.stderr === "" ? " " : undefined; $scope.json = hostEvent.event_data.res; } catch(err){ From 4271dc23d4d5341da0b82bd051f2bddd6a795b5b Mon Sep 17 00:00:00 2001 From: Chris Meyers Date: Tue, 28 Feb 2017 10:39:40 -0500 Subject: [PATCH 03/16] Merge pull request #5580 from chrismeyersfsu/fix-rabbit_mq_password_required rabbit_mq_password required From 45819f6b9a7f071ed52a2fa4ce59540789533c07 Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Tue, 28 Feb 2017 09:34:44 -0500 Subject: [PATCH 04/16] requeue websocket messages that don't (yet) have an established user There's a race between our `ws_connect` and `ws_receive` methods; it's possible to fall into a scenario where we're handling a legitimate message *before* django-channels is able to persist the `user_id` into the channel session. This results in a scenario where a user can open a browser tab and never receive new websocket messages. In this scenario, we should just toss the message back into the queue and try again later (up to a reasonable limit of retries). --- awx/main/consumers.py | 13 +++++++++++-- awx/settings/defaults.py | 5 +++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/awx/main/consumers.py b/awx/main/consumers.py index c42f16ef21..ff55507939 100644 --- a/awx/main/consumers.py +++ b/awx/main/consumers.py @@ -2,10 +2,11 @@ import json import logging import urllib -from channels import Group +from channels import Group, channel_layers from channels.sessions import channel_session from channels.handler import AsgiRequest +from django.conf import settings from django.core.serializers.json import DjangoJSONEncoder from django.contrib.auth.models import User @@ -49,11 +50,19 @@ def ws_disconnect(message): @channel_session def ws_receive(message): from awx.main.access import consumer_access + channel_layer_settings = channel_layers.configs[message.channel_layer.alias] + max_retries = channel_layer_settings.get('RECEIVE_MAX_RETRY', settings.CHANNEL_LAYER_RECEIVE_MAX_RETRY) user_id = message.channel_session.get('user_id', None) if user_id is None: - logger.error("No valid user found for websocket.") + retries = message.content.get('connect_retries', 0) + 1 + message.content['connect_retries'] = retries message.reply_channel.send({"text": json.dumps({"error": "no valid user"})}) + retries_left = max_retries - retries + if retries_left > 0: + message.channel_layer.send(message.channel.name, message.content) + else: + logger.error("No valid user found for websocket.") return None user = User.objects.get(pk=user_id) diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 090e939914..0901961fa5 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -866,6 +866,11 @@ TOWER_SETTINGS_MANIFEST = {} LOG_AGGREGATOR_ENABLED = False +# The number of retry attempts for websocket session establishment +# If you're encountering issues establishing websockets in clustered Tower, +# raising this value can help +CHANNEL_LAYER_RECEIVE_MAX_RETRY = 10 + # Logging configuration. LOGGING = { 'version': 1, From 7da52c8bef05beae963e90b9b45d226b30ed8410 Mon Sep 17 00:00:00 2001 From: Chris Meyers Date: Tue, 28 Feb 2017 12:39:55 -0500 Subject: [PATCH 05/16] emit job status over socket after database commit * Wait until the newly created job record hits the database before telling the websocket clients that the job's status is "pending" --- awx/main/models/unified_jobs.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index f17b2b4c55..7744f27821 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -964,10 +964,13 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique # Save the pending status, and inform the SocketIO listener. self.update_fields(start_args=json.dumps(kwargs), status='pending') - self.websocket_emit_status("pending") - from awx.main.scheduler.tasks import run_job_launch - connection.on_commit(lambda: run_job_launch.delay(self.id)) + def post_commit(): + from awx.main.scheduler.tasks import run_job_launch + self.websocket_emit_status("pending") + run_job_launch.delay(self.id) + + connection.on_commit(post_commit) # Each type of unified job has a different Task class; get the # appropirate one. From b85361732be4fd4db9ba6457fc1e9967eacfb6b2 Mon Sep 17 00:00:00 2001 From: Chris Meyers Date: Tue, 28 Feb 2017 12:53:59 -0500 Subject: [PATCH 06/16] Revert "emit job status over socket after database commit" This reverts commit edefeeacdaf11cf484a4b4893ee9acde5ef85390. --- awx/main/models/unified_jobs.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index 7744f27821..f17b2b4c55 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -964,13 +964,10 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique # Save the pending status, and inform the SocketIO listener. self.update_fields(start_args=json.dumps(kwargs), status='pending') + self.websocket_emit_status("pending") - def post_commit(): - from awx.main.scheduler.tasks import run_job_launch - self.websocket_emit_status("pending") - run_job_launch.delay(self.id) - - connection.on_commit(post_commit) + from awx.main.scheduler.tasks import run_job_launch + connection.on_commit(lambda: run_job_launch.delay(self.id)) # Each type of unified job has a different Task class; get the # appropirate one. From e09497108e1883dc07ecb03463b657e3bbf6934f Mon Sep 17 00:00:00 2001 From: Chris Meyers Date: Tue, 28 Feb 2017 12:56:55 -0500 Subject: [PATCH 07/16] all job status change websockets events should happen after the job hits the database --- awx/main/models/unified_jobs.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index f17b2b4c55..2ccae7fdaf 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -880,7 +880,7 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique workflow_node_id=self.workflow_node_id)) return websocket_data - def websocket_emit_status(self, status): + def _websocket_emit_status(self, status): status_data = dict(unified_job_id=self.id, status=status) status_data.update(self.websocket_emit_data()) status_data['group_name'] = 'jobs' @@ -890,6 +890,9 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique status_data['group_name'] = "workflow_events" emit_channel_notification('workflow_events-' + str(self.workflow_job_id), status_data) + def websocket_emit_status(self, status): + connection.on_commit(lambda: self._websocket_emit_status(status)) + def notification_data(self): return dict(id=self.id, name=self.name, From c4fb88c0d9c59030af0349886a91b88b8a290d31 Mon Sep 17 00:00:00 2001 From: Chris Meyers Date: Tue, 28 Feb 2017 13:04:21 -0500 Subject: [PATCH 08/16] remove uneeded post commit wrapper * Since we changed the lower level method to always use post commit message emit --- awx/main/scheduler/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/main/scheduler/__init__.py b/awx/main/scheduler/__init__.py index a48ca3ad23..dc0a4c82e0 100644 --- a/awx/main/scheduler/__init__.py +++ b/awx/main/scheduler/__init__.py @@ -382,7 +382,7 @@ class TaskManager(): )) task_obj.save() _send_notification_templates(task_obj, 'failed') - connection.on_commit(lambda: task_obj.websocket_emit_status('failed')) + task_obj.websocket_emit_status('failed') logger.error("Task %s appears orphaned... marking as failed" % task) From 9eed328107e089651e88bfe9829488d78346563b Mon Sep 17 00:00:00 2001 From: Wayne Witzel III Date: Tue, 28 Feb 2017 14:03:52 -0500 Subject: [PATCH 09/16] update asgi_amqp version --- docs/licenses/asgi-amqp.txt | 9 +++++++++ requirements/requirements.in | 2 +- requirements/requirements.txt | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 docs/licenses/asgi-amqp.txt diff --git a/docs/licenses/asgi-amqp.txt b/docs/licenses/asgi-amqp.txt new file mode 100644 index 0000000000..731a737315 --- /dev/null +++ b/docs/licenses/asgi-amqp.txt @@ -0,0 +1,9 @@ +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/requirements/requirements.in b/requirements/requirements.in index b0b5164b25..5d3b4c0e45 100644 --- a/requirements/requirements.in +++ b/requirements/requirements.in @@ -5,7 +5,7 @@ -e git+https://github.com/chrismeyersfsu/pyrax@tower#egg=pyrax apache-libcloud==1.3.0 appdirs==1.4.2 -asgi-amqp==0.4.0 +asgi-amqp==0.4.1 azure==2.0.0rc6 backports.ssl-match-hostname==3.5.0.1 boto==2.45.0 diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 2489dc5b36..0012ad8330 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -14,7 +14,7 @@ amqp==1.4.9 # via kombu anyjson==0.3.3 # via kombu apache-libcloud==1.3.0 appdirs==1.4.2 -asgi-amqp==0.4.0 +asgi-amqp==0.4.1 asgiref==1.0.0 # via asgi-amqp, channels, daphne attrs==16.3.0 # via service-identity autobahn==0.17.0 # via daphne From 09771927c96127bfd77b54ec43b02cf0936d7aa1 Mon Sep 17 00:00:00 2001 From: Michael Abashian Date: Wed, 1 Mar 2017 10:27:28 -0500 Subject: [PATCH 10/16] Encode default search param --- .../client/src/shared/smart-search/smart-search.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/ui/client/src/shared/smart-search/smart-search.controller.js b/awx/ui/client/src/shared/smart-search/smart-search.controller.js index d3b1d216f1..b7d3a45f6b 100644 --- a/awx/ui/client/src/shared/smart-search/smart-search.controller.js +++ b/awx/ui/client/src/shared/smart-search/smart-search.controller.js @@ -110,7 +110,7 @@ export default ['$stateParams', '$scope', '$state', 'QuerySet', 'GetBasePath', ' function setDefaults(term) { if ($scope.list.defaultSearchParams) { - return $scope.list.defaultSearchParams(term); + return $scope.list.defaultSearchParams(encodeURIComponent(term)); } else { return { search: encodeURIComponent(term) From 2610009b564d1da0ac53705218fdfc8961189e8b Mon Sep 17 00:00:00 2001 From: Michael Abashian Date: Wed, 1 Mar 2017 14:12:03 -0500 Subject: [PATCH 11/16] Fixed bug where typing in scm credential when adding/editing project wouldn't work --- awx/ui/client/src/forms/Projects.js | 1 + awx/ui/client/src/shared/directives.js | 14 +++++++++++--- awx/ui/client/src/shared/form-generator.js | 1 + 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/awx/ui/client/src/forms/Projects.js b/awx/ui/client/src/forms/Projects.js index 2185381e69..d5f165bce8 100644 --- a/awx/ui/client/src/forms/Projects.js +++ b/awx/ui/client/src/forms/Projects.js @@ -137,6 +137,7 @@ angular.module('ProjectFormDefinition', ['SchedulesListDefinition']) }, ngShow: "scm_type && scm_type.value !== 'manual'", sourceModel: 'credential', + awLookupType: 'scm_credential', sourceField: 'name', ngDisabled: '!(project_obj.summary_fields.user_capabilities.edit || canAdd)', subForm: 'sourceSubForm' diff --git a/awx/ui/client/src/shared/directives.js b/awx/ui/client/src/shared/directives.js index 1dcfb7ac62..ee67afcc90 100644 --- a/awx/ui/client/src/shared/directives.js +++ b/awx/ui/client/src/shared/directives.js @@ -482,6 +482,7 @@ function(ConfigurationUtils, i18n, $rootScope) { autopopulateLookup, modelKey = attrs.ngModel, modelName = attrs.source, + lookupType = attrs.awlookuptype, watcher = attrs.awRequiredWhen || undefined, watchBasePath; @@ -516,10 +517,14 @@ function(ConfigurationUtils, i18n, $rootScope) { } else { basePath = GetBasePath(elm.attr('data-basePath')) || elm.attr('data-basePath'); - switch(modelName) { + let switchType = lookupType ? lookupType : modelName; + switch(switchType) { case 'credential': query = '?kind=ssh&role_level=use_role'; break; + case 'scm_credential': + query = '?kind=scm&role_level=use_role'; + break; case 'network_credential': query = '?kind=net&role_level=use_role'; break; @@ -596,12 +601,12 @@ function(ConfigurationUtils, i18n, $rootScope) { function applyValidationStrategy(viewValue, ctrl) { // use supplied data attributes to build an endpoint, query, resolve outstanding promise - function applyValidation(viewValue) { + function applyValidation(viewValue) {console.log(viewValue); basePath = GetBasePath(elm.attr('data-basePath')) || elm.attr('data-basePath'); query = elm.attr('data-query'); query = query.replace(/\:value/, encodeURIComponent(viewValue)); - let base = ctrl.$name.split('_name')[0]; + let base = lookupType ? lookupType : ctrl.$name.split('_name')[0]; if (attrs.watchbasepath !== undefined && scope[attrs.watchbasepath] !== undefined) { basePath = scope[attrs.watchbasepath]; query += '&role_level=use_role'; @@ -612,6 +617,9 @@ function(ConfigurationUtils, i18n, $rootScope) { case 'credential': query += '&kind=ssh&role_level=use_role'; break; + case 'scm_credential': + query += '&kind=scm&role_level=use_role'; + break; case 'network_credential': query += '&kind=net&role_level=use_role'; break; diff --git a/awx/ui/client/src/shared/form-generator.js b/awx/ui/client/src/shared/form-generator.js index 600675f341..a1a2a6761f 100644 --- a/awx/ui/client/src/shared/form-generator.js +++ b/awx/ui/client/src/shared/form-generator.js @@ -1384,6 +1384,7 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat html += `data-basePath="${field.basePath}"`; html += `data-source="${field.sourceModel}"`; html += `data-query="?${field.sourceField}__iexact=:value"`; + html += (field.awLookupType !== undefined) ? ` data-awLookupType=${field.awLookupType} ` : ""; html += (field.autopopulateLookup !== undefined) ? ` autopopulateLookup=${field.autopopulateLookup} ` : ""; html += (field.watchBasePath !== undefined) ? ` watchBasePath=${field.watchBasePath} ` : ""; html += `ng-model-options="{ updateOn: 'default blur', debounce: { 'default': 300, 'blur': 0 } }"`; From 2697fcdbc3d156601d5dcaeeb91f615350aba68a Mon Sep 17 00:00:00 2001 From: Michael Abashian Date: Wed, 1 Mar 2017 14:14:08 -0500 Subject: [PATCH 12/16] Removed console --- awx/ui/client/src/shared/directives.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/ui/client/src/shared/directives.js b/awx/ui/client/src/shared/directives.js index ee67afcc90..8ea5d37105 100644 --- a/awx/ui/client/src/shared/directives.js +++ b/awx/ui/client/src/shared/directives.js @@ -601,7 +601,7 @@ function(ConfigurationUtils, i18n, $rootScope) { function applyValidationStrategy(viewValue, ctrl) { // use supplied data attributes to build an endpoint, query, resolve outstanding promise - function applyValidation(viewValue) {console.log(viewValue); + function applyValidation(viewValue) { basePath = GetBasePath(elm.attr('data-basePath')) || elm.attr('data-basePath'); query = elm.attr('data-query'); query = query.replace(/\:value/, encodeURIComponent(viewValue)); From 59b08cfbaf741deeb40138be18d83c65cb03ea35 Mon Sep 17 00:00:00 2001 From: James Laska Date: Wed, 1 Mar 2017 14:59:43 -0500 Subject: [PATCH 13/16] Merge pull request #5604 from jlaska/ami_playbook_changes Playbook changes to improve AMI publishing From 54bcdccdab8a0a85ec54bc205008508967b3c882 Mon Sep 17 00:00:00 2001 From: Chris Meyers Date: Thu, 2 Mar 2017 13:26:27 -0500 Subject: [PATCH 14/16] give a default other than None 1. If the setting isn't in the database, then the specified default is returned. 2. If the setting IS in the database, then the 'value' field, from the database, is returned; Unless, the value is null in the database, then the defined default is returned. * Take case 1. If the default=None then an AttributeError is raised * Thus, by setting default='', in case 1. We don't get an AttributeError because '' will be returned. * Also note that we don't allow_null=True because then the database entry could be None. Accessing the setting would raise an AttributeError in this case. Further, since we set default='' it doesn't matter if null is in the database. TL;DR set default= --- awx/main/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/main/conf.py b/awx/main/conf.py index bbdf159ae6..098b84f639 100644 --- a/awx/main/conf.py +++ b/awx/main/conf.py @@ -322,5 +322,5 @@ register( help_text=_('Useful to uniquely identify Tower instances.'), category=_('Logging'), category_slug='logging', - default=None, + default='', ) From 90a26de1805e090e2ad4886b0c8bafe73d894eb9 Mon Sep 17 00:00:00 2001 From: Matthew Jones Date: Mon, 6 Mar 2017 15:18:38 -0500 Subject: [PATCH 15/16] Fix an issue where notifications might not always be triggered In the case where a notification template were assigned to "failed" events but not "success" or "any" events. --- awx/main/tasks.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/awx/main/tasks.py b/awx/main/tasks.py index 584e6ce0bb..91ef460f16 100644 --- a/awx/main/tasks.py +++ b/awx/main/tasks.py @@ -218,7 +218,11 @@ def _send_notification_templates(instance, status_str): raise ValueError(_("status_str must be either succeeded or failed")) notification_templates = instance.get_notification_templates() if notification_templates: - all_notification_templates = set(notification_templates.get('success', []) + notification_templates.get('any', [])) + if status_str == 'succeeded': + notification_template_type = 'success' + else: + notification_template_type = 'error' + all_notification_templates = set(notification_templates.get(notification_template_type, []) + notification_templates.get('any', [])) if len(all_notification_templates): try: (notification_subject, notification_body) = getattr(instance, 'build_notification_%s_message' % status_str)() From 2c7dd8497beafd50ff6a93005c9f9de1dee846e5 Mon Sep 17 00:00:00 2001 From: Matthew Jones Date: Tue, 7 Mar 2017 13:54:52 -0500 Subject: [PATCH 16/16] Filter on reason also when logging in via sso and picking authtoken --- awx/sso/views.py | 1 + 1 file changed, 1 insertion(+) diff --git a/awx/sso/views.py b/awx/sso/views.py index 2a68deec1a..80092a8040 100644 --- a/awx/sso/views.py +++ b/awx/sso/views.py @@ -50,6 +50,7 @@ class CompleteView(BaseRedirectView): try: token = AuthToken.objects.filter(user=request.user, request_hash=request_hash, + reason='', expires__gt=now())[0] token.refresh() logger.info(smart_text(u"User {} logged in".format(self.request.user.username)))