From 2878bac07d42f60ff59b8000aff5e04e82339856 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 21 Sep 2014 14:59:11 -0400 Subject: [PATCH 01/15] Add CORS support to allow cross origin API requests --- mayan/settings/base.py | 5 +++++ requirements/common.txt | 1 + 2 files changed, 6 insertions(+) diff --git a/mayan/settings/base.py b/mayan/settings/base.py index 470302e689..eb73e19974 100644 --- a/mayan/settings/base.py +++ b/mayan/settings/base.py @@ -45,6 +45,7 @@ INSTALLED_APPS = ( 'django.contrib.comments', 'django.contrib.staticfiles', # 3rd party + 'corsheaders', 'south', 'rest_framework_swagger', 'filetransfers', @@ -102,6 +103,7 @@ INSTALLED_APPS = ( MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', + 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', @@ -262,3 +264,6 @@ REST_FRAMEWORK = { 'rest_framework.authentication.SessionAuthentication', ) } + +# CORS +CORS_ORIGIN_ALLOW_ALL = True diff --git a/requirements/common.txt b/requirements/common.txt index 504b8a9017..63518975f6 100644 --- a/requirements/common.txt +++ b/requirements/common.txt @@ -6,6 +6,7 @@ Django==1.6.5 django-filetransfers==0.1.0 django-pagination==1.0.7 django-compressor==1.4 +django-cors-headers==0.13 django-taggit==0.12 django-mptt==0.6.1 django-rest-swagger==0.1.14 From e9f733e2662dfb179547a70e861de7e8bc99d35c Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 21 Sep 2014 14:59:43 -0400 Subject: [PATCH 02/15] Fix typo --- mayan/apps/tags/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mayan/apps/tags/views.py b/mayan/apps/tags/views.py index b87bee614a..270c71fade 100644 --- a/mayan/apps/tags/views.py +++ b/mayan/apps/tags/views.py @@ -212,7 +212,7 @@ def tag_edit(request, tag_id): if form.is_valid(): tag.name = form.cleaned_data['name'] tag.save() - tag_properties = tag.tagproperties_set.get() + tag_properties = tag.properties.get() tag_properties.color = form.cleaned_data['color'] tag_properties.save() messages.success(request, _(u'Tag updated succesfully.')) From 2e4cd173c6951ab1b3be63d2958cb3716668c705 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 21 Sep 2014 15:13:56 -0400 Subject: [PATCH 03/15] Add document type detail API endpoint --- mayan/apps/documents/api_views.py | 27 ++++++++++++++++++++++++--- mayan/apps/documents/serializers.py | 7 ++++++- mayan/apps/documents/urls.py | 5 +++-- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/mayan/apps/documents/api_views.py b/mayan/apps/documents/api_views.py index 0ecaccd767..8e982fba4d 100644 --- a/mayan/apps/documents/api_views.py +++ b/mayan/apps/documents/api_views.py @@ -15,14 +15,18 @@ from rest_api.filters import MayanObjectPermissionsFilter from rest_api.permissions import MayanPermission from .conf.settings import DISPLAY_SIZE, ZOOM_MAX_LEVEL, ZOOM_MIN_LEVEL -from .models import Document, DocumentPage, DocumentVersion +from .models import Document, DocumentPage, DocumentType, DocumentVersion from .permissions import (PERMISSION_DOCUMENT_CREATE, PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_EDIT, PERMISSION_DOCUMENT_NEW_VERSION, PERMISSION_DOCUMENT_PROPERTIES_EDIT, - PERMISSION_DOCUMENT_VIEW) + PERMISSION_DOCUMENT_VIEW, + PERMISSION_DOCUMENT_TYPE_DELETE, + PERMISSION_DOCUMENT_TYPE_EDIT, + PERMISSION_DOCUMENT_TYPE_VIEW) from .serializers import (DocumentImageSerializer, DocumentPageSerializer, - DocumentSerializer, DocumentVersionSerializer) + DocumentSerializer, DocumentTypeSerializer, + DocumentVersionSerializer) class APIDocumentListView(generics.ListCreateAPIView): @@ -181,3 +185,20 @@ class APIDocumentPageView(generics.RetrieveUpdateAPIView): 'PATCH': [PERMISSION_DOCUMENT_EDIT] } mayan_permission_attribute_check = 'document' + + +class APIDocumentTypeView(generics.RetrieveUpdateDestroyAPIView): + """ + Returns the selected document type details. + """ + + serializer_class = DocumentTypeSerializer + queryset = DocumentType.objects.all() + + permission_classes = (MayanPermission,) + mayan_object_permissions = { + 'GET': [PERMISSION_DOCUMENT_TYPE_VIEW], + 'PUT': [PERMISSION_DOCUMENT_TYPE_EDIT], + 'PATCH': [PERMISSION_DOCUMENT_TYPE_EDIT], + 'DELETE': [PERMISSION_DOCUMENT_TYPE_DELETE] + } diff --git a/mayan/apps/documents/serializers.py b/mayan/apps/documents/serializers.py index a83b43b35a..fba2ee3c8a 100644 --- a/mayan/apps/documents/serializers.py +++ b/mayan/apps/documents/serializers.py @@ -2,7 +2,12 @@ from __future__ import absolute_import from rest_framework import serializers -from .models import Document, DocumentVersion, DocumentPage +from .models import Document, DocumentVersion, DocumentPage, DocumentType + + +class DocumentTypeSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = DocumentType class DocumentPageSerializer(serializers.HyperlinkedModelSerializer): diff --git a/mayan/apps/documents/urls.py b/mayan/apps/documents/urls.py index 9d36cc6cc4..21cd65e787 100644 --- a/mayan/apps/documents/urls.py +++ b/mayan/apps/documents/urls.py @@ -3,8 +3,8 @@ from __future__ import absolute_import from django.conf.urls import patterns, url from .api_views import (APIDocumentView, APIDocumentImageView, APIDocumentListView, - APIDocumentPageView, APIDocumentVersionCreateView, - APIDocumentVersionView) + APIDocumentPageView, APIDocumentTypeView, + APIDocumentVersionCreateView, APIDocumentVersionView) from .conf.settings import PRINT_SIZE, DISPLAY_SIZE urlpatterns = patterns('documents.views', @@ -76,4 +76,5 @@ api_urls = patterns('', url(r'^document_page/(?P[0-9]+)/$', APIDocumentPageView.as_view(), name='documentpage-detail'), url(r'^documents/(?P[0-9]+)/image/$', APIDocumentImageView.as_view(), name='document-image'), url(r'^documents/(?P[0-9]+)/new_version/$', APIDocumentVersionCreateView.as_view(), name='document-new-version'), + url(r'^documenttypes/(?P[0-9]+)/$', APIDocumentTypeView.as_view(), name='documenttype-detail'), ) From 050ae8c168cc8559c588a95052dfcd9be5d6ba1b Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 21 Sep 2014 15:21:19 -0400 Subject: [PATCH 04/15] Add Document type list API view and endpoint --- mayan/apps/documents/__init__.py | 1 + mayan/apps/documents/api_views.py | 15 +++++++++++++++ mayan/apps/documents/urls.py | 6 ++++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/mayan/apps/documents/__init__.py b/mayan/apps/documents/__init__.py index 6e93f6a158..801b2a1bca 100644 --- a/mayan/apps/documents/__init__.py +++ b/mayan/apps/documents/__init__.py @@ -158,3 +158,4 @@ namespace.add_statistic(DocumentUsageStatistics(name='document_usage', label=_(u endpoint = APIEndPoint('documents') endpoint.register_urls(api_urls) endpoint.add_endpoint('document-list', _(u'Returns a list of all the documents.')) +endpoint.add_endpoint('documenttype-list', _(u'Returns a list of all the document types.')) diff --git a/mayan/apps/documents/api_views.py b/mayan/apps/documents/api_views.py index 8e982fba4d..b19754160d 100644 --- a/mayan/apps/documents/api_views.py +++ b/mayan/apps/documents/api_views.py @@ -21,6 +21,7 @@ from .permissions import (PERMISSION_DOCUMENT_CREATE, PERMISSION_DOCUMENT_NEW_VERSION, PERMISSION_DOCUMENT_PROPERTIES_EDIT, PERMISSION_DOCUMENT_VIEW, + PERMISSION_DOCUMENT_TYPE_CREATE, PERMISSION_DOCUMENT_TYPE_DELETE, PERMISSION_DOCUMENT_TYPE_EDIT, PERMISSION_DOCUMENT_TYPE_VIEW) @@ -187,6 +188,20 @@ class APIDocumentPageView(generics.RetrieveUpdateAPIView): mayan_permission_attribute_check = 'document' +class APIDocumentTypeListView(generics.ListCreateAPIView): + """ + Returns a list of all the document types. + """ + + serializer_class = DocumentTypeSerializer + queryset = DocumentType.objects.all() + + permission_classes = (MayanPermission,) + filter_backends = (MayanObjectPermissionsFilter,) + mayan_object_permissions = {'GET': [PERMISSION_DOCUMENT_TYPE_VIEW]} + mayan_view_permissions = {'POST': [PERMISSION_DOCUMENT_TYPE_CREATE]} + + class APIDocumentTypeView(generics.RetrieveUpdateDestroyAPIView): """ Returns the selected document type details. diff --git a/mayan/apps/documents/urls.py b/mayan/apps/documents/urls.py index 21cd65e787..a4c9448592 100644 --- a/mayan/apps/documents/urls.py +++ b/mayan/apps/documents/urls.py @@ -3,8 +3,9 @@ from __future__ import absolute_import from django.conf.urls import patterns, url from .api_views import (APIDocumentView, APIDocumentImageView, APIDocumentListView, - APIDocumentPageView, APIDocumentTypeView, - APIDocumentVersionCreateView, APIDocumentVersionView) + APIDocumentPageView, APIDocumentTypeListView, + APIDocumentTypeView, APIDocumentVersionCreateView, + APIDocumentVersionView) from .conf.settings import PRINT_SIZE, DISPLAY_SIZE urlpatterns = patterns('documents.views', @@ -76,5 +77,6 @@ api_urls = patterns('', url(r'^document_page/(?P[0-9]+)/$', APIDocumentPageView.as_view(), name='documentpage-detail'), url(r'^documents/(?P[0-9]+)/image/$', APIDocumentImageView.as_view(), name='document-image'), url(r'^documents/(?P[0-9]+)/new_version/$', APIDocumentVersionCreateView.as_view(), name='document-new-version'), + url(r'^documenttypes/$', APIDocumentTypeListView.as_view(), name='documenttype-list'), url(r'^documenttypes/(?P[0-9]+)/$', APIDocumentTypeView.as_view(), name='documenttype-detail'), ) From 97de4f615c794756c499a3a713e398dcae22b097 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 21 Sep 2014 15:21:39 -0400 Subject: [PATCH 05/15] Add Document model related name to the Document Type model to allow retrieving all documents of a document type --- mayan/apps/documents/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mayan/apps/documents/models.py b/mayan/apps/documents/models.py index d64b200b26..ff0985b038 100644 --- a/mayan/apps/documents/models.py +++ b/mayan/apps/documents/models.py @@ -78,7 +78,7 @@ class Document(models.Model): Defines a single document with it's fields and properties """ uuid = models.CharField(max_length=48, blank=True, editable=False) - document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'), null=True, blank=True) + document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'), related_name='documents', null=True, blank=True) description = models.TextField(blank=True, null=True, verbose_name=_(u'description')) date_added = models.DateTimeField(verbose_name=_(u'added'), db_index=True, editable=False) From e522da36325641272c167229456beccb42f1dfbf Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 21 Sep 2014 15:22:12 -0400 Subject: [PATCH 06/15] Add retrieving all documents of document type via API --- mayan/apps/documents/serializers.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/mayan/apps/documents/serializers.py b/mayan/apps/documents/serializers.py index fba2ee3c8a..b3f6202e55 100644 --- a/mayan/apps/documents/serializers.py +++ b/mayan/apps/documents/serializers.py @@ -5,11 +5,6 @@ from rest_framework import serializers from .models import Document, DocumentVersion, DocumentPage, DocumentType -class DocumentTypeSerializer(serializers.HyperlinkedModelSerializer): - class Meta: - model = DocumentType - - class DocumentPageSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = DocumentPage @@ -35,3 +30,10 @@ class DocumentSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Document + + +class DocumentTypeSerializer(serializers.HyperlinkedModelSerializer): + documents = DocumentSerializer() + + class Meta: + model = DocumentType From eb3e7a10c923ece6119a4b781f12bb7970dfa415 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 21 Sep 2014 16:38:52 -0400 Subject: [PATCH 07/15] Abstract the way tag documents are retrieved --- mayan/apps/tags/__init__.py | 4 ++++ mayan/apps/tags/views.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mayan/apps/tags/__init__.py b/mayan/apps/tags/__init__.py index 34e6bb4717..f05e9dc7a9 100644 --- a/mayan/apps/tags/__init__.py +++ b/mayan/apps/tags/__init__.py @@ -61,7 +61,11 @@ class_permissions(Tag, [ PERMISSION_TAG_VIEW, ]) +def tag_documents(self): + return Document.objects.filter(tags__in=[self]) + Document.add_to_class('tags', TaggableManager()) +Tag.add_to_class('documents', property(tag_documents)) endpoint = APIEndPoint('tags') endpoint.register_urls(api_urls) diff --git a/mayan/apps/tags/views.py b/mayan/apps/tags/views.py index 270c71fade..89c5655039 100644 --- a/mayan/apps/tags/views.py +++ b/mayan/apps/tags/views.py @@ -236,7 +236,7 @@ def tag_tagged_item_list(request, tag_id): return document_list( request, - object_list=Document.objects.filter(tags__in=[tag]), + object_list=tag.documents.all(), title=_('documents with the tag "%s"') % tag, extra_context={ 'object': tag, From 364376f04ae3451e65e3c438c6851a94788d7a0b Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 21 Sep 2014 19:22:48 -0400 Subject: [PATCH 08/15] Specify document type fields and add the id field --- mayan/apps/documents/serializers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mayan/apps/documents/serializers.py b/mayan/apps/documents/serializers.py index b3f6202e55..71d057cb9e 100644 --- a/mayan/apps/documents/serializers.py +++ b/mayan/apps/documents/serializers.py @@ -37,3 +37,4 @@ class DocumentTypeSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = DocumentType + fields = ('id', 'url', 'name', 'documents') From 942ad7b93e94ebc2c7be91db10d9ed14b36f0d89 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 21 Sep 2014 19:23:17 -0400 Subject: [PATCH 09/15] Add user model API endpoints --- mayan/apps/user_management/__init__.py | 7 ++++ mayan/apps/user_management/api_views.py | 44 +++++++++++++++++++++++ mayan/apps/user_management/serializers.py | 11 ++++++ mayan/apps/user_management/urls.py | 7 ++++ 4 files changed, 69 insertions(+) create mode 100644 mayan/apps/user_management/api_views.py create mode 100644 mayan/apps/user_management/serializers.py diff --git a/mayan/apps/user_management/__init__.py b/mayan/apps/user_management/__init__.py index f442d68dc9..2203e9e891 100644 --- a/mayan/apps/user_management/__init__.py +++ b/mayan/apps/user_management/__init__.py @@ -1,14 +1,17 @@ from __future__ import absolute_import from django.contrib.auth.models import User, Group +from django.utils.translation import ugettext_lazy as _ from navigation.api import register_links, register_multi_item_links from project_setup.api import register_setup +from rest_api.classes import APIEndPoint from .links import (user_list, user_setup, user_edit, user_add, user_delete, user_multiple_delete, user_set_password, user_multiple_set_password, user_groups, group_list, group_setup, group_edit, group_add, group_delete, group_multiple_delete, group_members) +from .urls import api_urls register_links(User, [user_edit, user_set_password, user_groups, user_delete]) register_links([User, 'user_multiple_set_password', 'user_multiple_delete', 'user_list', 'user_add'], [user_list, user_add], menu_name=u'secondary_menu') @@ -27,3 +30,7 @@ user_management_views = [ register_setup(user_setup) register_setup(group_setup) + +endpoint = APIEndPoint('users') +endpoint.register_urls(api_urls) +endpoint.add_endpoint('user-list', _(u'Returns a list of all the users.')) diff --git a/mayan/apps/user_management/api_views.py b/mayan/apps/user_management/api_views.py new file mode 100644 index 0000000000..93effdf2d7 --- /dev/null +++ b/mayan/apps/user_management/api_views.py @@ -0,0 +1,44 @@ +from __future__ import absolute_import + +from django.contrib.auth.models import User + +from rest_framework import generics + +from rest_api.filters import MayanObjectPermissionsFilter +from rest_api.permissions import MayanPermission + +from .permissions import (PERMISSION_USER_CREATE, + PERMISSION_USER_DELETE, PERMISSION_USER_EDIT, + PERMISSION_USER_VIEW) +from .serializers import UserSerializer + + +class APIUserListView(generics.ListCreateAPIView): + """ + Returns a list of all the folders. + """ + + serializer_class = UserSerializer + queryset = User.objects.all() + + permission_classes = (MayanPermission,) + filter_backends = (MayanObjectPermissionsFilter,) + mayan_object_permissions = {'GET': [PERMISSION_USER_VIEW]} + mayan_view_permissions = {'POST': [PERMISSION_USER_CREATE]} + + +class APIUserView(generics.RetrieveUpdateDestroyAPIView): + """ + Returns the selected folder details. + """ + + serializer_class = UserSerializer + queryset = User.objects.all() + + permission_classes = (MayanPermission,) + mayan_object_permissions = { + 'GET': [PERMISSION_USER_VIEW], + 'PUT': [PERMISSION_USER_EDIT], + 'PATCH': [PERMISSION_USER_EDIT], + 'DELETE': [PERMISSION_USER_DELETE] + } diff --git a/mayan/apps/user_management/serializers.py b/mayan/apps/user_management/serializers.py new file mode 100644 index 0000000000..255c1b3717 --- /dev/null +++ b/mayan/apps/user_management/serializers.py @@ -0,0 +1,11 @@ +from __future__ import absolute_import + +from django.contrib.auth.models import User + +from rest_framework import serializers + + +class UserSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + fields = ('id', 'url', 'username', 'first_name', 'last_name', 'email', 'is_staff', 'is_active', 'is_superuser', 'last_login', 'date_joined') + model = User diff --git a/mayan/apps/user_management/urls.py b/mayan/apps/user_management/urls.py index dc2fbcd9f9..8e39795177 100644 --- a/mayan/apps/user_management/urls.py +++ b/mayan/apps/user_management/urls.py @@ -1,5 +1,7 @@ from django.conf.urls import patterns, url +from .api_views import APIUserListView, APIUserView + urlpatterns = patterns('user_management.views', url(r'^user/list/$', 'user_list', (), 'user_list'), url(r'^user/add/$', 'user_add', (), 'user_add'), @@ -17,3 +19,8 @@ urlpatterns = patterns('user_management.views', url(r'^group/multiple/delete/$', 'group_multiple_delete', (), 'group_multiple_delete'), url(r'^group/(?P\d+)/members/$', 'group_members', (), 'group_members'), ) + +api_urls = patterns('', + url(r'^users/$', APIUserListView.as_view(), name='user-list'), + url(r'^users/(?P[0-9]+)/$', APIUserView.as_view(), name='user-detail'), +) From f29aeabcfb307be2ef72dc51ff41b32e42d55e4a Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 21 Sep 2014 19:24:00 -0400 Subject: [PATCH 10/15] Add folder app API endpoint --- mayan/apps/folders/__init__.py | 8 ++++++ mayan/apps/folders/api_views.py | 43 +++++++++++++++++++++++++++++++ mayan/apps/folders/serializers.py | 11 ++++++++ mayan/apps/folders/urls.py | 7 +++++ 4 files changed, 69 insertions(+) create mode 100644 mayan/apps/folders/api_views.py create mode 100644 mayan/apps/folders/serializers.py diff --git a/mayan/apps/folders/__init__.py b/mayan/apps/folders/__init__.py index 3aa57639d0..0ada1ae8d7 100644 --- a/mayan/apps/folders/__init__.py +++ b/mayan/apps/folders/__init__.py @@ -1,10 +1,13 @@ from __future__ import absolute_import +from django.utils.translation import ugettext_lazy as _ + from acls.api import class_permissions from acls.permissions import ACLS_EDIT_ACL, ACLS_VIEW_ACL from documents.models import Document from navigation.api import (register_links, register_top_menu, register_multi_item_links, register_sidebar_template) +from rest_api.classes import APIEndPoint from .links import (folder_list, folder_create, folder_edit, folder_delete, folder_document_multiple_remove, folder_view, folder_add_document, @@ -14,6 +17,7 @@ from .models import Folder from .permissions import (PERMISSION_FOLDER_EDIT, PERMISSION_FOLDER_DELETE, PERMISSION_FOLDER_REMOVE_DOCUMENT, PERMISSION_FOLDER_VIEW, PERMISSION_FOLDER_ADD_DOCUMENT) +from .urls import api_urls register_multi_item_links(['folder_view'], [folder_document_multiple_remove]) @@ -43,3 +47,7 @@ class_permissions(Document, [ PERMISSION_FOLDER_ADD_DOCUMENT, PERMISSION_FOLDER_REMOVE_DOCUMENT, ]) + +endpoint = APIEndPoint('folders') +endpoint.register_urls(api_urls) +endpoint.add_endpoint('folder-list', _(u'Returns a list of all the folders.')) diff --git a/mayan/apps/folders/api_views.py b/mayan/apps/folders/api_views.py new file mode 100644 index 0000000000..ee7b8b0610 --- /dev/null +++ b/mayan/apps/folders/api_views.py @@ -0,0 +1,43 @@ +from __future__ import absolute_import + +from rest_framework import generics + +from rest_api.filters import MayanObjectPermissionsFilter +from rest_api.permissions import MayanPermission + +from .models import Folder +from .permissions import (PERMISSION_FOLDER_CREATE, + PERMISSION_FOLDER_DELETE, PERMISSION_FOLDER_EDIT, + PERMISSION_FOLDER_VIEW) +from .serializers import FolderSerializer + + +class APIFolderListView(generics.ListCreateAPIView): + """ + Returns a list of all the folders. + """ + + serializer_class = FolderSerializer + queryset = Folder.objects.all() + + permission_classes = (MayanPermission,) + filter_backends = (MayanObjectPermissionsFilter,) + mayan_object_permissions = {'GET': [PERMISSION_FOLDER_VIEW]} + mayan_view_permissions = {'POST': [PERMISSION_FOLDER_CREATE]} + + +class APIFolderView(generics.RetrieveUpdateDestroyAPIView): + """ + Returns the selected folder details. + """ + + serializer_class = FolderSerializer + queryset = Folder.objects.all() + + permission_classes = (MayanPermission,) + mayan_object_permissions = { + 'GET': [PERMISSION_FOLDER_VIEW], + 'PUT': [PERMISSION_FOLDER_EDIT], + 'PATCH': [PERMISSION_FOLDER_EDIT], + 'DELETE': [PERMISSION_FOLDER_DELETE] + } diff --git a/mayan/apps/folders/serializers.py b/mayan/apps/folders/serializers.py new file mode 100644 index 0000000000..f574de5906 --- /dev/null +++ b/mayan/apps/folders/serializers.py @@ -0,0 +1,11 @@ +from __future__ import absolute_import + +from rest_framework import serializers + +from .models import Folder + + +class FolderSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + fields = ('id', 'url', 'title', 'user', 'datetime_created') + model = Folder diff --git a/mayan/apps/folders/urls.py b/mayan/apps/folders/urls.py index 1fcd128534..dfb7a05161 100644 --- a/mayan/apps/folders/urls.py +++ b/mayan/apps/folders/urls.py @@ -1,5 +1,7 @@ from django.conf.urls import patterns, url +from .api_views import APIFolderListView, APIFolderView + urlpatterns = patterns('folders.views', url(r'^list/$', 'folder_list', (), 'folder_list'), url(r'^create/$', 'folder_create', (), 'folder_create'), @@ -14,3 +16,8 @@ urlpatterns = patterns('folders.views', url(r'^(?P\d+)/acl/list/$', 'folder_acl_list', (), 'folder_acl_list'), ) + +api_urls = patterns('', + url(r'^folders/$', APIFolderListView.as_view(), name='folder-list'), + url(r'^folders/(?P[0-9]+)/$', APIFolderView.as_view(), name='folder-detail'), +) From b7094260433d6421df118feec323fd7a0992ff22 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 21 Sep 2014 23:15:55 -0400 Subject: [PATCH 11/15] Add id to the document serializer, add required=False to the document type <-> document serialierz relation --- mayan/apps/documents/serializers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mayan/apps/documents/serializers.py b/mayan/apps/documents/serializers.py index 71d057cb9e..dc6d0d74b3 100644 --- a/mayan/apps/documents/serializers.py +++ b/mayan/apps/documents/serializers.py @@ -29,11 +29,12 @@ class DocumentSerializer(serializers.HyperlinkedModelSerializer): new_version = serializers.HyperlinkedIdentityField(view_name='document-new-version') class Meta: + fields = ('id', 'url', 'image', 'new_version', 'uuid', 'document_type', 'description', 'date_added', 'versions') model = Document class DocumentTypeSerializer(serializers.HyperlinkedModelSerializer): - documents = DocumentSerializer() + documents = DocumentSerializer(many=True, required=False) class Meta: model = DocumentType From def792790ce48789131726bd7539dbdb2a334b76 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 21 Sep 2014 23:17:10 -0400 Subject: [PATCH 12/15] A beautiful hack for an unknown problem: hidden imports. Hide the import for DocumentSerializer otherwise an unexplained ImportError is raised --- mayan/apps/folders/serializers.py | 9 +++++++++ mayan/apps/tags/serializers.py | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/mayan/apps/folders/serializers.py b/mayan/apps/folders/serializers.py index f574de5906..100fb91b91 100644 --- a/mayan/apps/folders/serializers.py +++ b/mayan/apps/folders/serializers.py @@ -6,6 +6,15 @@ from .models import Folder class FolderSerializer(serializers.HyperlinkedModelSerializer): + # FIXME: Doing a: from documents.serializers import DocumentSerializer + # causes an unexplained ImportError, so we import it hidden until the issue + # is resolved + + def __init__(self, *args, **kwargs): + from documents.serializers import DocumentSerializer + super(FolderSerializer, self).__init__(*args, **kwargs) + self.fields['documents'] = DocumentSerializer() + class Meta: fields = ('id', 'url', 'title', 'user', 'datetime_created') model = Folder diff --git a/mayan/apps/tags/serializers.py b/mayan/apps/tags/serializers.py index e6b44b5d10..36d6217648 100644 --- a/mayan/apps/tags/serializers.py +++ b/mayan/apps/tags/serializers.py @@ -5,6 +5,15 @@ from taggit.models import Tag class TagSerializer(serializers.HyperlinkedModelSerializer): + # FIXME: Doing a: from documents.serializers import DocumentSerializer + # causes an unexplained ImportError, so we import it hidden until the issue + # is resolved + + def __init__(self, *args, **kwargs): + from documents.serializers import DocumentSerializer + super(TagSerializer, self).__init__(*args, **kwargs) + self.fields['documents'] = DocumentSerializer() + color = serializers.CharField(source='properties.get.color') class Meta: From 36990ec8188cb6f72c2d8ffce86915a96915cc94 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Tue, 30 Sep 2014 09:58:42 -0400 Subject: [PATCH 13/15] Add document accesor method to display a document folders --- mayan/apps/folders/__init__.py | 5 +++++ mayan/apps/folders/views.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/mayan/apps/folders/__init__.py b/mayan/apps/folders/__init__.py index 0ada1ae8d7..0c5adc2842 100644 --- a/mayan/apps/folders/__init__.py +++ b/mayan/apps/folders/__init__.py @@ -48,6 +48,11 @@ class_permissions(Document, [ PERMISSION_FOLDER_REMOVE_DOCUMENT, ]) +def document_folders(self): + return Folder.objects.filter(folderdocument__document=self) + +Document.add_to_class('folders', property(document_folders)) + endpoint = APIEndPoint('folders') endpoint.register_urls(api_urls) endpoint.add_endpoint('folder-list', _(u'Returns a list of all the folders.')) diff --git a/mayan/apps/folders/views.py b/mayan/apps/folders/views.py index 2d75221141..c1537c5949 100644 --- a/mayan/apps/folders/views.py +++ b/mayan/apps/folders/views.py @@ -230,7 +230,7 @@ def document_folder_list(request, document_id): return folder_list( request, - queryset=Folder.objects.filter(folderdocument__document=document), + queryset=document.folders.all(), extra_context={ 'title': _(u'folders containing: %s') % document, 'object': document, From 6646f284338867f1d4fac13e47477fe35dceb2f1 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Fri, 3 Oct 2014 09:28:31 -0400 Subject: [PATCH 14/15] Add document folder list API endpoint --- mayan/apps/folders/api_views.py | 28 ++++++++++++++++++++++++++++ mayan/apps/folders/urls.py | 4 +++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/mayan/apps/folders/api_views.py b/mayan/apps/folders/api_views.py index ee7b8b0610..87c0cbc68a 100644 --- a/mayan/apps/folders/api_views.py +++ b/mayan/apps/folders/api_views.py @@ -1,7 +1,13 @@ from __future__ import absolute_import +from django.core.exceptions import PermissionDenied +from django.shortcuts import get_object_or_404 + from rest_framework import generics +from documents.models import Document +from documents.permissions import PERMISSION_DOCUMENT_VIEW +from permissions.models import Permission from rest_api.filters import MayanObjectPermissionsFilter from rest_api.permissions import MayanPermission @@ -41,3 +47,25 @@ class APIFolderView(generics.RetrieveUpdateDestroyAPIView): 'PATCH': [PERMISSION_FOLDER_EDIT], 'DELETE': [PERMISSION_FOLDER_DELETE] } + + +class APIDocumentFolderListView(generics.ListAPIView): + """ + Returns a list of all the folders to which a document belongs. + """ + + serializer_class = FolderSerializer + + permission_classes = (MayanPermission,) + filter_backends = (MayanObjectPermissionsFilter,) + mayan_object_permissions = {'GET': [PERMISSION_FOLDER_VIEW]} + + def get_queryset(self): + document = get_object_or_404(Document, pk=self.kwargs['pk']) + try: + Permission.objects.check_permissions(self.request.user, [PERMISSION_DOCUMENT_VIEW]) + except PermissionDenied: + AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, self.request.user, document) + + queryset = document.folders.all() + return queryset diff --git a/mayan/apps/folders/urls.py b/mayan/apps/folders/urls.py index dfb7a05161..ee030b514b 100644 --- a/mayan/apps/folders/urls.py +++ b/mayan/apps/folders/urls.py @@ -1,6 +1,7 @@ from django.conf.urls import patterns, url -from .api_views import APIFolderListView, APIFolderView +from .api_views import (APIDocumentFolderListView, APIFolderListView, + APIFolderView) urlpatterns = patterns('folders.views', url(r'^list/$', 'folder_list', (), 'folder_list'), @@ -20,4 +21,5 @@ urlpatterns = patterns('folders.views', api_urls = patterns('', url(r'^folders/$', APIFolderListView.as_view(), name='folder-list'), url(r'^folders/(?P[0-9]+)/$', APIFolderView.as_view(), name='folder-detail'), + url(r'^document/(?P[0-9]+)/folders/$', APIDocumentFolderListView.as_view(), name='document-folder-list'), ) From b20314cd435ce8597fd20c6f79fc97f80f475920 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Fri, 3 Oct 2014 09:28:59 -0400 Subject: [PATCH 15/15] Add document folder list API endpoint --- mayan/apps/tags/api_views.py | 28 ++++++++++++++++++++++++++++ mayan/apps/tags/serializers.py | 1 + mayan/apps/tags/urls.py | 3 ++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/mayan/apps/tags/api_views.py b/mayan/apps/tags/api_views.py index 203e08b8b5..602d36f43b 100644 --- a/mayan/apps/tags/api_views.py +++ b/mayan/apps/tags/api_views.py @@ -1,8 +1,14 @@ from __future__ import absolute_import +from django.core.exceptions import PermissionDenied +from django.shortcuts import get_object_or_404 + from rest_framework import generics from taggit.models import Tag +from documents.models import Document +from documents.permissions import PERMISSION_DOCUMENT_VIEW +from permissions.models import Permission from rest_api.filters import MayanObjectPermissionsFilter from rest_api.permissions import MayanPermission @@ -31,3 +37,25 @@ class APITagListView(generics.ListAPIView): filter_backends = (MayanObjectPermissionsFilter,) mayan_object_permissions = {'GET': [PERMISSION_TAG_VIEW]} + + +class APIDocumentTagListView(generics.ListAPIView): + """ + Returns a list of all the tags attached to a document. + """ + + serializer_class = TagSerializer + + permission_classes = (MayanPermission,) + filter_backends = (MayanObjectPermissionsFilter,) + mayan_object_permissions = {'GET': [PERMISSION_TAG_VIEW]} + + def get_queryset(self): + document = get_object_or_404(Document, pk=self.kwargs['pk']) + try: + Permission.objects.check_permissions(self.request.user, [PERMISSION_DOCUMENT_VIEW]) + except PermissionDenied: + AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, self.request.user, document) + + queryset = document.tags.all() + return queryset diff --git a/mayan/apps/tags/serializers.py b/mayan/apps/tags/serializers.py index 36d6217648..9bba498440 100644 --- a/mayan/apps/tags/serializers.py +++ b/mayan/apps/tags/serializers.py @@ -17,4 +17,5 @@ class TagSerializer(serializers.HyperlinkedModelSerializer): color = serializers.CharField(source='properties.get.color') class Meta: + fields = ('id', 'url', 'name', 'color', 'slug') model = Tag diff --git a/mayan/apps/tags/urls.py b/mayan/apps/tags/urls.py index 51d880aae4..fdcfe8b24d 100644 --- a/mayan/apps/tags/urls.py +++ b/mayan/apps/tags/urls.py @@ -2,7 +2,7 @@ from __future__ import absolute_import from django.conf.urls import patterns, url -from .api_views import APITagListView, APITagView +from .api_views import APIDocumentTagListView, APITagListView, APITagView urlpatterns = patterns('tags.views', url(r'^list/$', 'tag_list', (), 'tag_list'), @@ -26,4 +26,5 @@ urlpatterns = patterns('tags.views', api_urls = patterns('', url(r'^tags/(?P[0-9]+)/$', APITagView.as_view(), name='tag-detail'), url(r'^tags/$', APITagListView.as_view(), name='tag-list'), + url(r'^document/(?P[0-9]+)/tags/$', APIDocumentTagListView.as_view(), name='document-tag-list'), )