Inital pass at generic permissions, throttling etc.

This commit is contained in:
Tom Christie 2011-04-27 18:08:32 +01:00
parent 028851bfa1
commit 659898ffaf
2 changed files with 112 additions and 0 deletions

View File

@ -0,0 +1,74 @@
from django.core.cache import cache
from djangorestframework import status
import time
class BasePermission(object):
"""A base class from which all permission classes should inherit."""
def __init__(self, view):
self.view = view
def has_permission(self, auth):
return True
class IsAuthenticated(BasePermission):
""""""
def has_permission(self, auth):
return auth is not None and auth.is_authenticated()
#class IsUser(BasePermission):
# """The request has authenticated as a user."""
# def has_permission(self, auth):
# pass
#
#class IsAdminUser():
# """The request has authenticated as an admin user."""
# def has_permission(self, auth):
# pass
#
#class IsUserOrIsAnonReadOnly(BasePermission):
# """The request has authenticated as a user, or is a read-only request."""
# def has_permission(self, auth):
# pass
#
#class OAuthTokenInScope(BasePermission):
# def has_permission(self, auth):
# pass
#
#class UserHasModelPermissions(BasePermission):
# def has_permission(self, auth):
# pass
class Throttling(BasePermission):
"""Rate throttling of requests on a per-user basis.
The rate is set by a 'throttle' attribute on the view class.
The attribute is a two tuple of the form (number of requests, duration in seconds).
The user's id will be used as a unique identifier if the user is authenticated.
For anonymous requests, the IP address of the client will be used.
Previous request information used for throttling is stored in the cache.
"""
def has_permission(self, auth):
(num_requests, duration) = getattr(self.view, 'throttle', (0, 0))
if auth.is_authenticated():
ident = str(auth)
else:
ident = self.view.request.META.get('REMOTE_ADDR', None)
key = 'throttle_%s' % ident
history = cache.get(key, [])
now = time.time()
# Drop any requests from the history which have now passed the throttle duration
while history and history[0] < now - duration:
history.pop()
if len(history) >= num_requests:
raise ErrorResponse(status.HTTP_503_SERVICE_UNAVAILABLE, {'detail': 'request was throttled'})
history.insert(0, now)
cache.set(key, history, duration)

View File

@ -0,0 +1,38 @@
from django.conf.urls.defaults import patterns
from django.test import TestCase
from django.utils import simplejson as json
from djangorestframework.compat import RequestFactory
from djangorestframework.resource import Resource
from djangorestframework.permissions import Throttling
class MockResource(Resource):
permissions = ( Throttling, )
throttle = (3, 1) # 3 requests per second
def get(self, request):
return 'foo'
urlpatterns = patterns('',
(r'^$', MockResource.as_view()),
)
#class ThrottlingTests(TestCase):
# """Basic authentication"""
# urls = 'djangorestframework.tests.throttling'
#
# def test_requests_are_throttled(self):
# """Ensure request rate is limited"""
# for dummy in range(3):
# response = self.client.get('/')
# response = self.client.get('/')
#
# def test_request_throttling_is_per_user(self):
# """Ensure request rate is only limited per user, not globally"""
# pass
#
# def test_request_throttling_expires(self):
# """Ensure request rate is limited for a limited duration only"""
# pass