Add linking app setup API views and tests.

This commit is contained in:
Roberto Rosario
2017-02-11 02:12:25 -04:00
parent 3b9bc3fe78
commit 651f659a05
7 changed files with 546 additions and 5 deletions

View File

@@ -0,0 +1,196 @@
from __future__ import absolute_import, unicode_literals
from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404
from rest_framework import generics
from acls.models import AccessControlList
from permissions import Permission
from rest_api.filters import MayanObjectPermissionsFilter
from rest_api.permissions import MayanPermission
from .models import SmartLink
from .permissions import (
permission_smart_link_create, permission_smart_link_delete,
permission_smart_link_edit, permission_smart_link_view
)
from .serializers import SmartLinkConditionSerializer, SmartLinkSerializer
class APISmartLinkConditionListView(generics.ListCreateAPIView):
serializer_class = SmartLinkConditionSerializer
def get(self, *args, **kwargs):
"""
Returns a list of all the smart link conditions.
"""
return super(APISmartLinkConditionListView, self).get(*args, **kwargs)
def get_queryset(self):
return self.get_smart_link().conditions.all()
def get_serializer_context(self):
"""
Extra context provided to the serializer class.
"""
return {
'format': self.format_kwarg,
'request': self.request,
'smart_link': self.get_smart_link(),
'view': self
}
def get_smart_link(self):
if self.request.method == 'GET':
permission_required = permission_smart_link_view
else:
permission_required = permission_smart_link_edit
smart_link = get_object_or_404(SmartLink, pk=self.kwargs['pk'])
try:
Permission.check_permissions(
self.request.user, (permission_required,)
)
except PermissionDenied:
AccessControlList.objects.check_access(
permission_required, self.request.user, smart_link
)
return smart_link
def post(self, *args, **kwargs):
"""
Create a new smart link condition.
"""
return super(APISmartLinkConditionListView, self).post(*args, **kwargs)
class APISmartLinkConditionView(generics.RetrieveUpdateDestroyAPIView):
lookup_url_kwarg = 'condition_pk'
serializer_class = SmartLinkConditionSerializer
def delete(self, *args, **kwargs):
"""
Delete the selected smart link condition.
"""
return super(APISmartLinkConditionView, self).delete(*args, **kwargs)
def get(self, *args, **kwargs):
"""
Return the details of the selected smart link condition.
"""
return super(APISmartLinkConditionView, self).get(*args, **kwargs)
def get_queryset(self):
return self.get_smart_link().conditions.all()
def get_serializer_context(self):
"""
Extra context provided to the serializer class.
"""
return {
'format': self.format_kwarg,
'request': self.request,
'smart_link': self.get_smart_link(),
'view': self
}
def get_smart_link(self):
if self.request.method == 'GET':
permission_required = permission_smart_link_view
else:
permission_required = permission_smart_link_edit
smart_link = get_object_or_404(SmartLink, pk=self.kwargs['pk'])
try:
Permission.check_permissions(
self.request.user, (permission_required,)
)
except PermissionDenied:
AccessControlList.objects.check_access(
permission_required, self.request.user, smart_link
)
return smart_link
def patch(self, *args, **kwargs):
"""
Edit the selected smart link condition.
"""
return super(APISmartLinkConditionView, self).patch(*args, **kwargs)
def put(self, *args, **kwargs):
"""
Edit the selected smart link condition.
"""
return super(APISmartLinkConditionView, self).put(*args, **kwargs)
class APISmartLinkListView(generics.ListCreateAPIView):
filter_backends = (MayanObjectPermissionsFilter,)
mayan_object_permissions = {'GET': (permission_smart_link_view,)}
mayan_view_permissions = {'POST': (permission_smart_link_create,)}
permission_classes = (MayanPermission,)
queryset = SmartLink.objects.all()
serializer_class = SmartLinkSerializer
def get(self, *args, **kwargs):
"""
Returns a list of all the smart links.
"""
return super(APISmartLinkListView, self).get(*args, **kwargs)
def post(self, *args, **kwargs):
"""
Create a new smart link.
"""
return super(APISmartLinkListView, self).post(*args, **kwargs)
class APISmartLinkView(generics.RetrieveUpdateDestroyAPIView):
filter_backends = (MayanObjectPermissionsFilter,)
mayan_object_permissions = {
'DELETE': (permission_smart_link_delete,),
'GET': (permission_smart_link_view,),
'PATCH': (permission_smart_link_edit,),
'PUT': (permission_smart_link_edit,)
}
queryset = SmartLink.objects.all()
serializer_class = SmartLinkSerializer
def delete(self, *args, **kwargs):
"""
Delete the selected smart link.
"""
return super(APISmartLinkView, self).delete(*args, **kwargs)
def get(self, *args, **kwargs):
"""
Return the details of the selected smart ink.
"""
return super(APISmartLinkView, self).get(*args, **kwargs)
def patch(self, *args, **kwargs):
"""
Edit the selected smart link.
"""
return super(APISmartLinkView, self).patch(*args, **kwargs)
def put(self, *args, **kwargs):
"""
Edit the selected smart link.
"""
return super(APISmartLinkView, self).put(*args, **kwargs)

View File

@@ -12,6 +12,7 @@ from common import (
)
from common.widgets import two_state_template
from navigation import SourceColumn
from rest_api.classes import APIEndPoint
from .links import (
link_smart_link_create, link_smart_link_condition_create,
@@ -35,6 +36,8 @@ class LinkingApp(MayanAppConfig):
def ready(self):
super(LinkingApp, self).ready()
APIEndPoint(app=self, version_string='1')
Document = apps.get_model(
app_label='documents', model_name='Document'
)

View File

@@ -0,0 +1,50 @@
from __future__ import absolute_import, unicode_literals
from rest_framework import serializers
from rest_framework.reverse import reverse
from .models import SmartLink, SmartLinkCondition
class SmartLinkConditionSerializer(serializers.HyperlinkedModelSerializer):
smart_link_url = serializers.SerializerMethodField()
url = serializers.SerializerMethodField()
class Meta:
fields = (
'enabled', 'expression', 'foreign_document_data', 'inclusion',
'id', 'negated', 'operator', 'smart_link_url', 'url'
)
model = SmartLinkCondition
def create(self, validated_data):
validated_data['smart_link'] = self.context['smart_link']
return super(SmartLinkConditionSerializer, self).create(validated_data)
def get_smart_link_url(self, instance):
return reverse(
'rest_api:smartlink-detail', args=(instance.smart_link.pk,),
request=self.context['request'], format=self.context['format']
)
def get_url(self, instance):
return reverse(
'rest_api:smartlinkcondition-detail', args=(
instance.smart_link.pk, instance.pk,
), request=self.context['request'], format=self.context['format']
)
class SmartLinkSerializer(serializers.HyperlinkedModelSerializer):
conditions_url = serializers.HyperlinkedIdentityField(
view_name='rest_api:smartlinkcondition-list'
)
class Meta:
extra_kwargs = {
'url': {'view_name': 'rest_api:smartlink-detail'},
}
fields = (
'conditions_url', 'dynamic_label', 'enabled', 'label', 'id', 'url'
)
model = SmartLink

View File

@@ -1,5 +1,9 @@
from __future__ import unicode_literals
TEST_SMART_LINK_CONDITION_FOREIGN_DOCUMENT_DATA = 'label'
TEST_SMART_LINK_CONDITION_EXPRESSION = '\'test\''
TEST_SMART_LINK_CONDITION_EXPRESSION_EDITED = '\'test edited\''
TEST_SMART_LINK_CONDITION_OPERATOR = 'icontains'
TEST_SMART_LINK_DYNAMIC_LABEL = '{{ document.label }}'
TEST_SMART_LINK_EDITED_LABEL = 'test edited label'
TEST_SMART_LINK_LABEL_EDITED = 'test edited label'
TEST_SMART_LINK_LABEL = 'test label'

View File

@@ -0,0 +1,265 @@
from __future__ import unicode_literals
from django.contrib.auth import get_user_model
from django.core.urlresolvers import reverse
from django.test import override_settings
from rest_framework.test import APITestCase
from documents.models import DocumentType
from documents.tests.literals import (
TEST_DOCUMENT_TYPE, TEST_SMALL_DOCUMENT_PATH
)
from user_management.tests.literals import (
TEST_ADMIN_EMAIL, TEST_ADMIN_PASSWORD, TEST_ADMIN_USERNAME
)
from ..models import SmartLink, SmartLinkCondition
from .literals import (
TEST_SMART_LINK_CONDITION_FOREIGN_DOCUMENT_DATA,
TEST_SMART_LINK_CONDITION_EXPRESSION,
TEST_SMART_LINK_CONDITION_EXPRESSION_EDITED,
TEST_SMART_LINK_CONDITION_OPERATOR, TEST_SMART_LINK_DYNAMIC_LABEL,
TEST_SMART_LINK_LABEL_EDITED, TEST_SMART_LINK_LABEL
)
@override_settings(OCR_AUTO_OCR=False)
class SmartLinkAPITestCase(APITestCase):
def setUp(self):
self.admin_user = get_user_model().objects.create_superuser(
username=TEST_ADMIN_USERNAME, email=TEST_ADMIN_EMAIL,
password=TEST_ADMIN_PASSWORD
)
self.client.login(
username=TEST_ADMIN_USERNAME, password=TEST_ADMIN_PASSWORD
)
def tearDown(self):
if hasattr(self, 'document_type'):
self.document_type.delete()
def _create_document_type(self):
self.document_type = DocumentType.objects.create(
label=TEST_DOCUMENT_TYPE
)
def _create_document(self):
with open(TEST_SMALL_DOCUMENT_PATH) as file_object:
self.document = self.document_type.new_document(
file_object=file_object
)
def _create_smart_link(self):
return SmartLink.objects.create(
label=TEST_SMART_LINK_LABEL,
dynamic_label=TEST_SMART_LINK_DYNAMIC_LABEL
)
def test_smart_link_create_view(self):
response = self.client.post(
reverse('rest_api:smartlink-list'), {
'label': TEST_SMART_LINK_LABEL
}
)
smart_link = SmartLink.objects.first()
self.assertEqual(response.data['id'], smart_link.pk)
self.assertEqual(response.data['label'], TEST_SMART_LINK_LABEL)
self.assertEqual(SmartLink.objects.count(), 1)
self.assertEqual(smart_link.label, TEST_SMART_LINK_LABEL)
def test_smart_link_delete_view(self):
smart_link = self._create_smart_link()
self.client.delete(
reverse('rest_api:smartlink-detail', args=(smart_link.pk,))
)
self.assertEqual(SmartLink.objects.count(), 0)
def test_smart_link_detail_view(self):
smart_link = self._create_smart_link()
response = self.client.get(
reverse('rest_api:smartlink-detail', args=(smart_link.pk,))
)
self.assertEqual(
response.data['label'], TEST_SMART_LINK_LABEL
)
def test_smart_link_patch_view(self):
smart_link = self._create_smart_link()
self.client.patch(
reverse('rest_api:smartlink-detail', args=(smart_link.pk,)),
data={
'label': TEST_SMART_LINK_LABEL_EDITED,
}
)
smart_link.refresh_from_db()
self.assertEqual(smart_link.label, TEST_SMART_LINK_LABEL_EDITED)
def test_smart_link_put_view(self):
smart_link = self._create_smart_link()
self.client.put(
reverse('rest_api:smartlink-detail', args=(smart_link.pk,)),
data={
'label': TEST_SMART_LINK_LABEL_EDITED,
}
)
smart_link.refresh_from_db()
self.assertEqual(smart_link.label, TEST_SMART_LINK_LABEL_EDITED)
@override_settings(OCR_AUTO_OCR=False)
class SmartLinkConditionAPITestCase(APITestCase):
def setUp(self):
self.admin_user = get_user_model().objects.create_superuser(
username=TEST_ADMIN_USERNAME, email=TEST_ADMIN_EMAIL,
password=TEST_ADMIN_PASSWORD
)
self.client.login(
username=TEST_ADMIN_USERNAME, password=TEST_ADMIN_PASSWORD
)
def tearDown(self):
if hasattr(self, 'document_type'):
self.document_type.delete()
def _create_document_type(self):
self.document_type = DocumentType.objects.create(
label=TEST_DOCUMENT_TYPE
)
def _create_document(self):
with open(TEST_SMALL_DOCUMENT_PATH) as file_object:
self.document = self.document_type.new_document(
file_object=file_object
)
def _create_smart_link(self):
self.smart_link = SmartLink.objects.create(
label=TEST_SMART_LINK_LABEL,
dynamic_label=TEST_SMART_LINK_DYNAMIC_LABEL
)
self.smart_link.document_types.add(self.document_type)
def _create_smart_link_condition(self):
self.smart_link_condition = SmartLinkCondition.objects.create(
smart_link=self.smart_link,
foreign_document_data=TEST_SMART_LINK_CONDITION_FOREIGN_DOCUMENT_DATA,
expression=TEST_SMART_LINK_CONDITION_EXPRESSION,
operator=TEST_SMART_LINK_CONDITION_OPERATOR
)
def test_smart_link_condition_create_view(self):
self._create_document_type()
self._create_smart_link()
response = self.client.post(
reverse(
'rest_api:smartlinkcondition-list', args=(self.smart_link.pk,)
), {
'foreign_document_data': TEST_SMART_LINK_CONDITION_FOREIGN_DOCUMENT_DATA,
'expression': TEST_SMART_LINK_CONDITION_EXPRESSION,
'operator': TEST_SMART_LINK_CONDITION_OPERATOR
}
)
smart_link_condition = SmartLinkCondition.objects.first()
self.assertEqual(response.data['id'], smart_link_condition.pk)
self.assertEqual(
response.data['operator'], TEST_SMART_LINK_CONDITION_OPERATOR
)
self.assertEqual(SmartLinkCondition.objects.count(), 1)
self.assertEqual(
smart_link_condition.operator, TEST_SMART_LINK_CONDITION_OPERATOR
)
def test_smart_link_condition_delete_view(self):
self._create_document_type()
self._create_smart_link()
self._create_smart_link_condition()
self.client.delete(
reverse(
'rest_api:smartlinkcondition-detail',
args=(self.smart_link.pk, self.smart_link_condition.pk)
)
)
self.assertEqual(SmartLinkCondition.objects.count(), 0)
def test_smart_link_condition_detail_view(self):
self._create_document_type()
self._create_smart_link()
self._create_smart_link_condition()
response = self.client.get(
reverse(
'rest_api:smartlinkcondition-detail',
args=(self.smart_link.pk, self.smart_link_condition.pk)
)
)
self.assertEqual(
response.data['operator'], TEST_SMART_LINK_CONDITION_OPERATOR
)
def test_smart_link_condition_patch_view(self):
self._create_document_type()
self._create_smart_link()
self._create_smart_link_condition()
self.client.patch(
reverse(
'rest_api:smartlinkcondition-detail',
args=(self.smart_link.pk, self.smart_link_condition.pk)
),
data={
'expression': TEST_SMART_LINK_CONDITION_EXPRESSION_EDITED,
}
)
self.smart_link_condition.refresh_from_db()
self.assertEqual(
self.smart_link_condition.expression,
TEST_SMART_LINK_CONDITION_EXPRESSION_EDITED
)
def test_smart_link_condition_put_view(self):
self._create_document_type()
self._create_smart_link()
self._create_smart_link_condition()
self.client.put(
reverse(
'rest_api:smartlinkcondition-detail',
args=(self.smart_link.pk, self.smart_link_condition.pk)
),
data={
'expression': TEST_SMART_LINK_CONDITION_EXPRESSION_EDITED,
'foreign_document_data': TEST_SMART_LINK_CONDITION_FOREIGN_DOCUMENT_DATA,
'operator': TEST_SMART_LINK_CONDITION_OPERATOR,
}
)
self.smart_link_condition.refresh_from_db()
self.assertEqual(
self.smart_link_condition.expression,
TEST_SMART_LINK_CONDITION_EXPRESSION_EDITED
)

View File

@@ -13,7 +13,7 @@ from ..permissions import (
)
from .literals import (
TEST_SMART_LINK_DYNAMIC_LABEL, TEST_SMART_LINK_EDITED_LABEL,
TEST_SMART_LINK_DYNAMIC_LABEL, TEST_SMART_LINK_LABEL_EDITED,
TEST_SMART_LINK_LABEL
)
@@ -83,7 +83,7 @@ class SmartLinkViewTestCase(GenericDocumentViewTestCase):
response = self.post(
'linking:smart_link_edit', args=(smart_link.pk,), data={
'label': TEST_SMART_LINK_EDITED_LABEL
'label': TEST_SMART_LINK_LABEL_EDITED
}
)
self.assertEqual(response.status_code, 403)
@@ -101,13 +101,13 @@ class SmartLinkViewTestCase(GenericDocumentViewTestCase):
response = self.post(
'linking:smart_link_edit', args=(smart_link.pk,), data={
'label': TEST_SMART_LINK_EDITED_LABEL
'label': TEST_SMART_LINK_LABEL_EDITED
}, follow=True
)
smart_link = SmartLink.objects.get(pk=smart_link.pk)
self.assertContains(response, text='update', status_code=200)
self.assertEqual(smart_link.label, TEST_SMART_LINK_EDITED_LABEL)
self.assertEqual(smart_link.label, TEST_SMART_LINK_LABEL_EDITED)
def setup_smart_links(self):
smart_link = SmartLink.objects.create(

View File

@@ -2,6 +2,10 @@ from __future__ import unicode_literals
from django.conf.urls import patterns, url
from .api_views import (
APISmartLinkListView, APISmartLinkView, APISmartLinkConditionListView,
APISmartLinkConditionView
)
from .views import (
DocumentSmartLinkListView, ResolvedSmartLinkView,
SetupSmartLinkDocumentTypesView, SmartLinkConditionListView,
@@ -61,3 +65,22 @@ urlpatterns = patterns(
name='smart_link_condition_delete'
),
)
api_urls = [
url(
r'^smart_links/$', APISmartLinkListView.as_view(), name='smartlink-list'
),
url(
r'^smart_links/(?P<pk>[0-9]+)/$', APISmartLinkView.as_view(),
name='smartlink-detail'
),
url(
r'^smart_links/(?P<pk>[0-9]+)/conditions/$',
APISmartLinkConditionListView.as_view(), name='smartlinkcondition-list'
),
url(
r'^smart_links/(?P<pk>[0-9]+)/conditions/(?P<condition_pk>[0-9]+)/$',
APISmartLinkConditionView.as_view(),
name='smartlinkcondition-detail'
),
]