Skip to content

Instantly share code, notes, and snippets.

@flashingpumpkin
Last active December 26, 2015 03:39
Show Gist options
  • Save flashingpumpkin/7087473 to your computer and use it in GitHub Desktop.
Save flashingpumpkin/7087473 to your computer and use it in GitHub Desktop.
from pretend import stub
class Comparison(object):
def __or__(self, other):
return Or(self, other)
def __and__(self, other):
return And(self, other)
def __call__(self):
return self
class And(Comparison):
def __init__(self, this, that):
self.this = this
self.that = that
def has_object_permission(self, request, view, obj):
return (self.this().has_object_permission(request, view, obj)
and self.that().has_object_permission(request, view, obj))
class Or(Comparison):
def __init__(self, this, that):
self.this = this
self.that = that
def has_object_permission(self, request, view, obj):
return (self.this().has_object_permission(request, view, obj)
or self.that().has_object_permission(request, view, obj))
class BitwiseMeta(type):
def __or__(self, other):
return Or(self, other)
def __and__(self, other):
return And(self, other)
class BitwisePermission(object):
"""
Enables composable permissions with bitwise operators, such as:
permission_classes = (
IsOwner |
(IsPublic & IsRead) |
(IsUser & IsRead) |
(IsAlen & IsRead)
)
"""
__metaclass__ = BitwiseMeta
class IsPublic(BitwisePermission):
def has_object_permission(self, request, view, obj):
return obj.is_public
class IsOwner(BitwisePermission):
def has_object_permission(self, request, view, obj):
return request.user == obj.user
class IsUser(BitwisePermission):
def has_object_permission(self, request, view, obj):
return request.user in obj.users
class IsAlen(BitwisePermission):
def has_object_permission(self, request, view, obj):
return request.user.username == "alen"
class IsRead(BitwisePermission):
def has_object_permission(self, request, view, obj):
return request.method == "GET"
alen = stub(username='alen')
tom = stub(username='tom')
greg = stub(username='greg')
pin = stub(user=greg, users =[tom, greg], is_public=False)
permission = IsOwner | (IsPublic & IsRead) | (IsUser & IsRead) | (IsAlen & IsRead)
request = stub(user=alen, method="POST")
assert permission().has_object_permission(request, None, pin) == False
request.method = "GET"
assert permission().has_object_permission(request, None, pin)
request.user = tom
assert permission().has_object_permission(request, None, pin)
request.user = stub(username="Someone else")
request.method = "POST"
pin.is_public = True
assert permission().has_object_permission(request, None, pin) == False
request.method = "GET"
assert permission().has_object_permission(request, None, pin)
request.user = greg
request.is_public = False
assert permission().has_object_permission(request, None, pin)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment