From dbfd764acde317a6885355af316beb2510903b28 Mon Sep 17 00:00:00 2001 From: Michael DeHaan Date: Mon, 25 Mar 2013 19:00:07 -0400 Subject: [PATCH] Improve the can_user_add model hook to allow it to pre-examine data for context. --- lib/main/base_views.py | 2 +- lib/main/models/__init__.py | 22 ++++++++++++++++++---- lib/main/serializers.py | 2 +- lib/main/tests/inventory.py | 16 +++++++++++++--- lib/main/views.py | 2 -- 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/lib/main/base_views.py b/lib/main/base_views.py index 418be0e752..b8d3ac6bb5 100644 --- a/lib/main/base_views.py +++ b/lib/main/base_views.py @@ -44,7 +44,7 @@ class BaseList(generics.ListCreateAPIView): # org admins are allowed to create users return self.request.user.is_superuser or (self.request.user.admin_of_organizations.count() > 0) else: - return self.__class__.model.can_user_add(request.user) + return self.__class__.model.can_user_add(request.user, self.request.DATA) raise exceptions.NotImplementedError def get_queryset(self): diff --git a/lib/main/models/__init__.py b/lib/main/models/__init__.py index c82a0dd2e5..96a146bac3 100644 --- a/lib/main/models/__init__.py +++ b/lib/main/models/__init__.py @@ -157,7 +157,7 @@ class CommonModel(models.Model): raise exceptions.NotImplementedError() @classmethod - def can_user_add(cls, user): + def can_user_add(cls, user, data): return user.is_superuser @classmethod @@ -191,7 +191,7 @@ class Tag(models.Model): return reverse(lib.urls.views_TagsDetail, args=(self.pk,)) @classmethod - def can_user_add(cls, user): + def can_user_add(cls, user, data): # anybody can make up tags return True @@ -284,7 +284,7 @@ class Inventory(CommonModel): def _has_permission_types(cls, user, obj, allowed): if user.is_superuser: return True - by_org_admin = user in obj.organization.admins.all() + by_org_admin = obj.organization.admins.filter(pk = user.pk).count() by_team_permission = obj.permissions.filter( team__in = user.teams.all(), permission_type__in = allowed @@ -293,7 +293,21 @@ class Inventory(CommonModel): user = user, permission_type__in = allowed ).count() - return (by_org_admin + by_team_permission + by_user_permission) > 0 + + result = (by_org_admin + by_team_permission + by_user_permission) + return result > 0 + + @classmethod + def can_user_add(cls, user, data): + if not 'organization' in data: + return False + if user.is_superuser: + return True + if not user.is_superuser: + org = Organization.objects.get(pk=data['organization']) + if user in org.admins.all(): + return True + return False @classmethod def can_user_administrate(cls, user, obj): diff --git a/lib/main/serializers.py b/lib/main/serializers.py index 186596755a..3b6af2e094 100644 --- a/lib/main/serializers.py +++ b/lib/main/serializers.py @@ -87,7 +87,7 @@ class InventorySerializer(BaseSerializer): class Meta: model = Inventory - fields = ('url', 'id', 'name', 'description', 'creation_date') + fields = ('url', 'id', 'name', 'description', 'creation_date', 'organization') def get_related(self, obj): # FIXME: add related resources: inventories diff --git a/lib/main/tests/inventory.py b/lib/main/tests/inventory.py index d71aef75e9..f8baed1bb8 100644 --- a/lib/main/tests/inventory.py +++ b/lib/main/tests/inventory.py @@ -91,13 +91,23 @@ class InventoryTest(BaseTest): data = self.get(inventories_2, expect=403, auth=self.get_nobody_credentials()) # a super user can create inventory - - # self.post(url, expect=401, data=new_user, auth=None) + new_inv_1 = dict(name='inventory-c', description='baz', organization=1) + data = self.post(inventories, data=new_inv_1, expect=201, auth=self.get_super_credentials()) + self.assertEquals(data['id'], 3) # an org admin of any org can create inventory, if it is one of his organizations - # the organization parameter is required + # the organization parameter is required! + new_inv_incomplete = dict(name='inventory-d', description='baz') + data = self.post(inventories, data=new_inv_incomplete, expect=403, auth=self.get_normal_credentials()) + new_inv_not_my_org = dict(name='inventory-d', description='baz', organization=3) + + data = self.post(inventories, data=new_inv_not_my_org, expect=403, auth=self.get_normal_credentials()) + new_inv_my_org = dict(name='inventory-d', description='baz', organization=1) + data = self.post(inventories, data=new_inv_my_org, expect=201, auth=self.get_normal_credentials()) # a regular user cannot create inventory + new_inv_denied = dict(name='inventory-e', description='glorp', organization=1) + data = self.post(inventories, data=new_inv_denied, expect=403, auth=self.get_other_credentials()) # a super user can add hosts diff --git a/lib/main/views.py b/lib/main/views.py index 3ebd5900d6..04f1c64f52 100644 --- a/lib/main/views.py +++ b/lib/main/views.py @@ -282,5 +282,3 @@ class InventoryDetail(BaseDetail): serializer_class = InventorySerializer permission_classes = (CustomRbac,) - -