From b4890ee3317a3a9ec4c06e471c233e524c9c444a Mon Sep 17 00:00:00 2001 From: Yunfan Zhang Date: Tue, 3 Jul 2018 11:52:52 -0400 Subject: [PATCH 1/4] Handle exception with invalid HTTP content_type. Signed-off-by: Yunfan Zhang --- awx/api/generics.py | 6 +++++- awx/main/tests/functional/api/test_generic.py | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/awx/api/generics.py b/awx/api/generics.py index b3afb5235e..ebe643a6a2 100644 --- a/awx/api/generics.py +++ b/awx/api/generics.py @@ -23,7 +23,7 @@ from django.utils.translation import ugettext_lazy as _ from django.contrib.auth import views as auth_views # Django REST Framework -from rest_framework.exceptions import PermissionDenied, AuthenticationFailed, ParseError, NotAcceptable +from rest_framework.exceptions import PermissionDenied, AuthenticationFailed, ParseError, NotAcceptable, UnsupportedMediaType from rest_framework import generics from rest_framework.response import Response from rest_framework import status @@ -197,6 +197,10 @@ class APIView(views.APIView): except (PermissionDenied, ParseError) as exc: request.drf_request_user = None self.__init_request_error__ = exc + except UnsupportedMediaType as exc: + exc.detail = _('You did not use correct content_type in your HTTP request. \ + If you are using our REST API, the content_type must be application/json') + self.__init_request_error__ = exc return drf_request def finalize_response(self, request, response, *args, **kwargs): diff --git a/awx/main/tests/functional/api/test_generic.py b/awx/main/tests/functional/api/test_generic.py index 68ca294027..43586fdf6c 100644 --- a/awx/main/tests/functional/api/test_generic.py +++ b/awx/main/tests/functional/api/test_generic.py @@ -107,3 +107,13 @@ def test_filterable_fields(options, instance, admin_user): assert filterable_info['filterable'] is True assert 'filterable' not in non_filterable_info + + +@pytest.mark.django_db +def test_handle_content_type(post, admin): + ''' Tower should return 415 when wrong content type is in HTTP requests ''' + post(reverse('api:project_list'), + {'name': 't', 'organization': None}, + admin, + content_type='text/html', + expect=415) From 2a5853e4fcc4b75b6871cb0ea0f728caa4b2a726 Mon Sep 17 00:00:00 2001 From: AlanCoding Date: Tue, 3 Jul 2018 14:30:56 -0400 Subject: [PATCH 2/4] add back in application activity stream link --- awx/api/serializers.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 2dde811429..4e0d303efe 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -1193,10 +1193,13 @@ class OAuth2ApplicationSerializer(BaseSerializer): def get_related(self, obj): res = super(OAuth2ApplicationSerializer, self).get_related(obj) res.update(dict( - tokens = self.reverse('api:o_auth2_application_token_list', kwargs={'pk': obj.pk}), + tokens = self.reverse('api:o_auth2_application_token_list', kwargs={'pk': obj.pk}), + activity_stream = self.reverse( + 'api:o_auth2_application_activity_stream_list', kwargs={'pk': obj.pk} + ) )) return res - + def get_modified(self, obj): if obj is None: return None From 26360f8852fb7bf902edfadd51c9224465430169 Mon Sep 17 00:00:00 2001 From: kialam Date: Tue, 3 Jul 2018 13:11:49 -0400 Subject: [PATCH 3/4] =?UTF-8?q?Update=20the=20canvas=20element=E2=80=99s?= =?UTF-8?q?=20scale=20factor=20upon=20initialization.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And fix initial value of `$scope.current_scale`. --- awx/ui/client/src/network-ui/network.ui.controller.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/awx/ui/client/src/network-ui/network.ui.controller.js b/awx/ui/client/src/network-ui/network.ui.controller.js index 70114aeae1..1e2398dbef 100644 --- a/awx/ui/client/src/network-ui/network.ui.controller.js +++ b/awx/ui/client/src/network-ui/network.ui.controller.js @@ -1085,7 +1085,6 @@ var NetworkUIController = function($scope, $scope.topology_id = data.topology_id; $scope.panX = data.panX; $scope.panY = data.panX; - $scope.current_scale = data.scale; $scope.$emit('awxNet-UpdateZoomWidget', $scope.current_scale, true); $scope.link_id_seq = util.natural_numbers(data.link_id_seq); $scope.device_id_seq = util.natural_numbers(data.device_id_seq); @@ -1215,7 +1214,6 @@ var NetworkUIController = function($scope, $scope.current_scale = Math.min(2, Math.max(0.10, Math.min((window.innerWidth-200)/diff_x, (window.innerHeight-300)/diff_y))); $scope.$emit('awxNet-UpdateZoomWidget', $scope.current_scale, true); $scope.updateScaledXY(); - $scope.updatePanAndScale(); } // Calculate the new panX and panY to show the entire diagram if (min_x !== null && min_y !== null) { @@ -1224,7 +1222,6 @@ var NetworkUIController = function($scope, $scope.panX = $scope.current_scale * (-min_x - diff_x/2) + window.innerWidth/2; $scope.panY = $scope.current_scale * (-min_y - diff_y/2) + window.innerHeight/2; $scope.updateScaledXY(); - $scope.updatePanAndScale(); } //Update the device_id_seq to be greater than all device ids to prevent duplicate ids. @@ -1261,6 +1258,7 @@ var NetworkUIController = function($scope, } $scope.updateInterfaceDots(); + $scope.updatePanAndScale(); // Update the canvas element scale to the correct initial scale $scope.$emit('awxNet-instatiateSelect', $scope.devices); }; From d1f5485b9629a7b1618fc0684cbd8b8b753188af Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Tue, 3 Jul 2018 15:15:00 -0400 Subject: [PATCH 4/4] properly check read permissions in `GET /api/v2/wfjt/N/copy/` see: https://github.com/ansible/tower/issues/2323 --- awx/api/views.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/awx/api/views.py b/awx/api/views.py index bbd6e82152..bc6a785002 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -3720,7 +3720,11 @@ class WorkflowJobTemplateCopy(WorkflowsEnforcementMixin, CopyAPIView): copy_return_serializer_class = WorkflowJobTemplateSerializer def get(self, request, *args, **kwargs): + if get_request_version(request) < 2: + return self.v1_not_allowed() obj = self.get_object() + if not request.user.can_access(obj.__class__, 'read', obj): + raise PermissionDenied() can_copy, messages = request.user.can_access_with_errors(self.model, 'copy', obj) data = OrderedDict([ ('can_copy', can_copy), ('can_copy_without_user_input', can_copy),