Testing to whether a user can attach/unattach is now deferred to the model.

This commit is contained in:
Michael DeHaan 2013-03-23 14:31:36 -04:00
parent 4e7827829f
commit 0c9aa1a498
4 changed files with 42 additions and 12 deletions

View File

@ -22,7 +22,7 @@ class BaseList(generics.ListCreateAPIView):
if request.method == 'GET':
return True
if request.method == 'POST':
return False
return self.__class__.model.can_user_add(request.user)
raise exceptions.NotImplementedError
def get_queryset(self):
@ -32,6 +32,16 @@ class BaseSubList(BaseList):
''' used for subcollections with an overriden post '''
def list_permissions_check(self, request, obj=None):
''' determines some early yes/no access decisions, pre-filtering '''
if request.method == 'GET':
return True
if request.method == 'POST':
# the can_user_attach methods will be called below
return True
raise exceptions.NotImplementedError
def post(self, request, *args, **kwargs):
parent_id = kwargs['pk']

View File

@ -44,17 +44,24 @@ class CommonModel(models.Model):
def can_user_read(cls, user, obj):
raise exceptions.NotImplementedError()
@classmethod
def can_user_add(cls, user):
return user.is_superuser
@classmethod
def can_user_attach(cls, user, obj, sub_obj, relationship):
''' whether you can add sub_obj to obj using the relationship type in a subobject view '''
if relationship in [ 'projects', 'admins', 'users' ]:
if not sub_obj.can_user_read(user, sub_obj):
print "DEBUG: can't attach"
return False
print "DEBUG: defer"
return cls.can_user_administrate(user, obj)
raise Exception("unknown relationship type: %s" % relationship)
@classmethod
def can_user_unattach(cls, user, obj, relationship):
def can_user_unattach(cls, user, obj, sub_obj, relationship):
print "DEBUG: CUA?"
return cls.can_user_administrate(user, obj)
class Tag(models.Model):

View File

@ -13,6 +13,7 @@ class CustomRbac(permissions.BasePermission):
# no anonymous users
if request.user.is_anonymous():
# 401, not 403, hence no raised exception
print "PD4"
return False
# superusers are always good
if request.user.is_superuser:
@ -30,6 +31,7 @@ class CustomRbac(permissions.BasePermission):
if request.user.is_superuser:
return True
if not view.list_permissions_check(request):
print "DEBUG: PD1"
raise PermissionDenied()
elif not getattr(view, 'item_permissions_check', None):
raise Exception("internal error, list_permissions_check or item_permissions_check must be defined")
@ -42,9 +44,11 @@ class CustomRbac(permissions.BasePermission):
if request.user.is_superuser:
return True
if not self._common_user_check(request):
print "DEBUG: PD2"
return False
if not obj.active:
raise Http404()
if not view.item_permissions_check(request, obj):
print "DEBUG: PD3"
raise PermissionDenied()
return True

View File

@ -273,33 +273,42 @@ class OrganizationsTest(BaseTest):
# find projects attached to the first org
projects0_url = orgs['results'][0]['related']['projects']
projects7_url = orgs['results'][1]['related']['projects']
projects1_url = orgs['results'][1]['related']['projects']
# get all the projects on the first org
projects0 = self.get(projects0_url, expect=200, auth=self.get_super_credentials())
a_project = projects0['results'][-1]
# attempt to add the project to the 7th org and see what happens
self.post(projects7_url, a_project, expect=204, auth=self.get_super_credentials())
self.post(projects1_url, a_project, expect=204, auth=self.get_super_credentials())
projects1 = self.get(projects0_url, expect=200, auth=self.get_super_credentials())
self.assertEquals(projects1['count'], 3)
# make sure we can't add the project again (should generate a conflict error)
self.post(projects7_url, a_project, expect=409, auth=self.get_super_credentials())
projects7 = self.get(projects7_url, expect=200, auth=self.get_super_credentials())
self.assertEquals(projects7['count'], 6)
self.post(projects1_url, a_project, expect=409, auth=self.get_super_credentials())
projects1 = self.get(projects1_url, expect=200, auth=self.get_super_credentials())
self.assertEquals(projects1['count'], 6)
# make sure adding a project that does not exist, or a missing pk field, results in a 400
self.post(projects7_url, dict(id=99999), expect=400, auth=self.get_super_credentials())
self.post(projects7_url, dict(asdf=1234), expect=400, auth=self.get_super_credentials())
self.post(projects1_url, dict(id=99999), expect=400, auth=self.get_super_credentials())
self.post(projects1_url, dict(asdf=1234), expect=400, auth=self.get_super_credentials())
# test that by posting a pk + disassociate: True we can remove a relationship
a_project['disassociate'] = True
self.post(projects7_url, a_project, expect=204, auth=self.get_super_credentials())
projects7 = self.get(projects7_url, expect=200, auth=self.get_super_credentials())
self.assertEquals(projects7['count'], 5)
self.post(projects1_url, a_project, expect=204, auth=self.get_super_credentials())
projects1 = self.get(projects1_url, expect=200, auth=self.get_super_credentials())
self.assertEquals(projects1['count'], 5)
# FIXME: need to add tests for associating and disassocating from a non-priveledged acct
print projects1_url
a_project = projects1['results'][-1]
a_project['disassociate'] = 1
projects1 = self.get(projects1_url, expect=200, auth=self.get_super_credentials())
print "GOT: %s" % projects1
print "POSTING: %s" % a_project
self.post(projects1_url, a_project, expect=204, auth=self.get_normal_credentials())
projects1 = self.get(projects1_url, expect=200, auth=self.get_super_credentials())
self.assertEquals(projects1['count'], 4)
def test_post_item_subobjects_users(self):
pass