export_import: post bundle (#89034)
gitea/combo/pipeline/head This commit looks good Details

This commit is contained in:
Lauréline Guérin 2024-04-03 17:20:31 +02:00
parent 1a964cd76b
commit 10055d8e54
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
2 changed files with 66 additions and 42 deletions

View File

@ -14,13 +14,11 @@
# 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 io
import json
import tarfile
from django.contrib.auth.models import Group
from django.contrib.contenttypes.models import ContentType
from django.core.files.base import ContentFile
from django.http import Http404
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse
@ -202,11 +200,11 @@ def component_redirect(request, component_type, uuid):
class BundleCheck(GenericAPIView):
permission_classes = (permissions.IsAdminUser,)
def put(self, request, *args, **kwargs):
tar_io = io.BytesIO(request.read())
def post(self, request, *args, **kwargs):
bundle = request.FILES['bundle']
page_type = 'portal-agent-pages' if is_portal_agent() else 'pages'
try:
with tarfile.open(fileobj=tar_io) as tar:
with tarfile.open(fileobj=bundle) as tar:
try:
manifest = json.loads(tar.extractfile('manifest.json').read().decode())
except KeyError:
@ -314,10 +312,10 @@ class BundleImport(GenericAPIView):
permission_classes = (permissions.IsAdminUser,)
action = 'import_bundle'
def put(self, request, *args, **kwargs):
tar_io = io.BytesIO(request.read())
def post(self, request, *args, **kwargs):
bundle = request.FILES['bundle']
try:
with tarfile.open(fileobj=tar_io) as tar:
with tarfile.open(fileobj=bundle) as tar:
try:
manifest = json.loads(tar.extractfile('manifest.json').read().decode())
except KeyError:
@ -328,7 +326,7 @@ class BundleImport(GenericAPIView):
job = ApplicationAsyncJob(
action=self.action,
)
job.bundle.save('%s.tar' % application_slug, content=ContentFile(tar_io.getvalue()))
job.bundle.save('%s.tar' % application_slug, content=bundle)
job.save()
job.run(spool=True)
return Response({'err': 0, 'url': job.get_api_status_url(request)})

View File

@ -287,7 +287,7 @@ def test_bundle_import(app, admin_user):
)
bundles.append(bundle)
resp = app.put('/api/export-import/bundle-import/', bundles[0])
resp = app.post('/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', bundles[0])])
assert Page.objects.all().count() == 1
assert resp.json['err'] == 0
assert Application.objects.count() == 1
@ -321,7 +321,7 @@ def test_bundle_import(app, admin_user):
)
# check update
resp = app.put('/api/export-import/bundle-import/', bundles[1])
resp = app.post('/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', bundles[1])])
job_url = resp.json['url']
resp = app.get(job_url)
assert resp.json['data']['status'] == 'completed'
@ -347,7 +347,9 @@ def test_bundle_import(app, admin_user):
assert last_snapshot.application_version == '42.1'
# bad file format
resp = app.put('/api/export-import/bundle-import/', b'garbage', status=400)
resp = app.post(
'/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', b'garbage')], status=400
)
assert resp.json['err']
assert resp.json['err_desc'] == 'Invalid tar file'
@ -358,7 +360,11 @@ def test_bundle_import(app, admin_user):
tarinfo = tarfile.TarInfo('foo.json')
tarinfo.size = len(foo_fd.getvalue())
tar.addfile(tarinfo, fileobj=foo_fd)
resp = app.put('/api/export-import/bundle-import/', tar_io.getvalue(), status=400)
resp = app.post(
'/api/export-import/bundle-import/',
upload_files=[('bundle', 'bundle.tar', tar_io.getvalue())],
status=400,
)
assert resp.json['err']
assert resp.json['err_desc'] == 'Invalid tar file, missing manifest'
@ -374,7 +380,9 @@ def test_bundle_import(app, admin_user):
tarinfo = tarfile.TarInfo('manifest.json')
tarinfo.size = len(manifest_fd.getvalue())
tar.addfile(tarinfo, fileobj=manifest_fd)
resp = app.put('/api/export-import/bundle-import/', tar_io.getvalue())
resp = app.post(
'/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', tar_io.getvalue())]
)
job_url = resp.json['url']
resp = app.get(job_url)
assert resp.json['data']['status'] == 'failed'
@ -460,7 +468,7 @@ def test_bundle_import_pages_position(app, admin_user):
)
# import bundle
resp = app.put('/api/export-import/bundle-import/', bundle)
resp = app.post('/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', bundle)])
assert resp.json['err'] == 0
# pages from application are placed at the end
@ -506,7 +514,7 @@ def test_bundle_import_pages_position(app, admin_user):
)
# import bundle
resp = app.put('/api/export-import/bundle-import/', bundle)
resp = app.post('/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', bundle)])
assert resp.json['err'] == 0
# pages from application are placed before page3
@ -552,7 +560,7 @@ def test_bundle_import_pages_position(app, admin_user):
)
# import bundle
resp = app.put('/api/export-import/bundle-import/', bundle)
resp = app.post('/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', bundle)])
assert resp.json['err'] == 0
# pages from application are placed between page3 and page4
@ -598,7 +606,7 @@ def test_bundle_import_pages_position(app, admin_user):
page2 = Page.objects.create(slug='test2', title='Test Page 2', template_name='standard', uuid=page2.uuid)
# import bundle
resp = app.put('/api/export-import/bundle-import/', bundle)
resp = app.post('/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', bundle)])
assert resp.json['err'] == 0
# pages from application are placed after page4
@ -656,7 +664,7 @@ def test_bundle_import_pages_position(app, admin_user):
)
# import bundle
resp = app.put('/api/export-import/bundle-import/', bundle)
resp = app.post('/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', bundle)])
assert resp.json['err'] == 0
# pages from application are placed under page3
@ -723,7 +731,7 @@ def test_bundle_import_pages_position(app, admin_user):
)
# import bundle
resp = app.put('/api/export-import/bundle-import/', bundle)
resp = app.post('/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', bundle)])
assert resp.json['err'] == 0
# page1 is placed under page3, pages 11, 12, 121, 13 are placed between page41 and page42
@ -750,7 +758,7 @@ def test_bundle_import_pages_position(app, admin_user):
assert Page.objects.get(uuid=page42.uuid).parent.uuid == page4.uuid
# again, import bundle
resp = app.put('/api/export-import/bundle-import/', bundle)
resp = app.post('/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', bundle)])
assert resp.json['err'] == 0
# no changes
@ -824,7 +832,7 @@ def test_bundle_import_pages_position(app, admin_user):
)
# import bundle
resp = app.put('/api/export-import/bundle-import/', bundle)
resp = app.post('/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', bundle)])
assert resp.json['err'] == 0
# page1 is placed under page3, pages 11, 12, 13 are placed between page41 and page42, page 121 stays under page2
@ -851,7 +859,7 @@ def test_bundle_import_pages_position(app, admin_user):
assert Page.objects.get(uuid=page42.uuid).parent.uuid == page4.uuid
# again, import bundle
resp = app.put('/api/export-import/bundle-import/', bundle)
resp = app.post('/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', bundle)])
assert resp.json['err'] == 0
# no changes
@ -906,7 +914,7 @@ def test_bundle_import_pages_position(app, admin_user):
)
# import bundle
resp = app.put('/api/export-import/bundle-import/', bundle)
resp = app.post('/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', bundle)])
assert resp.json['err'] == 0
# page1 and page2 are placed after page4, but can not decide if page13 should be place next to page11 or page12.
@ -943,7 +951,7 @@ def test_bundle_declare(app, admin_user):
(f'pages/{page.uuid}', page),
visible=False,
)
resp = app.put('/api/export-import/bundle-declare/', bundle)
resp = app.post('/api/export-import/bundle-declare/', upload_files=[('bundle', 'bundle.tar', bundle)])
job_url = resp.json['url']
resp = app.get(job_url)
assert resp.json['data']['status'] == 'completed'
@ -984,14 +992,16 @@ def test_bundle_declare(app, admin_user):
# and remove a page to have an unkown reference in manifest
Page.objects.all().delete()
resp = app.put('/api/export-import/bundle-declare/', bundle)
resp = app.post('/api/export-import/bundle-declare/', upload_files=[('bundle', 'bundle.tar', bundle)])
assert Application.objects.count() == 1
application = Application.objects.latest('pk')
assert application.visible is True
assert ApplicationElement.objects.count() == 0
# bad file format
resp = app.put('/api/export-import/bundle-declare/', b'garbage', status=400)
resp = app.post(
'/api/export-import/bundle-declare/', upload_files=[('bundle', 'bundle.tar', b'garbage')], status=400
)
assert resp.json['err']
assert resp.json['err_desc'] == 'Invalid tar file'
@ -1002,7 +1012,11 @@ def test_bundle_declare(app, admin_user):
tarinfo = tarfile.TarInfo('foo.json')
tarinfo.size = len(foo_fd.getvalue())
tar.addfile(tarinfo, fileobj=foo_fd)
resp = app.put('/api/export-import/bundle-declare/', tar_io.getvalue(), status=400)
resp = app.post(
'/api/export-import/bundle-declare/',
upload_files=[('bundle', 'bundle.tar', tar_io.getvalue())],
status=400,
)
assert resp.json['err']
assert resp.json['err_desc'] == 'Invalid tar file, missing manifest'
@ -1018,7 +1032,9 @@ def test_bundle_declare(app, admin_user):
tarinfo = tarfile.TarInfo('manifest.json')
tarinfo.size = len(manifest_fd.getvalue())
tar.addfile(tarinfo, fileobj=manifest_fd)
resp = app.put('/api/export-import/bundle-declare/', tar_io.getvalue())
resp = app.post(
'/api/export-import/bundle-declare/', upload_files=[('bundle', 'bundle.tar', tar_io.getvalue())]
)
job_url = resp.json['url']
resp = app.get(job_url)
assert resp.json['data']['status'] == 'failed'
@ -1117,13 +1133,17 @@ def test_bundle_check(app, admin_user):
incomplete_bundles.append(tar_io.getvalue())
# incorrect bundles, missing information
resp = app.put('/api/export-import/bundle-check/', incomplete_bundles[0])
resp = app.post(
'/api/export-import/bundle-check/', upload_files=[('bundle', 'bundle.tar', incomplete_bundles[0])]
)
assert resp.json == {'data': {}}
resp = app.put('/api/export-import/bundle-check/', incomplete_bundles[1])
resp = app.post(
'/api/export-import/bundle-check/', upload_files=[('bundle', 'bundle.tar', incomplete_bundles[1])]
)
assert resp.json == {'data': {}}
# not yet imported
resp = app.put('/api/export-import/bundle-check/', bundles[0])
resp = app.post('/api/export-import/bundle-check/', upload_files=[('bundle', 'bundle.tar', bundles[0])])
assert resp.json == {
'data': {
'differences': [],
@ -1136,13 +1156,13 @@ def test_bundle_check(app, admin_user):
}
# import bundle
resp = app.put('/api/export-import/bundle-import/', bundles[0])
resp = app.post('/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', bundles[0])])
assert Application.objects.count() == 1
assert ApplicationElement.objects.count() == 1
# remove application links
Application.objects.all().delete()
resp = app.put('/api/export-import/bundle-check/', bundles[0])
resp = app.post('/api/export-import/bundle-check/', upload_files=[('bundle', 'bundle.tar', bundles[0])])
assert resp.json == {
'data': {
'differences': [],
@ -1160,12 +1180,12 @@ def test_bundle_check(app, admin_user):
}
# import bundle again, recreate links
resp = app.put('/api/export-import/bundle-import/', bundles[0])
resp = app.post('/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', bundles[0])])
assert Application.objects.count() == 1
assert ApplicationElement.objects.count() == 1
# no changes since last import
resp = app.put('/api/export-import/bundle-check/', bundles[0])
resp = app.post('/api/export-import/bundle-check/', upload_files=[('bundle', 'bundle.tar', bundles[0])])
assert resp.json == {
'data': {
'differences': [],
@ -1185,7 +1205,7 @@ def test_bundle_check(app, admin_user):
snapshots['page:%s' % page.slug] = (old_snapshot.pk, new_snapshot.pk)
# and check
resp = app.put('/api/export-import/bundle-check/', bundles[0])
resp = app.post('/api/export-import/bundle-check/', upload_files=[('bundle', 'bundle.tar', bundles[0])])
assert resp.json == {
'data': {
'differences': [
@ -1203,10 +1223,10 @@ def test_bundle_check(app, admin_user):
}
# update bundle
resp = app.put('/api/export-import/bundle-import/', bundles[1])
resp = app.post('/api/export-import/bundle-import/', upload_files=[('bundle', 'bundle.tar', bundles[1])])
# and check
resp = app.put('/api/export-import/bundle-check/', bundles[1])
resp = app.post('/api/export-import/bundle-check/', upload_files=[('bundle', 'bundle.tar', bundles[1])])
assert resp.json == {
'data': {
'differences': [],
@ -1218,7 +1238,7 @@ def test_bundle_check(app, admin_user):
# snapshots without application info
PageSnapshot.objects.update(application_slug=None, application_version=None)
resp = app.put('/api/export-import/bundle-check/', bundles[1])
resp = app.post('/api/export-import/bundle-check/', upload_files=[('bundle', 'bundle.tar', bundles[1])])
assert resp.json == {
'data': {
'differences': [],
@ -1231,7 +1251,9 @@ def test_bundle_check(app, admin_user):
}
# bad file format
resp = app.put('/api/export-import/bundle-check/', b'garbage', status=400)
resp = app.post(
'/api/export-import/bundle-check/', upload_files=[('bundle', 'bundle.tar', b'garbage')], status=400
)
assert resp.json['err']
assert resp.json['err_desc'] == 'Invalid tar file'
@ -1242,7 +1264,11 @@ def test_bundle_check(app, admin_user):
tarinfo = tarfile.TarInfo('foo.json')
tarinfo.size = len(foo_fd.getvalue())
tar.addfile(tarinfo, fileobj=foo_fd)
resp = app.put('/api/export-import/bundle-check/', tar_io.getvalue(), status=400)
resp = app.post(
'/api/export-import/bundle-check/',
upload_files=[('bundle', 'bundle.tar', tar_io.getvalue())],
status=400,
)
assert resp.json['err']
assert resp.json['err_desc'] == 'Invalid tar file, missing manifest'