Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Api working #35

Merged
merged 181 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
181 commits
Select commit Hold shift + click to select a range
2f88001
init and remove .env
gilles-arnout Mar 2, 2024
b5b24f2
basic login page
gilles-arnout Mar 2, 2024
59393c7
First implementation of a view. Much work to do.
AlexanderVanOyen Mar 2, 2024
66e1061
model manager and put function
AlexanderVanOyen Mar 2, 2024
43ad033
Merge remote-tracking branch 'origin/develop' into api_routes-impleme…
AlexanderVanOyen Mar 4, 2024
8165e90
add swagger ui on /swagger and remove .env from tracked files
robinpdev Mar 5, 2024
546f63b
course api
ReinhardDP Mar 7, 2024
9283344
Merge branch 'api_routes-implementation' of github.com:SELab-2/UGent-…
ReinhardDP Mar 7, 2024
2baf464
Project viewset and custom permission class
AlexanderVanOyen Mar 8, 2024
f224e8a
Added Material UI dependence and tested it out with some buttons.
Thibaud-Collyn Mar 8, 2024
d1aaba8
corrected instances
ReinhardDP Mar 9, 2024
d30a0aa
added permissions
ReinhardDP Mar 9, 2024
470806c
added courses to urls
ReinhardDP Mar 9, 2024
fb2692f
styled login page
gilles-arnout Mar 9, 2024
e0e4235
automatic submission number, student max in 1 group for every project
PJDeSmijter Mar 9, 2024
008aecc
add admin panel
robinpdev Mar 9, 2024
ada3209
fixed permission class, added url
AlexanderVanOyen Mar 9, 2024
31b22aa
Merge remote-tracking branch 'origin/api_routes-implementation' into …
AlexanderVanOyen Mar 9, 2024
fa9f422
new url for creating project, added field to project model
AlexanderVanOyen Mar 9, 2024
25e4146
course permissions fixed
ReinhardDP Mar 9, 2024
75b7b36
Merge branch 'api_routes-implementation' of github.com:SELab-2/UGent-…
ReinhardDP Mar 9, 2024
24db0ca
Merge branch 'develop' into login-screen
axellorreyne Mar 10, 2024
54be022
fix pages structure
gilles-arnout Mar 10, 2024
0ddd30c
GET requests support for groups+submissions, but error for groups whe…
RunoBoy Mar 10, 2024
b14d75b
removed deadline temporary to find bug
RunoBoy Mar 10, 2024
ca408dd
without deadline in project seems to work
RunoBoy Mar 10, 2024
2f9a381
deadline for projects fixed
RunoBoy Mar 10, 2024
82c29e2
Everything fixed to create submissions
RunoBoy Mar 10, 2024
c5fcf3e
API works now, fixed URLs and the requests
AlexanderVanOyen Mar 10, 2024
8cbc51f
list fixed
AlexanderVanOyen Mar 10, 2024
8dcfb2d
Merge branch 'develop' into api-testen-backend
PJDeSmijter Mar 10, 2024
fecde1f
Merge branch 'develop' into api_routes-implementation
PJDeSmijter Mar 10, 2024
ec129d7
fix merge
PJDeSmijter Mar 10, 2024
42b7ab4
Merge branch 'api_routes-implementation' into api-testen-backend
PJDeSmijter Mar 10, 2024
cefeb98
course api tests, permission fixes, test fixes
PJDeSmijter Mar 10, 2024
c3dd5a4
partial projects tests, todo invalid project & unautherised
PJDeSmijter Mar 11, 2024
c3e2adc
fix views invalid objects
PJDeSmijter Mar 11, 2024
629ef66
cleanup projects view
PJDeSmijter Mar 11, 2024
853bdac
Update test_project.py
PJDeSmijter Mar 11, 2024
2d00aab
fix lint
axellorreyne Mar 11, 2024
2c8ee17
splitting client and server components
gilles-arnout Mar 11, 2024
6da1e6d
user uploads toevoegen
robinpdev Mar 11, 2024
4982495
add testing workflow
robinpdev Mar 11, 2024
6c6cc39
try fixing test workflow
robinpdev Mar 11, 2024
057c25e
same
robinpdev Mar 11, 2024
c297348
lol
robinpdev Mar 11, 2024
a0f5a92
users changed
ReinhardDP Mar 11, 2024
2bd063a
Merge branch 'api_routes-implementation' of github.com:SELab-2/UGent-…
ReinhardDP Mar 11, 2024
00e76fc
Merge branch 'api_routes-implementation' into api-testen-backend
PJDeSmijter Mar 11, 2024
68fc4c1
naming change, permission for project api
AlexanderVanOyen Mar 11, 2024
3aa7015
permissions updated, course api expanded
ReinhardDP Mar 11, 2024
8bd347b
course api error fixed
ReinhardDP Mar 11, 2024
17ecff7
Merge branch 'api_routes-implementation' into api-testen-backend
PJDeSmijter Mar 11, 2024
1f3ca8a
Merge branch 'develop' into api_routes-implementation
PJDeSmijter Mar 11, 2024
350ce8f
Merge branch '29-model-fixes' into api_routes-implementation
PJDeSmijter Mar 11, 2024
d43a669
Created and applied global style for frontend.
Thibaud-Collyn Mar 11, 2024
f8e13b6
more checks added to projects api, added more functionality to groups…
AlexanderVanOyen Mar 11, 2024
f70db26
refactor testen
PJDeSmijter Mar 12, 2024
aa2a7b2
todo's checks
PJDeSmijter Mar 12, 2024
3376aa2
clean testen
PJDeSmijter Mar 12, 2024
84fcaca
course permissions fixed
ReinhardDP Mar 12, 2024
d2e8b10
model changes, test fixes
PJDeSmijter Mar 12, 2024
46a622f
commit before pull
gilles-arnout Mar 12, 2024
3fd2a72
Merge branch 'login-screen' of https://github.com/SELab-2/UGent-1 int…
gilles-arnout Mar 12, 2024
a81b817
small error fix in theme and layout
gilles-arnout Mar 12, 2024
3908805
user api and permissions
ReinhardDP Mar 12, 2024
65c45d2
Merge branch 'api-working' of github.com:SELab-2/UGent-1 into api-wor…
ReinhardDP Mar 12, 2024
2f06aee
model test fixes
PJDeSmijter Mar 12, 2024
f413c89
Merge branch 'api-working' of https://github.com/SELab-2/UGent-1 into…
PJDeSmijter Mar 12, 2024
cba6b28
fix dubbele max_score
PJDeSmijter Mar 12, 2024
7f5b60a
Merge branch 'login-screen' into api-testing-branch-voor-axel
axellorreyne Mar 12, 2024
495eadc
add auth urls
axellorreyne Mar 12, 2024
88a52a1
layout fix
PJDeSmijter Mar 12, 2024
dcfc5de
add auth agent
axellorreyne Mar 12, 2024
fefb8c3
add auth header
axellorreyne Mar 12, 2024
ea9f0fa
add basic frontend login logic
axellorreyne Mar 12, 2024
a324f35
add axios dependency
axellorreyne Mar 12, 2024
59723ce
change user manager
axellorreyne Mar 12, 2024
dd0110b
Merge branch 'api-testing-branch-voor-axel' into api-working
PJDeSmijter Mar 12, 2024
8e13b0a
fix migrations authentication
PJDeSmijter Mar 12, 2024
5b453f3
fix lint
PJDeSmijter Mar 12, 2024
3fa501e
fix username label
axellorreyne Mar 12, 2024
3dc671d
Merge remote-tracking branch 'origin/api-working' into api-working
axellorreyne Mar 12, 2024
a4268fd
add superuser and reset make commands
axellorreyne Mar 12, 2024
31fd002
fix lint
PJDeSmijter Mar 12, 2024
67168cb
Merge branch 'api-working' of https://github.com/SELab-2/UGent-1 into…
PJDeSmijter Mar 12, 2024
7ae361e
add user admin view
axellorreyne Mar 12, 2024
8bd7150
fix tests
PJDeSmijter Mar 12, 2024
7350911
some migrations, changes to group model, added functionality for grou…
AlexanderVanOyen Mar 12, 2024
71d4da0
Submissions correct API
RunoBoy Mar 12, 2024
9c53512
Submissions get correct file location
RunoBoy Mar 12, 2024
4f143b6
Merge branch 'api-working' of github.com:SELab-2/UGent-1 into api-wor…
RunoBoy Mar 12, 2024
d9c0785
group nr url
AlexanderVanOyen Mar 12, 2024
fc4332d
Merge branch 'api-working' of github.com:SELab-2/UGent-1 into api-wor…
RunoBoy Mar 12, 2024
d6566ef
Merge with latest changes
RunoBoy Mar 12, 2024
ad3cb7e
small todo to remember
RunoBoy Mar 12, 2024
ecbcb33
small todo to remember
RunoBoy Mar 12, 2024
5ad5775
list en join groups implementaties
AlexanderVanOyen Mar 12, 2024
e9e9462
Merge remote-tracking branch 'origin/api-working' into api-working
AlexanderVanOyen Mar 12, 2024
3008d3b
migretions Alexander
PJDeSmijter Mar 13, 2024
727a8c6
fix courses
PJDeSmijter Mar 13, 2024
46abe05
Revert "fix courses"
PJDeSmijter Mar 13, 2024
50c4462
permissions added to submissions
RunoBoy Mar 13, 2024
7935a89
course tests and view fixed (user test not finiched)
ReinhardDP Mar 13, 2024
fd17261
fix courses
PJDeSmijter Mar 13, 2024
0b55b17
fix lint
PJDeSmijter Mar 13, 2024
c0a2490
join course when you create it
ReinhardDP Mar 13, 2024
5d26614
pause to implement nested submissions
RunoBoy Mar 13, 2024
c69d375
Merge branch 'api-working' of github.com:SELab-2/UGent-1 into api-wor…
RunoBoy Mar 13, 2024
f660e21
fix groups
PJDeSmijter Mar 13, 2024
7376273
Merge branch 'api-working' of github.com:SELab-2/UGent-1 into api-wor…
ReinhardDP Mar 13, 2024
4fb0c7a
user tests fixed
ReinhardDP Mar 13, 2024
acab72f
fix groups - projects
PJDeSmijter Mar 13, 2024
b176700
user test done
ReinhardDP Mar 13, 2024
5a2e0a4
cleanup groups
PJDeSmijter Mar 13, 2024
3580f9f
course tests done
ReinhardDP Mar 13, 2024
ff1e0bd
Merge branch 'api-working' of github.com:SELab-2/UGent-1 into api-wor…
ReinhardDP Mar 13, 2024
331aaef
semi fixed tests projects
PJDeSmijter Mar 13, 2024
b168e87
Merge branch 'api-working' of https://github.com/SELab-2/UGent-1 into…
PJDeSmijter Mar 13, 2024
3109a2e
project admin test fixed
ReinhardDP Mar 13, 2024
63d711d
begin tests, project en groups api changes
AlexanderVanOyen Mar 13, 2024
669d062
Merge remote-tracking branch 'origin/api-working' into api-working
AlexanderVanOyen Mar 13, 2024
a4379a4
course test done (really done this time)
ReinhardDP Mar 13, 2024
f3922fd
Merge branch 'api-working' of github.com:SELab-2/UGent-1 into api-wor…
ReinhardDP Mar 13, 2024
d51497b
permissions groups en wat andere changes
AlexanderVanOyen Mar 13, 2024
9a8080e
fix group & projects
PJDeSmijter Mar 13, 2024
c9d8bdd
action submission
RunoBoy Mar 13, 2024
f31e83b
merge with recent changes
RunoBoy Mar 13, 2024
3cf45d4
fix lint
PJDeSmijter Mar 13, 2024
6af32f2
fix lint bis
PJDeSmijter Mar 13, 2024
d1dbe56
fix groups permissions
PJDeSmijter Mar 13, 2024
5d35bc7
fix group permissions bis
PJDeSmijter Mar 13, 2024
349f5b1
project permissions and teacher test
ReinhardDP Mar 13, 2024
6a7dca5
Merge branch 'api-working' of github.com:SELab-2/UGent-1 into api-wor…
ReinhardDP Mar 13, 2024
7e4970d
merge with recent changes
RunoBoy Mar 13, 2024
209ecc0
group permissions should work?
AlexanderVanOyen Mar 13, 2024
6d496b9
Merge remote-tracking branch 'origin/api-working' into api-working
AlexanderVanOyen Mar 13, 2024
22b392f
fix submissions
PJDeSmijter Mar 13, 2024
325037e
Merge branch 'api-working' of https://github.com/SELab-2/UGent-1 into…
PJDeSmijter Mar 13, 2024
d73ed72
Revert "Merge branch 'api-working' of https://github.com/SELab-2/UGen…
PJDeSmijter Mar 13, 2024
d4eff54
project tests done
ReinhardDP Mar 13, 2024
0bfaa92
Merge branch 'api-working' of github.com:SELab-2/UGent-1 into api-wor…
ReinhardDP Mar 13, 2024
ff47452
fixed imports
AlexanderVanOyen Mar 13, 2024
0e56080
Merge remote-tracking branch 'origin/api-working' into api-working
AlexanderVanOyen Mar 13, 2024
7a91ed0
tests
RunoBoy Mar 13, 2024
2467bf6
merged with recent changes
RunoBoy Mar 13, 2024
9beebc8
submission permissions
AlexanderVanOyen Mar 13, 2024
02f091f
group admin test (unfinished)
ReinhardDP Mar 13, 2024
74410df
submission permissions fix
AlexanderVanOyen Mar 13, 2024
e2d414a
Merge branch 'api-working' of github.com:SELab-2/UGent-1 into api-wor…
ReinhardDP Mar 13, 2024
2e1a581
Fix permissions to view group by id
RunoBoy Mar 13, 2024
35a6ccd
Merge remote-tracking branch 'origin/api-working' into api-working
RunoBoy Mar 13, 2024
72915b6
get_submissions in group
RunoBoy Mar 13, 2024
f9bb205
test project fix and extra
PJDeSmijter Mar 13, 2024
5475517
Merge branch 'api-working' of https://github.com/SELab-2/UGent-1 into…
PJDeSmijter Mar 13, 2024
9918d5b
fix submission view imports
axellorreyne Mar 13, 2024
fe52c7b
test project added get_groups
PJDeSmijter Mar 14, 2024
915fac2
test_admin for submissions
RunoBoy Mar 14, 2024
d8ef075
group tests ??!?!?!? legit unfixable?? pls help me
AlexanderVanOyen Mar 14, 2024
4447c50
Merge remote-tracking branch 'origin/api-working' into api-working
AlexanderVanOyen Mar 14, 2024
376be88
a lot of progress to group tests, just need to fix student tests basi…
AlexanderVanOyen Mar 14, 2024
0b33a33
test_teacher for submissions
RunoBoy Mar 14, 2024
36bd540
add submission 404 and deadline checks
axellorreyne Mar 14, 2024
c94a1e0
Merge remote-tracking branch 'origin/api-working' into api-working
axellorreyne Mar 14, 2024
aa5dd20
fix lint
axellorreyne Mar 14, 2024
4d7bc6f
test_student for submissions
RunoBoy Mar 14, 2024
24130e7
misc lint + auto formatting
axellorreyne Mar 14, 2024
6c96014
test_unauthenticated for submissions
RunoBoy Mar 14, 2024
407e729
all tests work
RunoBoy Mar 14, 2024
1732ec2
fix lint
RunoBoy Mar 14, 2024
644e622
fix lint numero dos
RunoBoy Mar 14, 2024
7e1807d
group unauth testen
PJDeSmijter Mar 14, 2024
dac7341
test get_submissions
PJDeSmijter Mar 14, 2024
33ef36b
fix group tests except join
PJDeSmijter Mar 14, 2024
8a4df00
course permission en test fix
PJDeSmijter Mar 14, 2024
2c41b54
fix lint
PJDeSmijter Mar 14, 2024
a6b2c73
fix visible groups
PJDeSmijter Mar 14, 2024
7aa9d22
extra course tests
PJDeSmijter Mar 14, 2024
43d6b44
small course test fix
PJDeSmijter Mar 14, 2024
6cb77bf
fix group join
AlexanderVanOyen Mar 14, 2024
2d61839
get_submissions fixed
AlexanderVanOyen Mar 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Backend test CI

on:
- pull_request

jobs:
backend-test:
runs-on: self-hosted
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.11
uses: actions/setup-python@v4
with:
python-version: "3.11"
- name: Install dependencies
working-directory: ./
run: |
python -m pip install --upgrade pip
pip install -r ./backend/requirements.txt
- name: Running Django tests
run: |
sh ./backend/runtests.sh
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
.env
django/db.sqlite3
backend/db.sqlite3
backend/uploads
venv/
.venv/

Expand Down
15 changes: 14 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,17 @@ stop:

lint:
docker exec pigeonhole-backend flake8 .
docker exec pigeonhole-frontend npm run lint
docker exec pigeonhole-frontend npm run lint

superuser:
docker exec -it pigeonhole-backend python manage.py createsuperuser

reset:
docker image prune -af
docker system prune

backendtest:
docker exec -it pigeonhole-backend sh /usr/src/app/backend/runtests.sh

backendshell:
docker exec -it pigeonhole-backend sh
3 changes: 2 additions & 1 deletion backend/pigeonhole/apps/courses/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Generated by Django 5.0.2 on 2024-03-02 21:03
# Generated by Django 5.0.3 on 2024-03-12 22:52

from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
Expand Down
26 changes: 26 additions & 0 deletions backend/pigeonhole/apps/courses/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from rest_framework import permissions

from backend.pigeonhole.apps.users.models import User
from backend.pigeonhole.apps.courses.models import Course


class CourseUserPermissions(permissions.BasePermission):
def has_permission(self, request, view):
if request.user.is_admin or request.user.is_superuser:
return True

if request.user.is_teacher:
if view.action in ['create', 'list', 'retrieve']:
return True
elif view.action in ['update', 'partial_update', 'destroy', 'get_projects'] and User.objects.filter(
id=request.user.id,
course=view.kwargs[
'pk']).exists():
return True
return

if request.user.is_student:
if view.action == 'get_projects':
return Course.objects.filter(course_id=view.kwargs['pk'], user=request.user).exists()
return view.action in ['list', 'retrieve']
return False
42 changes: 42 additions & 0 deletions backend/pigeonhole/apps/courses/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from backend.pigeonhole.apps.courses.models import CourseSerializer
from backend.pigeonhole.apps.projects.models import Project
from backend.pigeonhole.apps.projects.models import ProjectSerializer
from .models import Course
from .permissions import CourseUserPermissions


class CourseViewSet(viewsets.ModelViewSet):
queryset = Course.objects.all()
serializer_class = CourseSerializer
permission_classes = [IsAuthenticated, CourseUserPermissions]

def perform_create(self, serializer):
course = serializer.save()
user = self.request.user
user.course.add(course)

@action(detail=True, methods=['post'])
def join_course(self, request, *args, **kwargs):
course = self.get_object()
user = request.user

user.course.add(course)
return Response(status=status.HTTP_200_OK)

@action(detail=False, methods=['GET'])
def get_selected_courses(self, request, *args, **kwargs):
user = request.user
courses = user.course.all()
serializer = CourseSerializer(courses, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)

@action(detail=True, methods=['GET'])
def get_projects(self, request, *args, **kwargs):
course = self.get_object()
projects = Project.objects.filter(course_id=course)
return Response(ProjectSerializer(projects, many=True).data, status=status.HTTP_200_OK)
8 changes: 5 additions & 3 deletions backend/pigeonhole/apps/groups/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# Generated by Django 5.0.2 on 2024-03-02 21:03
# Generated by Django 5.0.3 on 2024-03-12 22:52

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


class Migration(migrations.Migration):

initial = True

dependencies = [
Expand All @@ -16,9 +17,10 @@ class Migration(migrations.Migration):
name='Group',
fields=[
('group_id', models.BigAutoField(primary_key=True, serialize=False)),
('group_nr', models.IntegerField()),
('group_nr', models.IntegerField(blank=True, null=True)),
('feedback', models.TextField(null=True)),
('final_score', models.IntegerField()),
('final_score', models.IntegerField(blank=True, null=True)),
('visible', models.BooleanField(default=True)),
('project_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='projects.project')),
],
),
Expand Down
10 changes: 6 additions & 4 deletions backend/pigeonhole/apps/groups/migrations/0002_initial.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
# Generated by Django 5.0.2 on 2024-03-02 21:03
# Generated by Django 5.0.3 on 2024-03-12 22:52

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


class Migration(migrations.Migration):

initial = True

dependencies = [
('groups', '0001_initial'),
('users', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.AddField(
model_name='group',
name='student',
field=models.ManyToManyField(to='users.student'),
name='user',
field=models.ManyToManyField(to=settings.AUTH_USER_MODEL),
),
]
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 5.0.2 on 2024-03-07 20:30
# Generated by Django 5.0.3 on 2024-03-13 11:04

from django.db import migrations, models

Expand All @@ -12,7 +12,7 @@ class Migration(migrations.Migration):
operations = [
migrations.AlterField(
model_name='group',
name='group_nr',
field=models.IntegerField(blank=True, null=True),
name='visible',
field=models.BooleanField(default=False),
),
]

This file was deleted.

20 changes: 20 additions & 0 deletions backend/pigeonhole/apps/groups/migrations/0004_alter_group_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Generated by Django 5.0.3 on 2024-03-13 18:34

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


class Migration(migrations.Migration):

dependencies = [
('groups', '0003_alter_group_visible'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.AlterField(
model_name='group',
name='user',
field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL),
),
]
45 changes: 41 additions & 4 deletions backend/pigeonhole/apps/groups/models.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,68 @@
from django.core.exceptions import ValidationError
from django.db import models
from rest_framework import serializers

from backend.pigeonhole.apps.projects.models import Project
from backend.pigeonhole.apps.users.models import Student
from backend.pigeonhole.apps.users.models import User


class Group(models.Model):
group_id = models.BigAutoField(primary_key=True)
group_nr = models.IntegerField(blank=True, null=True)
project_id = models.ForeignKey(Project, on_delete=models.CASCADE)
student = models.ManyToManyField(Student)
user = models.ManyToManyField(User, blank=True)
feedback = models.TextField(null=True)
final_score = models.IntegerField(null=True, blank=True)
visible = models.BooleanField(null=False, default=False)

objects = models.Manager()

# a student can only be in one group per project
def clean(self):
if self.user.exists(): # Only validate if there are users
for student in self.user.all():
existing_groups = Group.objects.filter(
project_id=self.project_id, user=student).exclude(
group_id=self.group_id)
if existing_groups.exists():
raise ValidationError(f"Student {student} is already part of "
"another group in this project.")

# a student can only be in one group per project, group_nr is
# automatically assigned and unique per project
def save(self, *args, **kwargs):
if not self.group_id:
if self.group_nr is None:
max_group_nr = Group.objects.filter(
project_id=self.project_id).aggregate(
models.Max('group_nr'))['group_nr__max'] or 0
models.Max('group_nr'))['group_nr__max'] or 0
self.group_nr = max_group_nr + 1
super().save(*args, **kwargs)


class GroupSerializer(serializers.ModelSerializer):
class Meta:
model = Group
fields = ["group_id", "group_nr", "final_score", "project_id", "student"]
fields = ["group_id", "group_nr", "final_score", "project_id", "user", "feedback", "visible"]

def to_representation(self, instance):
data = super().to_representation(instance)
request = self.context.get('request')

# if student not in group always hide final_score and feedback
if request and request.user.is_student and not instance.user.filter(
pk=request.user.pk).exists():
if 'final_score' in data:
del data['final_score']
if 'feedback' in data:
del data['feedback']
return data

# Check if the user is a student and the group is not visible
if request and request.user.is_student and not instance.visible:
# Hide sensitive information for students
if 'final_score' in data:
del data['final_score']
if 'feedback' in data:
del data['feedback']
return data
49 changes: 49 additions & 0 deletions backend/pigeonhole/apps/groups/permission.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from rest_framework.response import Response
from rest_framework import permissions, status

from backend.pigeonhole.apps.groups.models import Group
from backend.pigeonhole.apps.projects.models import Project


class CanAccessGroup(permissions.BasePermission):
# Custom user class to check if the user can join a group.
def has_permission(self, request, view):
if not request.user.is_authenticated:
# If user is not authenticated, deny permission
return False

if view.action in ['create', 'list']:
return False

user = request.user
group_id = int(view.kwargs.get('pk'))
if not Group.objects.filter(group_id=group_id).exists():
if user.is_admin or user.is_superuser:
return Response(status=status.HTTP_404_NOT_FOUND)
return False

project_id = Group.objects.get(group_id=group_id).project_id.project_id
if not Project.objects.filter(project_id=project_id).exists():
if user.is_admin or user.is_superuser:
return Response(status=status.HTTP_404_NOT_FOUND)
return False

course_id = Project.objects.get(project_id=project_id).course_id.course_id
if user.is_admin or user.is_superuser:
return view.action not in ['join', 'leave']
elif user.is_teacher:
if user.course.filter(course_id=course_id).exists():
return view.action in ['retrieve', 'get_submissions', 'update', 'partial_update']
elif user.is_student:
if user.course.filter(course_id=course_id).exists():
# check if the user is already in the group
if Group.objects.get(group_id=group_id).user.filter(id=user.id).exists():
return view.action in ['retrieve', 'get_submissions', 'leave']
elif Group.objects.get(group_id=group_id).user.count() < Project.objects.get(
project_id=project_id).group_size:
return view.action in ['retrieve', 'get_submissions', 'join']
elif view.action in ['join']:
return Response({'message': 'Group is full'}, status=status.HTTP_400_BAD_REQUEST)
elif view.action in ['leave']:
return Response({'message': 'User is not in the group'}, status=status.HTTP_400_BAD_REQUEST)
return False
Loading
Loading