Start tags app API refactor
Signed-off-by: Roberto Rosario <Roberto.Rosario@mayan-edms.com>
This commit is contained in:
@@ -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'
|
||||
)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
),
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user