mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-04 01:47:59 +03:00 
			
		
		
		
	Inital pass at generic permissions, throttling etc.
This commit is contained in:
		
							parent
							
								
									028851bfa1
								
							
						
					
					
						commit
						659898ffaf
					
				
							
								
								
									
										74
									
								
								djangorestframework/permissions.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								djangorestframework/permissions.py
									
									
									
									
									
										Normal 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)        
 | 
			
		||||
							
								
								
									
										38
									
								
								djangorestframework/tests/throttling.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								djangorestframework/tests/throttling.py
									
									
									
									
									
										Normal 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
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user