Skip to content
This repository has been archived by the owner on Dec 7, 2022. It is now read-only.

Commit

Permalink
Merge pull request #1650 from asmacdo/move-body-as-json
Browse files Browse the repository at this point in the history
Move request.body_as_json from middleware to decorator
  • Loading branch information
asmacdo committed Feb 17, 2015
2 parents afc415a + e4624f5 commit 25ae34a
Show file tree
Hide file tree
Showing 15 changed files with 210 additions and 47 deletions.
1 change: 1 addition & 0 deletions common/pulp/common/error_codes.py
Expand Up @@ -96,3 +96,4 @@
" directory: %(path)s"), ['path'])
PLP1008 = Error("PLP1008", _("The importer type %(importer_type_id)s does not exist"),
['importer_type_id'])
PLP1009 = Error("PLP1009", _("The request body does not contain valid JSON"), [])
16 changes: 0 additions & 16 deletions server/pulp/server/webservices/middleware/parse_body.py

This file was deleted.

1 change: 0 additions & 1 deletion server/pulp/server/webservices/settings.py
Expand Up @@ -22,7 +22,6 @@
MIDDLEWARE_CLASSES = (
'django.middleware.http.ConditionalGetMiddleware',
'pulp.server.webservices.middleware.exception.DjangoExceptionHandlerMiddleware',
'pulp.server.webservices.middleware.parse_body.ParseBodyMiddleware',
'pulp.server.webservices.middleware.postponed.DjangoPostponedOperationMiddleware',
'django.middleware.common.CommonMiddleware',
)
Expand Down
9 changes: 8 additions & 1 deletion server/pulp/server/webservices/views/consumer_groups.py
Expand Up @@ -10,7 +10,9 @@
from pulp.server.managers.consumer.group.cud import bind, unbind
from pulp.server.webservices.controllers.decorators import auth_required
from pulp.server.webservices.views.util import (generate_json_response,
generate_json_response_with_pulp_encoder)
generate_json_response_with_pulp_encoder,
json_body_allow_empty,
json_body_required)


class ConsumerGroupResourceView(View):
Expand Down Expand Up @@ -57,6 +59,7 @@ def delete(self, request, consumer_group_id):
return generate_json_response(result)

@auth_required(authorization.UPDATE)
@json_body_allow_empty
def put(self, request, consumer_group_id):
"""
Update a specified consumer group.
Expand All @@ -83,6 +86,7 @@ class ConsumerGroupAssociateActionView(View):
"""

@auth_required(authorization.EXECUTE)
@json_body_allow_empty
def post(self, request, consumer_group_id):
"""
Associate a consumer to the group.
Expand All @@ -109,6 +113,7 @@ class ConsumerGroupUnassociateActionView(View):
"""

@auth_required(authorization.EXECUTE)
@json_body_allow_empty
def post(self, request, consumer_group_id):
"""
Unassociate a consumer from the group.
Expand All @@ -135,6 +140,7 @@ class ConsumerGroupContentActionView(View):
"""

@auth_required(authorization.CREATE)
@json_body_allow_empty
def post(self, request, consumer_group_id, action):
"""
Install/update/uninstall content unit/s on each consumer in the group.
Expand Down Expand Up @@ -222,6 +228,7 @@ class ConsumerGroupBindingsView(View):
"""

@auth_required(authorization.CREATE)
@json_body_required
def post(self, request, consumer_group_id):
"""
Create a bind association between the consumers belonging to the given
Expand Down
6 changes: 5 additions & 1 deletion server/pulp/server/webservices/views/content.py
Expand Up @@ -14,7 +14,9 @@
from pulp.server.webservices import serialization
from pulp.server.webservices.controllers.decorators import auth_required
from pulp.server.webservices.views.util import (generate_json_response,
generate_json_response_with_pulp_encoder)
generate_json_response_with_pulp_encoder,
json_body_required,
json_body_allow_empty)


class OrphanCollectionView(View):
Expand Down Expand Up @@ -158,6 +160,7 @@ class DeleteOrphansActionView(View):
"""

@auth_required(authorization.DELETE)
@json_body_allow_empty
def post(self, request):
"""
Dispatch a delete_orphan_by_id task.
Expand Down Expand Up @@ -352,6 +355,7 @@ def get(self, request, type_id, unit_id):
return generate_json_response(resource)

@auth_required(authorization.UPDATE)
@json_body_required
def put(self, request, type_id, unit_id):
"""
Set the pulp_user_metadata field on a content unit.
Expand Down
6 changes: 5 additions & 1 deletion server/pulp/server/webservices/views/events.py
Expand Up @@ -6,7 +6,9 @@
from pulp.server.webservices.controllers.decorators import auth_required
from pulp.server.webservices.views.util import (generate_json_response,
generate_json_response_with_pulp_encoder,
generate_redirect_response)
generate_redirect_response,
json_body_allow_empty,
json_body_required)


class EventView(View):
Expand All @@ -33,6 +35,7 @@ def get(self, request):
return generate_json_response_with_pulp_encoder(events)

@auth_required(authorization.CREATE)
@json_body_required
def post(self, request):
"""
Create a new event listener.
Expand Down Expand Up @@ -102,6 +105,7 @@ def delete(self, request, event_listener_id):
return generate_json_response(None)

@auth_required(authorization.UPDATE)
@json_body_allow_empty
def put(self, request, event_listener_id):
"""
Update a specific event listener.
Expand Down
7 changes: 6 additions & 1 deletion server/pulp/server/webservices/views/permissions.py
Expand Up @@ -5,7 +5,8 @@
from pulp.server.managers import factory
from pulp.server.webservices.controllers.decorators import auth_required
from pulp.server.webservices.views.util import (generate_json_response,
generate_json_response_with_pulp_encoder)
generate_json_response_with_pulp_encoder,
json_body_required)


class PermissionView(View):
Expand Down Expand Up @@ -54,6 +55,7 @@ class GrantToUserView(View):
"""

@auth_required(authorization.EXECUTE)
@json_body_required
def post(self, request):
"""
Grant permissions to a user.
Expand Down Expand Up @@ -86,6 +88,7 @@ class RevokeFromUserView(View):
"""

@auth_required(authorization.EXECUTE)
@json_body_required
def post(self, request):
"""
Revoke permissions from a user.
Expand Down Expand Up @@ -117,6 +120,7 @@ class GrantToRoleView(View):
"""

@auth_required(authorization.EXECUTE)
@json_body_required
def post(self, request):
"""
Grant permissions to a role.
Expand Down Expand Up @@ -150,6 +154,7 @@ class RevokeFromRoleView(View):
"""

@auth_required(authorization.EXECUTE)
@json_body_required
def post(self, request):
"""
Revoke permissions from a role.
Expand Down
6 changes: 5 additions & 1 deletion server/pulp/server/webservices/views/roles.py
Expand Up @@ -7,7 +7,8 @@
from pulp.server.webservices.controllers.decorators import auth_required
from pulp.server.webservices.views.util import (generate_json_response,
generate_json_response_with_pulp_encoder,
generate_redirect_response)
generate_redirect_response,
json_body_required)


class RolesView(View):
Expand Down Expand Up @@ -51,6 +52,7 @@ def get(self, request):
return generate_json_response_with_pulp_encoder(roles)

@auth_required(authorization.CREATE)
@json_body_required
def post(self, request):
"""
Create a new role.
Expand Down Expand Up @@ -132,6 +134,7 @@ def delete(self, request, role_id):
return generate_json_response(result)

@auth_required(authorization.UPDATE)
@json_body_required
def put(self, request, role_id):
"""
Update a specific role.
Expand Down Expand Up @@ -177,6 +180,7 @@ def get(self, request, role_id):
return generate_json_response_with_pulp_encoder(role_users)

@auth_required(authorization.UPDATE)
@json_body_required
def post(self, request, role_id):
"""
Add user to a role.
Expand Down
22 changes: 22 additions & 0 deletions server/pulp/server/webservices/views/util.py
@@ -1,9 +1,12 @@
import functools
import json
from functools import wraps

from django.http import HttpResponse
from django.utils.encoding import iri_to_uri

from pulp.common import error_codes
from pulp.server.exceptions import PulpCodedValidationException
from pulp.server.webservices.controllers.base import json_encoder as pulp_json_encoder


Expand Down Expand Up @@ -46,3 +49,22 @@ def generate_redirect_response(response, href):
response.status_code = 201
response.reason_phrase = 'CREATED'
return response


def json_body_required(func, allow_empty=False):

@wraps(func)
def wrapper(*args, **kwargs):
request = args[1]
if allow_empty and not request.body:
request.body_as_json = {}
return func(*args, **kwargs)

try:
request.body_as_json = json.loads(request.body)
except ValueError:
raise PulpCodedValidationException(error_code=error_codes.PLP1009)
return func(*args, **kwargs)
return wrapper

json_body_allow_empty = functools.partial(json_body_required, allow_empty=True)
25 changes: 15 additions & 10 deletions server/test/unit/server/webservices/views/test_consumer_groups.py
@@ -1,3 +1,4 @@
import json
import unittest

import mock
Expand Down Expand Up @@ -96,7 +97,7 @@ def test_update_consumer_group(self, mock_factory, mock_resp):
expected_cont = {'id': 'foo', 'display_name': 'bar', '_href': '/v2/consumer_groups/foo/'}

request = mock.MagicMock()
request.body_as_json = {'display_name': 'bar'}
request.body = json.dumps({'display_name': 'bar'})
mock_factory.consumer_group_manager.return_value.update_consumer_group.return_value = resp
consumer_group = ConsumerGroupResourceView()
response = consumer_group.put(request, 'foo')
Expand All @@ -123,7 +124,7 @@ def test_cons_group_association_view(self, mock_factory, mock_resp):
mock_factory.consumer_group_manager.return_value.associate.return_value = 'ok'
mock_factory.consumer_group_query_manager.return_value.get_group.return_value = grp
request = mock.MagicMock()
request.body_as_json = {'criteria': {'filters': {'id': 'c1'}}}
request.body = json.dumps({'criteria': {'filters': {'id': 'c1'}}})
consumer_group_associate = ConsumerGroupAssociateActionView()
response = consumer_group_associate.post(request, 'my-group')

Expand All @@ -149,7 +150,7 @@ def test_cons_group_unassociation_view(self, mock_factory, mock_resp):
mock_factory.consumer_group_manager.return_value.unassociate.return_value = 'ok'
mock_factory.consumer_group_query_manager.return_value.get_group.return_value = grp
request = mock.MagicMock()
request.body_as_json = {'criteria': {'filters': {'id': 'c1'}}}
request.body = json.dumps({'criteria': {'filters': {'id': 'c1'}}})
consumer_group_unassociate = ConsumerGroupUnassociateActionView()
response = consumer_group_unassociate.post(request, 'my-group')

Expand All @@ -173,7 +174,7 @@ def test_verify_group_resources_repo(self, mock_factory):
mock_factory.repo_query_manager.return_value.find_by_id.return_value = None
mock_factory.repo_distributor_manager.return_value.get_distributor.return_value = 'yyy'
request = mock.MagicMock()
request.body_as_json = {'repo_id': 'xxx', 'distributor_id': 'yyy'}
request.body = json.dumps({'repo_id': 'xxx', 'distributor_id': 'yyy'})
bind_view = ConsumerGroupBindingsView()
try:
response = bind_view.post(request, 'test-group')
Expand All @@ -195,7 +196,7 @@ def test_verify_group_resources_distributor(self, mock_f):
mock_f.repo_query_manager.return_value.find_by_id.return_value = 'xxx'
mock_f.repo_distributor_manager.return_value.get_distributor.side_effect = MissingResource
request = mock.MagicMock()
request.body_as_json = {'repo_id': 'xxx', 'distributor_id': 'yyy'}
request.body = json.dumps({'repo_id': 'xxx', 'distributor_id': 'yyy'})
bind_view = ConsumerGroupBindingsView()
try:
response = bind_view.post(request, 'test-group')
Expand All @@ -217,7 +218,7 @@ def test_verify_group_resources_group(self, mock_f):
mock_f.repo_query_manager.return_value.find_by_id.return_value = 'xxx'
mock_f.repo_distributor_manager.return_value.get_distributor.return_value = 'yyy'
request = mock.MagicMock()
request.body_as_json = {'repo_id': 'xxx', 'distributor_id': 'yyy'}
request.body = json.dumps({'repo_id': 'xxx', 'distributor_id': 'yyy'})
bind_view = ConsumerGroupBindingsView()
try:
response = bind_view.post(request, 'test-group')
Expand All @@ -238,7 +239,7 @@ def test_create_binding(self, mock_resources, mock_bind):
"""
mock_resources.return_value = {}
request = mock.MagicMock()
request.body_as_json = {'repo_id': 'xxx', 'distributor_id': 'yyy'}
request.body = json.dumps({'repo_id': 'xxx', 'distributor_id': 'yyy'})
bind_view = ConsumerGroupBindingsView()
self.assertRaises(OperationPostponed, bind_view.post, request, 'test-group')
bind_args_tuple = ('test-group', 'xxx', 'yyy', True, None, {})
Expand All @@ -253,6 +254,7 @@ def test_create_binding_with_missing_group_id(self, mock_resources):
"""
mock_resources.return_value = {'group_id': 'nonexistent_id'}
request = mock.MagicMock()
request.body = json.dumps({})
bind_view = ConsumerGroupBindingsView()
try:
response = bind_view.post(request, 'nonexistent_id')
Expand All @@ -272,6 +274,7 @@ def test_create_binding_with_missing_repo_id(self, mock_resources):
"""
mock_resources.return_value = {'repo_id': 'nonexistent_id'}
request = mock.MagicMock()
request.body = json.dumps({})
bind_view = ConsumerGroupBindingsView()
try:
response = bind_view.post(request, 'test-group')
Expand All @@ -291,6 +294,7 @@ def test_create_binding_with_invalid_param(self, mock_resources):
"""
mock_resources.return_value = {'invalid_param': 'foo'}
request = mock.MagicMock()
request.body = json.dumps({})
bind_view = ConsumerGroupBindingsView()
try:
response = bind_view.post(request, 'test-group')
Expand Down Expand Up @@ -354,6 +358,7 @@ def test_consumer_group_bad_request_content(self):
Test consumer group invalid content action.
"""
request = mock.MagicMock()
request.body = json.dumps('')
consumer_group_content = ConsumerGroupContentActionView()
response = consumer_group_content.post(request, 'my-group', 'no_such_action')
self.assertTrue(isinstance(response, HttpResponseBadRequest))
Expand All @@ -368,7 +373,7 @@ def test_consumer_group_content_install(self, mock_factory):
"""
mock_factory.consumer_group_manager.return_value.install_content.return_value = 'ok'
request = mock.MagicMock()
request.body_as_json = {"units": [], "options": {}}
request.body = json.dumps({"units": [], "options": {}})
consumer_group_content = ConsumerGroupContentActionView()
self.assertRaises(OperationPostponed, consumer_group_content.post, request,
'my-group', 'install')
Expand All @@ -384,7 +389,7 @@ def test_consumer_group_content_update(self, mock_factory):
"""
mock_factory.consumer_group_manager.return_value.update_content.return_value = 'ok'
request = mock.MagicMock()
request.body_as_json = {"units": [], "options": {}}
request.body = json.dumps({"units": [], "options": {}})
consumer_group_content = ConsumerGroupContentActionView()
self.assertRaises(OperationPostponed, consumer_group_content.post, request,
'my-group', 'update')
Expand All @@ -400,7 +405,7 @@ def test_consumer_group_content_uninstall(self, mock_factory):
"""
mock_factory.consumer_group_manager.return_value.uninstall_content.return_value = 'ok'
request = mock.MagicMock()
request.body_as_json = {"units": [], "options": {}}
request.body = json.dumps({"units": [], "options": {}})
consumer_group_content = ConsumerGroupContentActionView()
self.assertRaises(OperationPostponed, consumer_group_content.post, request,
'my-group', 'uninstall')
Expand Down

0 comments on commit 25ae34a

Please sign in to comment.