assets: add basic API to upload an asset from wcs (#22391)

This commit is contained in:
Frédéric Péters 2019-08-12 22:37:10 +02:00
parent d782655ff4
commit e375bf09e8
3 changed files with 112 additions and 0 deletions

View File

@ -0,0 +1,64 @@
# combo - content management system
# Copyright (C) 2019 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 <http://www.gnu.org/licenses/>.
import base64
from django.core.files import File
from django.utils.six import BytesIO
from rest_framework import serializers, permissions, status
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from .models import Asset
class FileSerializer(serializers.Serializer):
content = serializers.CharField(required=True, allow_blank=False)
content_type = serializers.CharField(required=False, allow_null=True)
filename = serializers.CharField(required=False, allow_null=True)
def validate_content(self, value):
try:
return base64.decodestring(value.encode('ascii'))
except Exception as e:
raise serializers.ValidationError('content must be base64 (%r)' % e)
class AssetSerializer(serializers.Serializer):
asset = FileSerializer(required=True)
class Set(GenericAPIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = AssetSerializer
def post(self, request, key, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
if not serializer.is_valid():
response = {'err': 1, 'err_desc': serializer.errors}
return Response(response, status.HTTP_400_BAD_REQUEST)
data = serializer.validated_data
asset, created = Asset.objects.get_or_create(key=key)
asset.asset = File(
BytesIO(data['asset']['content']),
name=data['asset'].get('filename'))
asset.save()
response = {'err': 0}
return Response(response)
view_set = Set.as_view()

View File

@ -19,6 +19,7 @@ from django.conf.urls import url, include
from combo.urls_utils import decorated_includes, manager_required
from . import views
from . import api_views
assets_manager_urls = [
url(r'^$', views.assets, name='combo-manager-assets'),
@ -35,4 +36,7 @@ urlpatterns = [
url(r'^assets/(?P<key>[\w_:-]+)$', views.serve_asset),
url(r'^manage/assets/', decorated_includes(manager_required,
include(assets_manager_urls))),
url('^api/assets/set/(?P<key>[\w_:-]+)/$', api_views.view_set,
name='api-assets-set'),
]

44
tests/test_assets.py Normal file
View File

@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
import base64
from django.core.urlresolvers import reverse
import pytest
from combo.apps.assets.models import Asset
pytestmark = pytest.mark.django_db
def test_asset_set_api(app, john_doe):
app.authorization = ('Basic', (john_doe.username, john_doe.username))
resp = app.post_json(reverse('api-assets-set', kwargs={'key': 'plop'}), params={
'asset': {
'content': base64.encodestring(b'plop').decode('ascii'),
'content_type': 'text/plain',
'filename': 'plop.txt',
}
})
assert Asset.objects.get(key='plop').asset.read() == b'plop'
resp = app.post_json(reverse('api-assets-set', kwargs={'key': 'plop'}), params={
'asset': {
'content': base64.encodestring(b'plop2').decode('ascii'),
'content_type': 'text/plain',
'filename': 'plop.txt',
}
})
assert Asset.objects.get(key='plop').asset.read() == b'plop2'
resp = app.post_json(reverse('api-assets-set', kwargs={'key': 'plop'}), params={}, status=400)
assert resp.json.get('err') == 1
for invalid_value in (None, 'not base 64', u'éléphant'):
resp = app.post_json(reverse('api-assets-set', kwargs={'key': 'plop'}), params={
'asset': {
'content': invalid_value,
'content_type': 'text/plain',
'filename': 'plop.txt',
}
}, status=400)
assert resp.json.get('err') == 1