[untested] finished models permissions
This commit is contained in:
parent
7acc292bad
commit
5ce9a808aa
3 changed files with 413 additions and 46 deletions
|
@ -3,67 +3,111 @@ Serializers for the Palto project's API v1.
|
|||
|
||||
A serializers tell the API how should a model should be serialized to be used by an external user.
|
||||
"""
|
||||
from typing import Type
|
||||
|
||||
from rest_framework import serializers
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
|
||||
from Palto.Palto import models
|
||||
|
||||
|
||||
# TODO(Raphaël): Voir pour les related_name
|
||||
# TODO: voir les relations inversées ?
|
||||
|
||||
|
||||
class UserSerializer(serializers.ModelSerializer):
|
||||
class ModelSerializerContrains(serializers.ModelSerializer):
|
||||
"""
|
||||
Similar to the base ModelSerializer, but automatically check for contrains for the user
|
||||
when trying to create a new instance or modifying a field.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model: Type[models.ModelPermissionHelper]
|
||||
|
||||
def create(self, validated_data):
|
||||
# get the fields that this user can modify
|
||||
field_contrains = self.Meta.model.user_fields_contrains(self.context["request"].user)
|
||||
|
||||
# for every constrains
|
||||
for field, constrains in field_contrains.items():
|
||||
# check if the value is in the constrains.
|
||||
value = validated_data.get(field)
|
||||
if value is not None and value not in constrains:
|
||||
raise PermissionDenied(f"You are not allowed to use this value for the field {field}.")
|
||||
|
||||
return super().create(validated_data)
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
# get the fields that this user can modify
|
||||
field_contrains = self.Meta.model.user_fields_contrains(self.context["request"].user)
|
||||
|
||||
# for every constrains
|
||||
for field, constrains in field_contrains.items():
|
||||
# check if the value of the request is in the constrains.
|
||||
value = validated_data.get(field)
|
||||
if value is not None and value not in constrains:
|
||||
raise PermissionDenied(f"You are not allowed to use this value for the field {field}.")
|
||||
|
||||
# check if the value of the already existing instance is in the constrains.
|
||||
value = getattr(instance, field, None)
|
||||
if value is not None and value not in constrains:
|
||||
raise PermissionDenied(f"You are not allowed to use this value for the field {field}.")
|
||||
|
||||
# check that the user is managing the department
|
||||
if instance.department not in self.context["request"].user.managing_departments:
|
||||
raise PermissionDenied("You don't manage this department.")
|
||||
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
|
||||
class UserSerializer(ModelSerializerContrains):
|
||||
class Meta:
|
||||
model = models.User
|
||||
fields = ['id', 'username', 'first_name', 'last_name', 'email']
|
||||
|
||||
|
||||
class DepartmentSerializer(serializers.ModelSerializer):
|
||||
class DepartmentSerializer(ModelSerializerContrains):
|
||||
class Meta:
|
||||
model = models.Department
|
||||
fields = ['id', 'name', 'email', 'managers']
|
||||
# NOTE: teachers, students
|
||||
fields = ['id', 'name', 'email', 'managers', 'teachers', 'students']
|
||||
|
||||
|
||||
class StudentGroupSerializer(serializers.ModelSerializer):
|
||||
class StudentGroupSerializer(ModelSerializerContrains):
|
||||
class Meta:
|
||||
model = models.StudentGroup
|
||||
fields = ['id', 'name', 'owner', 'department']
|
||||
# NOTE: students
|
||||
fields = ['id', 'name', 'owner', 'department', 'students']
|
||||
|
||||
|
||||
class TeachingUnitSerializer(serializers.ModelSerializer):
|
||||
class TeachingUnitSerializer(ModelSerializerContrains):
|
||||
class Meta:
|
||||
model = models.TeachingUnit
|
||||
fields = ['id', 'name', 'department']
|
||||
# NOTE: managers, teachers, student_groups
|
||||
fields = ['id', 'name', 'department', 'managers', 'teachers', 'student_groups']
|
||||
|
||||
|
||||
class StudentCardSerializer(serializers.ModelSerializer):
|
||||
class StudentCardSerializer(ModelSerializerContrains):
|
||||
class Meta:
|
||||
model = models.StudentCard
|
||||
fields = ['id', 'uid', 'department', 'owner']
|
||||
|
||||
|
||||
class TeachingSessionSerializer(serializers.ModelSerializer):
|
||||
class TeachingSessionSerializer(ModelSerializerContrains):
|
||||
class Meta:
|
||||
model = models.TeachingSession
|
||||
fields = ['id', 'start', 'duration', 'note', 'unit', 'group', 'teacher']
|
||||
|
||||
|
||||
class AttendanceSerializer(serializers.ModelSerializer):
|
||||
class AttendanceSerializer(ModelSerializerContrains):
|
||||
class Meta:
|
||||
model = models.Attendance
|
||||
fields = ['id', 'date', 'student', 'session']
|
||||
|
||||
|
||||
class AbsenceSerializer(serializers.ModelSerializer):
|
||||
class AbsenceSerializer(ModelSerializerContrains):
|
||||
class Meta:
|
||||
model = models.Absence
|
||||
fields = ['id', 'message', 'student', 'session']
|
||||
|
||||
|
||||
class AbsenceAttachmentSerializer(serializers.ModelSerializer):
|
||||
class AbsenceAttachmentSerializer(ModelSerializerContrains):
|
||||
class Meta:
|
||||
model = models.AbsenceAttachment
|
||||
fields = ['id', 'content', 'absence']
|
||||
|
|
|
@ -158,14 +158,10 @@ class DepartmentApiTestCase(test.APITestCase):
|
|||
|
||||
self.client.force_login(student1)
|
||||
|
||||
"""
|
||||
TODO: this test require to show the field students before creating it.
|
||||
|
||||
# check for a get request and that he can see the other student
|
||||
response = self.client.get("/api/v1/departments/")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertIn(serializers.UserSerializer(student2).data, response.json()["results"])
|
||||
"""
|
||||
|
||||
# check for a post request
|
||||
response = self.client.post("/api/v1/departments/", data=self.DEPARTMENT_CREATION_DATA)
|
||||
|
@ -173,8 +169,114 @@ class DepartmentApiTestCase(test.APITestCase):
|
|||
|
||||
|
||||
class StudentGroupApiTestCase(test.APITestCase):
|
||||
pass
|
||||
def setUp(self):
|
||||
self.user_admin = factories.FakeUserFactory(is_superuser=True)
|
||||
self.user_other = factories.FakeUserFactory()
|
||||
|
||||
# fake group creation data
|
||||
self.test_manager_related = factories.FakeUserFactory()
|
||||
self.test_manager_other = factories.FakeUserFactory()
|
||||
|
||||
self.test_teacher_owner = factories.FakeUserFactory()
|
||||
self.test_teacher_other = factories.FakeUserFactory()
|
||||
|
||||
self.test_students_group = [factories.FakeUserFactory() for _ in range(10)]
|
||||
self.test_students_other = [factories.FakeUserFactory() for _ in range(10)]
|
||||
|
||||
self.test_department = factories.FakeDepartmentFactory(
|
||||
managers=[self.test_manager_related],
|
||||
teachers=[self.test_teacher_owner, self.test_teacher_other],
|
||||
students=[*self.test_students_group, *self.test_students_other],
|
||||
)
|
||||
|
||||
self.student_group_creation_data: dict = {
|
||||
"name": "Groupe 1",
|
||||
"owner": self.test_teacher_owner.pk,
|
||||
"department": self.test_department.pk,
|
||||
"students": map(lambda obj: obj.pk, self.test_students_group)
|
||||
}
|
||||
|
||||
def test_permission_admin(self):
|
||||
""" Test the API permission for an administrator """
|
||||
|
||||
# TODO: use reverse to get the url ?
|
||||
self.client.force_login(self.user_admin)
|
||||
|
||||
# check for a get request
|
||||
response = self.client.get("/api/v1/student_groups/")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.json()["count"], models.StudentGroup.objects.count())
|
||||
|
||||
# check for a post request
|
||||
response = self.client.post("/api/v1/student_groups/", data=self.student_group_creation_data)
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
|
||||
def test_permission_anonymous(self):
|
||||
""" Test the API permission for an anonymous user """
|
||||
|
||||
# TODO: use reverse to get the url ?
|
||||
self.client.logout()
|
||||
|
||||
# check for a get request
|
||||
response = self.client.get("/api/v1/student_groups/")
|
||||
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
# check for a post request
|
||||
response = self.client.post("/api/v1/student_groups/", data=self.student_group_creation_data)
|
||||
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
def test_permission_unrelated(self):
|
||||
""" Test the API permission for an unrelated user """
|
||||
|
||||
# TODO: use reverse to get the url ?
|
||||
for user in (self.user_other, *self.test_students_other):
|
||||
self.client.force_login(user)
|
||||
|
||||
# check for a get request and that he can't see anything
|
||||
response = self.client.get("/api/v1/student_groups/")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.json()["count"], 0)
|
||||
|
||||
# check for a post request
|
||||
response = self.client.post("/api/v1/student_groups/", data=self.student_group_creation_data)
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_permission_related(self):
|
||||
""" Test the API permission for a related user """
|
||||
|
||||
for user in self.test_students_group:
|
||||
# TODO: use reverse to get the url ?
|
||||
self.client.force_login(user)
|
||||
|
||||
# check for a get request and that he can see the students
|
||||
response = self.client.get("/api/v1/student_groups/")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(
|
||||
list(serializers.UserSerializer(student).data for student in self.test_students_group),
|
||||
response.json()["results"]["students"]
|
||||
)
|
||||
|
||||
# check for a post request
|
||||
response = self.client.post("/api/v1/student_groups/", data=self.student_group_creation_data)
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
def test_permission_owner(self):
|
||||
""" Test the API permission for the owner """
|
||||
|
||||
# TODO: use reverse to get the url ?
|
||||
self.client.force_login(self.test_teacher_owner)
|
||||
|
||||
# check for a get request and that he can see the students
|
||||
response = self.client.get("/api/v1/student_groups/")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(
|
||||
list(serializers.UserSerializer(student).data for student in self.test_students_group),
|
||||
response.json()["results"]["students"]
|
||||
)
|
||||
|
||||
# check for a post request
|
||||
response = self.client.post("/api/v1/student_groups/", data=self.student_group_creation_data)
|
||||
# TODO: autorisé ?
|
||||
|
||||
class TeachingUnitApiTestCase(test.APITestCase):
|
||||
pass
|
||||
|
|
|
@ -3,10 +3,11 @@ Models for the Palto project.
|
|||
|
||||
Models are the class that represent and abstract the database.
|
||||
"""
|
||||
|
||||
import operator
|
||||
import uuid
|
||||
from abc import abstractmethod
|
||||
from datetime import datetime, timedelta
|
||||
from functools import reduce
|
||||
from typing import Iterable
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
|
@ -15,14 +16,26 @@ from django.db import models
|
|||
from django.db.models import QuerySet, Q, F
|
||||
|
||||
|
||||
class ModelPermissionHelper:
|
||||
# TODO(Raphaël): split permissions from models for readability
|
||||
# TODO(Raphaël): allow other function for permissions than in
|
||||
|
||||
|
||||
class ModelPermissionHelper:
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def can_user_create(cls, user: "User") -> bool:
|
||||
"""
|
||||
Return True if the user can create a new instance of this object
|
||||
"""
|
||||
|
||||
return user.is_superuser
|
||||
|
||||
@classmethod
|
||||
def user_fields_contrains(cls, user: "User") -> dict[str, QuerySet]:
|
||||
"""
|
||||
Return the list of fields in that model that the user can modify
|
||||
"""
|
||||
|
||||
return {}
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
|
@ -76,17 +89,24 @@ class User(AbstractUser, ModelPermissionHelper):
|
|||
@classmethod
|
||||
def can_user_create(cls, user: "User") -> bool:
|
||||
# if the requesting user is admin
|
||||
return user.is_superuser
|
||||
# TODO: propriétaire d'établissement
|
||||
if user.is_superuser:
|
||||
return True
|
||||
|
||||
# if the user is managing a department, allow him to create user
|
||||
if user.managing_departments.count() > 0:
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def all_editable_by_user(cls, user: "User") -> QuerySet:
|
||||
queryset = QuerySet()
|
||||
|
||||
if user.is_superuser:
|
||||
# if the requesting user is admin
|
||||
queryset = cls.objects.all()
|
||||
else:
|
||||
queryset = QuerySet()
|
||||
# TODO: propriétaire d'établissement
|
||||
# all the users related to a department the user is managing
|
||||
if user.managing_departments.count() > 0:
|
||||
queryset = cls.objects.all()
|
||||
|
||||
return queryset.order_by("pk")
|
||||
|
||||
|
@ -157,8 +177,10 @@ class Department(models.Model, ModelPermissionHelper):
|
|||
# if the requesting user is admin
|
||||
queryset = cls.objects.all()
|
||||
else:
|
||||
queryset = QuerySet()
|
||||
# TODO: propriétaire d'établissement ?
|
||||
queryset = cls.objects.filter(
|
||||
# if the user is the manager of the department
|
||||
managers=user,
|
||||
)
|
||||
|
||||
return queryset.order_by("pk")
|
||||
|
||||
|
@ -198,9 +220,27 @@ class StudentGroup(models.Model, ModelPermissionHelper):
|
|||
@classmethod
|
||||
def can_user_create(cls, user: "User") -> bool:
|
||||
# if the requesting user is admin
|
||||
return user.is_superuser
|
||||
# TODO: department managers can create group
|
||||
# TODO: can teacher create group ?
|
||||
if user.is_superuser:
|
||||
return True
|
||||
|
||||
# if the user is managing a department
|
||||
if user.managing_departments.count() > 0:
|
||||
return True
|
||||
|
||||
# if the user is teaching a department
|
||||
if user.teaching_departments.count() > 0:
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def user_fields_contrains(cls, user: "User") -> dict[str, QuerySet]:
|
||||
# if the user is admin, no contrains
|
||||
if user.is_superuser:
|
||||
return {}
|
||||
|
||||
return {
|
||||
# the managers and teachers can only interact with their departments
|
||||
"department": (user.managing_departments | user.teaching_departments).distinct()
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def all_editable_by_user(cls, user: "User") -> QuerySet:
|
||||
|
@ -267,8 +307,23 @@ class TeachingUnit(models.Model, ModelPermissionHelper):
|
|||
@classmethod
|
||||
def can_user_create(cls, user: "User") -> bool:
|
||||
# if the requesting user is admin
|
||||
return user.is_superuser
|
||||
# TODO: allow department manager
|
||||
if user.is_superuser:
|
||||
return True
|
||||
|
||||
# if the user is managing a department
|
||||
if user.managing_departments.count() > 0:
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def user_fields_contrains(cls, user: "User") -> dict[str, QuerySet]:
|
||||
# if the user is admin, no contrains
|
||||
if user.is_superuser:
|
||||
return {}
|
||||
|
||||
return {
|
||||
# the managers can only interact with their departments
|
||||
"department": user.managing_departments
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def all_editable_by_user(cls, user: "User") -> QuerySet:
|
||||
|
@ -324,8 +379,27 @@ class StudentCard(models.Model, ModelPermissionHelper):
|
|||
@classmethod
|
||||
def can_user_create(cls, user: "User") -> bool:
|
||||
# if the requesting user is admin
|
||||
return user.is_superuser
|
||||
# TODO: Allow new student cards by department managers ?
|
||||
if user.is_superuser:
|
||||
return True
|
||||
|
||||
if user.managing_departments.count() > 0:
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def user_fields_contrains(cls, user: "User") -> dict[str, QuerySet]:
|
||||
# if the user is admin, no contrains
|
||||
if user.is_superuser:
|
||||
return {}
|
||||
|
||||
return {
|
||||
# the managers can only interact with their departments
|
||||
"department": user.managing_departments,
|
||||
# the owner of the card can be any students in a department that is managed by the user
|
||||
"owner": reduce(
|
||||
operator.or_,
|
||||
(department.students.all() for department in user.managing_departments)
|
||||
)
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def all_editable_by_user(cls, user: "User") -> QuerySet:
|
||||
|
@ -390,8 +464,64 @@ class TeachingSession(models.Model, ModelPermissionHelper):
|
|||
@classmethod
|
||||
def can_user_create(cls, user: "User") -> bool:
|
||||
# if the requesting user is admin
|
||||
return user.is_superuser
|
||||
# TODO: Allow new teaching session by managers or teachers
|
||||
if user.is_superuser:
|
||||
return True
|
||||
|
||||
# if the user is managing a department
|
||||
if user.managing_departments.count() > 0:
|
||||
return True
|
||||
|
||||
# if the user is managing a unit
|
||||
if user.managing_units.count() > 0:
|
||||
return True
|
||||
|
||||
# if the user is teaching a unit
|
||||
if user.teaching_units.count() > 0:
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def user_fields_contrains(cls, user: "User") -> dict[str, QuerySet]:
|
||||
# if the user is admin, no contrains
|
||||
if user.is_superuser:
|
||||
return {}
|
||||
|
||||
return {
|
||||
# the managers can only interact with their departments
|
||||
"department": (user.managing_departments | user.teaching_departments).distinct(),
|
||||
"teacher":
|
||||
# the teacher can be any teacher in a department that the user is managing
|
||||
reduce(
|
||||
operator.or_,
|
||||
(department.teachers.all() for department in user.managing_departments)
|
||||
) | reduce(
|
||||
# or a teacher in a unit that the user is managing
|
||||
operator.or_,
|
||||
(department.teachers.all() for department in user.managing_units)
|
||||
) | (
|
||||
# or the user itself
|
||||
User.objects.filter(pk=user.pk)
|
||||
),
|
||||
"unit":
|
||||
# the unit can be any unit in the department that the user is managing
|
||||
reduce(
|
||||
operator.or_,
|
||||
(department.teaching_units.all() for department in user.managing_departments)
|
||||
) | (
|
||||
# or the units that the user is teaching
|
||||
user.teaching_sessions
|
||||
),
|
||||
"group":
|
||||
# any group of a department where the user is a manager
|
||||
reduce(
|
||||
operator.or_,
|
||||
(department.student_groups for department in user.managing_departments)
|
||||
) |
|
||||
# any group where the user is a manager or a teacher of a unit
|
||||
reduce(
|
||||
operator.or_,
|
||||
(unit.student_groups for unit in (user.managing_units | user.teaching_units))
|
||||
)
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def all_editable_by_user(cls, user: "User") -> QuerySet:
|
||||
|
@ -465,8 +595,67 @@ class Attendance(models.Model, ModelPermissionHelper):
|
|||
@classmethod
|
||||
def can_user_create(cls, user: "User") -> bool:
|
||||
# if the requesting user is admin
|
||||
return user.is_superuser
|
||||
# TODO: Allow new attendance by managers or teachers
|
||||
if user.is_superuser:
|
||||
return True
|
||||
|
||||
# if the user is managing a department
|
||||
if user.managing_departments.count() > 0:
|
||||
return True
|
||||
|
||||
# if the user is managing a unit
|
||||
if user.managing_units.count() > 0:
|
||||
return True
|
||||
|
||||
# if the user is teaching a unit
|
||||
if user.teaching_units.count() > 0:
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def user_fields_contrains(cls, user: "User") -> dict[str, QuerySet]:
|
||||
# if the user is admin, no contrains
|
||||
if user.is_superuser:
|
||||
return {}
|
||||
|
||||
return {
|
||||
# the managers can only interact with their departments
|
||||
"department": user.managing_departments | user.teaching_departments,
|
||||
"student":
|
||||
# student can be any student from a department the user is managing or teaching
|
||||
reduce(
|
||||
operator.or_,
|
||||
(
|
||||
department.students.all()
|
||||
for department in (user.managing_departments | user.teaching_departments)
|
||||
)
|
||||
) |
|
||||
# or any student from a unit the user is managing or teaching
|
||||
reduce(
|
||||
operator.or_,
|
||||
(
|
||||
student_group.students.all()
|
||||
for unit in (user.managing_units | user.teaching_units)
|
||||
for student_group in unit.student_groups
|
||||
)
|
||||
),
|
||||
"session":
|
||||
# the session can be any session where the user is managing the department
|
||||
reduce(
|
||||
operator.or_,
|
||||
(
|
||||
unit.sessions
|
||||
for department in user.managing_departments
|
||||
for unit in department.teaching_units
|
||||
)
|
||||
) |
|
||||
# or where is the user is a teacher
|
||||
reduce(
|
||||
operator.or_,
|
||||
(
|
||||
unit.sessions
|
||||
for unit in (user.teaching_units | user.managing_units)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def all_editable_by_user(cls, user: "User") -> QuerySet:
|
||||
|
@ -517,7 +706,7 @@ class Absence(models.Model, ModelPermissionHelper):
|
|||
message: str = models.TextField()
|
||||
|
||||
department: Department = models.ForeignKey(to=Department, on_delete=models.CASCADE, related_name="absences")
|
||||
student: User = models.ForeignKey(to=get_user_model(), on_delete=models.CASCADE, related_name="absented_sessions")
|
||||
student: User = models.ForeignKey(to=get_user_model(), on_delete=models.CASCADE, related_name="absences")
|
||||
start: datetime = models.DateTimeField()
|
||||
end: datetime = models.DateTimeField()
|
||||
|
||||
|
@ -554,8 +743,25 @@ class Absence(models.Model, ModelPermissionHelper):
|
|||
@classmethod
|
||||
def can_user_create(cls, user: "User") -> bool:
|
||||
# if the requesting user is admin
|
||||
return user.is_superuser
|
||||
# TODO: Allow new absence by students
|
||||
if user.is_superuser:
|
||||
return True
|
||||
|
||||
# if the user is a student
|
||||
if user.studying_departments.count() > 0:
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def user_fields_contrains(cls, user: "User") -> dict[str, QuerySet]:
|
||||
# if the user is admin, no contrains
|
||||
if user.is_superuser:
|
||||
return {}
|
||||
|
||||
return {
|
||||
# all the departments the user is studying in
|
||||
"department": user.studying_departments,
|
||||
# the student itself
|
||||
"student": User.objects.filter(pk=user.pk),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def all_editable_by_user(cls, user: "User") -> QuerySet:
|
||||
|
@ -617,8 +823,23 @@ class AbsenceAttachment(models.Model, ModelPermissionHelper):
|
|||
@classmethod
|
||||
def can_user_create(cls, user: "User") -> bool:
|
||||
# if the requesting user is admin
|
||||
return user.is_superuser
|
||||
# TODO: Allow new absence attachment by students
|
||||
if user.is_superuser:
|
||||
return True
|
||||
|
||||
# if the user is a student
|
||||
if user.objects.count():
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def user_fields_contrains(cls, user: "User") -> dict[str, QuerySet]:
|
||||
# if the user is admin, no contrains
|
||||
if user.is_superuser:
|
||||
return {}
|
||||
|
||||
return {
|
||||
# all the departments the user is studying in
|
||||
"absence": user.absences,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def all_editable_by_user(cls, user: "User") -> QuerySet:
|
||||
|
|
Loading…
Reference in a new issue