Skip to content

Commit

Permalink
Single submission view (#453)
Browse files Browse the repository at this point in the history
  • Loading branch information
DeLany123 authored May 23, 2024
1 parent 4270777 commit 04b982c
Show file tree
Hide file tree
Showing 50 changed files with 921 additions and 580 deletions.
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,3 @@ frontend/cypress/videos/*
!data/nginx/nginx.dev.conf
!data/nginx/nginx.test.conf
!data/nginx/nginx.prod.conf

docs/.vitepress/dist
docs/.vitepress/cache
66 changes: 35 additions & 31 deletions backend/api/locale/en/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-05-20 12:28+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 <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down Expand Up @@ -149,74 +149,78 @@ msgid "docker.errors.no_staff"
msgstr "User is not allowed to assign othher owners than himself to the image."

#: serializers/docker_serializer.py:31
#: serializers/course_serializer.py:116
msgid "courses.error.invitation_link"
msgstr "The invitation link is not unique, please try again."

msgid "feedback.error.no_teacher"
msgstr "The user is no teacher."

#: serializers/docker_serializer.py:19
msgid "docker.errors.custom"
msgstr "User is not allowed to create public images"

#: serializers/group_serializer.py:57
#: serializers/group_serializer.py:56
msgid "group.errors.score_exceeds_max"
msgstr "The score exceeds the group's max score."

#: serializers/group_serializer.py:67 serializers/group_serializer.py:97
#: 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:75 serializers/group_serializer.py:113
#: serializers/group_serializer.py:74 serializers/group_serializer.py:108
msgid "group.errors.locked"
msgstr "The group is currently locked."

#: serializers/group_serializer.py:79
#: serializers/group_serializer.py:78
msgid "group.errors.full"
msgstr "The group is already full."

#: serializers/group_serializer.py:83
#: 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:87
#: serializers/group_serializer.py:86
msgid "group.errors.already_in_group"
msgstr "The student is already in the group."

#: serializers/group_serializer.py:105
msgid "group.errors.size_one"
msgstr "Unable to leave a group with size 1."

#: serializers/group_serializer.py:109
#: serializers/group_serializer.py:104
msgid "group.errors.not_present"
msgstr "The student is currently not in the group."

#: serializers/project_serializer.py:23
#: serializers/project_serializer.py:22
msgid "project.errors.invalid_instance"
msgstr "Error while parsing the provided zip."

#: serializers/project_serializer.py:122
#: serializers/project_serializer.py:81
msgid "project.errors.context"
msgstr "The project is not supplied in the context."

#: serializers/project_serializer.py:127
#: 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:141
#: 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:183
#: serializers/project_serializer.py:142
msgid "project.errors.zip_structure"
msgstr "Error while parsing the provided zip."

#: serializers/submission_serializer.py:99 tests/test_submission.py:275
#: 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:102 tests/test_submission.py:346
#: 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:105 tests/test_submission.py:376
#: 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:108
#: serializers/submission_serializer.py:105
msgid "project.error.submissions.no_files"
msgstr "The submission is empty."

Expand All @@ -232,39 +236,39 @@ msgstr "The teacher was successfully added."
msgid "teachers.success.destroy"
msgstr "The teacher was successfully destroyed."

#: views/course_view.py:136
#: views/course_view.py:137
msgid "courses.success.assistants.add"
msgstr "The assistant was successfully added to the course."

#: views/course_view.py:163
#: views/course_view.py:164
msgid "courses.success.assistants.remove"
msgstr "The assistant was successfully removed from the course."

#: views/course_view.py:225
#: views/course_view.py:226
msgid "courses.success.students.add"
msgstr "The student was successfully added to the course."

#: views/course_view.py:246
#: views/course_view.py:247
msgid "courses.success.students.remove"
msgstr "The student was successfully removed from the course."

#: views/course_view.py:291
#: views/course_view.py:292
msgid "courses.success.teachers.add"
msgstr "The teacher was successfully added to the course."

#: views/course_view.py:315
#: views/course_view.py:316
msgid "courses.success.teachers.remove"
msgstr "The teacher was successfully removed from the course."

#: views/group_view.py:73
#: views/group_view.py:74
msgid "group.success.students.add"
msgstr "The student was successfully added to the group."

#: views/group_view.py:93
#: views/group_view.py:94
msgid "group.success.students.remove"
msgstr "The student was successfully removed from the group."

#: views/group_view.py:112
#: views/group_view.py:113
msgid "group.success.submissions.add"
msgstr "The submission was successfully added to the group."

Expand Down Expand Up @@ -292,6 +296,6 @@ msgstr "No zip file available."
msgid "extra_check_result.download.log"
msgstr "No log file available."

#: views/submission_view.py:59
#: views/submission_view.py:60
msgid "extra_check_result.download.artifact"
msgstr "No artifact available."
35 changes: 0 additions & 35 deletions backend/api/management/commands/teacher_join_course.py

This file was deleted.

26 changes: 26 additions & 0 deletions backend/api/migrations/0019_feedback.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Generated by Django 5.0.4 on 2024-05-02 15:15

import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('api', '0018_course_invitation_link_and_more'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='Feedback',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('message', models.TextField()),
('creation_date', models.DateTimeField(auto_now_add=True)),
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='feedback_messages', to=settings.AUTH_USER_MODEL)),
('submission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='feedback', to='api.submission')),
],
),
]
14 changes: 14 additions & 0 deletions backend/api/migrations/0024_merge_20240507_1230.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Django 5.0.4 on 2024-05-07 12:30

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('api', '0019_feedback'),
('api', '0023_submission_zip_alter_checkresult_error_message_and_more'),
]

operations = [
]
14 changes: 14 additions & 0 deletions backend/api/migrations/0026_merge_20240518_1058.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Django 5.0.4 on 2024-05-18 10:58

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('api', '0024_merge_20240507_1230'),
('api', '0025_extracheckresult_artifact'),
]

operations = [
]
38 changes: 38 additions & 0 deletions backend/api/models/feedback.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from django.db import models
from api.models.submission import Submission
from authentication.models import User


class Feedback(models.Model):
"""Model that represents a feedback message."""

# ID should be generated automatically

# Feedback message
message = models.TextField(null=False)

# Feedback message author
author = models.ForeignKey(
User,
# If the author is deleted, the feedback message should be deleted as well
on_delete=models.CASCADE,
related_name="feedback_messages",
blank=False,
null=False,
)

# Feedback message creation date
creation_date = models.DateTimeField(
# The default value is the current date and time
auto_now_add=True,
blank=False,
null=False
)

submission = models.ForeignKey(
Submission,
on_delete=models.CASCADE,
related_name="feedback",
blank=False,
null=False
)
17 changes: 17 additions & 0 deletions backend/api/permissions/feedback_permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from rest_framework import permissions

from api.permissions.role_permissions import is_teacher


class IsAdminOrTeacherForPatch(permissions.BasePermission):
"""
Custom permission to only allow admins to access objects in general,
but teachers can only make PATCH requests.
"""

def has_permission(self, request, view):
if request.user.is_authenticated and request.user.is_staff:
return True
elif request.method == 'PATCH' and is_teacher(request.user):
return True
return False
9 changes: 6 additions & 3 deletions backend/api/permissions/submission_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@

class SubmissionPermission(BasePermission):
def has_permission(self, request: Request, view: APIView) -> bool:
if request.method not in SAFE_METHODS:
submission_id = view.kwargs.get("pk")

if request.method not in SAFE_METHODS or submission_id is None:
return False

user: User = cast(User, request.user)

return user.is_staff or is_teacher(user) or is_assistant(user)
# check if user is in group of submission
group = Submission.objects.get(id=submission_id).group
return user.is_staff or is_teacher(user) or is_assistant(user) or group.students.filter(id=user.id).exists()

def has_object_permission(self, request: Request, view: APIView, obj: Submission) -> bool:
if request.method not in SAFE_METHODS:
Expand Down
Loading

0 comments on commit 04b982c

Please sign in to comment.