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
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
78 additions
and
53 deletions
+78
-53
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
+6
-6
No files found.
djangorestframework/authentication.py
View file @
afd49023
...
...
@@ -88,13 +88,14 @@ class UserLoggedInAuthentication(BaseAuthentication):
Otherwise returns :const:`None`.
"""
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.
resp
=
CsrfViewMiddleware
()
.
process_view
(
request
,
None
,
(),
{})
if
resp
is
None
:
# csrf passed
return
request
.
user
return
user
return
None
...
...
djangorestframework/mixins.py
View file @
afd49023
...
...
@@ -3,7 +3,6 @@ The :mod:`mixins` module provides a set of reusable `mixin`
classes that can be added to a `View`.
"""
from
django.contrib.auth.models
import
AnonymousUser
from
django.core.paginator
import
Paginator
from
django.db.models.fields.related
import
ForeignKey
from
urlobject
import
URLObject
...
...
@@ -19,7 +18,7 @@ __all__ = (
# Base behavior mixins
'RequestMixin'
,
'ResponseMixin'
,
'
Auth
Mixin'
,
'
Permissions
Mixin'
,
'ResourceMixin'
,
# Reverse URL lookup behavior
'InstanceMixin'
,
...
...
@@ -45,6 +44,13 @@ class RequestMixin(object):
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
"""
The class to use as a wrapper for the original request object.
...
...
@@ -56,6 +62,12 @@ class RequestMixin(object):
"""
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
):
"""
Creates and returns an instance of :class:`request.Request`.
...
...
@@ -63,7 +75,9 @@ class RequestMixin(object):
parsers set on the view.
"""
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
def
_parsed_media_types
(
self
):
...
...
@@ -134,57 +148,32 @@ class ResponseMixin(object):
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
=
()
"""
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
=
()
permissions_classes
=
()
"""
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.
"""
@property
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
):
def
get_permissions
(
self
):
"""
Attempt to authenticate the request using each authentication class in turn.
Returns a ``User`` object, which may be ``AnonymousUser``.
Instantiates and returns the list of permissions that this view requires.
"""
for
authentication_cls
in
self
.
authentication
:
authentication
=
authentication_cls
(
self
)
user
=
authentication
.
authenticate
(
self
.
request
)
if
user
:
return
user
return
AnonymousUser
()
return
[
p
(
self
)
for
p
in
self
.
permissions_classes
]
# 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.
"""
user
=
self
.
user
for
permission_cls
in
self
.
permissions
:
permission
=
permission_cls
(
self
)
for
permission
in
self
.
get_permissions
():
permission
.
check_permission
(
user
)
...
...
djangorestframework/request.py
View file @
afd49023
...
...
@@ -8,14 +8,15 @@ The wrapped request then offers a richer API, in particular :
- full support of PUT method, including support for file uploads
- 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
import
status
from
djangorestframework.utils.mediatypes
import
is_form_media_type
from
djangorestframework.utils
import
as_tuple
from
StringIO
import
StringIO
__all__
=
(
'Request'
,)
...
...
@@ -27,6 +28,7 @@ class Request(object):
Kwargs:
- request(HttpRequest). The original request instance.
- 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
...
...
@@ -34,10 +36,12 @@ class Request(object):
_CONTENTTYPE_PARAM
=
'_content_type'
_CONTENT_PARAM
=
'_content'
def
__init__
(
self
,
request
=
None
,
parser
s
=
None
):
def
__init__
(
self
,
request
,
parsers
=
None
,
authentication
s
=
None
):
self
.
request
=
request
if
parsers
is
not
None
:
self
.
parsers
=
parsers
if
authentications
is
not
None
:
self
.
authentications
=
authentications
@property
def
method
(
self
):
...
...
@@ -87,6 +91,16 @@ class Request(object):
self
.
_load_data_and_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
):
"""
Parses the request content into self.DATA and self.FILES.
...
...
@@ -192,6 +206,27 @@ class Request(object):
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
):
"""
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
class
MockView
(
View
):
permissions
=
(
permissions
.
IsAuthenticated
,)
permissions
_classes
=
(
permissions
.
IsAuthenticated
,)
def
post
(
self
,
request
):
return
HttpResponse
({
'a'
:
1
,
'b'
:
2
,
'c'
:
3
})
...
...
djangorestframework/tests/throttling.py
View file @
afd49023
...
...
@@ -13,17 +13,17 @@ from djangorestframework.resources import FormResource
from
djangorestframework.response
import
Response
class
MockView
(
View
):
permissions
=
(
PerUserThrottling
,
)
permissions
_classes
=
(
PerUserThrottling
,
)
throttle
=
'3/sec'
def
get
(
self
,
request
):
return
Response
(
'foo'
)
class
MockView_PerViewThrottling
(
MockView
):
permissions
=
(
PerViewThrottling
,
)
permissions
_classes
=
(
PerViewThrottling
,
)
class
MockView_PerResourceThrottling
(
MockView
):
permissions
=
(
PerResourceThrottling
,
)
permissions
_classes
=
(
PerResourceThrottling
,
)
resource
=
FormResource
class
MockView_MinuteThrottling
(
MockView
):
...
...
@@ -54,7 +54,7 @@ class ThrottlingTests(TestCase):
"""
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
):
"""
...
...
djangorestframework/views.py
View file @
afd49023
...
...
@@ -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.
Performs request deserialization, response serialization, authentication and input validation.
...
...
@@ -91,13 +91,13 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
List of parser classes the resource can parse the request with.
"""
authentication
=
(
authentication
.
UserLoggedInAuthentication
,
authentication
_classes
=
(
authentication
.
UserLoggedInAuthentication
,
authentication
.
BasicAuthentication
)
"""
List of all authenticating methods to attempt.
"""
permissions
=
(
permissions
.
FullAnonAccess
,)
permissions
_classes
=
(
permissions
.
FullAnonAccess
,)
"""
List of all permissions that must be checked.
"""
...
...
@@ -206,15 +206,15 @@ class View(ResourceMixin, RequestMixin, ResponseMixin, AuthMixin, DjangoView):
# all other authentication is CSRF exempt.
@csrf_exempt
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
self
.
request
=
self
.
create_request
(
request
)
self
.
request
=
request
=
self
.
create_request
(
request
)
self
.
args
=
args
self
.
kwargs
=
kwargs
try
:
self
.
initial
(
request
,
*
args
,
**
kwargs
)
#
Authenticate and check request
has the relevant permissions
self
.
_check_permissions
(
)
#
check that user
has the relevant permissions
self
.
check_permissions
(
request
.
user
)
# Get the appropriate handler method
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