From aa36e3ac6e1740b510e69d86a6d60e6606fa92dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Fri, 12 Feb 2016 15:33:00 +0100 Subject: [PATCH] general: add API to push documents (#7080) --- fargo/fargo/api_views.py | 107 +++++++++++++++++++++++++++++++++++++++++++++++ fargo/settings.py | 18 ++++++++ fargo/urls.py | 3 ++ setup.py | 1 + 4 files changed, 129 insertions(+) create mode 100644 fargo/fargo/api_views.py diff --git a/fargo/fargo/api_views.py b/fargo/fargo/api_views.py new file mode 100644 index 0000000..afe69a4 --- /dev/null +++ b/fargo/fargo/api_views.py @@ -0,0 +1,107 @@ +# fargo - document box +# Copyright (C) 2015-2016 Entr'ouvert +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import base64 + +from django.conf import settings +from django.core.files.base import ContentFile +from django.contrib.auth.models import User +from django.utils.text import slugify + +from rest_framework import serializers, authentication +from rest_framework.decorators import permission_classes +from rest_framework.generics import GenericAPIView +from rest_framework.permissions import IsAdminUser +from rest_framework.response import Response +from rest_framework import permissions, status + +from .models import Origin, Document, UserDocument, Validation + +try: + from mellon.models import UserSAMLIdentifier +except ImportError: + UserSAMLIdentifier = None + + +class PushDocumentSerializer(serializers.Serializer): + origin = serializers.CharField(required=True) + file_b64_content = serializers.CharField(required=True) + file_name = serializers.CharField(required=False) + document_type = serializers.ChoiceField(required=True, + choices=[x.get('name') for x in settings.FARGO_DOCUMENT_TYPES]) + user_email = serializers.CharField(required=False) + user_nameid = serializers.CharField(required=False) + + def validate(self, data): + if not (data.get('user_email') or data.get('user_nameid')): + raise serializers.ValidationError('user must be specified') + return data + + def validate_user_email(self, value): + try: + user = User.objects.get(email=value) + except User.DoesNotExist: + raise serializers.ValidationError('unknown user') + return value + + def validate_user_nameid(self, value): + if UserSAMLIdentifier is None: + raise serializers.ValidationError('nameid lookups require django-mellon') + try: + UserSAMLIdentifier.objects.get(name_id=value) + except UserSAMLIdentifier.DoesNotExist: + raise serializers.ValidationError('unknown user') + return value + + +class PushDocument(GenericAPIView): + serializer_class = PushDocumentSerializer + permission_classes = (IsAdminUser,) + + def post(self, request, format=None): + serializer = self.get_serializer(data=request.data) + if not serializer.is_valid(): + response = {'result': 0, 'errors': serializer.errors} + return Response(response, status.HTTP_400_BAD_REQUEST) + + data = serializer.validated_data + if data.get('user_email'): + user = User.objects.get(email=data.get('user_email')) + elif data.get('user_nameid'): + user = UserSAMLIdentifier.objects.get(name_id=data.get('user_nameid')).user + + origin, created = Origin.objects.get_or_create( + slug=slugify(data.get('origin')), + defaults={'label': data.get('origin')}) + + document_file = ContentFile(base64.decodestring(data.get('file_b64_content'))) + if data.get('file_name'): + document_file.name = data.get('file_name') + document = Document(content=document_file) + document.save() + + user_document = UserDocument( + user=user, + filename=data.get('file_name'), + document=document, + origin=origin) + user_document.save() + + response = {'hello': 'world'} + response_status = status.HTTP_200_OK + return Response(response, response_status) + +push_document = PushDocument.as_view() diff --git a/fargo/settings.py b/fargo/settings.py index 346fabd..174eaba 100644 --- a/fargo/settings.py +++ b/fargo/settings.py @@ -41,6 +41,7 @@ INSTALLED_APPS = ( 'django_tables2', 'gadjo', 'fargo.fargo', + 'rest_framework', ) MIDDLEWARE_CLASSES = ( @@ -148,6 +149,23 @@ FARGO_DOCUMENT_TYPES = [ LOGIN_REDIRECT_URL = 'home' +REST_FRAMEWORK = { + 'NON_FIELD_ERRORS_KEY': '__all__', + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'rest_framework.authentication.BasicAuthentication', + 'rest_framework.authentication.SessionAuthentication', + ), + 'DEFAULT_PERMISSION_CLASSES': ( + 'rest_framework.permissions.IsAuthenticated', + ), + 'DEFAULT_FILTER_BACKENDS': ( + 'rest_framework.filters.DjangoFilterBackend', + 'rest_framework.filters.OrderingFilter', + ), + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', + 'PAGE_SIZE': 10, +} + local_settings_file = os.environ.get('FARGO_SETTINGS_FILE', os.path.join(os.path.dirname(__file__), 'local_settings.py')) diff --git a/fargo/urls.py b/fargo/urls.py index 86d5b15..cf1ff3b 100644 --- a/fargo/urls.py +++ b/fargo/urls.py @@ -5,6 +5,7 @@ from django.contrib import admin from .fargo.views import (home, jsonp, json, document, download, pick, delete, upload, remote_download, login, logout, pick_list, metadata, validation, document_types) +from .fargo.api_views import (push_document, ) urlpatterns = patterns( '', @@ -28,6 +29,8 @@ urlpatterns = patterns( url(r'^login/$', login, name='auth_login'), url(r'^logout/$', logout, name='auth_logout'), url(r'^document-types/$', document_types, name='document_types'), + + url(r'^api/push-document', push_document, name='api-push-document'), ) diff --git a/setup.py b/setup.py index 6d0edbe..82e2cc1 100755 --- a/setup.py +++ b/setup.py @@ -98,6 +98,7 @@ setup( 'gadjo', 'django-tables2', 'django-jsonfield >= 0.9.3', + 'djangorestframework>=3.1', ], zip_safe=False, cmdclass={ -- 2.7.0