Disallow HTTP update methods in job_detail API endpoint.

This commit is contained in:
Yunfan Zhang 2018-06-08 17:29:20 -04:00
parent 18384bc509
commit 1bc1a6f63f
3 changed files with 64 additions and 12 deletions

View File

@ -1613,12 +1613,12 @@ class OAuth2UserTokenList(SubListCreateAPIView):
relationship = 'main_oauth2accesstoken'
parent_key = 'user'
swagger_topic = 'Authentication'
class UserAuthorizedTokenList(SubListCreateAPIView):
view_name = _("OAuth2 User Authorized Access Tokens")
model = OAuth2AccessToken
serializer_class = UserAuthorizedTokenSerializer
parent_model = User
@ -1628,12 +1628,12 @@ class UserAuthorizedTokenList(SubListCreateAPIView):
def get_queryset(self):
return get_access_token_model().objects.filter(application__isnull=False, user=self.request.user)
class OrganizationApplicationList(SubListCreateAPIView):
view_name = _("Organization OAuth2 Applications")
model = OAuth2Application
serializer_class = OAuth2ApplicationSerializer
parent_model = Organization
@ -1643,16 +1643,16 @@ class OrganizationApplicationList(SubListCreateAPIView):
class UserPersonalTokenList(SubListCreateAPIView):
view_name = _("OAuth2 Personal Access Tokens")
model = OAuth2AccessToken
serializer_class = UserPersonalTokenSerializer
parent_model = User
relationship = 'main_oauth2accesstoken'
parent_key = 'user'
swagger_topic = 'Authentication'
def get_queryset(self):
return get_access_token_model().objects.filter(application__isnull=True, user=self.request.user)
@ -4084,6 +4084,29 @@ class JobDetail(UnifiedJobDeletionMixin, RetrieveUpdateDestroyAPIView):
metadata_class = JobTypeMetadata
serializer_class = JobDetailSerializer
# NOTE: When removing the V1 API in 3.4, delete the following four methods,
# and let this class inherit from RetrieveDestroyAPIView instead of
# RetrieveUpdateDestroyAPIView.
@property
def allowed_methods(self):
methods = super(JobDetail, self).allowed_methods
if get_request_version(getattr(self, 'request', None)) > 1:
methods.remove('PUT')
methods.remove('PATCH')
return methods
def put(self, request, *args, **kwargs):
if get_request_version(self.request) > 1:
return Response({"error": _("PUT not allowed for Job Details in version 2 of the API")},
status=status.HTTP_405_METHOD_NOT_ALLOWED)
return super(JobDetail, self).put(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
if get_request_version(self.request) > 1:
return Response({"error": _("PUT not allowed for Job Details in version 2 of the API")},
status=status.HTTP_405_METHOD_NOT_ALLOWED)
return super(JobDetail, self).patch(request, *args, **kwargs)
def update(self, request, *args, **kwargs):
obj = self.get_object()
# Only allow changes (PUT/PATCH) when job status is "new".

View File

@ -1,14 +1,16 @@
# Python
import pytest
import mock
from dateutil.parser import parse
from dateutil.relativedelta import relativedelta
from crum import impersonate
# Django rest framework
from rest_framework.exceptions import PermissionDenied
# AWX
from awx.api.versioning import reverse
from awx.api.views import RelatedJobsPreventDeleteMixin, UnifiedJobDeletionMixin
from awx.main.models import (
JobTemplate,
User,
@ -17,8 +19,6 @@ from awx.main.models import (
ProjectUpdate,
)
from crum import impersonate
@pytest.mark.django_db
def test_extra_credentials(get, organization_factory, job_template_factory, credential):
@ -167,6 +167,33 @@ def test_block_related_unprocessed_events(mocker, organization, project, delete,
view.perform_destroy(organization)
@pytest.mark.django_db
def test_disallowed_http_update_methods(put, patch, post, inventory, project, admin_user):
jt = JobTemplate.objects.create(
name='test_disallowed_methods', inventory=inventory,
project=project
)
job = jt.create_unified_job()
post(
url=reverse('api:job_detail', kwargs={'pk': job.pk, 'version': 'v2'}),
data={},
user=admin_user,
expect=405
)
put(
url=reverse('api:job_detail', kwargs={'pk': job.pk, 'version': 'v2'}),
data={},
user=admin_user,
expect=405
)
patch(
url=reverse('api:job_detail', kwargs={'pk': job.pk, 'version': 'v2'}),
data={},
user=admin_user,
expect=405
)
class TestControllerNode():
@pytest.fixture
def project_update(self, project):

View File

@ -67,6 +67,8 @@
[[#1873](https://github.com/ansible/awx/issues/1873)].
* Switched authentication to Django sessions.
* Implemented OAuth2 support for token based authentication [[#21](https://github.com/ansible/awx/issues/21)].
* Added the ability to forcibly expire sessions through `awx-manage expire_sessions`.
* Disallowed using HTTP PUT/PATCH methods to modify existing jobs in Job Details API endpoint.
3.2.0
=====