Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
D
django-rest-framework
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
django-rest-framework
Commits
afd49023
Commit
afd49023
authored
Feb 23, 2012
by
Sébastien Piquemal
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
authentication refactor : request.user + tests pass
parent
9da1ae81
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
79 additions
and
54 deletions
+79
-54
djangorestframework/authentication.py
+3
-2
djangorestframework/mixins.py
+26
-37
djangorestframework/request.py
+38
-3
djangorestframework/tests/authentication.py
+1
-1
djangorestframework/tests/throttling.py
+4
-4
djangorestframework/views.py
+7
-7
No files found.
djangorestframework/authentication.py
View file @
afd49023
...
@@ -88,13 +88,14 @@ class UserLoggedInAuthentication(BaseAuthentication):
...
@@ -88,13 +88,14 @@ class UserLoggedInAuthentication(BaseAuthentication):
Otherwise returns :const:`None`.
Otherwise returns :const:`None`.
"""
"""
request
.
DATA
# Make sure our generic parsing runs first
request
.
DATA
# Make sure our generic parsing runs first
user
=
getattr
(
request
.
request
,
'user'
,
None
)
if
getattr
(
request
,
'user'
,
None
)
and
request
.
user
.
is_active
:
if
user
and
user
.
is_active
:
# Enforce CSRF validation for session based authentication.
# Enforce CSRF validation for session based authentication.
resp
=
CsrfViewMiddleware
()
.
process_view
(
request
,
None
,
(),
{})
resp
=
CsrfViewMiddleware
()
.
process_view
(
request
,
None
,
(),
{})
if
resp
is
None
:
# csrf passed
if
resp
is
None
:
# csrf passed
return
request
.
user
return
user
return
None
return
None
...
...
djangorestframework/mixins.py
View file @
afd49023
...
@@ -3,7 +3,6 @@ The :mod:`mixins` module provides a set of reusable `mixin`
...
@@ -3,7 +3,6 @@ The :mod:`mixins` module provides a set of reusable `mixin`
classes that can be added to a `View`.
classes that can be added to a `View`.
"""
"""
from
django.contrib.auth.models
import
AnonymousUser
from
django.core.paginator
import
Paginator
from
django.core.paginator
import
Paginator
from
django.db.models.fields.related
import
ForeignKey
from
django.db.models.fields.related
import
ForeignKey
from
urlobject
import
URLObject
from
urlobject
import
URLObject
...
@@ -19,7 +18,7 @@ __all__ = (
...
@@ -19,7 +18,7 @@ __all__ = (
# Base behavior mixins
# Base behavior mixins
'RequestMixin'
,
'RequestMixin'
,
'ResponseMixin'
,
'ResponseMixin'
,
'
Auth
Mixin'
,
'
Permissions
Mixin'
,
'ResourceMixin'
,
'ResourceMixin'
,
# Reverse URL lookup behavior
# Reverse URL lookup behavior
'InstanceMixin'
,
'InstanceMixin'
,
...
@@ -45,6 +44,13 @@ class RequestMixin(object):
...
@@ -45,6 +44,13 @@ class RequestMixin(object):
Should be a tuple/list of classes as described in the :mod:`parsers` module.
Should be a tuple/list of classes as described in the :mod:`parsers` module.
"""
"""
authentication_classes
=
()
"""
The set of authentication types that this view can handle.
Should be a tuple/list of classes as described in the :mod:`authentication` module.
"""
request_class
=
Request
request_class
=
Request
"""
"""
The class to use as a wrapper for the original request object.
The class to use as a wrapper for the original request object.
...
@@ -56,6 +62,12 @@ class RequestMixin(object):
...
@@ -56,6 +62,12 @@ class RequestMixin(object):
"""
"""
return
[
p
(
self
)
for
p
in
self
.
parser_classes
]
return
[
p
(
self
)
for
p
in
self
.
parser_classes
]
def
get_authentications
(
self
):
"""
Instantiates and returns the list of authentications the request will use.
"""
return
[
a
(
self
)
for
a
in
self
.
authentication_classes
]
def
create_request
(
self
,
request
):
def
create_request
(
self
,
request
):
"""
"""
Creates and returns an instance of :class:`request.Request`.
Creates and returns an instance of :class:`request.Request`.
...
@@ -63,7 +75,9 @@ class RequestMixin(object):
...
@@ -63,7 +75,9 @@ class RequestMixin(object):
parsers set on the view.
parsers set on the view.
"""
"""
parsers
=
self
.
get_parsers
()
parsers
=
self
.
get_parsers
()
return
self
.
request_class
(
request
,
parsers
=
parsers
)
authentications
=
self
.
get_authentications
()
return
self
.
request_class
(
request
,
parsers
=
parsers
,
authentications
=
authentications
)
@property
@property
def
_parsed_media_types
(
self
):
def
_parsed_media_types
(
self
):
...
@@ -134,57 +148,32 @@ class ResponseMixin(object):
...
@@ -134,57 +148,32 @@ class ResponseMixin(object):
return
[
renderer
.
format
for
renderer
in
self
.
get_renderers
()]
return
[
renderer
.
format
for
renderer
in
self
.
get_renderers
()]
##########
Auth
Mixin ##########
##########
Permissions
Mixin ##########
class
Auth
Mixin
(
object
):
class
Permissions
Mixin
(
object
):
"""
"""
Simple :class:`mixin` class to add
authentication and
permission checking to a :class:`View` class.
Simple :class:`mixin` class to add permission checking to a :class:`View` class.
"""
"""
authentication
=
()
permissions_classes
=
()
"""
The set of authentication types that this view can handle.
Should be a tuple/list of classes as described in the :mod:`authentication` module.
"""
permissions
=
()
"""
"""
The set of permissions that will be enforced on this view.
The set of permissions that will be enforced on this view.
Should be a tuple/list of classes as described in the :mod:`permissions` module.
Should be a tuple/list of classes as described in the :mod:`permissions` module.
"""
"""
@property
def
get_permissions
(
self
):
def
user
(
self
):
"""
Returns the :obj:`user` for the current request, as determined by the set of
:class:`authentication` classes applied to the :class:`View`.
"""
if
not
hasattr
(
self
,
'_user'
):
self
.
_user
=
self
.
_authenticate
()
return
self
.
_user
def
_authenticate
(
self
):
"""
"""
Attempt to authenticate the request using each authentication class in turn.
Instantiates and returns the list of permissions that this view requires.
Returns a ``User`` object, which may be ``AnonymousUser``.
"""
"""
for
authentication_cls
in
self
.
authentication
:
return
[
p
(
self
)
for
p
in
self
.
permissions_classes
]
authentication
=
authentication_cls
(
self
)
user
=
authentication
.
authenticate
(
self
.
request
)
if
user
:
return
user
return
AnonymousUser
()
# TODO: wrap this behavior around dispatch()
# TODO: wrap this behavior around dispatch()
def
_check_permissions
(
self
):
def
check_permissions
(
self
,
user
):
"""
"""
Check user permissions and either raise an ``ImmediateResponse`` or return.
Check user permissions and either raise an ``ImmediateResponse`` or return.
"""
"""
user
=
self
.
user
for
permission
in
self
.
get_permissions
():
for
permission_cls
in
self
.
permissions
:
permission
=
permission_cls
(
self
)
permission
.
check_permission
(
user
)
permission
.
check_permission
(
user
)
...
...
djangorestframework/request.py
View file @
afd49023
...
@@ -8,14 +8,15 @@ The wrapped request then offers a richer API, in particular :
...
@@ -8,14 +8,15 @@ The wrapped request then offers a richer API, in particular :
- full support of PUT method, including support for file uploads
- full support of PUT method, including support for file uploads
- form overloading of HTTP method, content type and content
- form overloading of HTTP method, content type and content
"""
"""
from
StringIO
import
StringIO
from
django.contrib.auth.models
import
AnonymousUser
from
djangorestframework.response
import
ImmediateResponse
from
djangorestframework.response
import
ImmediateResponse
from
djangorestframework
import
status
from
djangorestframework
import
status
from
djangorestframework.utils.mediatypes
import
is_form_media_type
from
djangorestframework.utils.mediatypes
import
is_form_media_type
from
djangorestframework.utils
import
as_tuple
from
djangorestframework.utils
import
as_tuple
from
StringIO
import
StringIO
__all__
=
(
'Request'
,)
__all__
=
(
'Request'
,)
...
@@ -27,6 +28,7 @@ class Request(object):
...
@@ -27,6 +28,7 @@ class Request(object):
Kwargs:
Kwargs:
- request(HttpRequest). The original request instance.
- request(HttpRequest). The original request instance.
- parsers(list/tuple). The parsers to use for parsing the request content.
- parsers(list/tuple). The parsers to use for parsing the request content.
- authentications(list/tuple). The authentications used to try authenticating the request's user.
"""
"""
_USE_FORM_OVERLOADING
=
True
_USE_FORM_OVERLOADING
=
True
...
@@ -34,10 +36,12 @@ class Request(object):
...
@@ -34,10 +36,12 @@ class Request(object):
_CONTENTTYPE_PARAM
=
'_content_type'
_CONTENTTYPE_PARAM
=
'_content_type'
_CONTENT_PARAM
=
'_content'
_CONTENT_PARAM
=
'_content'
def
__init__
(
self
,
request
=
None
,
parser
s
=
None
):
def
__init__
(
self
,
request
,
parsers
=
None
,
authentication
s
=
None
):
self
.
request
=
request
self
.
request
=
request
if
parsers
is
not
None
:
if
parsers
is
not
None
:
self
.
parsers
=
parsers
self
.
parsers
=
parsers
if
authentications
is
not
None
:
self
.
authentications
=
authentications
@property
@property
def
method
(
self
):
def
method
(
self
):
...
@@ -87,6 +91,16 @@ class Request(object):
...
@@ -87,6 +91,16 @@ class Request(object):
self
.
_load_data_and_files
()
self
.
_load_data_and_files
()
return
self
.
_files
return
self
.
_files
@property
def
user
(
self
):
"""
Returns the :obj:`user` for the current request, authenticated
with the set of :class:`authentication` instances applied to the :class:`Request`.
"""
if
not
hasattr
(
self
,
'_user'
):
self
.
_user
=
self
.
_authenticate
()
return
self
.
_user
def
_load_data_and_files
(
self
):
def
_load_data_and_files
(
self
):
"""
"""
Parses the request content into self.DATA and self.FILES.
Parses the request content into self.DATA and self.FILES.
...
@@ -192,6 +206,27 @@ class Request(object):
...
@@ -192,6 +206,27 @@ class Request(object):
parsers
=
property
(
_get_parsers
,
_set_parsers
)
parsers
=
property
(
_get_parsers
,
_set_parsers
)
def
_authenticate
(
self
):
"""
Attempt to authenticate the request using each authentication instance in turn.
Returns a ``User`` object, which may be ``AnonymousUser``.
"""
for
authentication
in
self
.
authentications
:
user
=
authentication
.
authenticate
(
self
)
if
user
:
return
user
return
AnonymousUser
()
def
_get_authentications
(
self
):
if
hasattr
(
self
,
'_authentications'
):
return
self
.
_authentications
return
()
def
_set_authentications
(
self
,
value
):
self
.
_authentications
=
value
authentications
=
property
(
_get_authentications
,
_set_authentications
)
def
__getattr__
(
self
,
name
):
def
__getattr__
(
self
,
name
):
"""
"""
When an attribute is not present on the calling instance, try to get it
When an attribute is not present on the calling instance, try to get it
...
...
djangorestframework/tests/authentication.py
View file @
afd49023
...
@@ -12,7 +12,7 @@ import base64
...
@@ -12,7 +12,7 @@ import base64
class
MockView
(
View
):
class
MockView
(
View
):
permissions
=
(
permissions
.
IsAuthenticated
,)
permissions
_classes
=
(
permissions
.
IsAuthenticated
,)
def
post
(
self
,
request
):
def
post
(
self
,
request
):
return
HttpResponse
({
'a'
:
1
,
'b'
:
2
,
'c'
:
3
})
return
HttpResponse
({
'a'
:
1
,
'b'
:
2
,
'c'
:
3
})
...
...
djangorestframework/tests/throttling.py
View file @
afd49023
...
@@ -13,17 +13,17 @@ from djangorestframework.resources import FormResource
...
@@ -13,17 +13,17 @@ from djangorestframework.resources import FormResource
from
djangorestframework.response
import
Response
from
djangorestframework.response
import
Response
class
MockView
(
View
):
class
MockView
(
View
):
permissions
=
(
PerUserThrottling
,
)
permissions
_classes
=
(
PerUserThrottling
,
)
throttle
=
'3/sec'
throttle
=
'3/sec'
def
get
(
self
,
request
):
def
get
(
self
,
request
):
return
Response
(
'foo'
)
return
Response
(
'foo'
)
class
MockView_PerViewThrottling
(
MockView
):
class
MockView_PerViewThrottling
(
MockView
):
permissions
=
(
PerViewThrottling
,
)
permissions
_classes
=
(
PerViewThrottling
,
)
class
MockView_PerResourceThrottling
(
MockView
):
class
MockView_PerResourceThrottling
(
MockView
):
permissions
=
(
PerResourceThrottling
,
)
permissions
_classes
=
(
PerResourceThrottling
,
)
resource
=
FormResource
resource
=
FormResource
class
MockView_MinuteThrottling
(
MockView
):
class
MockView_MinuteThrottling
(
MockView
):
...
@@ -54,7 +54,7 @@ class ThrottlingTests(TestCase):
...
@@ -54,7 +54,7 @@ class ThrottlingTests(TestCase):
"""
"""
Explicitly set the timer, overriding time.time()
Explicitly set the timer, overriding time.time()
"""
"""
view
.
permissions
[
0
]
.
timer
=
lambda
self
:
value
view
.
permissions
_classes
[
0
]
.
timer
=
lambda
self
:
value
def
test_request_throttling_expires
(
self
):
def
test_request_throttling_expires
(
self
):
"""
"""
...
...
djangorestframework/views.py
View file @
afd49023
...
@@ -69,7 +69,7 @@ _resource_classes = (
...
@@ -69,7 +69,7 @@ _resource_classes = (
)
)
class
View
(
ResourceMixin
,
RequestMixin
,
ResponseMixin
,
Auth
Mixin
,
DjangoView
):
class
View
(
ResourceMixin
,
RequestMixin
,
ResponseMixin
,
Permissions
Mixin
,
DjangoView
):
"""
"""
Handles incoming requests and maps them to REST operations.
Handles incoming requests and maps them to REST operations.
Performs request deserialization, response serialization, authentication and input validation.
Performs request deserialization, response serialization, authentication and input validation.
...
@@ -91,13 +91,13 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
...
@@ -91,13 +91,13 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
List of parser classes the resource can parse the request with.
List of parser classes the resource can parse the request with.
"""
"""
authentication
=
(
authentication
.
UserLoggedInAuthentication
,
authentication
_classes
=
(
authentication
.
UserLoggedInAuthentication
,
authentication
.
BasicAuthentication
)
authentication
.
BasicAuthentication
)
"""
"""
List of all authenticating methods to attempt.
List of all authenticating methods to attempt.
"""
"""
permissions
=
(
permissions
.
FullAnonAccess
,)
permissions
_classes
=
(
permissions
.
FullAnonAccess
,)
"""
"""
List of all permissions that must be checked.
List of all permissions that must be checked.
"""
"""
...
@@ -206,15 +206,15 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
...
@@ -206,15 +206,15 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
# all other authentication is CSRF exempt.
# all other authentication is CSRF exempt.
@csrf_exempt
@csrf_exempt
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
self
.
request
=
self
.
create_request
(
request
)
self
.
request
=
request
=
self
.
create_request
(
request
)
self
.
args
=
args
self
.
args
=
args
self
.
kwargs
=
kwargs
self
.
kwargs
=
kwargs
try
:
try
:
self
.
initial
(
request
,
*
args
,
**
kwargs
)
self
.
initial
(
request
,
*
args
,
**
kwargs
)
#
Authenticate and check request
has the relevant permissions
#
check that user
has the relevant permissions
self
.
_check_permissions
(
)
self
.
check_permissions
(
request
.
user
)
# Get the appropriate handler method
# Get the appropriate handler method
if
request
.
method
.
lower
()
in
self
.
http_method_names
:
if
request
.
method
.
lower
()
in
self
.
http_method_names
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment