diff --git a/client/src/components/learningPath/DocumentUploadForm.vue b/client/src/components/learningPath/DocumentUploadForm.vue
index 628a46c6..966447ea 100644
--- a/client/src/components/learningPath/DocumentUploadForm.vue
+++ b/client/src/components/learningPath/DocumentUploadForm.vue
@@ -83,9 +83,7 @@ function showFileInformation() {
-
+
{{ $t("circlePage.documents.modalAction") }}
diff --git a/docs/file_uploads.md b/docs/file_uploads.md
index d76310a4..e470e326 100644
--- a/docs/file_uploads.md
+++ b/docs/file_uploads.md
@@ -11,6 +11,26 @@ There are buckets for each environment:
- myvbv-stage.iterativ.ch
- myvbv-prod.iterativ.ch
+Add the following CORS configuration under bucket -> permissions
+
+```
+[
+ {
+ "AllowedHeaders": [
+ "*"
+ ],
+ "AllowedMethods": [
+ "POST",
+ "GET"
+ ],
+ "AllowedOrigins": [
+ "*"
+ ],
+ "ExposeHeaders": []
+ }
+]
+```
+
## IAM Users
In order to access the buckets a user is required. These users are created in
diff --git a/server/vbv_lernwelt/course/migrations/0008_circledocument.py b/server/vbv_lernwelt/course/migrations/0008_circledocument.py
index 261310f4..21a0c355 100644
--- a/server/vbv_lernwelt/course/migrations/0008_circledocument.py
+++ b/server/vbv_lernwelt/course/migrations/0008_circledocument.py
@@ -5,7 +5,6 @@ from django.db import migrations, models
class Migration(migrations.Migration):
-
dependencies = [
("files", "0001_initial"),
("learnpath", "0008_alter_learningcontent_contents"),
@@ -37,7 +36,7 @@ class Migration(migrations.Migration):
(
"file",
models.OneToOneField(
- on_delete=django.db.models.deletion.CASCADE, to="files.file"
+ on_delete=django.db.models.deletion.CASCADE, to="files.uploadfile"
),
),
(
diff --git a/server/vbv_lernwelt/course/models.py b/server/vbv_lernwelt/course/models.py
index 2179f25f..f37503b3 100644
--- a/server/vbv_lernwelt/course/models.py
+++ b/server/vbv_lernwelt/course/models.py
@@ -7,7 +7,7 @@ from wagtail.models import Page
from vbv_lernwelt.core.model_utils import find_available_slug
from vbv_lernwelt.core.models import User
from vbv_lernwelt.course.serializer_helpers import get_course_serializer_class
-from vbv_lernwelt.files.models import File
+from vbv_lernwelt.files.models import UploadFile
class Course(models.Model):
@@ -241,7 +241,7 @@ class CourseSessionUser(models.Model):
class CircleDocument(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
- file = models.OneToOneField(File, on_delete=models.CASCADE)
+ file = models.OneToOneField(UploadFile, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
course_session = models.ForeignKey("course.CourseSession", on_delete=models.CASCADE)
diff --git a/server/vbv_lernwelt/course/tests/test_document_uploads.py b/server/vbv_lernwelt/course/tests/test_document_uploads.py
index 526667e3..4c55cbf9 100644
--- a/server/vbv_lernwelt/course/tests/test_document_uploads.py
+++ b/server/vbv_lernwelt/course/tests/test_document_uploads.py
@@ -6,7 +6,7 @@ from vbv_lernwelt.core.models import User
from vbv_lernwelt.course.consts import COURSE_TEST_ID
from vbv_lernwelt.course.creators.test_course import create_test_course
from vbv_lernwelt.course.models import CircleDocument, CourseSession, CourseSessionUser
-from vbv_lernwelt.files.models import File
+from vbv_lernwelt.files.models import UploadFile
from vbv_lernwelt.learnpath.models import Circle, LearningSequence
@@ -66,7 +66,7 @@ class DocumentUploadApiTestCase(APITestCase):
)
file_id = response.data["file_id"]
- file = File.objects.get(id=file_id)
+ file = UploadFile.objects.get(id=file_id)
self.assertIsNone(file.upload_finished_at)
@@ -109,11 +109,11 @@ class DocumentUploadApiTestCase(APITestCase):
self.assertEqual(response.status_code, 200)
self.assertNotEqual(response.data["url"], "")
- file = File.objects.get(id=file_id)
+ file = UploadFile.objects.get(id=file_id)
self.assertIsNotNone(file.upload_finished_at)
def test_can_only_finish_own_files(self):
- file = File(
+ file = UploadFile(
original_file_name="test.pdf",
file_name="test.pdf",
file_type="application/pdf",
@@ -131,7 +131,7 @@ class DocumentUploadApiTestCase(APITestCase):
ls = LearningSequence.objects.get(
slug="test-lehrgang-lp-circle-analyse-ls-beobachten"
)
- file = File(
+ file = UploadFile(
original_file_name="test.pdf",
file_name="test.pdf",
file_type="application/pdf",
@@ -157,7 +157,7 @@ class DocumentUploadApiTestCase(APITestCase):
except CircleDocument.DoesNotExist:
pass
- file = File.objects.get(id=file.id)
+ file = UploadFile.objects.get(id=file.id)
self.assertIsNone(file.upload_finished_at)
def test_student_cannot_delete_document(self):
@@ -165,7 +165,7 @@ class DocumentUploadApiTestCase(APITestCase):
ls = LearningSequence.objects.get(
slug="test-lehrgang-lp-circle-analyse-ls-beobachten"
)
- file = File(
+ file = UploadFile(
original_file_name="test.pdf",
file_name="test.pdf",
file_type="application/pdf",
@@ -185,7 +185,6 @@ class DocumentUploadApiTestCase(APITestCase):
response = self.client.delete(f"/api/core/document/{document.id}/")
self.assertEqual(response.status_code, 403)
-
# expert cannot upload in other course
# expert cannot delete other upload
# exper cannot change course
diff --git a/server/vbv_lernwelt/course/views.py b/server/vbv_lernwelt/course/views.py
index e235db7e..137aa372 100644
--- a/server/vbv_lernwelt/course/views.py
+++ b/server/vbv_lernwelt/course/views.py
@@ -23,7 +23,7 @@ from vbv_lernwelt.course.serializers import (
DocumentUploadStartInputSerializer,
)
from vbv_lernwelt.course.services import mark_course_completion
-from vbv_lernwelt.files.models import File
+from vbv_lernwelt.files.models import UploadFile
from vbv_lernwelt.files.services import FileDirectUploadService
from vbv_lernwelt.learnpath.utils import get_wagtail_type
@@ -148,11 +148,11 @@ def get_course_session_users(request, course_slug):
data = {
"cockpit_user": cockpit_user_csu[0].to_dict()
- | {
- "circles": cockpit_user_csu[0]
- .expert.all()
- .values("id", "title", "slug", "translation_key")
- },
+ | {
+ "circles": cockpit_user_csu[0]
+ .expert.all()
+ .values("id", "title", "slug", "translation_key")
+ },
"users": user_data,
}
@@ -200,7 +200,7 @@ def document_upload_finish(request):
serializer.is_valid(raise_exception=True)
file_id = serializer.validated_data["file_id"]
- file = get_object_or_404(File, id=file_id)
+ file = get_object_or_404(UploadFile, id=file_id)
if file.uploaded_by != request.user:
raise PermissionDenied()
@@ -213,7 +213,7 @@ def document_upload_finish(request):
@api_view(["POST"])
def document_direct_upload(request, file_id):
- file = get_object_or_404(File, id=file_id)
+ file = get_object_or_404(UploadFile, id=file_id)
file_obj = request.FILES["file"]
diff --git a/server/vbv_lernwelt/files/management/commands/delete_unreferenced_files.py b/server/vbv_lernwelt/files/management/commands/delete_unreferenced_files.py
index 90f6ac21..e968f9b2 100644
--- a/server/vbv_lernwelt/files/management/commands/delete_unreferenced_files.py
+++ b/server/vbv_lernwelt/files/management/commands/delete_unreferenced_files.py
@@ -1,6 +1,6 @@
from django.core.management.base import BaseCommand
-from vbv_lernwelt.files.models import File
+from vbv_lernwelt.files.models import UploadFile
class Command(BaseCommand):
@@ -20,7 +20,7 @@ class Command(BaseCommand):
num_deleted = 0
- unreferenced_uploads = File.objects.filter(upload_finished_at__isnull=True)
+ unreferenced_uploads = UploadFile.objects.filter(upload_finished_at__isnull=True)
if dry_run:
print("------ DRY RUN -------")
diff --git a/server/vbv_lernwelt/files/migrations/0001_initial.py b/server/vbv_lernwelt/files/migrations/0001_initial.py
index 0f4f89df..810bbfea 100644
--- a/server/vbv_lernwelt/files/migrations/0001_initial.py
+++ b/server/vbv_lernwelt/files/migrations/0001_initial.py
@@ -17,7 +17,7 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
- name="File",
+ name="UploadFile",
fields=[
(
"id",
diff --git a/server/vbv_lernwelt/files/models.py b/server/vbv_lernwelt/files/models.py
index 30271730..69a3dd12 100644
--- a/server/vbv_lernwelt/files/models.py
+++ b/server/vbv_lernwelt/files/models.py
@@ -11,7 +11,7 @@ from vbv_lernwelt.files.utils import file_generate_upload_path
# Code https://github.com/HackSoftware/Django-Styleguide-Example/tree/bdadf52b849bb5fa47854a3094f4da6fe9d54d02/styleguide_example/files
-class File(models.Model):
+class UploadFile(models.Model):
file = models.FileField(upload_to=file_generate_upload_path, blank=True, null=True)
original_file_name = models.TextField()
diff --git a/server/vbv_lernwelt/files/services.py b/server/vbv_lernwelt/files/services.py
index 43ed8924..bfdb8896 100644
--- a/server/vbv_lernwelt/files/services.py
+++ b/server/vbv_lernwelt/files/services.py
@@ -9,7 +9,7 @@ from django.utils import timezone
from vbv_lernwelt.core.models import User
from vbv_lernwelt.files.enums import FileUploadStorage
from vbv_lernwelt.files.integrations import s3_generate_presigned_post
-from vbv_lernwelt.files.models import File
+from vbv_lernwelt.files.models import UploadFile
from vbv_lernwelt.files.utils import (
bytes_to_mib,
file_generate_local_upload_url,
@@ -59,12 +59,12 @@ class FileStandardUploadService:
return file_name, file_type
@transaction.atomic
- def create(self, file_name: str = "", file_type: str = "") -> File:
+ def create(self, file_name: str = "", file_type: str = "") -> UploadFile:
_validate_file_size(self.file_obj)
file_name, file_type = self._infer_file_name_and_type(file_name, file_type)
- obj = File(
+ obj = UploadFile(
file=self.file_obj,
original_file_name=file_name,
file_name=file_generate_name(file_name),
@@ -79,7 +79,7 @@ class FileStandardUploadService:
return obj
@transaction.atomic
- def update(self, file: File, file_name: str = "", file_type: str = "") -> File:
+ def update(self, file: UploadFile, file_name: str = "", file_type: str = "") -> UploadFile:
_validate_file_size(self.file_obj)
file_name, file_type = self._infer_file_name_and_type(file_name, file_type)
@@ -111,8 +111,8 @@ class FileDirectUploadService:
self.user = user
@transaction.atomic
- def start(self, file_name: str, file_type: str) -> Tuple[File, Dict[str, Any]]:
- file = File(
+ def start(self, file_name: str, file_type: str) -> Tuple[UploadFile, Dict[str, Any]]:
+ file = UploadFile(
original_file_name=file_name,
file_name=file_generate_name(file_name),
file_type=file_type,
@@ -145,7 +145,7 @@ class FileDirectUploadService:
return file, presigned_data
@transaction.atomic
- def finish(self, *, file: File) -> File:
+ def finish(self, *, file: UploadFile) -> UploadFile:
# Potentially, check against user
file.upload_finished_at = timezone.now()
file.full_clean()
@@ -154,7 +154,7 @@ class FileDirectUploadService:
return file
@transaction.atomic
- def upload_local(self, *, file: File, file_obj) -> File:
+ def upload_local(self, *, file: UploadFile, file_obj) -> UploadFile:
_validate_file_size(file_obj)
# Potentially, check against user