aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml6
-rw-r--r--rest_framework/authentication.py12
-rw-r--r--rest_framework/request.py4
-rw-r--r--rest_framework/serializers.py8
-rw-r--r--rest_framework/tests/test_authentication.py26
-rw-r--r--tox.ini32
6 files changed, 64 insertions, 24 deletions
diff --git a/.travis.yml b/.travis.yml
index f6b4753d..60b48cba 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,7 +7,7 @@ python:
- "3.3"
env:
- - DJANGO="https://www.djangoproject.com/download/1.7a2/tarball/"
+ - DJANGO="https://www.djangoproject.com/download/1.7b1/tarball/"
- DJANGO="django==1.6.2"
- DJANGO="django==1.5.5"
- DJANGO="django==1.4.10"
@@ -23,7 +23,7 @@ install:
- "if [[ ${DJANGO::11} == 'django==1.3' ]]; then pip install django-filter==0.5.4; fi"
- "if [[ ${DJANGO::11} != 'django==1.3' ]]; then pip install django-filter==0.7; fi"
- "if [[ ${TRAVIS_PYTHON_VERSION::1} == '3' ]]; then pip install -e git+https://github.com/linovia/django-guardian.git@feature/django_1_7#egg=django-guardian-1.2.0; fi"
- - "if [[ ${DJANGO} == 'https://www.djangoproject.com/download/1.7a2/tarball/' ]]; then pip install -e git+https://github.com/linovia/django-guardian.git@feature/django_1_7#egg=django-guardian-1.2.0; fi"
+ - "if [[ ${DJANGO} == 'https://www.djangoproject.com/download/1.7b1/tarball/' ]]; then pip install -e git+https://github.com/linovia/django-guardian.git@feature/django_1_7#egg=django-guardian-1.2.0; fi"
- export PYTHONPATH=.
script:
@@ -32,7 +32,7 @@ script:
matrix:
exclude:
- python: "2.6"
- env: DJANGO="https://www.djangoproject.com/download/1.7a2/tarball/"
+ env: DJANGO="https://www.djangoproject.com/download/1.7b1/tarball/"
- python: "3.2"
env: DJANGO="django==1.4.10"
- python: "3.2"
diff --git a/rest_framework/authentication.py b/rest_framework/authentication.py
index b0e88d88..da9ca510 100644
--- a/rest_framework/authentication.py
+++ b/rest_framework/authentication.py
@@ -6,6 +6,7 @@ import base64
from django.contrib.auth import authenticate
from django.core.exceptions import ImproperlyConfigured
+from django.conf import settings
from rest_framework import exceptions, HTTP_HEADER_ENCODING
from rest_framework.compat import CsrfViewMiddleware
from rest_framework.compat import oauth, oauth_provider, oauth_provider_store
@@ -291,6 +292,7 @@ class OAuth2Authentication(BaseAuthentication):
OAuth 2 authentication backend using `django-oauth2-provider`
"""
www_authenticate_realm = 'api'
+ allow_query_params_token = settings.DEBUG
def __init__(self, *args, **kwargs):
super(OAuth2Authentication, self).__init__(*args, **kwargs)
@@ -308,7 +310,13 @@ class OAuth2Authentication(BaseAuthentication):
auth = get_authorization_header(request).split()
- if not auth or auth[0].lower() != b'bearer':
+ if auth and auth[0].lower() == b'bearer':
+ access_token = auth[1]
+ elif 'access_token' in request.POST:
+ access_token = request.POST['access_token']
+ elif 'access_token' in request.GET and self.allow_query_params_token:
+ access_token = request.GET['access_token']
+ else:
return None
if len(auth) == 1:
@@ -318,7 +326,7 @@ class OAuth2Authentication(BaseAuthentication):
msg = 'Invalid bearer header. Token string should not contain spaces.'
raise exceptions.AuthenticationFailed(msg)
- return self.authenticate_credentials(request, auth[1])
+ return self.authenticate_credentials(request, access_token)
def authenticate_credentials(self, request, access_token):
"""
diff --git a/rest_framework/request.py b/rest_framework/request.py
index ca70b49e..40467c03 100644
--- a/rest_framework/request.py
+++ b/rest_framework/request.py
@@ -346,7 +346,7 @@ class Request(object):
media_type = self.content_type
if stream is None or media_type is None:
- empty_data = QueryDict('', self._request._encoding)
+ empty_data = QueryDict('', encoding=self._request._encoding)
empty_files = MultiValueDict()
return (empty_data, empty_files)
@@ -362,7 +362,7 @@ class Request(object):
# re-raise. Ensures we don't simply repeat the error when
# attempting to render the browsable renderer response, or when
# logging the request or similar.
- self._data = QueryDict('', self._request._encoding)
+ self._data = QueryDict('', encoding=self._request._encoding)
self._files = MultiValueDict()
raise
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 01606e9c..cb7539e0 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -757,6 +757,9 @@ class ModelSerializer(Serializer):
field.read_only = True
ret[accessor_name] = field
+
+ # Ensure that 'read_only_fields' is an iterable
+ assert isinstance(self.opts.read_only_fields, (list, tuple)), '`read_only_fields` must be a list or tuple'
# Add the `read_only` flag to any fields that have been specified
# in the `read_only_fields` option
@@ -771,7 +774,10 @@ class ModelSerializer(Serializer):
"on serializer '%s'." %
(field_name, self.__class__.__name__))
ret[field_name].read_only = True
-
+
+ # Ensure that 'write_only_fields' is an iterable
+ assert isinstance(self.opts.write_only_fields, (list, tuple)), '`write_only_fields` must be a list or tuple'
+
for field_name in self.opts.write_only_fields:
assert field_name not in self.base_fields.keys(), (
"field '%s' on serializer '%s' specified in "
diff --git a/rest_framework/tests/test_authentication.py b/rest_framework/tests/test_authentication.py
index 8caeb081..c37d2a51 100644
--- a/rest_framework/tests/test_authentication.py
+++ b/rest_framework/tests/test_authentication.py
@@ -3,6 +3,7 @@ from django.contrib.auth.models import User
from django.http import HttpResponse
from django.test import TestCase
from django.utils import unittest
+from django.utils.http import urlencode
from rest_framework import HTTP_HEADER_ENCODING
from rest_framework import exceptions
from rest_framework import permissions
@@ -53,10 +54,14 @@ urlpatterns = patterns('',
permission_classes=[permissions.TokenHasReadWriteScope]))
)
+class OAuth2AuthenticationDebug(OAuth2Authentication):
+ allow_query_params_token = True
+
if oauth2_provider is not None:
urlpatterns += patterns('',
url(r'^oauth2/', include('provider.oauth2.urls', namespace='oauth2')),
url(r'^oauth2-test/$', MockView.as_view(authentication_classes=[OAuth2Authentication])),
+ url(r'^oauth2-test-debug/$', MockView.as_view(authentication_classes=[OAuth2AuthenticationDebug])),
url(r'^oauth2-with-scope-test/$', MockView.as_view(authentication_classes=[OAuth2Authentication],
permission_classes=[permissions.TokenHasReadWriteScope])),
)
@@ -546,6 +551,27 @@ class OAuth2Tests(TestCase):
self.assertEqual(response.status_code, 200)
@unittest.skipUnless(oauth2_provider, 'django-oauth2-provider not installed')
+ def test_post_form_passing_auth_url_transport(self):
+ """Ensure GETing form over OAuth with correct client credentials in form data succeed"""
+ response = self.csrf_client.post('/oauth2-test/',
+ data={'access_token': self.access_token.token})
+ self.assertEqual(response.status_code, 200)
+
+ @unittest.skipUnless(oauth2_provider, 'django-oauth2-provider not installed')
+ def test_get_form_passing_auth_url_transport(self):
+ """Ensure GETing form over OAuth with correct client credentials in query succeed when DEBUG is True"""
+ query = urlencode({'access_token': self.access_token.token})
+ response = self.csrf_client.get('/oauth2-test-debug/?%s' % query)
+ self.assertEqual(response.status_code, 200)
+
+ @unittest.skipUnless(oauth2_provider, 'django-oauth2-provider not installed')
+ def test_get_form_failing_auth_url_transport(self):
+ """Ensure GETing form over OAuth with correct client credentials in query fails when DEBUG is False"""
+ query = urlencode({'access_token': self.access_token.token})
+ response = self.csrf_client.get('/oauth2-test/?%s' % query)
+ self.assertIn(response.status_code, (status.HTTP_401_UNAUTHORIZED, status.HTTP_403_FORBIDDEN))
+
+ @unittest.skipUnless(oauth2_provider, 'django-oauth2-provider not installed')
def test_post_form_passing_auth(self):
"""Ensure POSTing form over OAuth with correct credentials passes and does not require CSRF"""
auth = self._create_authorization_header()
diff --git a/tox.ini b/tox.ini
index 47fdf67f..855ab0ce 100644
--- a/tox.ini
+++ b/tox.ini
@@ -7,22 +7,22 @@ commands = {envpython} rest_framework/runtests/runtests.py
[testenv:py3.3-django1.7]
basepython = python3.3
-deps = https://www.djangoproject.com/download/1.7a2/tarball/
- django-filter==0.6a1
+deps = https://www.djangoproject.com/download/1.7b1/tarball/
+ django-filter==0.7
defusedxml==0.3
Pillow==2.3.0
[testenv:py3.2-django1.7]
basepython = python3.2
-deps = https://www.djangoproject.com/download/1.7a2/tarball/
- django-filter==0.6a1
+deps = https://www.djangoproject.com/download/1.7b1/tarball/
+ django-filter==0.7
defusedxml==0.3
Pillow==2.3.0
[testenv:py2.7-django1.7]
basepython = python2.7
-deps = https://www.djangoproject.com/download/1.7a2/tarball/
- django-filter==0.6a1
+deps = https://www.djangoproject.com/download/1.7b1/tarball/
+ django-filter==0.7
defusedxml==0.3
django-oauth-plus==2.2.1
oauth2==1.5.211
@@ -33,21 +33,21 @@ deps = https://www.djangoproject.com/download/1.7a2/tarball/
[testenv:py3.3-django1.6]
basepython = python3.3
deps = Django==1.6
- django-filter==0.6a1
+ django-filter==0.7
defusedxml==0.3
Pillow==2.3.0
[testenv:py3.2-django1.6]
basepython = python3.2
deps = Django==1.6
- django-filter==0.6a1
+ django-filter==0.7
defusedxml==0.3
Pillow==2.3.0
[testenv:py2.7-django1.6]
basepython = python2.7
deps = Django==1.6
- django-filter==0.6a1
+ django-filter==0.7
defusedxml==0.3
django-oauth-plus==2.2.1
oauth2==1.5.211
@@ -58,7 +58,7 @@ deps = Django==1.6
[testenv:py2.6-django1.6]
basepython = python2.6
deps = Django==1.6
- django-filter==0.6a1
+ django-filter==0.7
defusedxml==0.3
django-oauth-plus==2.2.1
oauth2==1.5.211
@@ -69,21 +69,21 @@ deps = Django==1.6
[testenv:py3.3-django1.5]
basepython = python3.3
deps = django==1.5.5
- django-filter==0.6a1
+ django-filter==0.7
defusedxml==0.3
Pillow==2.3.0
[testenv:py3.2-django1.5]
basepython = python3.2
deps = django==1.5.5
- django-filter==0.6a1
+ django-filter==0.7
defusedxml==0.3
Pillow==2.3.0
[testenv:py2.7-django1.5]
basepython = python2.7
deps = django==1.5.5
- django-filter==0.6a1
+ django-filter==0.7
defusedxml==0.3
django-oauth-plus==2.2.1
oauth2==1.5.211
@@ -94,7 +94,7 @@ deps = django==1.5.5
[testenv:py2.6-django1.5]
basepython = python2.6
deps = django==1.5.5
- django-filter==0.6a1
+ django-filter==0.7
defusedxml==0.3
django-oauth-plus==2.2.1
oauth2==1.5.211
@@ -105,7 +105,7 @@ deps = django==1.5.5
[testenv:py2.7-django1.4]
basepython = python2.7
deps = django==1.4.10
- django-filter==0.6a1
+ django-filter==0.7
defusedxml==0.3
django-oauth-plus==2.2.1
oauth2==1.5.211
@@ -116,7 +116,7 @@ deps = django==1.4.10
[testenv:py2.6-django1.4]
basepython = python2.6
deps = django==1.4.10
- django-filter==0.6a1
+ django-filter==0.7
defusedxml==0.3
django-oauth-plus==2.2.1
oauth2==1.5.211