mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-04 09:57:55 +03:00 
			
		
		
		
	Fix composable permissions
In some cases we end with an operation between two `OperandHolder`. This didn't work as it didn't knew how to deal with | or & This fixes by adding those operations.
This commit is contained in:
		
							parent
							
								
									0f5dfe8b3c
								
							
						
					
					
						commit
						74574217a4
					
				| 
						 | 
				
			
			@ -11,7 +11,21 @@ from rest_framework import exceptions
 | 
			
		|||
SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OperandHolder:
 | 
			
		||||
class OperationHolderMixin:
 | 
			
		||||
    def __and__(self, other):
 | 
			
		||||
        return OperandHolder(AND, self, other)
 | 
			
		||||
 | 
			
		||||
    def __or__(self, other):
 | 
			
		||||
        return OperandHolder(OR, self, other)
 | 
			
		||||
 | 
			
		||||
    def __rand__(self, other):
 | 
			
		||||
        return OperandHolder(AND, other, self)
 | 
			
		||||
 | 
			
		||||
    def __ror__(self, other):
 | 
			
		||||
        return OperandHolder(OR, other, self)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OperandHolder(OperationHolderMixin):
 | 
			
		||||
    def __init__(self, operator_class, op1_class, op2_class):
 | 
			
		||||
        self.operator_class = operator_class
 | 
			
		||||
        self.op1_class = op1_class
 | 
			
		||||
| 
						 | 
				
			
			@ -59,18 +73,8 @@ class OR:
 | 
			
		|||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BasePermissionMetaclass(type):
 | 
			
		||||
    def __and__(cls, other):
 | 
			
		||||
        return OperandHolder(AND, cls, other)
 | 
			
		||||
 | 
			
		||||
    def __or__(cls, other):
 | 
			
		||||
        return OperandHolder(OR, cls, other)
 | 
			
		||||
 | 
			
		||||
    def __rand__(cls, other):
 | 
			
		||||
        return OperandHolder(AND, other, cls)
 | 
			
		||||
 | 
			
		||||
    def __ror__(cls, other):
 | 
			
		||||
        return OperandHolder(OR, other, cls)
 | 
			
		||||
class BasePermissionMetaclass(OperationHolderMixin, type):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@six.add_metaclass(BasePermissionMetaclass)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -589,3 +589,14 @@ class PermissionsCompositionTests(TestCase):
 | 
			
		|||
            permissions.IsAuthenticated
 | 
			
		||||
        )
 | 
			
		||||
        assert composed_perm().has_permission(request, None) is True
 | 
			
		||||
 | 
			
		||||
    def test_several_levels_and_precedence(self):
 | 
			
		||||
        request = factory.get('/1', format='json')
 | 
			
		||||
        request.user = self.user
 | 
			
		||||
        composed_perm = (
 | 
			
		||||
            permissions.IsAuthenticated &
 | 
			
		||||
            permissions.IsAuthenticated |
 | 
			
		||||
            permissions.IsAuthenticated &
 | 
			
		||||
            permissions.IsAuthenticated
 | 
			
		||||
        )
 | 
			
		||||
        assert composed_perm().has_permission(request, None) is True
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user