Start tags app API refactor

Signed-off-by: Roberto Rosario <Roberto.Rosario@mayan-edms.com>
This commit is contained in:
Roberto Rosario
2019-02-06 05:20:42 -04:00
parent ea3ba2c4de
commit 278f97b7e4
5 changed files with 250 additions and 471 deletions

View File

@@ -1,7 +1,9 @@
from __future__ import absolute_import, unicode_literals
from rest_framework import generics, status
from rest_framework.decorators import action
from drf_yasg.utils import swagger_auto_schema
from rest_framework import generics, serializers, status, routers, viewsets
from rest_framework.decorators import action, detail_route
from rest_framework.exceptions import ValidationError
from rest_framework.response import Response
@@ -10,12 +12,7 @@ from mayan.apps.documents.api_views import DocumentViewSet
from mayan.apps.documents.models import Document
from mayan.apps.documents.permissions import permission_document_view
from mayan.apps.documents.serializers import DocumentSerializer
from mayan.apps.rest_api.filters import MayanObjectPermissionsFilter
from mayan.apps.rest_api.generics import (
ListAPIView, ListCreateAPIView, RetrieveDestroyAPIView,
RetrieveUpdateDestroyAPIView
)
from mayan.apps.rest_api.permissions import MayanPermission
from mayan.apps.rest_api.viewsets import MayanAPIModelViewSet
from .models import Tag
from .permissions import (
@@ -23,121 +20,84 @@ from .permissions import (
permission_tag_edit, permission_tag_remove, permission_tag_view
)
from .serializers import (
DocumentTagAttachSerializer, DocumentTagSerializer, TagAttachSerializer,
TagRemoveSerializer, TagSerializer,
DocumentTagAttachSerializer, DocumentTagSerializer,
TagDocumentAttachRemoveSerializer,
TagSerializer,
)
from django.conf.urls import url, include
from django.contrib.auth.models import User
from rest_framework import routers, serializers, viewsets
from rest_framework.decorators import detail_route
from rest_framework.response import Response
from drf_yasg.utils import swagger_auto_schema
class TagViewSet(viewsets.ModelViewSet):
filter_backends = (MayanObjectPermissionsFilter,)
lookup_field = 'pk'
class TagViewSet(MayanAPIModelViewSet):
lookup_url_kwarg='tag_id'
permission_classes = (MayanPermission,)
object_permission_map = {
'destroy': permission_tag_delete,
'document_attach': permission_tag_attach,
'document_list': permission_tag_view,
'document_remove': permission_tag_remove,
'list': permission_tag_view,
'partial_update': permission_tag_edit,
'update': permission_tag_edit
}
queryset = Tag.objects.all()
serializer_class = TagSerializer
view_permission_map = {
'create': permission_tag_create
}
#@swagger_auto_schema(operation_description='GET /articles/today/')
@swagger_auto_schema(
operation_description="partial_update description override", responses={200: TagAttachSerializer}
)
@action(
detail=True, lookup_field='pk', lookup_url_kwarg='tag_id',
methods=('post',), serializer_class=TagAttachSerializer,
url_name='document-attach', url_path='attach'
detail=True, lookup_url_kwarg='tag_id', methods=('post',),
serializer_class=TagDocumentAttachRemoveSerializer,
url_name='document-attach', url_path='documents/attach'
)
def attach(self, request, *args, **kwargs):
#print '!!! attach', args, kwargs#, self.context
#return Response({})
def document_attach(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
#print '((((((((', serializer.validated_data
#self.perform_attach(serializer=serializer)
serializer.attach(instance=self.get_object())
serializer.attach(instance=instance)
headers = self.get_success_headers(data=serializer.data)
return Response(
serializer.data, status=status.HTTP_200_OK, headers=headers
)
#def perform_attach(self, serializer):
# #print '!!!!', serializer
# serializer.attach(instance=self.get_object())
#def get_success_headers(self, data):
# try:
# return {'Location': str(data[api_settings.URL_FIELD_NAME])}
# except (TypeError, KeyError):
# return {}
@action(
detail=True, lookup_field='pk', lookup_url_kwarg='tag_id',
url_name='document-list', url_path='documents'
detail=True, lookup_url_kwarg='tag_id',
serializer_class=DocumentSerializer, url_name='document-list',
url_path='documents'
)
def document_list(self, request, *args, **kwargs):
queryset = self.get_object().documents.all()
#TODO:Filter queryset
#queryset = self.filter_queryset(self.get_queryset())
queryset = self.get_object().get_documents(user=self.request.user)
page = self.paginate_queryset(queryset)
serializer = self.get_serializer(
queryset, many=True, context={'request': request}
)
if page is not None:
#serializer = self.get_serializer(page, many=True)
serializer = DocumentSerializer(page, many=True, context={'request': request})
return self.get_paginated_response(serializer.data)
#serializer = self.get_serializer(queryset, many=True)
serializer = DocumentSerializer(queryset, many=True, context={'request': request})
return Response(serializer.data)
#serializer = DocumentSerializer(
# instance=, many=True,
# context={'request': request}
#)
#return Response(serializer.data)
@action(
detail=True, lookup_field='pk', lookup_url_kwarg='tag_id',
methods=('post',), serializer_class=TagRemoveSerializer,
url_name='document-remove', url_path='remove'
methods=('post',), serializer_class=TagDocumentAttachRemoveSerializer,
url_name='document-remove', url_path='documents/remove'
)
def remove(self, request, *args, **kwargs):
#print '!!! attach', args, kwargs#, self.context
#return Response({})
def document_remove(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
#print '((((((((', serializer.validated_data
#self.perform_attach(serializer=serializer)
serializer.remove(instance=self.get_object())
serializer.attach(instance=instance)
headers = self.get_success_headers(data=serializer.data)
return Response(
serializer.data, status=status.HTTP_200_OK, headers=headers
)
#def get_serializer_class(self, *args, **kwargs):
# #if self.action == 'attach':
# print '!!!!get_serializer_class', args, kwargs
# return TagAttachSerializer
class DocumentTagViewSet(ExternalObjectMixin, viewsets.ReadOnlyModelViewSet):
external_object_class = Document
external_object_pk_url_kwarg = 'document_id'
external_object_permission = permission_tag_view
lookup_field = 'pk'
#lookup_field = 'pk'
object_permission = {
'list': permission_document_view,
'retrieve': permission_document_view
@@ -145,7 +105,8 @@ class DocumentTagViewSet(ExternalObjectMixin, viewsets.ReadOnlyModelViewSet):
serializer_class = DocumentTagSerializer
@action(
detail=True, lookup_field='pk', lookup_url_kwarg='document_id',
#detail=True, lookup_field='pk', lookup_url_kwarg='document_id',
detail=True, lookup_url_kwarg='document_id',
methods=('post',), serializer_class=DocumentTagAttachSerializer,
url_name='tag-attach', url_path='attach'
)

View File

@@ -65,7 +65,7 @@ class Tag(models.Model):
Return a filtered queryset documents that have this tag attached.
"""
return AccessControlList.objects.restrict_queryset(
permission=permission_document_view, queryset=self.documents,
permission=permission_document_view, queryset=self.documents.all(),
user=user
)

View File

@@ -1,5 +1,6 @@
from __future__ import absolute_import, unicode_literals
from django.core.exceptions import ImproperlyConfigured
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
@@ -9,7 +10,7 @@ from rest_framework.reverse import reverse
from mayan.apps.acls.models import AccessControlList
from mayan.apps.documents.models import Document
from mayan.apps.documents.serializers import DocumentSerializer
from mayan.apps.rest_api.relations import MultiKwargHyperlinkedIdentityField
from mayan.apps.rest_api.mixins import ExternalObjectListSerializerMixin
from .models import Tag
from .permissions import permission_tag_attach
@@ -42,55 +43,6 @@ class TagSerializer(serializers.HyperlinkedModelSerializer):
model = Tag
"""
class WritableTagSerializer(serializers.ModelSerializer):
documents_pk_list = serializers.CharField(
help_text=_(
'Comma separated list of document primary keys to which this tag '
'will be attached.'
), required=False
)
class Meta:
fields = (
'color', 'documents_pk_list', 'id', 'label',
)
model = Tag
def _add_documents(self, documents_pk_list, instance):
instance.documents.add(
*Document.objects.filter(pk__in=documents_pk_list.split(','))
)
def create(self, validated_data):
documents_pk_list = validated_data.pop('documents_pk_list', '')
instance = super(WritableTagSerializer, self).create(validated_data)
if documents_pk_list:
self._add_documents(
documents_pk_list=documents_pk_list, instance=instance
)
return instance
def update(self, instance, validated_data):
documents_pk_list = validated_data.pop('documents_pk_list', '')
instance = super(WritableTagSerializer, self).update(
instance, validated_data
)
if documents_pk_list:
instance.documents.clear()
self._add_documents(
documents_pk_list=documents_pk_list, instance=instance
)
return instance
"""
class DocumentTagSerializer(TagSerializer):
#document_attach_url = serializers.HyperlinkedIdentityField(
# lookup_url_kwarg='document_id', view_name='rest_api:document-tag-attach'
@@ -165,227 +117,32 @@ class DocumentTagAttachSerializer(serializers.Serializer):
)
class TagAttachSerializer(serializers.Serializer):
#class TagAttachSerializer(TagSerializer):
documents_pk_list = serializers.CharField(
class TagDocumentAttachRemoveSerializer(ExternalObjectListSerializerMixin, serializers.Serializer):
document_id = serializers.CharField(
help_text=_(
'Primary key of document to which this tag will be attached or '
'removed.'
), required=False, write_only=True
)
documents_id_list = serializers.CharField(
help_text=_(
'Comma separated list of document primary keys to which this '
'tag will be attached.'
), write_only=True
'tag will be attached or removed.'
), required=False, write_only=True
)
#class Meta(TagSerializer.Meta):
# fields = TagSerializer.Meta.fields + ('documents_pk_list',)
# read_only_fields = TagSerializer.Meta.fields
class Meta:
external_object_list_model = Document
external_object_list_permission = permission_tag_attach
external_object_list_pk_field = 'document_id'
external_object_list_pk_list_field = 'document_id_list'
def attach(self, instance):
queryset = AccessControlList.objects.restrict_queryset(
permission=permission_tag_attach, queryset=Document.objects.all(),
user=self.context['request'].user
)
for document in queryset.filter(pk__in=self.validated_data['documents_pk_list'].split(',')):
queryset = self.get_external_object_list()
for document in queryset:
instance.attach_to(document=document, user=self.context['request'].user)
#print '@@@@@@@', self.validated_data['document_pk_list']
#print '@@@@@@@', instance
#print '22222', validated_data
#print '!!!', self.data['document_pk_list']
class TagRemoveSerializer(serializers.Serializer):
documents_pk_list = serializers.CharField(
help_text=_(
'Comma separated list of document primary keys from which this '
'tag will be removed.'
), write_only=True
)
def remove(self, instance):
queryset = AccessControlList.objects.restrict_queryset(
permission=permission_tag_attach, queryset=Document.objects.all(),
user=self.context['request'].user
)
for document in queryset.filter(pk__in=self.validated_data['documents_pk_list'].split(',')):
instance.remove_from(document=document, user=self.context['request'].user)
class RelatedModel(object):
@classmethod
def generate(cls, serializer, validated_data):
result = []
kwargs = getattr(serializer.Meta, 'related_model_kwargs', {})
kwargs.update({'serializer': serializer})
for field_name in getattr(serializer.Meta, 'related_models', []):
kwargs.update({'field_name': field_name})
related_field = cls(**kwargs)
related_field.pop_pk_list(validated_data=validated_data)
result.append(related_field)
return result
def __init__(self, field_name, serializer, pk_list_field=None, model=None, object_permission=None):
self.field_name = field_name
self._pk_list_field = pk_list_field
self.model = model
self.object_permission = object_permission
self.serializer = serializer
def create(self, instance):
field = self.get_field(instance=instance)
field.clear()
#model = self.get_model()
queryset = self.get_model().objects.filter(pk__in=self.pk_list.split(','))
permission = self.object_permission.get('create')
if permission:
queryset = AccessControlList.objects.restrict_queryset(
permission=permission,
queryset=queryset,
user=self.serializer.context['request'].user
)
self.related_add()
field.add(*queryset)
#fieldqueryset=queryset)
#def related_add(self, queryset):
# self.get_field().add(*queryset)
#def _get_m2m_field(self, instance):
# getattr(instance, m2m_field_name).all()
"""
def _add_m2m(self, instance, m2m_pk_list, permission):
m2m_field = self._get_m2m_field()
m2m_field.clear()
queryset = AccessControlList.objects.restrict_queryset(
permission=permission,
queryset=m2m_model.objects.filter(pk__in=m2m_pk_list.split(',')),
user=self.context['request'].user
)
#m2m_field.add(*queryset)
self._m2m_add(m2m_field=m2m_field, queryset=queryset)
"""
def get_model(self):
return self.model or self.get_field.model
def get_field(self, instance):
return getattr(instance, self.field_name)
def get_pk_list_field_name(self):
return self._pk_list_field or '{}_pk_list'.format(self.field_name)
def pop_pk_list(self, validated_data):
self.pk_list = validated_data.pop(self.get_pk_list_field_name(), '')
class RelatedModelSerializerMixin(object):
#m2m_pk_list_name = 'documents_pk_list'
#m2m_field_name = 'documents'
#m2m_model = Document
"""
class Meta:
extra_kwargs = {
'url': {
'lookup_field': 'pk', 'lookup_url_kwarg': 'tag_pk',
'view_name': 'rest_api:tag-detail'
}
}
fields = (
'color', 'documents_count', 'documents_pk_list', 'documents_url',
'id', 'label', 'url'
)
model = Tag
related_models = ('documents',)
related_models_kwargs = {
'documents': {
'pk_list_field': 'documents_pk_list', 'model': Document,
'permissions': {'create': permission_tag_attach}
}
}
"""
def _get_m2m_field(self, instance):
getattr(instance, m2m_field_name).all()
def _add_m2m(self, instance, m2m_pk_list, permission):
m2m_field = self._get_m2m_field()
m2m_field.clear()
queryset = AccessControlList.objects.restrict_queryset(
permission=permission,
queryset=m2m_model.objects.filter(pk__in=m2m_pk_list.split(',')),
user=self.context['request'].user
)
#m2m_field.add(*queryset)
self._m2m_add(m2m_field=m2m_field, queryset=queryset)
#def _m2m_add(self, m2m_field, queryset):
# m2m_field.add(*queryset)
def _m2m_add(self, m2m_field, queryset):
for document in queryset.all():
m2m_field.add(document=document, user=self.context['request'].user)
def create(self, validated_data):
related_objects = RelatedModel.generate(
serializer=self, validated_data=validated_data
)
instance = super(RelatedModelSerializerMixin, self).create(
validated_data=validated_data
)
#TODO: return a container class
#TODO:related_objects.create(instance=instance)
for related_object in related_objects:
related_object.create(instance=instance)
#if m2m_pk_list:
## self._add_m2m(
# instance=instance, m2m_pk_list=m2m_pk_list,
# permission=permission_tag_add
# )
return instance
'''
# Extract the related field data before calling the superclass
# .create() and avoid an error due to unknown field data.
#related_models = self.Meta.related_models
#self.Meta.related_models
related_models_dictionary = {}
for related_model in self.Meta.related_models:
#if self.m2m_pk_list_name:
m2m_pk_list = validated_data.pop(self.get_related_model_pk_list(), '')
instance = super(RelatedObjectSerializerMixin, self).create(
validated_data=validated_data
)
if m2m_pk_list:
self._add_m2m(
instance=instance, m2m_pk_list=m2m_pk_list,
permission=permission_tag_add
)
return instance
'''
queryset = self.get_external_object_list()
for document in queryset:
instance.attach_from(document=document, user=self.context['request'].user)

View File

@@ -18,93 +18,7 @@ from .literals import (
TEST_TAG_COLOR, TEST_TAG_COLOR_EDITED, TEST_TAG_LABEL,
TEST_TAG_LABEL_EDITED
)
from .mixins import TagTestMixin
class TagAPITestCase(TagTestMixin, BaseAPITestCase):
def test_tag_create_view_no_permission(self):
response = self._request_api_tag_create_view()
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(Tag.objects.count(), 0)
def test_tag_create_view_with_permission(self):
self.grant_permission(permission=permission_tag_create)
response = self._request_api_tag_create_view()
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
tag = Tag.objects.first()
self.assertEqual(response.data['id'], tag.pk)
self.assertEqual(response.data['label'], TEST_TAG_LABEL)
self.assertEqual(response.data['color'], TEST_TAG_COLOR)
self.assertEqual(Tag.objects.count(), 1)
self.assertEqual(tag.label, TEST_TAG_LABEL)
self.assertEqual(tag.color, TEST_TAG_COLOR)
def test_tag_delete_view_no_access(self):
self._create_test_tag()
response = self._request_api_tag_delete_view()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertTrue(self.test_tag in Tag.objects.all())
self.assertEqual(Tag.objects.all().count(), 1)
def test_tag_delete_view_with_access(self):
self._create_test_tag()
self.grant_access(obj=self.test_tag, permission=permission_tag_delete)
response = self._request_api_tag_delete_view()
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
self.assertEqual(Tag.objects.all().count(), 0)
def test_tag_edit_patch_view_no_access(self):
self._create_test_tag()
response = self._request_api_tag_edit_patch_view()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.test_tag.refresh_from_db()
self.assertEqual(self.test_tag.label, TEST_TAG_LABEL)
self.assertEqual(self.test_tag.color, TEST_TAG_COLOR)
self.assertEqual(Tag.objects.all().count(), 1)
def test_tag_edit_patch_view_with_access(self):
self._create_test_tag()
self.grant_access(obj=self.test_tag, permission=permission_tag_edit)
response = self._request_api_tag_edit_patch_view()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.test_tag.refresh_from_db()
self.assertEqual(self.test_tag.label, TEST_TAG_LABEL_EDITED)
self.assertEqual(self.test_tag.color, TEST_TAG_COLOR_EDITED)
self.assertEqual(Tag.objects.all().count(), 1)
def test_tag_edit_put_view_no_access(self):
self._create_test_tag()
response = self._request_api_tag_edit_put_view()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.test_tag.refresh_from_db()
self.assertEqual(self.test_tag.label, TEST_TAG_LABEL)
self.assertEqual(self.test_tag.color, TEST_TAG_COLOR)
self.assertEqual(Tag.objects.all().count(), 1)
def test_tag_edit_put_view_with_access(self):
self._create_test_tag()
self.grant_access(obj=self.test_tag, permission=permission_tag_edit)
response = self._request_api_tag_edit_put_view()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.test_tag.refresh_from_db()
self.assertEqual(self.test_tag.label, TEST_TAG_LABEL_EDITED)
self.assertEqual(self.test_tag.color, TEST_TAG_COLOR_EDITED)
self.assertEqual(Tag.objects.all().count(), 1)
def test_tag_list_view_no_access(self):
self._create_test_tag()
response = self._request_api_tag_list_view()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['count'], 0)
def test_tag_list_view_with_access(self):
self._create_test_tag()
self.grant_access(obj=self.test_tag, permission=permission_tag_view)
response = self._request_api_tag_list_view()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['count'], 1)
from .mixins import TagAPITestMixin, TagTestMixin
class DocumentTagAPITestCase(TagTestMixin, DocumentTestMixin, BaseAPITestCase):
@@ -117,13 +31,12 @@ class DocumentTagAPITestCase(TagTestMixin, DocumentTestMixin, BaseAPITestCase):
data={'tag_id': self.test_tag.pk}
)
def test_document_tag_attach_view_no_access(self):
def test_document_tag_attach_view_no_permission(self):
self._create_test_tag()
self.test_document = self.upload_document()
response = self._request_api_document_tag_attach_view()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertTrue(self.test_tag not in self.test_document.tags.all())
self.assertEqual(Tag.objects.all().count(), 1)
def test_document_tag_attach_view_with_document_access(self):
self._create_test_tag()
@@ -132,7 +45,6 @@ class DocumentTagAPITestCase(TagTestMixin, DocumentTestMixin, BaseAPITestCase):
response = self._request_api_document_tag_attach_view()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertTrue(self.test_tag not in self.test_document.tags.all())
self.assertEqual(Tag.objects.all().count(), 1)
def test_document_tag_attach_view_with_tag_access(self):
self._create_test_tag()
@@ -141,7 +53,6 @@ class DocumentTagAPITestCase(TagTestMixin, DocumentTestMixin, BaseAPITestCase):
response = self._request_api_document_tag_attach_view()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertTrue(self.test_tag not in self.test_document.tags.all())
self.assertEqual(Tag.objects.all().count(), 1)
def test_document_tag_attach_view_with_full_access(self):
self._create_test_tag()
@@ -153,7 +64,6 @@ class DocumentTagAPITestCase(TagTestMixin, DocumentTestMixin, BaseAPITestCase):
response = self._request_api_document_tag_attach_view()
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertTrue(self.test_tag in self.test_document.tags.all())
self.assertEqual(Tag.objects.all().count(), 1)
def _request_api_document_tag_detail_view(self):
return self.get(
@@ -205,7 +115,7 @@ class DocumentTagAPITestCase(TagTestMixin, DocumentTestMixin, BaseAPITestCase):
kwargs={'document_id': self.test_document.pk}
)
def test_document_tag_list_view_no_access(self):
def test_document_tag_list_view_no_permission(self):
self._create_test_tag()
self.test_document = self.upload_document()
self.test_tag.documents.add(self.test_document)
@@ -248,7 +158,7 @@ class DocumentTagAPITestCase(TagTestMixin, DocumentTestMixin, BaseAPITestCase):
}
)
def test_document_tag_remove_view_no_access(self):
def test_document_tag_remove_view_no_permission(self):
self._create_test_tag()
self.test_document = self.upload_document()
self.test_tag.documents.add(self.test_document)
@@ -291,16 +201,143 @@ class DocumentTagAPITestCase(TagTestMixin, DocumentTestMixin, BaseAPITestCase):
self.assertEqual(Tag.objects.all().count(), 1)
class TagAPITestCase(TagAPITestMixin, TagTestMixin, BaseAPITestCase):
def test_tag_create_view_no_permission(self):
response = self._request_api_tag_create_view()
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertEqual(Tag.objects.count(), 0)
def test_tag_create_view_with_permission(self):
self.grant_permission(permission=permission_tag_create)
response = self._request_api_tag_create_view()
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
tag = Tag.objects.first()
self.assertEqual(response.data['id'], tag.pk)
self.assertEqual(response.data['label'], TEST_TAG_LABEL)
self.assertEqual(response.data['color'], TEST_TAG_COLOR)
self.assertEqual(Tag.objects.count(), 1)
self.assertEqual(tag.label, TEST_TAG_LABEL)
self.assertEqual(tag.color, TEST_TAG_COLOR)
def test_tag_delete_view_no_permission(self):
self._create_test_tag()
response = self._request_api_tag_delete_view()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertTrue(self.test_tag in Tag.objects.all())
self.assertEqual(Tag.objects.all().count(), 1)
def test_tag_delete_view_with_access(self):
self._create_test_tag()
self.grant_access(obj=self.test_tag, permission=permission_tag_delete)
response = self._request_api_tag_delete_view()
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
self.assertEqual(Tag.objects.all().count(), 0)
def test_tag_edit_patch_view_no_permission(self):
self._create_test_tag()
response = self._request_api_tag_edit_patch_view()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.test_tag.refresh_from_db()
self.assertEqual(self.test_tag.label, TEST_TAG_LABEL)
self.assertEqual(self.test_tag.color, TEST_TAG_COLOR)
self.assertEqual(Tag.objects.all().count(), 1)
def test_tag_edit_patch_view_with_access(self):
self._create_test_tag()
self.grant_access(obj=self.test_tag, permission=permission_tag_edit)
response = self._request_api_tag_edit_patch_view()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.test_tag.refresh_from_db()
self.assertEqual(self.test_tag.label, TEST_TAG_LABEL_EDITED)
self.assertEqual(self.test_tag.color, TEST_TAG_COLOR_EDITED)
self.assertEqual(Tag.objects.all().count(), 1)
def test_tag_edit_put_view_no_permission(self):
self._create_test_tag()
response = self._request_api_tag_edit_put_view()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.test_tag.refresh_from_db()
self.assertEqual(self.test_tag.label, TEST_TAG_LABEL)
self.assertEqual(self.test_tag.color, TEST_TAG_COLOR)
self.assertEqual(Tag.objects.all().count(), 1)
def test_tag_edit_put_view_with_access(self):
self._create_test_tag()
self.grant_access(obj=self.test_tag, permission=permission_tag_edit)
response = self._request_api_tag_edit_put_view()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.test_tag.refresh_from_db()
self.assertEqual(self.test_tag.label, TEST_TAG_LABEL_EDITED)
self.assertEqual(self.test_tag.color, TEST_TAG_COLOR_EDITED)
self.assertEqual(Tag.objects.all().count(), 1)
def test_tag_list_view_no_permission(self):
self._create_test_tag()
response = self._request_api_tag_list_view()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['count'], 0)
def test_tag_list_view_with_access(self):
self._create_test_tag()
self.grant_access(obj=self.test_tag, permission=permission_tag_view)
response = self._request_api_tag_list_view()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['count'], 1)
class TagDocumentAPITestCase(TagTestMixin, DocumentTestMixin, BaseAPITestCase):
auto_upload_document = False
def _request_api_tag_document_attach_view(self):
return self.post(
viewname='rest_api:tag-document-attach',
kwargs={'tag_id': self.test_tag.pk},
data={'document_id': self.test_document.pk}
)
def test_tag_document_attach_view_no_permission(self):
self._create_test_tag()
self.test_document = self.upload_document()
response = self._request_api_tag_document_attach_view()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertTrue(self.test_tag not in self.test_document.tags.all())
def test_tag_document_attach_view_with_document_access(self):
self._create_test_tag()
self.test_document = self.upload_document()
self.grant_access(obj=self.test_document, permission=permission_tag_attach)
response = self._request_api_tag_document_attach_view()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertTrue(self.test_tag not in self.test_document.tags.all())
def test_tag_document_attach_view_with_tag_access(self):
self._create_test_tag()
self.test_document = self.upload_document()
self.grant_access(obj=self.test_tag, permission=permission_tag_attach)
response = self._request_api_tag_document_attach_view()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertTrue(self.test_tag not in self.test_document.tags.all())
def test_tag_document_attach_view_with_full_access(self):
self._create_test_tag()
self.test_document = self.upload_document()
self.grant_access(
obj=self.test_document, permission=permission_tag_attach
)
self.grant_access(obj=self.test_tag, permission=permission_tag_attach)
response = self._request_api_tag_document_attach_view()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertTrue(self.test_tag in self.test_document.tags.all())
def _request_api_tag_document_list_view(self):
return self.get(
viewname='rest_api:tag-document-list',
kwargs={'tag_id': self.test_tag.pk}
)
def test_tag_document_list_view_no_access(self):
def test_tag_document_list_view_no_permission(self):
self._create_test_tag()
self.test_document = self.upload_document()
self.test_tag.documents.add(self.test_document)
@@ -340,3 +377,52 @@ class TagDocumentAPITestCase(TagTestMixin, DocumentTestMixin, BaseAPITestCase):
response.data['results'][0]['uuid'],
force_text(self.test_document.uuid)
)
def _request_api_tag_document_remove_view(self):
return self.post(
viewname='rest_api:tag-document-remove', kwargs={
'tag_id': self.test_tag.pk
}, data={'document_id': self.test_document.pk}
)
def test_tag_document_remove_view_no_permission(self):
self._create_test_tag()
self.test_document = self.upload_document()
self.test_tag.documents.add(self.test_document)
response = self._request_api_tag_document_remove_view()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertTrue(self.test_tag in self.test_document.tags.all())
self.assertEqual(Tag.objects.all().count(), 1)
def test_tag_document_remove_view_with_document_access(self):
self._create_test_tag()
self.test_document = self.upload_document()
self.test_tag.documents.add(self.test_document)
self.grant_access(obj=self.test_document, permission=permission_tag_remove)
response = self._request_api_tag_document_remove_view()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertTrue(self.test_tag in self.test_document.tags.all())
self.assertEqual(Tag.objects.all().count(), 1)
def test_tag_document_remove_view_with_tag_access(self):
self._create_test_tag()
self.test_document = self.upload_document()
self.test_tag.documents.add(self.test_document)
self.grant_access(obj=self.test_tag, permission=permission_tag_remove)
response = self._request_api_tag_document_remove_view()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertTrue(self.test_tag in self.test_document.tags.all())
self.assertEqual(Tag.objects.all().count(), 1)
def test_tag_document_remove_view_with_full_access(self):
self._create_test_tag()
self.test_document = self.upload_document()
self.test_tag.documents.add(self.test_document)
self.grant_access(
obj=self.test_document, permission=permission_tag_remove
)
self.grant_access(obj=self.test_tag, permission=permission_tag_remove)
response = self._request_api_tag_document_remove_view()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertFalse(self.test_tag not in self.test_document.tags.all())
self.assertEqual(Tag.objects.all().count(), 1)

View File

@@ -2,10 +2,6 @@ from __future__ import unicode_literals
from django.conf.urls import url
#from .api_views import (
# APIDocumentTagView, APIDocumentTagListView, APITagDocumentListView,
# APITagListView, APITagView
#)
from .api_views import DocumentTagViewSet, TagViewSet
from .views import (
@@ -61,31 +57,10 @@ urlpatterns = [
)
]
api_router_entries = (
{'prefix': r'tags', 'viewset': TagViewSet, 'basename': 'tag'},
{
'prefix': r'documents/(?P<document_id>\d+)/tags',
'viewset': DocumentTagViewSet, 'basename': 'document_tag'
'viewset': DocumentTagViewSet, 'basename': 'document-tag'
},
)
"""
url(
regex=r'^tags/(?P<tag_pk>\d+)/documents/$',
name='tag-document-list', view=APITagDocumentListView.as_view(),
),
url(
regex=r'^tags/(?P<tag_pk>\d+)/$', name='tag-detail',
view=APITagView.as_view()
),
url(regex=r'^tags/$', name='tag-list', view=APITagListView.as_view()),
url(
regex=r'^documents/(?P<document_pk>\d+)/tags/$',
name='document-tag-list', view=APIDocumentTagListView.as_view()
),
url(
regex=r'^documents/(?P<document_pk>\d+)/tags/(?P<tag_pk>[0-9]+)/$',
name='document-tag-detail', view=APIDocumentTagView.as_view()
),
"""