From 3a58f869bb8282e85a89bb269d6f3d4d1ad9ee7a Mon Sep 17 00:00:00 2001 From: Topvennie Date: Tue, 14 May 2024 10:59:16 +0200 Subject: [PATCH 1/8] fix: docker image owner --- backend/api/serializers/docker_serializer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/api/serializers/docker_serializer.py b/backend/api/serializers/docker_serializer.py index eb009eb3..ee7b2c1f 100644 --- a/backend/api/serializers/docker_serializer.py +++ b/backend/api/serializers/docker_serializer.py @@ -13,7 +13,8 @@ class Meta: def validate(self, attrs): data = super().validate(attrs=attrs) - data["owner"] = self.context["request"].user + if not self.partial: + data["owner"] = self.context["request"].user if "public" in data and data["public"] and not data["owner"].is_staff: raise ValidationError(_("docker.errors.custom")) From f94c42180ad4680d532c9bae397650d292ba1129 Mon Sep 17 00:00:00 2001 From: Topvennie Date: Wed, 15 May 2024 18:19:39 +0200 Subject: [PATCH 2/8] fix: crash from partial update --- backend/api/serializers/docker_serializer.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/api/serializers/docker_serializer.py b/backend/api/serializers/docker_serializer.py index ee7b2c1f..115da192 100644 --- a/backend/api/serializers/docker_serializer.py +++ b/backend/api/serializers/docker_serializer.py @@ -15,6 +15,8 @@ def validate(self, attrs): if not self.partial: data["owner"] = self.context["request"].user + else: + data["owner"] = self.instance.owner if "public" in data and data["public"] and not data["owner"].is_staff: raise ValidationError(_("docker.errors.custom")) From 087a8f45dde5b5c647ccf52aecc55df02e9bfeb6 Mon Sep 17 00:00:00 2001 From: Topvennie Date: Wed, 15 May 2024 18:34:24 +0200 Subject: [PATCH 3/8] chore: allow owner updates --- backend/api/serializers/docker_serializer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/api/serializers/docker_serializer.py b/backend/api/serializers/docker_serializer.py index 115da192..3dfdce99 100644 --- a/backend/api/serializers/docker_serializer.py +++ b/backend/api/serializers/docker_serializer.py @@ -16,7 +16,7 @@ def validate(self, attrs): if not self.partial: data["owner"] = self.context["request"].user else: - data["owner"] = self.instance.owner + data["owner"] = data["owner"] if "owner" in data else self.instance.owner if "public" in data and data["public"] and not data["owner"].is_staff: raise ValidationError(_("docker.errors.custom")) From cac233ac1f211555ef6155f3b2e00a398a1702a4 Mon Sep 17 00:00:00 2001 From: Topvennie Date: Wed, 15 May 2024 18:35:52 +0200 Subject: [PATCH 4/8] chore: cleanup my booboo --- backend/api/serializers/docker_serializer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/api/serializers/docker_serializer.py b/backend/api/serializers/docker_serializer.py index 3dfdce99..dc1f2a66 100644 --- a/backend/api/serializers/docker_serializer.py +++ b/backend/api/serializers/docker_serializer.py @@ -15,8 +15,8 @@ def validate(self, attrs): if not self.partial: data["owner"] = self.context["request"].user - else: - data["owner"] = data["owner"] if "owner" in data else self.instance.owner + elif "owner" not in data: + data["owner"] = self.instance.owner if "public" in data and data["public"] and not data["owner"].is_staff: raise ValidationError(_("docker.errors.custom")) From 8a4f1e32615aef698e749fbbba3ded74481ed406 Mon Sep 17 00:00:00 2001 From: Topvennie Date: Wed, 15 May 2024 19:50:38 +0200 Subject: [PATCH 5/8] chore: docker images permissions --- backend/api/locale/en/LC_MESSAGES/django.po | 68 ++++++++++---------- backend/api/locale/nl/LC_MESSAGES/django.po | 68 ++++++++++---------- backend/api/serializers/docker_serializer.py | 17 +++-- 3 files changed, 81 insertions(+), 72 deletions(-) diff --git a/backend/api/locale/en/LC_MESSAGES/django.po b/backend/api/locale/en/LC_MESSAGES/django.po index dbe86326..5eda2f33 100755 --- a/backend/api/locale/en/LC_MESSAGES/django.po +++ b/backend/api/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-05-11 18:26+0200\n" +"POT-Creation-Date: 2024-05-15 19:49+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -92,11 +92,11 @@ msgstr "Unkown error." msgid "submission.error.failedstructurecheck" msgstr "The zip file doesn't have the right structure." -#: serializers/checks_serializer.py:49 tests/test_project.py:494 +#: serializers/checks_serializer.py:49 tests/test_project.py:495 msgid "project.error.structure_checks.already_existing" msgstr "The structure check is already present in the project." -#: serializers/checks_serializer.py:65 tests/test_project.py:528 +#: serializers/checks_serializer.py:65 tests/test_project.py:529 msgid "project.error.structure_checks.extension_blocked_and_obligated" msgstr "An extension can't be blocked and obligated at the same time." @@ -112,71 +112,71 @@ msgstr "The field 'time_limit' has to be between 10 and 1000." msgid "extra_check.error.memory_limit" msgstr "The field 'memory_limit' has to be between 100 and 1024." -#: serializers/course_serializer.py:136 -msgid "courses.error.invitation_link" -msgstr "The invitation link is not unique, please try again." - -#: serializers/course_serializer.py:143 serializers/course_serializer.py:158 -#: serializers/course_serializer.py:177 serializers/course_serializer.py:196 -#: serializers/course_serializer.py:215 +#: serializers/course_serializer.py:136 serializers/course_serializer.py:151 +#: serializers/course_serializer.py:170 serializers/course_serializer.py:189 +#: serializers/course_serializer.py:208 msgid "courses.error.context" msgstr "The course is not supplied in the context." -#: serializers/course_serializer.py:164 tests/test_locale.py:28 +#: serializers/course_serializer.py:157 tests/test_locale.py:28 #: tests/test_locale.py:38 msgid "courses.error.students.already_present" msgstr "The student is already present in the course." -#: serializers/course_serializer.py:168 serializers/course_serializer.py:187 -#: serializers/course_serializer.py:206 serializers/course_serializer.py:225 +#: serializers/course_serializer.py:161 serializers/course_serializer.py:180 +#: serializers/course_serializer.py:199 serializers/course_serializer.py:218 msgid "courses.error.past_course" msgstr "The course is from a past year, thus cannot be manipulated." -#: serializers/course_serializer.py:183 +#: serializers/course_serializer.py:176 msgid "courses.error.students.not_present" msgstr "The student is not present in the course." -#: serializers/course_serializer.py:202 +#: serializers/course_serializer.py:195 msgid "courses.error.teachers.already_present" msgstr "The teacher is already present in the course." -#: serializers/course_serializer.py:221 +#: serializers/course_serializer.py:214 msgid "courses.error.teachers.not_present" msgstr "The teacher is not present in the course." -#: serializers/course_serializer.py:229 +#: serializers/course_serializer.py:222 msgid "courses.error.teachers.last_teacher" msgstr "The course must have at least one teacher." -#: serializers/docker_serializer.py:19 +#: serializers/docker_serializer.py:18 +msgid "docker.errors.no_staff" +msgstr "User is not allowed to assign othher owners than himself to the image." + +#: serializers/docker_serializer.py:31 msgid "docker.errors.custom" msgstr "User is not allowed to create public images" -#: serializers/group_serializer.py:49 +#: serializers/group_serializer.py:56 msgid "group.errors.score_exceeds_max" msgstr "The score exceeds the group's max score." -#: serializers/group_serializer.py:59 serializers/group_serializer.py:89 +#: serializers/group_serializer.py:66 serializers/group_serializer.py:96 msgid "group.error.context" msgstr "The group is not supplied in the context." -#: serializers/group_serializer.py:67 serializers/group_serializer.py:101 +#: serializers/group_serializer.py:74 serializers/group_serializer.py:108 msgid "group.errors.locked" msgstr "The group is currently locked." -#: serializers/group_serializer.py:71 +#: serializers/group_serializer.py:78 msgid "group.errors.full" msgstr "The group is already full." -#: serializers/group_serializer.py:75 +#: serializers/group_serializer.py:82 msgid "group.errors.not_in_course" msgstr "The student is not present in the related course." -#: serializers/group_serializer.py:79 +#: serializers/group_serializer.py:86 msgid "group.errors.already_in_group" msgstr "The student is already in the group." -#: serializers/group_serializer.py:97 +#: serializers/group_serializer.py:104 msgid "group.errors.not_present" msgstr "The student is currently not in the group." @@ -188,31 +188,31 @@ msgstr "Error while parsing the provided zip." msgid "project.errors.context" msgstr "The project is not supplied in the context." -#: serializers/project_serializer.py:85 +#: serializers/project_serializer.py:86 msgid "project.errors.start_date_in_past" msgstr "The start date of the project lies in the past." -#: serializers/project_serializer.py:99 +#: serializers/project_serializer.py:100 msgid "project.errors.deadline_before_start_date" msgstr "The deadline of the project lies before the start date of the project." -#: serializers/project_serializer.py:132 +#: serializers/project_serializer.py:142 msgid "project.errors.zip_structure" msgstr "Error while parsing the provided zip." -#: serializers/submission_serializer.py:67 tests/test_submission.py:330 +#: serializers/submission_serializer.py:96 tests/test_submission.py:275 msgid "project.error.submissions.past_project" msgstr "The deadline of the project has already passed." -#: serializers/submission_serializer.py:70 tests/test_submission.py:401 +#: serializers/submission_serializer.py:99 tests/test_submission.py:346 msgid "project.error.submissions.non_visible_project" msgstr "The project is currently in a non-visible state." -#: serializers/submission_serializer.py:73 tests/test_submission.py:431 +#: serializers/submission_serializer.py:102 tests/test_submission.py:376 msgid "project.error.submissions.archived_project" msgstr "The project is archived." -#: serializers/submission_serializer.py:76 +#: serializers/submission_serializer.py:105 msgid "project.error.submissions.no_files" msgstr "The submission is empty." @@ -280,10 +280,10 @@ msgstr "The student was successfully added." msgid "students.success.destroy" msgstr "The student was successfully destroyed." -#: views/submission_view.py:28 +#: views/submission_view.py:29 msgid "submission.download.zip" msgstr "No zip file available." -#: views/submission_view.py:49 +#: views/submission_view.py:50 msgid "extra_check_result.download.log" msgstr "No log file available." diff --git a/backend/api/locale/nl/LC_MESSAGES/django.po b/backend/api/locale/nl/LC_MESSAGES/django.po index b89c1041..648e58f9 100755 --- a/backend/api/locale/nl/LC_MESSAGES/django.po +++ b/backend/api/locale/nl/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-05-11 18:26+0200\n" +"POT-Creation-Date: 2024-05-15 19:49+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -92,11 +92,11 @@ msgstr "Onbekende fout." msgid "submission.error.failedstructurecheck" msgstr "De ingediende zip file heeft niet de juiste structuur." -#: serializers/checks_serializer.py:49 tests/test_project.py:494 +#: serializers/checks_serializer.py:49 tests/test_project.py:495 msgid "project.error.structure_checks.already_existing" msgstr "De structuur check was al aanwezig." -#: serializers/checks_serializer.py:65 tests/test_project.py:528 +#: serializers/checks_serializer.py:65 tests/test_project.py:529 msgid "project.error.structure_checks.extension_blocked_and_obligated" msgstr "Een extensie kan niet geblokkeerd en vereist zijn tegelijkertijd." @@ -112,72 +112,72 @@ msgstr "Het veld 'time_limit' moet tussen 10 en 1000 liggen." msgid "extra_check.error.memory_limit" msgstr "Het veld 'memory_limit' moet tussen 100 en 1024 liggen." -#: serializers/course_serializer.py:136 -msgid "courses.error.invitation_link" -msgstr "De uitnodigingslink is niet uniek, probeer het opnieuw." - -#: serializers/course_serializer.py:143 serializers/course_serializer.py:158 -#: serializers/course_serializer.py:177 serializers/course_serializer.py:196 -#: serializers/course_serializer.py:215 +#: serializers/course_serializer.py:136 serializers/course_serializer.py:151 +#: serializers/course_serializer.py:170 serializers/course_serializer.py:189 +#: serializers/course_serializer.py:208 msgid "courses.error.context" msgstr "De opleiding is niet meegeleverd als context." -#: serializers/course_serializer.py:164 tests/test_locale.py:28 +#: serializers/course_serializer.py:157 tests/test_locale.py:28 #: tests/test_locale.py:38 msgid "courses.error.students.already_present" msgstr "De student bevindt zich al in de opleiding." -#: serializers/course_serializer.py:168 serializers/course_serializer.py:187 -#: serializers/course_serializer.py:206 serializers/course_serializer.py:225 +#: serializers/course_serializer.py:161 serializers/course_serializer.py:180 +#: serializers/course_serializer.py:199 serializers/course_serializer.py:218 msgid "courses.error.past_course" msgstr "De opleiding die men probeert te manipuleren is van een vorig jaar." -#: serializers/course_serializer.py:183 +#: serializers/course_serializer.py:176 msgid "courses.error.students.not_present" msgstr "De student bevindt zich niet in de opleiding." -#: serializers/course_serializer.py:202 +#: serializers/course_serializer.py:195 msgid "courses.error.teachers.already_present" msgstr "De lesgever bevindt zich al in de opleiding." -#: serializers/course_serializer.py:221 +#: serializers/course_serializer.py:214 msgid "courses.error.teachers.not_present" msgstr "De lesgever bevindt zich niet in de opleiding." -#: serializers/course_serializer.py:229 +#: serializers/course_serializer.py:222 msgid "courses.error.teachers.last_teacher" msgstr "De opleiding moet minstens één lesgever hebben." -#: serializers/docker_serializer.py:19 +#: serializers/docker_serializer.py:18 +msgid "docker.errors.no_staff" +msgstr "Gebruiker is alleen toegelaten om zichzelf als eigenaar op te geven" + +#: serializers/docker_serializer.py:31 msgid "docker.errors.custom" msgstr "Gebruiker is niet toegelaten om publieke afbeeldingen te maken" -#: serializers/group_serializer.py:49 +#: serializers/group_serializer.py:56 msgid "group.errors.score_exceeds_max" msgstr "De score van de groep is groter dan de maximum score." -#: serializers/group_serializer.py:59 serializers/group_serializer.py:89 +#: serializers/group_serializer.py:66 serializers/group_serializer.py:96 msgid "group.error.context" msgstr "De groep is niet meegegeven als context waar dat nodig is." -#: serializers/group_serializer.py:67 serializers/group_serializer.py:101 +#: serializers/group_serializer.py:74 serializers/group_serializer.py:108 msgid "group.errors.locked" msgstr "De groep is momenteel vergrendeld." -#: serializers/group_serializer.py:71 +#: serializers/group_serializer.py:78 msgid "group.errors.full" msgstr "De groep is al vol." -#: serializers/group_serializer.py:75 +#: serializers/group_serializer.py:82 msgid "group.errors.not_in_course" msgstr "" "De student bevindt zich niet in de opleiding waartoe het project hoort." -#: serializers/group_serializer.py:79 +#: serializers/group_serializer.py:86 msgid "group.errors.already_in_group" msgstr "De student bevindt zich al in de groep." -#: serializers/group_serializer.py:97 +#: serializers/group_serializer.py:104 msgid "group.errors.not_present" msgstr "De student bevindt zich niet in de groep." @@ -189,31 +189,31 @@ msgstr "Error tijdens de zip te overlopen." msgid "project.errors.context" msgstr "Het project is niet meegegeven als context waar dat nodig is." -#: serializers/project_serializer.py:85 +#: serializers/project_serializer.py:86 msgid "project.errors.start_date_in_past" msgstr "De startdatum van het project ligt in het verleden." -#: serializers/project_serializer.py:99 +#: serializers/project_serializer.py:100 msgid "project.errors.deadline_before_start_date" msgstr "De uiterste inleverdatum voor het project ligt voor de startdatum." -#: serializers/project_serializer.py:132 +#: serializers/project_serializer.py:142 msgid "project.errors.zip_structure" msgstr "Error tijdens de zip te overlopen." -#: serializers/submission_serializer.py:67 tests/test_submission.py:330 +#: serializers/submission_serializer.py:96 tests/test_submission.py:275 msgid "project.error.submissions.past_project" msgstr "De uiterste inleverdatum voor het project is gepasseerd." -#: serializers/submission_serializer.py:70 tests/test_submission.py:401 +#: serializers/submission_serializer.py:99 tests/test_submission.py:346 msgid "project.error.submissions.non_visible_project" msgstr "Het project is niet zichtbaar." -#: serializers/submission_serializer.py:73 tests/test_submission.py:431 +#: serializers/submission_serializer.py:102 tests/test_submission.py:376 msgid "project.error.submissions.archived_project" msgstr "Het project is gearchiveerd." -#: serializers/submission_serializer.py:76 +#: serializers/submission_serializer.py:105 msgid "project.error.submissions.no_files" msgstr "De indiening is leeg" @@ -281,10 +281,10 @@ msgstr "De student is successvol toegevoegd." msgid "students.success.destroy" msgstr "De student is successvol verwijderd." -#: views/submission_view.py:28 +#: views/submission_view.py:29 msgid "submission.download.zip" msgstr "Geen zip bestand beschikbaar." -#: views/submission_view.py:49 +#: views/submission_view.py:50 msgid "extra_check_result.download.log" msgstr "Geen log bestand beschikbaar." diff --git a/backend/api/serializers/docker_serializer.py b/backend/api/serializers/docker_serializer.py index dc1f2a66..6eafef00 100644 --- a/backend/api/serializers/docker_serializer.py +++ b/backend/api/serializers/docker_serializer.py @@ -13,12 +13,21 @@ class Meta: def validate(self, attrs): data = super().validate(attrs=attrs) - if not self.partial: - data["owner"] = self.context["request"].user - elif "owner" not in data: - data["owner"] = self.instance.owner + if "owner" in data and data["owner"] != self.context["request"].user and not self.context["request"].user.is_staff: + # Only allow staff to set the owner of an image to someone else + raise ValidationError(_("docker.errors.no_staff")) + + if "owner" not in data: + # Add the owner data if not present + if not self.partial: + # If it's created assign the user who made the request + data["owner"] = self.context["request"].user + else: + # Else use the pre exisiting owner + data["owner"] = self.instance.owner if "public" in data and data["public"] and not data["owner"].is_staff: + # Only allow staff to have public images raise ValidationError(_("docker.errors.custom")) return data From 143c994d369c218b1fed27dbf4620b111365decf Mon Sep 17 00:00:00 2001 From: Francis Vauterin <159532420+francisvaut@users.noreply.github.com> Date: Thu, 16 May 2024 14:20:32 +0200 Subject: [PATCH 6/8] chore: better submission status (#421) * chore: better submission status * chore: add tests + fix tests * fix: backend tests * chore: round status percentages * Revert "chore: round status percentages" This reverts commit cfb55c7d1353965a5a2ad35ed0ffece26fa9037b. * chore: rename test to make tybo happy --- backend/api/serializers/project_serializer.py | 55 ++++++++++++++++--- backend/api/tests/test_project.py | 6 +- frontend/src/assets/lang/app/en.json | 3 +- frontend/src/assets/lang/app/nl.json | 3 +- .../src/components/projects/ProjectMeter.vue | 16 ++++-- .../unit/services/setup/delete_handlers.ts | 5 ++ .../test/unit/services/setup/get_handlers.ts | 17 ------ .../test/unit/services/setup/post_handlers.ts | 15 ++++- .../unit/services/structure_check.test.ts | 50 +++++++++++++++++ .../submission_status_service.test.ts | 2 +- frontend/src/test/unit/types/data.ts | 5 +- frontend/src/test/unit/types/helper.ts | 3 +- .../test/unit/types/submissionStatus.test.ts | 6 +- frontend/src/types/SubmisionStatus.ts | 6 +- 14 files changed, 149 insertions(+), 43 deletions(-) diff --git a/backend/api/serializers/project_serializer.py b/backend/api/serializers/project_serializer.py index 274d4e55..b4493229 100644 --- a/backend/api/serializers/project_serializer.py +++ b/backend/api/serializers/project_serializer.py @@ -1,7 +1,7 @@ from api.logic.parse_zip_files import parse_zip from api.models.group import Group from api.models.project import Project -from api.models.submission import Submission +from api.models.submission import Submission, ExtraCheckResult, StructureCheckResult, StateEnum from api.serializers.course_serializer import CourseSerializer from django.core.files.uploadedfile import InMemoryUploadedFile from django.utils import timezone @@ -14,28 +14,69 @@ class SubmissionStatusSerializer(serializers.Serializer): non_empty_groups = serializers.IntegerField(read_only=True) groups_submitted = serializers.IntegerField(read_only=True) - submissions_passed = serializers.IntegerField(read_only=True) + structure_checks_passed = serializers.IntegerField(read_only=True) + extra_checks_passed = serializers.IntegerField(read_only=True) def to_representation(self, instance: Project): """Return the submission status of the project""" if not isinstance(instance, Project): raise ValidationError(gettext("project.errors.invalid_instance")) - non_empty_groups = instance.groups.filter(students__isnull=False).count() - groups_submitted = Submission.objects.filter(group__project=instance).count() - submissions_passed = Submission.objects.filter(group__project=instance, is_valid=True).count() + non_empty_groups = Group.objects.filter(project=instance, students__isnull=False).distinct().count() + + groups_submitted_ids = Submission.objects.filter(group__project=instance).values_list('group__id', flat=True) + unique_groups = set(groups_submitted_ids) + groups_submitted = len(unique_groups) + + # The total amount of groups with at least one submission should never exceed the total number of non empty groups + # (the seeder does not account for this restriction) + if (groups_submitted > non_empty_groups): + non_empty_groups = groups_submitted + + passed_structure_checks_submission_ids = StructureCheckResult.objects.filter( + submission__group__project=instance, + submission__is_valid=True, + result=StateEnum.SUCCESS + ).values_list('submission__id', flat=True) + + passed_structure_checks_group_ids = Submission.objects.filter( + id__in=passed_structure_checks_submission_ids + ).values_list('group_id', flat=True) + + unique_groups = set(passed_structure_checks_group_ids) + structure_checks_passed = len(unique_groups) + + passed_extra_checks_submission_ids = ExtraCheckResult.objects.filter( + submission__group__project=instance, + submission__is_valid=True, + result=StateEnum.SUCCESS + ).values_list('submission__id', flat=True) + + passed_extra_checks_group_ids = Submission.objects.filter( + id__in=passed_extra_checks_submission_ids + ).values_list('group_id', flat=True) + + unique_groups = set(passed_extra_checks_group_ids) + extra_checks_passed = len(unique_groups) + + # The total number of passed extra checks combined with the number of passed structure checks + # can never exceed the total number of submissions (the seeder does not account for this restriction) + if (structure_checks_passed + extra_checks_passed > groups_submitted): + extra_checks_passed = groups_submitted - structure_checks_passed return { "non_empty_groups": non_empty_groups, "groups_submitted": groups_submitted, - "submissions_passed": submissions_passed, + "structure_checks_passed": structure_checks_passed, + "extra_checks_passed": extra_checks_passed } class Meta: fields = [ "non_empty_groups", "groups_submitted", - "submissions_passed", + "structure_checks_passed", + "extra_checks_passed" ] diff --git a/backend/api/tests/test_project.py b/backend/api/tests/test_project.py index 98047703..0684088e 100644 --- a/backend/api/tests/test_project.py +++ b/backend/api/tests/test_project.py @@ -802,10 +802,10 @@ def test_submission_status_non_empty_groups(self): # Only two of the three created groups contain at least one student self.assertEqual( content_json["status"], - {"non_empty_groups": 2, "groups_submitted": 0, "submissions_passed": 0}, + {"non_empty_groups": 2, "groups_submitted": 0, "extra_checks_passed": 0, "structure_checks_passed": 0}, ) - def test_submission_status_groups_submitted_and_passed_checks(self): + def test_submission_status_groups_submitted_and_not_passed_checks(self): """Retrieve the submission status for a project.""" course = create_course(name="test course", academic_startyear=2024) project = create_project( @@ -866,7 +866,7 @@ def test_submission_status_groups_submitted_and_passed_checks(self): self.assertEqual( content_json["status"], - {"non_empty_groups": 3, "groups_submitted": 2, "submissions_passed": 2}, + {"non_empty_groups": 3, "groups_submitted": 2, "extra_checks_passed": 0, "structure_checks_passed": 0}, ) def test_retrieve_list_submissions(self): diff --git a/frontend/src/assets/lang/app/en.json b/frontend/src/assets/lang/app/en.json index a76b97fc..bafc4d00 100644 --- a/frontend/src/assets/lang/app/en.json +++ b/frontend/src/assets/lang/app/en.json @@ -186,7 +186,8 @@ "noSubmissions": "This project does not have any submissions", "submissions": "Submission | Submissions", "groups": "Group | Groups", - "testsSucceed": "Succeeded tests", + "structureTestsSucceed": "Succeeded structure tests", + "extraTestsSucceed": "Succeeded extra tests", "testsFail": "Failed tests", "submit": "Submit" }, diff --git a/frontend/src/assets/lang/app/nl.json b/frontend/src/assets/lang/app/nl.json index f403b20d..7864c171 100644 --- a/frontend/src/assets/lang/app/nl.json +++ b/frontend/src/assets/lang/app/nl.json @@ -183,7 +183,8 @@ "noSubmissions": "Dit project heeft geen indieningen", "submissions": "Indiening | Indieningen", "groups": "Groep | Groepen", - "testsSucceed": "Geslaagde testen", + "structureTestsSucceed": "Geslaagde structuur testen", + "extraTestsSucceed": "Geslaagde extra testen", "testsFail": "Gefaalde testen", "submit": "Indienen" }, diff --git a/frontend/src/components/projects/ProjectMeter.vue b/frontend/src/components/projects/ProjectMeter.vue index 823dd351..c02fc00c 100644 --- a/frontend/src/components/projects/ProjectMeter.vue +++ b/frontend/src/components/projects/ProjectMeter.vue @@ -17,15 +17,23 @@ const { t } = useI18n(); const meterItems = computed(() => { const groups = props.project !== null ? props.project.status.non_empty_groups : 0; const groupsSubmitted = props.project !== null ? props.project.status.groups_submitted : 0; - const submissionsPassed = props.project !== null ? props.project.status.submissions_passed : 0; - const submissionsFailed = groupsSubmitted - submissionsPassed; + const structureChecksPassed = props.project !== null ? props.project.status.structure_checks_passed : 0; + const extraChecksPassed = props.project !== null ? props.project.status.extra_checks_passed : 0; + const submissionsFailed = groupsSubmitted - structureChecksPassed; + return [ { - value: (submissionsPassed / groups) * 100, + value: (extraChecksPassed / groups) * 100, color: '#749b68', - label: t('components.card.testsSucceed'), + label: t('components.card.extraTestsSucceed'), icon: 'pi pi-check', }, + { + value: (structureChecksPassed / groups) * 100, + color: '#fa9746', + label: t('components.card.structureTestsSucceed'), + icon: 'pi pi-exclamation-circle', + }, { value: (submissionsFailed / groups) * 100, color: '#FF5445', diff --git a/frontend/src/test/unit/services/setup/delete_handlers.ts b/frontend/src/test/unit/services/setup/delete_handlers.ts index c43ac547..593db386 100644 --- a/frontend/src/test/unit/services/setup/delete_handlers.ts +++ b/frontend/src/test/unit/services/setup/delete_handlers.ts @@ -29,4 +29,9 @@ export const deleteHandlers = [ assistants.splice(index, 1); return HttpResponse.json(assistants); }), + http.delete(baseUrl + endpoints.structureChecks.retrieve.replace('{id}', ':id'), async ({ params }) => { + const index = structureChecks.findIndex((x) => x.id === params.id); + structureChecks.splice(index, 1); + return HttpResponse.json(structureChecks); + }), ]; diff --git a/frontend/src/test/unit/services/setup/get_handlers.ts b/frontend/src/test/unit/services/setup/get_handlers.ts index d212b3f6..51a805ba 100644 --- a/frontend/src/test/unit/services/setup/get_handlers.ts +++ b/frontend/src/test/unit/services/setup/get_handlers.ts @@ -86,27 +86,10 @@ export const getHandlers = [ const project = projects.find((x) => x.id === params.id); const groupIds = project !== null && project !== undefined ? project.groups : []; const submissionIds = project !== null && project !== undefined ? project.submissions : []; - const subGroupIds = Array.from( - new Set(submissions.filter((x) => submissionIds.includes(x.id)).map((x) => x.group)), - ); - // Filter submissions for each subgroup and get the submission with the highest number - const subgroupSubmissions = subGroupIds.map((groupId) => { - const submissionsForGroup = submissions.filter((submission) => submission.group === groupId); - if (submissionsForGroup.length > 0) { - return submissionsForGroup.reduce((maxSubmission, currentSubmission) => { - return currentSubmission.submission_number > maxSubmission.submission_number - ? currentSubmission - : maxSubmission; - }); - } else { - return null; - } - }); return HttpResponse.json({ groups_submitted: new Set(submissions.filter((x) => submissionIds.includes(x.id)).map((x) => x.group)).size, non_empty_groups: groups.filter((x) => groupIds.includes(x.id) && x.students.length > 0).length, - submissions_passed: subgroupSubmissions.filter((x) => x?.structureChecks_passed).length, }); }), http.get(baseUrl + endpoints.structureChecks.byProject.replace('{projectId}', ':id'), ({ params }) => { diff --git a/frontend/src/test/unit/services/setup/post_handlers.ts b/frontend/src/test/unit/services/setup/post_handlers.ts index 5409c5df..e935501c 100644 --- a/frontend/src/test/unit/services/setup/post_handlers.ts +++ b/frontend/src/test/unit/services/setup/post_handlers.ts @@ -54,18 +54,29 @@ export const postHandlers = [ faculties.push(newFaculty); return HttpResponse.json(faculties); }), - http.post(baseUrl + endpoints.groups.byProject.replace('{projectId}', ':id'), async ({ request, params }) => { + http.post(baseUrl + endpoints.groups.byProject.replace('{projectId}', ':id'), async ({ request }) => { const buffer = await request.arrayBuffer(); const requestBody = new TextDecoder().decode(buffer); const newGroup = JSON.parse(requestBody); groups.push(newGroup); return HttpResponse.json(groups); }), - http.post(baseUrl + endpoints.projects.byCourse.replace('{courseId}', ':id'), async ({ request, params }) => { + http.post(baseUrl + endpoints.projects.byCourse.replace('{courseId}', ':id'), async ({ request }) => { const buffer = await request.arrayBuffer(); const requestBody = new TextDecoder().decode(buffer); const newProject = JSON.parse(requestBody); projects.push(newProject); return HttpResponse.json(projects); }), + http.post( + baseUrl + endpoints.structureChecks.byProject.replace('{projectId}', ':id'), + async ({ request, params }) => { + const buffer = await request.arrayBuffer(); + const requestBody = new TextDecoder().decode(buffer); + const newStructureCheck = JSON.parse(requestBody); + newStructureCheck.project = params.id; + structureChecks.push(newStructureCheck); + return HttpResponse.json(structureChecks); + }, + ), ]; diff --git a/frontend/src/test/unit/services/structure_check.test.ts b/frontend/src/test/unit/services/structure_check.test.ts index 91a596c0..5e8a6c6f 100644 --- a/frontend/src/test/unit/services/structure_check.test.ts +++ b/frontend/src/test/unit/services/structure_check.test.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { describe, it, expect } from 'vitest'; import { useStructureCheck } from '@/composables/services/structure_check.service.ts'; +import { StructureCheck } from '@/types/StructureCheck'; const { structureChecks, @@ -59,3 +60,52 @@ describe('structureCheck', (): void => { expect(structureChecks.value?.[3]?.blocked_extensions).toBeNull(); }); }); + +it('create structureCheck', async () => { + resetService(); + + const exampleStructureCheck = new StructureCheck( + '', // id + 'structure_check_name', // name + [], // blocked extensions + [], // obligated extensions + null, // project + ); + + await getStructureCheckByProject('123456'); + expect(structureChecks).not.toBeNull(); + expect(Array.isArray(structureChecks.value)).toBe(true); + const prevLength = structureChecks.value?.length ?? 0; + + await createStructureCheck(exampleStructureCheck, '123456'); + await getStructureCheckByProject('123456'); + + expect(structureChecks).not.toBeNull(); + expect(Array.isArray(structureChecks.value)).toBe(true); + expect(structureChecks.value?.length).toBe(prevLength + 1); + + // Only check for fields that are sent to the backend + expect(structureChecks.value?.[prevLength]?.name).toBe('structure_check_name'); +}); + +it('delete structureCheck', async () => { + resetService(); + + await getStructureCheckByProject('123456'); + expect(structureChecks.value).not.toBeNull(); + expect(Array.isArray(structureChecks.value)).toBe(true); + const prevLength = structureChecks.value?.length ?? 0; + + let structureCheckId = ''; + if (structureChecks.value?.[2]?.id !== undefined && structureChecks.value?.[2].id !== null) { + structureCheckId = structureChecks.value?.[2]?.id; + } + + await deleteStructureCheck(structureCheckId); + await getStructureCheckByProject('123456'); + + expect(structureChecks).not.toBeNull(); + expect(Array.isArray(structureChecks.value)).toBe(true); + expect(structureChecks.value?.length).toBe(prevLength - 1); + expect(structureChecks.value?.[2]?.id).not.toBe(structureCheckId); +}); diff --git a/frontend/src/test/unit/services/submission_status_service.test.ts b/frontend/src/test/unit/services/submission_status_service.test.ts index 896a4df6..d7a90797 100644 --- a/frontend/src/test/unit/services/submission_status_service.test.ts +++ b/frontend/src/test/unit/services/submission_status_service.test.ts @@ -16,6 +16,6 @@ describe('submision_status', (): void => { expect(submissionStatus.value).not.toBeNull(); expect(submissionStatus.value?.groups_submitted).toBe(1); expect(submissionStatus.value?.non_empty_groups).toBe(2); - expect(submissionStatus.value?.submissions_passed).toBe(1); + // No need to check for structure_check_passed and extra_checks_passed since those queries are not implemented in the frontend }); }); diff --git a/frontend/src/test/unit/types/data.ts b/frontend/src/test/unit/types/data.ts index 9c004c27..255ddc3c 100644 --- a/frontend/src/test/unit/types/data.ts +++ b/frontend/src/test/unit/types/data.ts @@ -123,8 +123,9 @@ export const structureCheckData = { export const submissionStatusData = { non_empty_groups: 5, - groups_submitted: 2, - submissions_passed: 1, + groups_submitted: 4, + structure_checks_passed: 3, + extra_checks_passed: 1, }; export const submissionData = { diff --git a/frontend/src/test/unit/types/helper.ts b/frontend/src/test/unit/types/helper.ts index 60c32d6b..bab3fede 100644 --- a/frontend/src/test/unit/types/helper.ts +++ b/frontend/src/test/unit/types/helper.ts @@ -156,7 +156,8 @@ export function createSubmissionStatus(submissionStatusData: any): SubmissionSta return new SubmissionStatus( submissionStatusData.non_empty_groups, submissionStatusData.groups_submitted, - submissionStatusData.submissions_passed, + submissionStatusData.structure_checks_passed, + submissionStatusData.extra_checks_passed, ); } diff --git a/frontend/src/test/unit/types/submissionStatus.test.ts b/frontend/src/test/unit/types/submissionStatus.test.ts index b1f7d5b8..7629ad60 100644 --- a/frontend/src/test/unit/types/submissionStatus.test.ts +++ b/frontend/src/test/unit/types/submissionStatus.test.ts @@ -11,7 +11,8 @@ describe('submissionStatus type', () => { expect(submissionStatus).toBeInstanceOf(SubmissionStatus); expect(submissionStatus.non_empty_groups).toBe(submissionStatusData.non_empty_groups); expect(submissionStatus.groups_submitted).toBe(submissionStatusData.groups_submitted); - expect(submissionStatus.submissions_passed).toBe(submissionStatusData.submissions_passed); + expect(submissionStatus.structure_checks_passed).toBe(submissionStatusData.structure_checks_passed); + expect(submissionStatus.extra_checks_passed).toBe(submissionStatusData.extra_checks_passed); }); it('create a submissionStatus instance from JSON data', () => { @@ -21,6 +22,7 @@ describe('submissionStatus type', () => { expect(submissionStatus).toBeInstanceOf(SubmissionStatus); expect(submissionStatus.non_empty_groups).toBe(submissionStatusData.non_empty_groups); expect(submissionStatus.groups_submitted).toBe(submissionStatusData.groups_submitted); - expect(submissionStatus.submissions_passed).toBe(submissionStatusData.submissions_passed); + expect(submissionStatus.structure_checks_passed).toBe(submissionStatusData.structure_checks_passed); + expect(submissionStatus.extra_checks_passed).toBe(submissionStatusData.extra_checks_passed); }); }); diff --git a/frontend/src/types/SubmisionStatus.ts b/frontend/src/types/SubmisionStatus.ts index 159b1129..597bbece 100644 --- a/frontend/src/types/SubmisionStatus.ts +++ b/frontend/src/types/SubmisionStatus.ts @@ -2,7 +2,8 @@ export class SubmissionStatus { constructor( public non_empty_groups: number, public groups_submitted: number, - public submissions_passed: number, + public structure_checks_passed: number, + public extra_checks_passed: number, ) {} /** @@ -14,7 +15,8 @@ export class SubmissionStatus { return new SubmissionStatus( submissionStatus.non_empty_groups, submissionStatus.groups_submitted, - submissionStatus.submissions_passed, + submissionStatus.structure_checks_passed, + submissionStatus.extra_checks_passed, ); } } From dda6010264ef2dfe1d0de37b90b8ab3da8652304 Mon Sep 17 00:00:00 2001 From: Vincent Vallaeys Date: Thu, 16 May 2024 14:21:12 +0200 Subject: [PATCH 7/8] feat: artifacts (#422) --- backend/api/fixtures/realistic/realistic.yaml | 10 ++++++ backend/api/locale/en/LC_MESSAGES/django.po | 32 +++++++++-------- backend/api/locale/nl/LC_MESSAGES/django.po | 34 ++++++++++-------- backend/api/logic/get_file_path.py | 5 +++ .../0025_extracheckresult_artifact.py | 24 +++++++++++++ backend/api/models/checks.py | 7 ++++ backend/api/models/submission.py | 11 +++++- .../api/permissions/submission_permissions.py | 15 ++++++++ .../api/serializers/submission_serializer.py | 3 ++ backend/api/tasks/extra_check.py | 25 ++++++++++++- backend/api/views/submission_view.py | 18 +++++++--- .../projects/0/0/checks/generate_gibberish.sh | 6 ++++ .../artifacts/artifact_extra_check_0.zip | 0 .../artifacts/artifact_extra_check_1.zip | Bin 0 -> 86006 bytes .../artifacts/artifact_extra_check_0.zip | 0 .../artifacts/artifact_extra_check_1.zip | Bin 0 -> 86006 bytes 16 files changed, 156 insertions(+), 34 deletions(-) create mode 100644 backend/api/migrations/0025_extracheckresult_artifact.py create mode 100644 backend/data/fixtures/realistic/projects/0/0/submissions/0/submission_1/artifacts/artifact_extra_check_0.zip create mode 100644 backend/data/fixtures/realistic/projects/0/0/submissions/0/submission_1/artifacts/artifact_extra_check_1.zip create mode 100644 backend/data/fixtures/realistic/projects/0/0/submissions/0/submission_2/artifacts/artifact_extra_check_0.zip create mode 100644 backend/data/fixtures/realistic/projects/0/0/submissions/0/submission_2/artifacts/artifact_extra_check_1.zip diff --git a/backend/api/fixtures/realistic/realistic.yaml b/backend/api/fixtures/realistic/realistic.yaml index 84cf1c2a..bf2f4f15 100644 --- a/backend/api/fixtures/realistic/realistic.yaml +++ b/backend/api/fixtures/realistic/realistic.yaml @@ -172,6 +172,7 @@ time_limit: 10 memory_limit: 50 show_log: false + show_artifact: false - model: api.extracheck pk: 1 fields: @@ -182,6 +183,7 @@ time_limit: 30 memory_limit: 128 show_log: true + show_artifact: true # MARK: Students - model: api.student @@ -457,41 +459,49 @@ fields: extra_check: 0 log_file: fixtures/realistic/projects/0/0/submissions/0/submission_1/logs/log_extra_check_0.txt + artifact: "" - model: api.extracheckresult pk: 3 fields: extra_check: 1 log_file: fixtures/realistic/projects/0/0/submissions/0/submission_1/logs/log_extra_check_1.txt + artifact: fixtures/realistic/projects/0/0/submissions/0/submission_1/artifacts/artifact_extra_check_1.zip - model: api.extracheckresult pk: 5 fields: extra_check: 0 log_file: fixtures/realistic/projects/0/0/submissions/0/submission_2/logs/log_extra_check_0.txt + artifact: "" - model: api.extracheckresult pk: 6 fields: extra_check: 1 log_file: fixtures/realistic/projects/0/0/submissions/0/submission_2/logs/log_extra_check_1.txt + artifact: fixtures/realistic/projects/0/0/submissions/0/submission_2/artifacts/artifact_extra_check_1.zip - model: api.extracheckresult pk: 8 fields: extra_check: 0 log_file: "" + artifact: "" - model: api.extracheckresult pk: 9 fields: extra_check: 1 log_file: "" + artifact: "" - model: api.extracheckresult pk: 11 fields: extra_check: 0 log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_0.txt + artifact: "" - model: api.extracheckresult pk: 12 fields: extra_check: 1 log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_1.txt + artifact: "" # MARK: Teachers - model: api.teacher diff --git a/backend/api/locale/en/LC_MESSAGES/django.po b/backend/api/locale/en/LC_MESSAGES/django.po index 5eda2f33..dbf3b355 100755 --- a/backend/api/locale/en/LC_MESSAGES/django.po +++ b/backend/api/locale/en/LC_MESSAGES/django.po @@ -34,61 +34,61 @@ msgstr "Docker image is ready" msgid "dockerimage.state.error" msgstr "Docker image failed to build" -#: models/submission.py:61 +#: models/submission.py:62 msgid "submission.state.queued" msgstr "Queued" -#: models/submission.py:62 +#: models/submission.py:63 msgid "submission.state.running" msgstr "Running" -#: models/submission.py:63 +#: models/submission.py:64 msgid "submission.state.success" msgstr "Success" -#: models/submission.py:64 +#: models/submission.py:65 msgid "submission.state.failed" msgstr "Failed" -#: models/submission.py:69 +#: models/submission.py:70 msgid "submission.error.blockedextension" msgstr "The zip file contains a file with a non-allowed extension." -#: models/submission.py:70 +#: models/submission.py:71 msgid "submission.error.obligatedextensionnotfound" msgstr "" "The submitted zip file doesn't have any file with an obligated file " "extension." -#: models/submission.py:71 +#: models/submission.py:72 msgid "submission.error.filedirnotfound" msgstr "The submitted zip file lacks an obligated directory." -#: models/submission.py:74 +#: models/submission.py:75 msgid "submission.error.dockerimageerror" msgstr "try again later." -#: models/submission.py:75 +#: models/submission.py:76 msgid "submission.error.timelimit" msgstr "Timelimit exceeded." -#: models/submission.py:76 +#: models/submission.py:77 msgid "submission.error.memorylimit" msgstr "Memorylimit exceeded." -#: models/submission.py:77 +#: models/submission.py:78 msgid "submission.error.checkerror" msgstr "A check failed." -#: models/submission.py:78 +#: models/submission.py:79 msgid "submission.error.runtimeerror" msgstr "Crashed." -#: models/submission.py:79 +#: models/submission.py:80 msgid "submission.error.unknown" msgstr "Unkown error." -#: models/submission.py:80 +#: models/submission.py:81 msgid "submission.error.failedstructurecheck" msgstr "The zip file doesn't have the right structure." @@ -287,3 +287,7 @@ msgstr "No zip file available." #: views/submission_view.py:50 msgid "extra_check_result.download.log" msgstr "No log file available." + +#: views/submission_view.py:60 +msgid "extra_check_result.download.artifact" +msgstr "No artifact available." diff --git a/backend/api/locale/nl/LC_MESSAGES/django.po b/backend/api/locale/nl/LC_MESSAGES/django.po index 648e58f9..7acb1b3d 100755 --- a/backend/api/locale/nl/LC_MESSAGES/django.po +++ b/backend/api/locale/nl/LC_MESSAGES/django.po @@ -34,61 +34,61 @@ msgstr "Docker image is klaar." msgid "dockerimage.state.error" msgstr "Docker image is gefaald om te bouwen." -#: models/submission.py:61 +#: models/submission.py:62 msgid "submission.state.queued" msgstr "wachten" -#: models/submission.py:62 +#: models/submission.py:63 msgid "submission.state.running" msgstr "lopen" -#: models/submission.py:63 +#: models/submission.py:64 msgid "submission.state.success" msgstr "succes" -#: models/submission.py:64 +#: models/submission.py:65 msgid "submission.state.failed" msgstr "gefaald" -#: models/submission.py:69 +#: models/submission.py:70 msgid "submission.error.blockedextension" msgstr "De zip file bevat een niet toegelaten bestandstype." -#: models/submission.py:70 +#: models/submission.py:71 msgid "submission.error.obligatedextensionnotfound" msgstr "" "Er is geen enkel bestand met een bepaalde bestandstype die verplicht is in " "het ingediende zip-bestand." -#: models/submission.py:71 +#: models/submission.py:72 msgid "submission.error.filedirnotfound" msgstr "De ingediende zip file mankeerd een verplichtte map." -#: models/submission.py:74 +#: models/submission.py:75 msgid "submission.error.dockerimageerror" msgstr "Probeer later opnieuw." -#: models/submission.py:75 +#: models/submission.py:76 msgid "submission.error.timelimit" msgstr "Tijdslimit bereikt." -#: models/submission.py:76 +#: models/submission.py:77 msgid "submission.error.memorylimit" msgstr "Geheugenlimiet bereikt." -#: models/submission.py:77 +#: models/submission.py:78 msgid "submission.error.checkerror" msgstr "Een check faalde." -#: models/submission.py:78 +#: models/submission.py:79 msgid "submission.error.runtimeerror" msgstr "Crashed." -#: models/submission.py:79 +#: models/submission.py:80 msgid "submission.error.unknown" msgstr "Onbekende fout." -#: models/submission.py:80 +#: models/submission.py:81 msgid "submission.error.failedstructurecheck" msgstr "De ingediende zip file heeft niet de juiste structuur." @@ -288,3 +288,9 @@ msgstr "Geen zip bestand beschikbaar." #: views/submission_view.py:50 msgid "extra_check_result.download.log" msgstr "Geen log bestand beschikbaar." + +#: views/submission_view.py:60 +#, fuzzy +#| msgid "extra_check_result.download.log" +msgid "extra_check_result.download.artifact" +msgstr "Geen artifact beschikbaar." diff --git a/backend/api/logic/get_file_path.py b/backend/api/logic/get_file_path.py index f0b735d0..c75adb0f 100644 --- a/backend/api/logic/get_file_path.py +++ b/backend/api/logic/get_file_path.py @@ -56,3 +56,8 @@ def get_docker_image_file_path(instance: DockerImage, _: str) -> str: def get_docker_image_tag(instance: DockerImage) -> str: return f"{DOCKER_BUILD_ROOT_NAME}_{instance.id}" + + +def get_extra_check_artifact_file_path(instance: ExtraCheckResult, uuid: str) -> str: + return (f"{_get_project_dir_path(instance.submission.group.project)}" + f"submissions/{instance.submission.group.id}/{uuid}/artifacts/{_get_uuid()}.zip") diff --git a/backend/api/migrations/0025_extracheckresult_artifact.py b/backend/api/migrations/0025_extracheckresult_artifact.py new file mode 100644 index 00000000..7e3984aa --- /dev/null +++ b/backend/api/migrations/0025_extracheckresult_artifact.py @@ -0,0 +1,24 @@ +# Generated by Django 5.0.4 on 2024-05-13 21:33 + +from api.logic.get_file_path import get_extra_check_artifact_file_path +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0024_alter_dockerimage_state'), + ] + + operations = [ + migrations.AddField( + model_name='extracheckresult', + name='artifact', + field=models.FileField(max_length=256, null=True, upload_to=get_extra_check_artifact_file_path), + ), + migrations.AddField( + model_name='extracheck', + name='show_artifact', + field=models.BooleanField(default=True), + ), + ] diff --git a/backend/api/models/checks.py b/backend/api/models/checks.py index efc7b42d..7f5aa570 100644 --- a/backend/api/models/checks.py +++ b/backend/api/models/checks.py @@ -113,3 +113,10 @@ class ExtraCheck(models.Model): blank=False, null=False ) + + # Whether the artifacts should made available to the student + show_artifact = models.BooleanField( + default=True, + blank=False, + null=False + ) diff --git a/backend/api/models/submission.py b/backend/api/models/submission.py index 20294604..ee3afdb1 100644 --- a/backend/api/models/submission.py +++ b/backend/api/models/submission.py @@ -1,6 +1,7 @@ from typing import TYPE_CHECKING -from api.logic.get_file_path import (get_extra_check_log_file_path, +from api.logic.get_file_path import (get_extra_check_artifact_file_path, + get_extra_check_log_file_path, get_submission_file_path) from api.models.checks import ExtraCheck, StructureCheck from api.models.group import Group @@ -137,3 +138,11 @@ class ExtraCheckResult(CheckResult): blank=False, null=True ) + + # File path for the artifact of the extra checks + artifact = models.FileField( + upload_to=get_extra_check_artifact_file_path, + max_length=256, + blank=False, + null=True + ) diff --git a/backend/api/permissions/submission_permissions.py b/backend/api/permissions/submission_permissions.py index 7bc7f642..7180a0fa 100644 --- a/backend/api/permissions/submission_permissions.py +++ b/backend/api/permissions/submission_permissions.py @@ -57,3 +57,18 @@ def has_object_permission(self, request: Request, view: APIView, obj: ExtraCheck return obj.extra_check.show_log return True + + +class ExtraCheckResultArtifactPermission(ExtraCheckResultPermission): + def has_object_permission(self, request: Request, view: APIView, obj: ExtraCheckResult) -> bool: + result = super().has_object_permission(request, view, obj) + + if not result: + return False + + user: User = cast(User, request.user) + + if is_student(user): + return obj.extra_check.show_artifact + + return True diff --git a/backend/api/serializers/submission_serializer.py b/backend/api/serializers/submission_serializer.py index db2d505c..acdf26f8 100644 --- a/backend/api/serializers/submission_serializer.py +++ b/backend/api/serializers/submission_serializer.py @@ -39,6 +39,9 @@ def to_representation(self, instance: ExtraCheckResult) -> dict | None: representation["log_file"] = request.build_absolute_uri( reverse("extra-check-result-detail", args=[str(instance.id)]) + "log/" ) + representation["artifact"] = request.build_absolute_uri( + reverse("extra-check-result-detail", args=[str(instance.id)]) + "artifact/" + ) return representation return None diff --git a/backend/api/tasks/extra_check.py b/backend/api/tasks/extra_check.py index 7ad94afc..5ddb1565 100644 --- a/backend/api/tasks/extra_check.py +++ b/backend/api/tasks/extra_check.py @@ -1,3 +1,5 @@ +import io +import os import shutil import zipfile from time import sleep @@ -11,6 +13,7 @@ from api.models.docker import StateEnum as DockerStateEnum from api.models.submission import ErrorMessageEnum, ExtraCheckResult, StateEnum from celery import shared_task +from django.core.files import File from django.core.files.base import ContentFile from docker.models.containers import Container from docker.types import LogConfig @@ -48,6 +51,7 @@ def task_extra_check_start(structure_check_result: bool, extra_check_result: Ext submission_directory = "/".join(extra_check_result.submission.zip.path.split("/") [:-1]) + "/submission/" # Directory where the files will be extracted + artifacts_directory = f"{submission_directory}/artifacts" # Directory where the artifacts will be stored extra_check_name = extra_check_result.extra_check.file.name.split("/")[-1] # Name of the extra check file submission_uuid = extra_check_result.submission.zip.path.split("/")[-2] # Uuid of the submission @@ -55,6 +59,9 @@ def task_extra_check_start(structure_check_result: bool, extra_check_result: Ext with zipfile.ZipFile(extra_check_result.submission.zip.path, 'r') as zip: zip.extractall(submission_directory) + # Create artifacts directory + os.makedirs(artifacts_directory, exist_ok=True) + container: Container | None = None try: @@ -76,6 +83,9 @@ def task_extra_check_start(structure_check_result: bool, extra_check_result: Ext f"{get_submission_full_dir_path(extra_check_result.submission)}/submission": { "bind": "/submission", "mode": "rw" }, + f"{get_submission_full_dir_path(extra_check_result.submission)}/submission/artifacts": { + "bind": "/submission/artifacts", "mode": "rw" + }, get_extra_check_file_full_path(extra_check_result.extra_check): { "bind": f"/submission/{extra_check_name}", "mode": "ro" } @@ -141,6 +151,7 @@ def task_extra_check_start(structure_check_result: bool, extra_check_result: Ext extra_check_result.error_message = ErrorMessageEnum.UNKNOWN # Cleanup and data saving + # Start by saving any logs finally: logs: str if container: @@ -153,7 +164,19 @@ def task_extra_check_start(structure_check_result: bool, extra_check_result: Ext logs = "Container error" extra_check_result.log_file.save(submission_uuid, content=ContentFile(logs), save=False) - extra_check_result.save() + + # Zip and save any possible artifacts + memory_zip = io.BytesIO() + if os.listdir(artifacts_directory): + with zipfile.ZipFile(memory_zip, 'w') as zip: + for root, _, files in os.walk(artifacts_directory): + for file in files: + zip.write(os.path.join(root, file), os.path.relpath(os.path.join(root, file), artifacts_directory)) + + memory_zip.seek(0) + extra_check_result.artifact.save(submission_uuid, ContentFile(memory_zip.read()), False) + + extra_check_result.save() # Remove directory try: diff --git a/backend/api/views/submission_view.py b/backend/api/views/submission_view.py index 9010b64e..f1f42a58 100644 --- a/backend/api/views/submission_view.py +++ b/backend/api/views/submission_view.py @@ -1,8 +1,9 @@ from api.models.submission import (ExtraCheckResult, StructureCheckResult, Submission) from api.permissions.submission_permissions import ( - ExtraCheckResultLogPermission, ExtraCheckResultPermission, - StructureCheckResultPermission, SubmissionPermission) + ExtraCheckResultArtifactPermission, ExtraCheckResultLogPermission, + ExtraCheckResultPermission, StructureCheckResultPermission, + SubmissionPermission) from api.serializers.submission_serializer import ( ExtraCheckResultSerializer, StructureCheckResultSerializer, SubmissionSerializer) @@ -42,11 +43,20 @@ class ExtraCheckResultViewSet(RetrieveModelMixin, GenericViewSet): serializer_class = ExtraCheckResultSerializer permission_classes = [ExtraCheckResultPermission] - @action(detail=True, permission_classes=[IsAdminUser | ExtraCheckResultLogPermission]) + @action(detail=True, permission_classes=[IsAdminUser | ExtraCheckResultArtifactPermission]) def log(self, request, **__): extra_check_result: ExtraCheckResult = self.get_object() if not extra_check_result.log_file: return Response({"message": _("extra_check_result.download.log")}, status=404) - return FileResponse(open(extra_check_result.log_file.path, "rb"), as_attachment=True) + return FileResponse(open(extra_check_result.log_file.path, "rb"), as_attachment=True, filename="log.txt") + + @action(detail=True, permission_classes=[IsAdminUser | ExtraCheckResultLogPermission]) + def artifact(self, request, **__): + extra_check_result: ExtraCheckResult = self.get_object() + + if not extra_check_result.artifact: + return Response({"message": _("extra_check_result.download.artifact")}, status=404) + + return FileResponse(open(extra_check_result.artifact.path, "rb"), as_attachment=True, filename="artifact.zip") diff --git a/backend/data/fixtures/realistic/projects/0/0/checks/generate_gibberish.sh b/backend/data/fixtures/realistic/projects/0/0/checks/generate_gibberish.sh index 182840c5..9690ec1e 100755 --- a/backend/data/fixtures/realistic/projects/0/0/checks/generate_gibberish.sh +++ b/backend/data/fixtures/realistic/projects/0/0/checks/generate_gibberish.sh @@ -1,5 +1,7 @@ #!/bin/bash +# generate gibberish logs + # Function to generate a random sequence of characters generate_sequence() { cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 50 @@ -14,3 +16,7 @@ while [ $count -le 50 ]; do generate_sequence count=$((count+1)) done + +# Generate an artifact + +wget https://golang.org/doc/gopher/modelsheet.jpg -P artifacts diff --git a/backend/data/fixtures/realistic/projects/0/0/submissions/0/submission_1/artifacts/artifact_extra_check_0.zip b/backend/data/fixtures/realistic/projects/0/0/submissions/0/submission_1/artifacts/artifact_extra_check_0.zip new file mode 100644 index 00000000..e69de29b diff --git a/backend/data/fixtures/realistic/projects/0/0/submissions/0/submission_1/artifacts/artifact_extra_check_1.zip b/backend/data/fixtures/realistic/projects/0/0/submissions/0/submission_1/artifacts/artifact_extra_check_1.zip new file mode 100644 index 0000000000000000000000000000000000000000..912548a73d6256b6a340d903c25f7d0e9051923f GIT binary patch literal 86006 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 Date: Thu, 16 May 2024 14:21:29 +0200 Subject: [PATCH 8/8] chore: went through some todos (#426) * chore: went through some todos * chore: allow docker image updates --- backend/api/models/checks.py | 3 --- backend/api/permissions/group_permissions.py | 19 +++++++++++++ .../api/permissions/project_permissions.py | 5 ---- backend/api/signals.py | 27 +++++++++++++------ backend/api/tasks/docker_image.py | 12 +++++++-- backend/api/views/course_view.py | 3 +-- backend/api/views/docker_view.py | 11 +++----- backend/api/views/group_view.py | 1 - backend/api/views/submission_view.py | 1 - 9 files changed, 52 insertions(+), 30 deletions(-) diff --git a/backend/api/models/checks.py b/backend/api/models/checks.py index 7f5aa570..dfb7e2f0 100644 --- a/backend/api/models/checks.py +++ b/backend/api/models/checks.py @@ -14,8 +14,6 @@ class FileExtension(models.Model): unique=True ) -# TODO: Remove zip.* translations - class StructureCheck(models.Model): """Model that represents a structure check for a project. @@ -100,7 +98,6 @@ class ExtraCheck(models.Model): ) # Maximum memory the container uses in MB - # TODO: Set max and min memory_limit = models.PositiveSmallIntegerField( default=128, blank=False, diff --git a/backend/api/permissions/group_permissions.py b/backend/api/permissions/group_permissions.py index e75da21d..00f15f6a 100644 --- a/backend/api/permissions/group_permissions.py +++ b/backend/api/permissions/group_permissions.py @@ -1,8 +1,10 @@ +from api.models.group import Group from api.permissions.role_permissions import (is_assistant, is_student, is_teacher) from authentication.models import User from rest_framework.permissions import SAFE_METHODS, BasePermission from rest_framework.request import Request +from rest_framework.views import APIView from rest_framework.viewsets import ViewSet @@ -59,6 +61,23 @@ def has_object_permission(self, request: Request, view: ViewSet, group) -> bool: class GroupSubmissionPermission(BasePermission): """Permission class for submission related group endpoints""" + def has_permission(self, request: Request, view: APIView) -> bool: + user: User = request.user + group_id = view.kwargs.get('pk') + group: Group | None = Group.objects.get(id=group_id) if group_id else None + + if group is None: + return True + + # Teachers and assistants of that course can view all submissions + if is_teacher(user): + return group.project.course.teachers.filter(id=user.teacher.id).exists() + + if is_assistant(user): + return group.project.course.assistants.filter(id=user.assistant.id).exists() + + return is_student(user) and group.students.filter(id=user.student.id).exists() + def had_object_permission(self, request: Request, view: ViewSet, group) -> bool: user: User = request.user course = group.project.course diff --git a/backend/api/permissions/project_permissions.py b/backend/api/permissions/project_permissions.py index 55ff054a..a13b4946 100644 --- a/backend/api/permissions/project_permissions.py +++ b/backend/api/permissions/project_permissions.py @@ -13,11 +13,6 @@ def has_permission(self, request: Request, view: ViewSet) -> bool: """Check if user has permission to view a general project endpoint.""" user: User = request.user - # TODO: Sure return True corresponds with the comments made above - # The general project endpoint that lists all projects is not accessible for any role. - if request.method in SAFE_METHODS: - return True - # We only allow teachers and assistants to create new projects. return is_teacher(user) or is_assistant(user) diff --git a/backend/api/signals.py b/backend/api/signals.py index b705255a..82bc905c 100644 --- a/backend/api/signals.py +++ b/backend/api/signals.py @@ -7,24 +7,26 @@ from api.models.student import Student from api.models.submission import (ExtraCheckResult, StateEnum, StructureCheckResult, Submission) -from api.tasks.docker_image import task_docker_image_build +from api.tasks.docker_image import (task_docker_image_build, + task_docker_image_remove) from api.tasks.extra_check import task_extra_check_start from api.tasks.structure_check import task_structure_check_start from authentication.models import User from authentication.signals import user_created -from django.db.models.signals import post_delete, post_save +from django.db.models.signals import post_delete, post_save, pre_delete from django.dispatch import Signal, receiver -# Signals +# MARK: Signals run_docker_image_build = Signal() +run_docker_image_remove = Signal() run_all_checks = Signal() run_structure_checks = Signal() run_extra_checks = Signal() -# Receivers +# MARK: Receivers @receiver(user_created) @@ -44,6 +46,11 @@ def _run_docker_image_build(docker_image: DockerImage, **_): task_docker_image_build.apply_async((docker_image,)) +@receiver(run_docker_image_remove) +def _run_docker_image_remove(docker_image: DockerImage, **_): + task_docker_image_remove.apply_async((docker_image,)) + + @receiver(run_all_checks) def _run_all_checks(submission: Submission, **_): # Get all checks @@ -75,7 +82,7 @@ def _run_extra_checks(submission: Submission, **_): task_extra_check_start.apply_async((True, extra_check_result,)) -# Hooks +# MARK: Hooks @receiver(post_save, sender=StructureCheck) @@ -108,7 +115,6 @@ def hook_extra_check(sender, instance: ExtraCheck, **kwargs): @receiver(post_save, sender=Submission) def hook_submission(sender, instance: Submission, created: bool, **kwargs): - # TODO: Maybe remove the raw check if created and not kwargs.get('raw', False): run_all_checks.send(sender=Submission, submission=instance) pass @@ -116,11 +122,16 @@ def hook_submission(sender, instance: Submission, created: bool, **kwargs): @receiver(post_save, sender=DockerImage) def hook_docker_image(sender, instance: DockerImage, created: bool, **kwargs): - # Run when it's created if created: run_docker_image_build.send(sender=DockerImage, docker_image=instance) -# Helpers + +@receiver(pre_delete, sender=DockerImage) +def hook_docker_image_delete(sender, instance: DockerImage, **kwargs): + run_docker_image_remove.send(sender=DockerImage, docker_image=instance) + + +# MARK: Helpers # Get all structure checks and create a result for each one diff --git a/backend/api/tasks/docker_image.py b/backend/api/tasks/docker_image.py index cf614a0d..3636ef36 100644 --- a/backend/api/tasks/docker_image.py +++ b/backend/api/tasks/docker_image.py @@ -6,7 +6,6 @@ from ypovoli.settings import MEDIA_ROOT -# TODO: Remove built image when it's deleted from the database @shared_task def task_docker_image_build(docker_image: DockerImage): # Set state @@ -19,9 +18,18 @@ def task_docker_image_build(docker_image: DockerImage): client.images.build(path=MEDIA_ROOT, dockerfile=docker_image.file.path, tag=get_docker_image_tag(docker_image), rm=True, quiet=True, forcerm=True) docker_image.state = StateEnum.READY - except (docker.errors.APIError, docker.errors.BuildError, docker.errors.APIError, TypeError): + except (docker.errors.APIError, docker.errors.BuildError, TypeError): docker_image.state = StateEnum.ERROR # TODO: Sent notification # Update the state docker_image.save() + + +@shared_task +def task_docker_image_remove(docker_image: DockerImage): + try: + client = docker.from_env() + client.images.remove(get_docker_image_tag(docker_image)) + except docker.errors.APIError: + pass diff --git a/backend/api/views/course_view.py b/backend/api/views/course_view.py index c3f42786..3adc2e6c 100644 --- a/backend/api/views/course_view.py +++ b/backend/api/views/course_view.py @@ -10,9 +10,9 @@ from api.serializers.assistant_serializer import (AssistantIDSerializer, AssistantSerializer) from api.serializers.course_serializer import (CourseCloneSerializer, - SaveInvitationLinkSerializer, CourseSerializer, CreateCourseSerializer, + SaveInvitationLinkSerializer, StudentJoinSerializer, StudentLeaveSerializer, TeacherJoinSerializer, @@ -39,7 +39,6 @@ class CourseViewSet(viewsets.ModelViewSet): serializer_class = CourseSerializer permission_classes = [IsAdminUser | CoursePermission] - # TODO: Creating should return the info of the new object and not a message "created" (General TODO) def create(self, request: Request, *_): """Override the create method to add the teacher to the course""" serializer = CreateCourseSerializer(data=request.data, context={"request": request}) diff --git a/backend/api/views/docker_view.py b/backend/api/views/docker_view.py index 7792de1b..1e2da9d7 100644 --- a/backend/api/views/docker_view.py +++ b/backend/api/views/docker_view.py @@ -1,22 +1,19 @@ from api.models.docker import DockerImage from api.permissions.docker_permissions import DockerPermission from api.serializers.docker_serializer import DockerImageSerializer -from rest_framework.permissions import IsAdminUser +from api.views.pagination.basic_pagination import BasicPagination from django.db.models import Q from django.db.models.manager import BaseManager from rest_framework.decorators import action from rest_framework.mixins import (CreateModelMixin, DestroyModelMixin, RetrieveModelMixin, UpdateModelMixin) +from rest_framework.permissions import IsAdminUser from rest_framework.request import Request from rest_framework.response import Response from rest_framework.viewsets import GenericViewSet -from api.views.pagination.basic_pagination import BasicPagination - - -# TODO: Remove update abilities, maybe? -class DockerImageViewSet(RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, GenericViewSet): +class DockerImageViewSet(RetrieveModelMixin, UpdateModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet): queryset = DockerImage.objects.all() serializer_class = DockerImageSerializer @@ -64,8 +61,6 @@ def patch_public(self, request: Request, **_) -> Response: return Response(serializer.data) - # TODO: Maybe not necessary - # https://www.django-rest-framework.org/api-guide/permissions/#overview-of-access-restriction-methods def list(self, request: Request) -> Response: images: BaseManager[DockerImage] = DockerImage.objects.all() if not request.user.is_staff: diff --git a/backend/api/views/group_view.py b/backend/api/views/group_view.py index c3595f4d..7c118bcd 100644 --- a/backend/api/views/group_view.py +++ b/backend/api/views/group_view.py @@ -40,7 +40,6 @@ def students(self, request, **_): ) return Response(serializer.data) - # TODO: I can access this endpoint unauthorized @action(detail=True, permission_classes=[IsAdminUser | GroupSubmissionPermission]) def submissions(self, request, **_): """Returns a list of submissions for the given group""" diff --git a/backend/api/views/submission_view.py b/backend/api/views/submission_view.py index f1f42a58..37911477 100644 --- a/backend/api/views/submission_view.py +++ b/backend/api/views/submission_view.py @@ -16,7 +16,6 @@ from rest_framework.viewsets import GenericViewSet -# TODO: Permission to ask for logs class SubmissionViewSet(RetrieveModelMixin, GenericViewSet): queryset = Submission.objects.all() serializer_class = SubmissionSerializer