From b68ab024ec1d497793dc437eb34dc2280fcc9857 Mon Sep 17 00:00:00 2001 From: Michael DeHaan Date: Sat, 23 Mar 2013 16:03:17 -0400 Subject: [PATCH] Listing tags attached to an organization, and basic model/view things around tag details --- lib/main/base_views.py | 8 ++++++-- lib/main/models/__init__.py | 9 ++++++--- lib/main/tests.py | 17 ++++++++++++++++- lib/main/views.py | 32 ++++++++++++++++++++++++++++---- lib/urls.py | 3 +++ 5 files changed, 59 insertions(+), 10 deletions(-) diff --git a/lib/main/base_views.py b/lib/main/base_views.py index cc16e68994..46629a5a21 100644 --- a/lib/main/base_views.py +++ b/lib/main/base_views.py @@ -26,8 +26,12 @@ class BaseList(generics.ListCreateAPIView): raise exceptions.NotImplementedError def get_queryset(self): - if self.__class__.model == User: - return self._get_queryset().filter(is_active=True) + base = self._get_queryset() + model = self.__class__.model + if model == User: + return base.filter(is_active=True) + elif model in [ Tag, AuditTrail ]: + return base else: return self._get_queryset().filter(active=True) diff --git a/lib/main/models/__init__.py b/lib/main/models/__init__.py index 7f9815e5a6..de32fbae31 100644 --- a/lib/main/models/__init__.py +++ b/lib/main/models/__init__.py @@ -24,8 +24,8 @@ class CommonModel(models.Model): description = models.TextField(blank=True, default='') created_by = models.ForeignKey('auth.User', on_delete=SET_NULL, null=True, related_name='%s(class)s_created') # not blank=False on purpose for admin! creation_date = models.DateField(auto_now_add=True) - tags = models.ManyToManyField('Tag', related_name='%(class)s_tags', blank=True) - audit_trail = models.ManyToManyField('AuditTrail', related_name='%(class)s_audit_trails', blank=True) + tags = models.ManyToManyField('Tag', related_name='%(class)s_by_tag', blank=True) + audit_trail = models.ManyToManyField('AuditTrail', related_name='%(class)s_by_audit_trail', blank=True) active = models.BooleanField(default=True) def __unicode__(self): @@ -75,7 +75,10 @@ class Tag(models.Model): def __unicode__(self): return unicode(self.name) - + + def get_absolute_url(self): + import lib.urls + return reverse(lib.urls.views_TagsDetail, args=(self.pk,)) class AuditTrail(CommonModel): ''' diff --git a/lib/main/tests.py b/lib/main/tests.py index d81b6ac82b..14283745fe 100644 --- a/lib/main/tests.py +++ b/lib/main/tests.py @@ -257,7 +257,22 @@ class OrganizationsTest(BaseTest): self.assertEquals(org1_users['count'], 1) def test_get_item_subobjects_tags(self): - pass + + # put some tags on the org + org1 = Organization.objects.get(pk=2) + tag1 = Tag.objects.create(name='atag') + tag2 = Tag.objects.create(name='btag') + org1.tags.add(tag1) + org1.tags.add(tag2) + + # see if we can list the users added to the organization + orgs = self.get(self.collection(), expect=200, auth=self.get_super_credentials()) + org1_tags_url = orgs['results'][1]['related']['tags'] + org1_tags = self.get(org1_tags_url, expect=200, auth=self.get_normal_credentials()) + self.assertEquals(org1_tags['count'], 2) + org1_tags = self.get(org1_tags_url, expect=200, auth=self.get_super_credentials()) + self.assertEquals(org1_tags['count'], 2) + org1_tags = self.get(org1_tags_url, expect=403, auth=self.get_other_credentials()) def test_get_item_subobjects_audit_trail(self): pass diff --git a/lib/main/views.py b/lib/main/views.py index e0f14c36fa..4976637629 100644 --- a/lib/main/views.py +++ b/lib/main/views.py @@ -48,12 +48,15 @@ class OrganizationsAuditTrailList(BaseList): serializer_class = AuditTrailSerializer permission_classes = (CustomRbac,) -class OrganizationsUsersList(BaseList): +class OrganizationsUsersList(BaseSubList): model = User serializer_class = UserSerializer permission_classes = (CustomRbac,) + parent_model = Organization + relationship = 'users' + def _get_queryset(self): ''' to list users in the organization, I must be a superuser or org admin ''' organization = Organization.objects.get(pk=self.kwargs['pk']) @@ -61,11 +64,14 @@ class OrganizationsUsersList(BaseList): raise PermissionDenied() return User.objects.filter(organizations__in = [ organization ]) -class OrganizationsAdminsList(BaseList): +class OrganizationsAdminsList(BaseSubList): model = User serializer_class = UserSerializer permission_classes = (CustomRbac,) + + parent_model = Organization + relationship = 'admins' def _get_queryset(self): ''' to list admins in the organization, I must be a superuser or org admin ''' @@ -91,8 +97,21 @@ class OrganizationsProjectsList(BaseSubList): return Project.objects.filter(organizations__in = [ organization ]) class OrganizationsTagsList(BaseList): - # FIXME: guts & tests - pass + + model = Tag + serializer_class = TagSerializer + permission_classes = (CustomRbac,) + + parent_model = Organization # for sub list + relationship = 'tags' # " " + + def _get_queryset(self): + ''' to list tags in the organization, I must be a superuser or org admin ''' + organization = Organization.objects.get(pk=self.kwargs['pk']) + if not (self.request.user.is_superuser or self.request.user in organization.admins.all()): + # FIXME: use: organization.can_user_administrate(self.request.user) + raise PermissionDenied() + return Tag.objects.filter(organization_by_tag__in = [ organization ]) class ProjectsDetail(BaseDetail): @@ -100,5 +119,10 @@ class ProjectsDetail(BaseDetail): serializer_class = ProjectSerializer permission_classes = (CustomRbac,) +class TagsDetail(BaseDetail): + + model = Tag + serializer_class = TagSerializer + permission_classes = (CustomRbac,) diff --git a/lib/urls.py b/lib/urls.py index 6718662195..84b5e96104 100644 --- a/lib/urls.py +++ b/lib/urls.py @@ -26,6 +26,7 @@ views_ProjectsDetail = views.OrganizationsDetail.as_view() # events services # jobs services # tags service +views_TagsDetail = views.TagsDetail.as_view() urlpatterns = patterns('', @@ -64,6 +65,8 @@ urlpatterns = patterns('', # jobs services # tags service + url(r'^api/v1/tags/(?P[0-9]+)/$', views_TagsDetail), + ) if 'django.contrib.admin' in settings.INSTALLED_APPS: