Last active
December 26, 2015 03:39
-
-
Save flashingpumpkin/7087473 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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