def test_returns_400_response_when_request_doesnt_have_client_id_in_data(self): request = self.get_request(data={ constants.SIGNATURE_PARAM_NAME:'4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=', }) signed_view = signature_required(self.view) response = signed_view(request) self.assertEqual(400, response.status_code)
def test_returns_400_response_when_request_doesnt_have_client_id_in_data(self): request = self.get_request(data={ constants.SIGNATURE_PARAM_NAME: '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=', }) signed_view = signature_required(self.view) response = signed_view(request) self.assertEqual(400, response.status_code)
def test_returns_200_when_signature_doesnt_match_but_allow_unsigned_is_true(self, get_signature): get_signature.return_value = 'ABCDEFGHIJKLMNOPQRSTUVWXYZFtYkCdi4XAc-vOLtI=' client = models.AuthorizedClient.objects.create(client_id='apps-testclient') request = self.get_request(data={ constants.SIGNATURE_PARAM_NAME: 'YQ==', constants.CLIENT_ID_PARAM_NAME: client.client_id, }) signed_view = signature_required(self.view) response = signed_view(request) self.assertEqual(200, response.status_code)
def test_returns_200_view_return_value_when_signature_matches(self, get_signature): get_signature.return_value = '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' client = models.AuthorizedClient.objects.create(client_id='apps-testclient') request = self.get_request(data={ constants.SIGNATURE_PARAM_NAME: '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=', constants.CLIENT_ID_PARAM_NAME: client.client_id, }) signed_view = signature_required(self.view) response = signed_view(request) self.assertEqual(200, response.status_code)
def test_json_api_is_properly_parsed_into_signature(self, get_signature): signature = 'QEw8WN5YzbWlct5ZXH3GIumeiL8m4NErPtXOz_jWexc=' client = models.AuthorizedClient.objects.create(client_id='apps-testclient') url = "/my/path/?{}={}&{}={}".format( constants.CLIENT_ID_PARAM_NAME, client.client_id, constants.SIGNATURE_PARAM_NAME, signature, ) data = {'our': 'data', 'goes': 'here'} json_string = json.dumps(data) request = test.client.RequestFactory().post(url, data=json_string, content_type="application/vnd.api+json") signed_view = signature_required(self.view) signed_view(request) get_signature.assert_called_with(client.private_key, '/my/path/?__client_id=apps-testclient', json_string)
def test_does_not_fire_successful_signal_from_signature_required_when_invalid(self, get_signature, send_signal): get_signature.return_value = 'ABCDEFGHIJKLMNOPQRSTUVWXYZFtYkCdi4XAc-vOLtI=' client = models.AuthorizedClient.objects.create(client_id='apps-testclient') request = self.get_request(data={ constants.SIGNATURE_PARAM_NAME: '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=', constants.CLIENT_ID_PARAM_NAME: client.client_id, }) signed_view = signature_required(self.view) response = signed_view(request) self.assertEqual(400, response.status_code) self.assertFalse(send_signal.called)
def test_calls_create_signature_properly_with_get_data(self, get_signature): get_signature.return_value = '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' client = models.AuthorizedClient.objects.create(client_id='apps-testclient') request = test.client.RequestFactory().get('/my/path/', data={ 'username': '******', constants.SIGNATURE_PARAM_NAME: '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=', constants.CLIENT_ID_PARAM_NAME: client.client_id, }) signed_view = signature_required(self.view) signed_view(request) get_signature.assert_called_once_with(client.private_key, request.get_full_path(), None)
def test_json_is_properly_parsed_into_signature(self, get_signature): signature = 'QEw8WN5YzbWlct5ZXH3GIumeiL8m4NErPtXOz_jWexc=' url = "/my/path/?{}={}&{}={}".format( constants.CLIENT_ID_PARAM_NAME, 'apps-testclient', constants.SIGNATURE_PARAM_NAME, signature, ) data = {'our': 'data', 'goes': 'here'} json_string = json.dumps(data) request = test.client.RequestFactory().post(url, data=json_string, content_type="application/json") signed_view = signature_required(self.view) signed_view(request) get_signature.assert_called_with(TEST_PRIVATE_KEY, '/my/path/?__client_id=apps-testclient', json_string)
def test_fires_successful_signed_request_signal_from_signature_required_decorator(self, get_signature, send_signal): get_signature.return_value = '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' request = self.get_request( data={ constants.SIGNATURE_PARAM_NAME: '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=', constants.CLIENT_ID_PARAM_NAME: 'apps-testclient', } ) instance = SignatureValidator(request) with mock.patch('request_signer.decorators.get_validator', mock.Mock(return_value=instance)): signed_view = signature_required(self.view) response = signed_view(request) self.assertEqual(200, response.status_code) send_signal.assert_called_once_with(sender=instance, request=request)
def test_calls_create_signature_properly_with_post_data(self, get_signature): get_signature.return_value = '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' client = models.AuthorizedClient.objects.create(client_id='apps-testclient') url = '/my/path/?' url += constants.SIGNATURE_PARAM_NAME + '=4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' url += "&" + constants.CLIENT_ID_PARAM_NAME + "=" + client.client_id request = test.client.RequestFactory().post(url, data={'username': '******'}) signed_view = signature_required(self.view) signed_view(request) get_signature.assert_called_once_with(client.private_key, unquote(request.get_full_path()), request.POST)
def test_json_is_properly_parsed_into_signature(self, get_signature): signature = 'QEw8WN5YzbWlct5ZXH3GIumeiL8m4NErPtXOz_jWexc=' get_signature.return_value = signature client = models.AuthorizedClient.objects.create(client_id='apps-testclient') url = "/my/path/?{}={}&{}={}".format( constants.SIGNATURE_PARAM_NAME, signature, constants.CLIENT_ID_PARAM_NAME, client.client_id ) data = {'our': 'data', 'goes': 'here'} json_string = json.dumps(data) request = test.client.RequestFactory().post(url, data=json_string, content_type="application/json") signed_view = signature_required(self.view) signed_view(request) get_signature.assert_called_once_with(client.private_key, unquote(request.get_full_path()), json_string)
def test_calls_create_signature_properly_with_get_data(self, get_signature): get_signature.return_value = '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' client = models.AuthorizedClient.objects.create(client_id='apps-testclient') request = test.client.RequestFactory().get('/my/path/', data={ 'username': '******', constants.SIGNATURE_PARAM_NAME: '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=', constants.CLIENT_ID_PARAM_NAME: client.client_id, }) signed_view = signature_required(self.view) signed_view(request) call_url = unquote(request.get_full_path()) call_url = re.sub('&__signature=4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=', '', call_url) get_signature.assert_called_once_with(client.private_key, call_url, None)
def test_fires_successful_signed_request_signal_from_signature_required_decorator(self, get_signature, send_signal): get_signature.return_value = '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' client = models.AuthorizedClient.objects.create(client_id='apps-testclient') request = self.get_request(data={ constants.SIGNATURE_PARAM_NAME: '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=', constants.CLIENT_ID_PARAM_NAME: client.client_id, }) instance = SignatureValidator(request) with mock.patch('request_signer.decorators.get_validator', mock.Mock(return_value=instance)): signed_view = signature_required(self.view) response = signed_view(request) self.assertEqual(200, response.status_code) send_signal.assert_called_once_with(sender=instance, request=request)
def test_json_is_properly_parsed_into_signature(self, get_signature): signature = '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' get_signature.return_value = signature client = models.AuthorizedClient.objects.create(client_id='apps-testclient') url = "/my/path/?{}={}&{}={}".format( constants.SIGNATURE_PARAM_NAME, signature, constants.CLIENT_ID_PARAM_NAME, client.client_id ) data = {'our': 'data', 'goes': 'here'} json_string = json.dumps(data) request = test.client.RequestFactory().post(url, data=json_string, content_type="application/json") signed_view = signature_required(self.view) signed_view(request) get_signature.assert_called_once_with(client.private_key, request.get_full_path(), data)
def test_calls_create_signature_properly_with_post_data(self, get_signature): signature = '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' get_signature.return_value = '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' url = "/my/path/?{}={}&{}={}".format( constants.CLIENT_ID_PARAM_NAME, 'apps-testclient', constants.SIGNATURE_PARAM_NAME, signature, ) request = test.client.RequestFactory().post(url, data={'username': '******'}) signed_view = signature_required(self.view) signed_view(request) get_signature.assert_called_once_with( TEST_PRIVATE_KEY, '/my/path/?__client_id=apps-testclient', dict(request.POST) )
def test_invalid_json_requests_raise_json_parse_eror(self, get_signature): signature = '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' get_signature.return_value = signature client = models.AuthorizedClient.objects.create(client_id='apps-testclient') url = "/my/path/?{}={}&{}={}".format( constants.SIGNATURE_PARAM_NAME, signature, constants.CLIENT_ID_PARAM_NAME, client.client_id ) data = "'our': 'data', 'goes': 'here'" request = test.client.RequestFactory().post(url, data=data, content_type="application/json") signed_view = signature_required(self.view) with self.assertRaises(ValueError) as context: signed_view(request) self.assertEqual("No JSON object could be decoded", context.exception.message)
def test_calls_create_signature_properly_with_no_content_type(self, get_signature): get_signature.return_value = '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' client = models.AuthorizedClient.objects.create(client_id='apps-testclient') request = test.client.RequestFactory().get('/my/path/', data={ 'username': '******', constants.SIGNATURE_PARAM_NAME: '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=', constants.CLIENT_ID_PARAM_NAME: client.client_id, }) if 'CONTENT_TYPE' in request.META: del request.META['CONTENT_TYPE'] signed_view = signature_required(self.view) signed_view(request) call_url = unquote(request.get_full_path()) call_url = re.sub('&__signature=4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=', '', call_url) get_signature.assert_called_once_with(client.private_key, call_url, None)
def test_does_not_create_signature_with_multivalue_dict_to_prevent_data_loss(self, get_signature): get_signature.return_value = '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' client = models.AuthorizedClient.objects.create(client_id='apps-testclient') url = '/my/path/?' url += constants.SIGNATURE_PARAM_NAME + '=4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' url += "&" + constants.CLIENT_ID_PARAM_NAME + "=" + client.client_id request = test.client.RequestFactory().post(url, data={ 'usernames': ['t1', 't2', 't3']}) signed_view = signature_required(self.view) signed_view(request) get_signature.assert_called_once_with(client.private_key, unquote(request.get_full_path()), request.POST) posted_data = get_signature.mock_calls[0][1][2] self.assertEqual([('usernames', ['t1', 't2', 't3'])], posted_data.items())
def test_does_not_create_signature_with_multivalue_dict_to_prevent_data_loss(self, get_signature): signature = '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' get_signature.return_value = '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' url = "/my/path/?{}={}&{}={}".format( constants.CLIENT_ID_PARAM_NAME, 'apps-testclient', constants.SIGNATURE_PARAM_NAME, signature, ) request = test.client.RequestFactory().post(url, data={'usernames': ['t1', 't2', 't3']}) signed_view = signature_required(self.view) signed_view(request) expected_url = re.sub(r'&__signature={}$'.format(signature), '', unquote(request.get_full_path()), count=1) get_signature.assert_called_once_with(TEST_PRIVATE_KEY, expected_url, dict(request.POST)) posted_data = get_signature.mock_calls[0][1][2] self.assertEqual([('usernames', ['t1', 't2', 't3'])], list(posted_data.items()))
def test_calls_create_signature_properly_with_no_content_type(self, get_signature): signature = '4ZAQJqmWE_C9ozPkpJ3Owh0Z_DFtYkCdi4XAc-vOLtI=' get_signature.return_value = signature client = models.AuthorizedClient.objects.create(client_id='apps-testclient') request = test.client.RequestFactory().get("/my/path/?{}={}&{}={}".format( constants.CLIENT_ID_PARAM_NAME, client.client_id, constants.SIGNATURE_PARAM_NAME, signature, )) if 'CONTENT_TYPE' in request.META: del request.META['CONTENT_TYPE'] signed_view = signature_required(self.view) signed_view(request) call_url = unquote(request.get_full_path()) call_url = re.sub(r'&__signature={}$'.format(signature), '', call_url, count=1) get_signature.assert_called_once_with(client.private_key, call_url, {})
from django.conf.urls import patterns, include, url from django.contrib import admin from request_signer.decorators import signature_required from server import views admin.autodiscover() urlpatterns = patterns( '', url(r'^admin/', include(admin.site.urls)), url(r'sample/', signature_required(views.SampleView.as_view())), )
def test_adds_signature_required_attribute_to_view(self): self.assertFalse(hasattr(self.view, 'signature_required')) signed_view = signature_required(self.view) self.assertTrue(getattr(signed_view, 'signature_required', False))
def test_returns_400_response_when_request_doesnt_have_signature_in_data(self): request = self.get_request() signed_view = signature_required(self.view) response = signed_view(request) self.assertEqual(400, response.status_code)
def test_signed_views_are_csrf_exempt(self): signed_view = signature_required(self.view) self.assertTrue(getattr(signed_view, 'csrf_exempt', False))
from django.conf.urls import include, url from django.contrib import admin from django import http from request_signer.decorators import signature_required admin.autodiscover() urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^test/$', signature_required(lambda request, *args, **kwargs: http.HttpResponse("Completed Test View!"))), url(r'^test/(?P<arg>.*)/$', signature_required(lambda request, *args, **kwargs: http.HttpResponse("X"))) ]