added permissions and authentication to API
This commit is contained in:
parent
6dcc3a448e
commit
0a39a9a1b9
8 changed files with 288 additions and 218 deletions
|
@ -1,7 +1,14 @@
|
|||
from django.urls import path, include
|
||||
from rest_framework_simplejwt.views import TokenRefreshView, TokenObtainPairView, TokenVerifyView
|
||||
|
||||
import Palto.Palto.api.v1.urls as v1_urls
|
||||
|
||||
urlpatterns = [
|
||||
# Authentification (JWT)
|
||||
path('auth/jwt/token/', TokenObtainPairView.as_view(), name='token'),
|
||||
path('auth/jwt/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
|
||||
path('auth/jwt/token/verify/', TokenVerifyView.as_view(), name='token_verify'),
|
||||
|
||||
# API
|
||||
path('v1/', include(v1_urls)),
|
||||
]
|
||||
|
|
205
Palto/Palto/api/v1/permissions.py
Normal file
205
Palto/Palto/api/v1/permissions.py
Normal file
|
@ -0,0 +1,205 @@
|
|||
from rest_framework import permissions
|
||||
|
||||
from Palto.Palto.models import (Department, TeachingUnit, StudentCard, StudentGroup, User, TeachingSession, Attendance,
|
||||
Absence, AbsenceAttachment)
|
||||
|
||||
|
||||
class UserPermission(permissions.BasePermission):
|
||||
def has_object_permission(self, request, view, obj: User) -> bool:
|
||||
# if the requesting user is admin, allow all
|
||||
if request.user.is_superuser:
|
||||
return True
|
||||
|
||||
if request.method in permissions.SAFE_METHODS:
|
||||
# if the user is in one of the same department as the requesting user, allow read
|
||||
if obj in Department.multiple_related_users(request.user.related_departments):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class DepartmentPermission(permissions.BasePermission):
|
||||
def has_object_permission(self, request, view, obj: Department) -> bool:
|
||||
# if the requesting user is admin, allow all
|
||||
if request.user.is_superuser:
|
||||
return True
|
||||
|
||||
# if the group department is managed by the user, allow all
|
||||
if obj in request.user.managing_departments:
|
||||
return True
|
||||
|
||||
if request.method in permissions.SAFE_METHODS:
|
||||
# allow read to everybody
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class StudentGroupPermission(permissions.BasePermission):
|
||||
def has_object_permission(self, request, view, obj: StudentGroup) -> bool:
|
||||
# if the requesting user is admin, allow all
|
||||
if request.user.is_superuser:
|
||||
return True
|
||||
|
||||
# if the group department is managed by the user, allow all
|
||||
if obj.department in request.user.managing_departments:
|
||||
return True
|
||||
|
||||
# if the user is the owner of the group, allow all
|
||||
if obj.owner is request.user:
|
||||
return True
|
||||
|
||||
if request.method in permissions.SAFE_METHODS:
|
||||
# if the student is in the group, allow read
|
||||
if obj in request.user.student_groups:
|
||||
return True
|
||||
|
||||
# if the user is a teacher from the same department, allow read
|
||||
if obj.department in request.user.teaching_departments:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class TeachingUnitPermission(permissions.BasePermission):
|
||||
def has_object_permission(self, request, view, obj: TeachingUnit) -> bool:
|
||||
# if the requesting user is admin, allow all
|
||||
if request.user.is_superuser:
|
||||
return True
|
||||
|
||||
# if the teaching unit department is managed by the user, allow all
|
||||
if obj.department in request.user.managing_departments:
|
||||
return True
|
||||
|
||||
# if the teaching unit is managed by the user, allow all
|
||||
if obj in request.user.managing_units:
|
||||
return True
|
||||
|
||||
if request.method in permissions.SAFE_METHODS:
|
||||
# if the user is related to the department, allow read
|
||||
if obj.department in request.user.related_departments:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class StudentCardPermission(permissions.BasePermission):
|
||||
def has_object_permission(self, request, view, obj: StudentCard) -> bool:
|
||||
# if the requesting user is admin, allow all
|
||||
if request.user.is_superuser:
|
||||
return True
|
||||
|
||||
# if the card department is managed by the user, allow all
|
||||
if obj.department in request.user.managing_departments:
|
||||
return True
|
||||
|
||||
if request.method in permissions.SAFE_METHODS:
|
||||
# if the owner of the card is the user, allow read
|
||||
if obj.owner is request.user:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class TeachingSessionPermission(permissions.BasePermission):
|
||||
def has_object_permission(self, request, view, obj: TeachingSession) -> bool:
|
||||
# if the requesting user is admin, allow all
|
||||
if request.user.is_superuser:
|
||||
return True
|
||||
|
||||
# if the teacher is the user, allow all
|
||||
if obj.teacher is request.user:
|
||||
return True
|
||||
|
||||
# if the unit of the session is managed by the user, allow all
|
||||
if obj.unit in request.user.managing_units:
|
||||
return True
|
||||
|
||||
# if the department of the session is managed by the user, allow all
|
||||
if obj.unit.department in request.user.managing_departments:
|
||||
return True
|
||||
|
||||
if request.method in permissions.SAFE_METHODS:
|
||||
# if the user was one of the student, allow read
|
||||
if request.user in obj.group.students:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class AttendancePermission(permissions.BasePermission):
|
||||
def has_object_permission(self, request, view, obj: Attendance) -> bool:
|
||||
# if the requesting user is admin, allow all
|
||||
if request.user.is_superuser:
|
||||
return True
|
||||
|
||||
# if the teacher is the user, allow all
|
||||
if obj.session.teacher is request.user:
|
||||
return True
|
||||
|
||||
# if the unit of the session is managed by the user, allow all
|
||||
if obj.session.unit in request.user.managing_units:
|
||||
return True
|
||||
|
||||
# if the department of the session is managed by the user, allow all
|
||||
if obj.session.unit.department in request.user.managing_departments:
|
||||
return True
|
||||
|
||||
if request.method in permissions.SAFE_METHODS:
|
||||
# if the user was the student, allow read
|
||||
if obj.student is request.user:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class AbsencePermission(permissions.BasePermission):
|
||||
def has_object_permission(self, request, view, obj: Absence) -> bool:
|
||||
# if the requesting user is admin, allow all
|
||||
if request.user.is_superuser:
|
||||
return True
|
||||
|
||||
# if the department of the session is managed by the user, allow all
|
||||
if obj.session.unit.department in request.user.managing_departments:
|
||||
return True
|
||||
|
||||
# if the user was the student, allow all
|
||||
if obj.student is request.user:
|
||||
return True
|
||||
|
||||
if request.method in permissions.SAFE_METHODS:
|
||||
# if the unit of the session is managed by the user, allow read
|
||||
if obj.session.unit in request.user.managing_units:
|
||||
return True
|
||||
|
||||
# if the teacher is the user, allow read
|
||||
if obj.session.teacher is request.user:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class AbsenceAttachmentPermission(permissions.BasePermission):
|
||||
def has_object_permission(self, request, view, obj: AbsenceAttachment) -> bool:
|
||||
# if the requesting user is admin, allow all
|
||||
if request.user.is_superuser:
|
||||
return True
|
||||
|
||||
# if the department of the session is managed by the user, allow all
|
||||
if obj.absence.session.unit.department in request.user.managing_departments:
|
||||
return True
|
||||
|
||||
# if the user was the student, allow all
|
||||
if obj.absence.student is request.user:
|
||||
return True
|
||||
|
||||
if request.method in permissions.SAFE_METHODS:
|
||||
# if the unit of the session is managed by the user, allow read
|
||||
if obj.absence.session.unit in request.user.managing_units:
|
||||
return True
|
||||
|
||||
# if the teacher is the user, allow read
|
||||
if obj.absence.session.teacher is request.user:
|
||||
return True
|
||||
|
||||
return False
|
|
@ -4,39 +4,40 @@ from Palto.Palto.models import (User, Department, TeachingUnit, StudentCard, Tea
|
|||
AbsenceAttachment, StudentGroup)
|
||||
|
||||
|
||||
# TODO(Raphaël): Les champs sont-ils sûr ? (carte uid ?)
|
||||
# TODO(Raphaël): Connection à l'API avec token ?
|
||||
# TODO(Raphaël): Voir pour les relations
|
||||
# TODO(Raphaël): Voir pour les related_name
|
||||
|
||||
|
||||
class UserSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['id', 'username', 'first_name', 'last_name']
|
||||
fields = ['id', 'username', 'first_name', 'last_name', 'email']
|
||||
|
||||
|
||||
class DepartmentSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Department
|
||||
fields = ['id', 'name', 'mail']
|
||||
fields = ['id', 'name', 'email', 'managers']
|
||||
# NOTE: teachers, students
|
||||
|
||||
|
||||
class StudentGroupSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = StudentGroup
|
||||
fields = ['id', 'name']
|
||||
fields = ['id', 'name', 'owner', 'department']
|
||||
# NOTE: students
|
||||
|
||||
|
||||
class TeachingUnitSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = TeachingUnit
|
||||
fields = ['id', 'name', 'department']
|
||||
# NOTE: managers, teachers, student_groups
|
||||
|
||||
|
||||
class StudentCardSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = StudentCard
|
||||
fields = ['id', 'uid', 'owner']
|
||||
fields = ['id', 'uid', 'department', 'owner']
|
||||
|
||||
|
||||
class TeachingSessionSerializer(serializers.ModelSerializer):
|
||||
|
@ -48,13 +49,13 @@ class TeachingSessionSerializer(serializers.ModelSerializer):
|
|||
class AttendanceSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Attendance
|
||||
fields = ['id', 'date', 'student']
|
||||
fields = ['id', 'date', 'student', 'session']
|
||||
|
||||
|
||||
class AbsenceSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Absence
|
||||
fields = ['id', 'message', 'student']
|
||||
fields = ['id', 'message', 'student', 'session']
|
||||
|
||||
|
||||
class AbsenceAttachmentSerializer(serializers.ModelSerializer):
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
from rest_framework import viewsets
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
|
||||
from .permissions import (UserPermission, DepartmentPermission, StudentGroupPermission, TeachingUnitPermission,
|
||||
StudentCardPermission, TeachingSessionPermission, AttendancePermission, AbsencePermission,
|
||||
AbsenceAttachmentPermission)
|
||||
from .serializers import (UserSerializer, AbsenceAttachmentSerializer, AbsenceSerializer, AttendanceSerializer,
|
||||
TeachingSessionSerializer, StudentCardSerializer, StudentGroupSerializer,
|
||||
DepartmentSerializer, TeachingUnitSerializer)
|
||||
|
@ -10,72 +13,53 @@ from ...models import (User, AbsenceAttachment, Absence, Attendance, TeachingSes
|
|||
|
||||
class UserViewSet(viewsets.ModelViewSet):
|
||||
serializer_class = UserSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return User.all_visible_to(self.request.user)
|
||||
|
||||
def get_permissions(self):
|
||||
return User.permissions_for(self.request.user, self.request.method)
|
||||
queryset = User.objects.all()
|
||||
permission_classes = [IsAuthenticated, UserPermission]
|
||||
|
||||
|
||||
class DepartmentViewSet(UserViewSet):
|
||||
serializer_class = DepartmentSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return Department.all_visible_to(self.request.user)
|
||||
queryset = Department.objects.all()
|
||||
permission_classes = [DepartmentPermission]
|
||||
|
||||
|
||||
class StudentGroupViewSet(UserViewSet):
|
||||
serializer_class = StudentGroupSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
return StudentGroup.all_visible_to(self.request.user)
|
||||
queryset = StudentGroup.objects.all()
|
||||
permission_classes = [IsAuthenticated, StudentGroupPermission]
|
||||
|
||||
|
||||
class TeachingUnitViewSet(UserViewSet):
|
||||
serializer_class = TeachingUnitSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
return TeachingUnit.all_visible_to(self.request.user)
|
||||
queryset = TeachingUnit.objects.all()
|
||||
permission_classes = [IsAuthenticated, TeachingUnitPermission]
|
||||
|
||||
|
||||
class StudentCardViewSet(UserViewSet):
|
||||
serializer_class = StudentCardSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
return StudentCard.all_visible_to(self.request.user)
|
||||
queryset = StudentCard.objects.all()
|
||||
permission_classes = [IsAuthenticated, StudentCardPermission]
|
||||
|
||||
|
||||
class TeachingSessionViewSet(UserViewSet):
|
||||
serializer_class = TeachingSessionSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
return TeachingSession.all_visible_to(self.request.user)
|
||||
queryset = TeachingSession.objects.all()
|
||||
permission_classes = [IsAuthenticated, TeachingSessionPermission]
|
||||
|
||||
|
||||
class AttendanceViewSet(UserViewSet):
|
||||
serializer_class = AttendanceSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
return Attendance.all_visible_to(self.request.user)
|
||||
queryset = Attendance.objects.all()
|
||||
permission_classes = [IsAuthenticated, AttendancePermission]
|
||||
|
||||
|
||||
class AbsenceViewSet(UserViewSet):
|
||||
serializer_class = AbsenceSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
return Absence.all_visible_to(self.request.user)
|
||||
queryset = Absence.objects.all()
|
||||
permission_classes = [IsAuthenticated, AbsencePermission]
|
||||
|
||||
|
||||
class AbsenceAttachmentViewSet(UserViewSet):
|
||||
serializer_class = AbsenceAttachmentSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
return AbsenceAttachment.all_visible_to(self.request.user)
|
||||
queryset = AbsenceAttachment.objects.all()
|
||||
permission_classes = [IsAuthenticated, AbsenceAttachmentPermission]
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import uuid
|
||||
from abc import abstractmethod, ABC
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Iterable
|
||||
|
||||
|
@ -7,27 +6,9 @@ from django.contrib.auth import get_user_model
|
|||
from django.contrib.auth.models import AbstractUser
|
||||
from django.db import models
|
||||
from django.db.models import QuerySet, Q
|
||||
from rest_framework import permissions
|
||||
|
||||
|
||||
# Create your models here.
|
||||
class ModelApiMixin(ABC):
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def all_visible_to(cls, user: "User") -> QuerySet:
|
||||
"""
|
||||
Return all the objects visible to a user.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def permissions_for(cls, user: "User", method: str) -> permissions.BasePermission:
|
||||
"""
|
||||
Return the permissions for a user and the method used to access the object.
|
||||
"""
|
||||
|
||||
|
||||
class User(AbstractUser, ModelApiMixin):
|
||||
class User(AbstractUser):
|
||||
"""
|
||||
A user.
|
||||
|
||||
|
@ -59,25 +40,8 @@ class User(AbstractUser, ModelApiMixin):
|
|||
|
||||
return self.multiple_related_departments([self])
|
||||
|
||||
@classmethod
|
||||
def all_visible_to(cls, user: "User") -> QuerySet["User"]:
|
||||
if user.is_superuser:
|
||||
queryset = User.objects.all()
|
||||
else:
|
||||
queryset = Department.multiple_related_users(user.related_departments)
|
||||
|
||||
return queryset.order_by("pk")
|
||||
|
||||
@classmethod
|
||||
def permissions_for(cls, user: "User", method: str) -> permissions.BasePermission:
|
||||
# TODO: ???
|
||||
if method in permissions.SAFE_METHODS:
|
||||
return permissions.AllowAny()
|
||||
|
||||
return permissions.IsAdminUser()
|
||||
|
||||
|
||||
class Department(models.Model, ModelApiMixin):
|
||||
class Department(models.Model):
|
||||
"""
|
||||
A scholar department.
|
||||
|
||||
|
@ -87,7 +51,7 @@ class Department(models.Model, ModelApiMixin):
|
|||
|
||||
id: uuid.UUID = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False, max_length=36)
|
||||
name: str = models.CharField(max_length=64)
|
||||
mail: str = models.EmailField()
|
||||
email: str = models.EmailField()
|
||||
|
||||
managers = models.ManyToManyField(to=get_user_model(), blank=True, related_name="managing_departments")
|
||||
teachers = models.ManyToManyField(to=get_user_model(), blank=True, related_name="teaching_departments")
|
||||
|
@ -119,12 +83,8 @@ class Department(models.Model, ModelApiMixin):
|
|||
|
||||
return self.multiple_related_users([self])
|
||||
|
||||
@classmethod
|
||||
def all_visible_to(cls, user: "User") -> QuerySet["User"]:
|
||||
return cls.objects.all().order_by("pk")
|
||||
|
||||
|
||||
class StudentGroup(models.Model, ModelApiMixin):
|
||||
class StudentGroup(models.Model):
|
||||
"""
|
||||
A student group.
|
||||
|
||||
|
@ -137,6 +97,7 @@ class StudentGroup(models.Model, ModelApiMixin):
|
|||
id: uuid.UUID = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False, max_length=36)
|
||||
name: str = models.CharField(max_length=128)
|
||||
|
||||
owner = models.ForeignKey(to=get_user_model(), on_delete=models.CASCADE, related_name="owning_groups")
|
||||
department = models.ForeignKey(to=Department, on_delete=models.CASCADE, related_name="student_groups")
|
||||
students = models.ManyToManyField(to=get_user_model(), blank=True, related_name="student_groups")
|
||||
|
||||
|
@ -146,24 +107,8 @@ class StudentGroup(models.Model, ModelApiMixin):
|
|||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@classmethod
|
||||
def all_visible_to(cls, user: "User") -> QuerySet["User"]:
|
||||
if user.is_superuser:
|
||||
queryset = cls.objects.all()
|
||||
|
||||
else:
|
||||
queryset = cls.objects.filter(
|
||||
# get all the groups where the user is
|
||||
Q(students=user) |
|
||||
# get all the groups where the department is managed by the user
|
||||
Q(department=user.managing_departments)
|
||||
# TODO: prof ? rôle créateur du groupe ?
|
||||
).distinct()
|
||||
|
||||
return queryset.order_by("pk")
|
||||
|
||||
|
||||
class TeachingUnit(models.Model, ModelApiMixin):
|
||||
class TeachingUnit(models.Model):
|
||||
"""
|
||||
A teaching unit.
|
||||
|
||||
|
@ -188,21 +133,8 @@ class TeachingUnit(models.Model, ModelApiMixin):
|
|||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@classmethod
|
||||
def all_visible_to(cls, user: "User") -> QuerySet["User"]:
|
||||
if user.is_superuser:
|
||||
queryset = cls.objects.all()
|
||||
|
||||
else:
|
||||
queryset = cls.objects.filter(
|
||||
# get all the units with a common department with the user
|
||||
Q(department__in=user.related_departments)
|
||||
)
|
||||
|
||||
return queryset.order_by("pk")
|
||||
|
||||
|
||||
class StudentCard(models.Model, ModelApiMixin):
|
||||
class StudentCard(models.Model):
|
||||
"""
|
||||
A student card.
|
||||
|
||||
|
@ -212,28 +144,14 @@ class StudentCard(models.Model, ModelApiMixin):
|
|||
id: uuid.UUID = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False, max_length=36)
|
||||
uid: bytes = models.BinaryField(max_length=7)
|
||||
|
||||
department: Department = models.ForeignKey(to=Department, on_delete=models.CASCADE, related_name="student_cards")
|
||||
owner: User = models.ForeignKey(to=get_user_model(), on_delete=models.CASCADE, related_name="student_cards")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__name__} id={str(self.id)[:8]} owner={self.owner.username!r}>"
|
||||
|
||||
@classmethod
|
||||
def all_visible_to(cls, user: "User") -> QuerySet["User"]:
|
||||
if user.is_superuser:
|
||||
queryset = cls.objects.all()
|
||||
|
||||
else:
|
||||
queryset = cls.objects.filter(
|
||||
# get all the cards that are owned by the user
|
||||
Q(owner=user) |
|
||||
# get all the cards where the owner is studying in a department where the user is a manager
|
||||
Q(owner__studying_departments__managers=user)
|
||||
).distinct()
|
||||
|
||||
return queryset.order_by("pk")
|
||||
|
||||
|
||||
class TeachingSession(models.Model, ModelApiMixin):
|
||||
class TeachingSession(models.Model):
|
||||
"""
|
||||
A session of a teaching unit.
|
||||
|
||||
|
@ -262,27 +180,8 @@ class TeachingSession(models.Model, ModelApiMixin):
|
|||
def end(self) -> datetime:
|
||||
return self.start + self.duration
|
||||
|
||||
@classmethod
|
||||
def all_visible_to(cls, user: "User") -> QuerySet["User"]:
|
||||
if user.is_superuser:
|
||||
queryset = cls.objects.all()
|
||||
|
||||
else:
|
||||
queryset = cls.objects.filter(
|
||||
# get all the sessions where the user is a teacher
|
||||
Q(teacher=user) |
|
||||
# get all the sessions where the user is in the group
|
||||
Q(group__students=user) |
|
||||
# get all the sessions where the user is managing the unit
|
||||
Q(unit__managers=user) |
|
||||
# get all the sessions where the user is managing the department
|
||||
Q(unit__department__managers=user)
|
||||
).distinct()
|
||||
|
||||
return queryset.order_by("pk")
|
||||
|
||||
|
||||
class Attendance(models.Model, ModelApiMixin):
|
||||
class Attendance(models.Model):
|
||||
"""
|
||||
A student attendance to a session.
|
||||
|
||||
|
@ -312,27 +211,8 @@ class Attendance(models.Model, ModelApiMixin):
|
|||
f">"
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def all_visible_to(cls, user: "User") -> QuerySet["User"]:
|
||||
if user.is_superuser:
|
||||
queryset = cls.objects.all()
|
||||
|
||||
else:
|
||||
queryset = cls.objects.filter(
|
||||
# get all the session where the user was the teacher
|
||||
Q(session__teacher=user) |
|
||||
# get all the session where the user was the student
|
||||
Q(student=user) |
|
||||
# get all the sessions where the user is managing the unit
|
||||
Q(session__unit__managers=user) |
|
||||
# get all the sessions where the user is managing the department
|
||||
Q(session__unit__department__managers=user)
|
||||
).distinct()
|
||||
|
||||
return queryset.order_by("pk")
|
||||
|
||||
|
||||
class Absence(models.Model, ModelApiMixin):
|
||||
class Absence(models.Model):
|
||||
"""
|
||||
A student justified absence to a session.
|
||||
|
||||
|
@ -357,27 +237,8 @@ class Absence(models.Model, ModelApiMixin):
|
|||
def __str__(self):
|
||||
return f"[{str(self.id)[:8]}] {self.student}"
|
||||
|
||||
@classmethod
|
||||
def all_visible_to(cls, user: "User") -> QuerySet["User"]:
|
||||
if user.is_superuser:
|
||||
queryset = cls.objects.all()
|
||||
|
||||
else:
|
||||
queryset = cls.objects.filter(
|
||||
# get all the absence where the user was the teacher
|
||||
Q(session__teacher=user) |
|
||||
# get all the absence where the user was the student
|
||||
Q(student=user) |
|
||||
# get all the absences where the user is managing the unit
|
||||
Q(session__unit__managers=user) |
|
||||
# get all the absences where the user is managing the department
|
||||
Q(session__unit__department__managers=user)
|
||||
).distinct()
|
||||
|
||||
return queryset.order_by("pk")
|
||||
|
||||
|
||||
class AbsenceAttachment(models.Model, ModelApiMixin):
|
||||
class AbsenceAttachment(models.Model):
|
||||
"""
|
||||
An attachment to a student justified absence.
|
||||
|
||||
|
@ -391,22 +252,3 @@ class AbsenceAttachment(models.Model, ModelApiMixin):
|
|||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__name__} id={str(self.id)[:8]} content={self.content!r}>"
|
||||
|
||||
@classmethod
|
||||
def all_visible_to(cls, user: "User") -> QuerySet["User"]:
|
||||
if user.is_superuser:
|
||||
queryset = cls.objects.all()
|
||||
|
||||
else:
|
||||
queryset = cls.objects.filter(
|
||||
# get all the absence attachments where the user was the teacher
|
||||
Q(absence__session__teacher=user) |
|
||||
# get all the absence attachments where the user was the student
|
||||
Q(absence__student=user) |
|
||||
# get all the absence attachments where the user is managing the unit
|
||||
Q(absence__session__unit__managers=user) |
|
||||
# get all the absence attachments where the user is managing the department
|
||||
Q(absence__session__unit__department__managers=user)
|
||||
).distinct()
|
||||
|
||||
return queryset.order_by("pk")
|
||||
|
|
|
@ -10,6 +10,7 @@ For the full list of settings and their values, see
|
|||
https://docs.djangoproject.com/en/4.2/ref/settings/
|
||||
"""
|
||||
import os
|
||||
from datetime import timedelta
|
||||
from pathlib import Path
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
|
@ -50,12 +51,15 @@ INSTALLED_APPS = [
|
|||
'rest_framework',
|
||||
"debug_toolbar",
|
||||
'django_extensions',
|
||||
'rest_framework_simplejwt',
|
||||
'corsheaders',
|
||||
|
||||
"Palto.Palto",
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
"debug_toolbar.middleware.DebugToolbarMiddleware",
|
||||
'corsheaders.middleware.CorsMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
|
@ -147,6 +151,13 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|||
# Rest API configuration
|
||||
# https://www.django-rest-framework.org/
|
||||
REST_FRAMEWORK = {
|
||||
# Default way to authenticate to the REST api.
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': [
|
||||
'rest_framework_simplejwt.authentication.JWTAuthentication',
|
||||
'rest_framework.authentication.SessionAuthentication',
|
||||
'rest_framework.authentication.BasicAuthentication',
|
||||
],
|
||||
|
||||
# Use Django's standard `django.contrib.auth` permissions,
|
||||
# or allow read-only access for unauthenticated users.
|
||||
'DEFAULT_PERMISSION_CLASSES': [
|
||||
|
@ -168,5 +179,23 @@ REST_FRAMEWORK = {
|
|||
'PAGE_SIZE': 30
|
||||
}
|
||||
|
||||
# JWT Authentification
|
||||
SIMPLE_JWT = {
|
||||
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=15),
|
||||
"REFRESH_TOKEN_LIFETIME": timedelta(days=1),
|
||||
}
|
||||
|
||||
|
||||
# User model
|
||||
AUTH_USER_MODEL = "Palto.User"
|
||||
|
||||
|
||||
# CORS settings
|
||||
# TODO(Raphaël): Only in debug !
|
||||
CORS_ORIGIN_ALLOW_ALL = True
|
||||
|
||||
|
||||
# Login
|
||||
LOGIN_URL = "/admin/login/"
|
||||
LOGIN_REDIRECT_URL = "/"
|
||||
LOGOUT_REDIRECT_URL = "/"
|
||||
|
|
|
@ -14,7 +14,7 @@ Including another URLconf
|
|||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
import debug_toolbar
|
||||
|
||||
from django.contrib import admin
|
||||
from django.urls import path, re_path, include
|
||||
from django.views.static import serve
|
||||
|
@ -32,7 +32,7 @@ urlpatterns = [
|
|||
|
||||
# Debug
|
||||
path('admin/', admin.site.urls), # Admin page
|
||||
path("__debug__/", include(debug_toolbar.urls)), # Debug toolbar
|
||||
path("__debug__/", include('debug_toolbar.urls')), # Debug toolbar
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ django
|
|||
djangorestframework
|
||||
django-debug-toolbar
|
||||
django-extensions
|
||||
djangorestframework-simplejwt[crypto]
|
||||
django-cors-headers
|
||||
Werkzeug
|
||||
|
||||
markdown
|
||||
|
|
Loading…
Reference in a new issue