139 lines
4.5 KiB
Python
139 lines
4.5 KiB
Python
"""Gedeelde permissies voor roltoegang en module-gating."""
|
|
from rest_framework.permissions import BasePermission, SAFE_METHODS
|
|
|
|
|
|
def _profile(user):
|
|
return getattr(user, "gebruikersprofiel", None)
|
|
|
|
|
|
def user_role(user):
|
|
profile = _profile(user)
|
|
return getattr(profile, "rol", None)
|
|
|
|
|
|
def linked_person(user):
|
|
profile = _profile(user)
|
|
return getattr(profile, "persoon", None)
|
|
|
|
|
|
def is_admin_user(user):
|
|
return bool(
|
|
user
|
|
and user.is_authenticated
|
|
and (user.is_staff or user_role(user) == "beheerder")
|
|
)
|
|
|
|
|
|
INTERNAL_READ_ROLES = {
|
|
"medewerker",
|
|
"roostermaker",
|
|
"directie",
|
|
"zorgcoordinator",
|
|
"stagebegeleider",
|
|
"kijker",
|
|
}
|
|
|
|
|
|
def has_view_write_role(user, view):
|
|
write_roles = set(getattr(view, "write_roles", ()))
|
|
return user_role(user) in write_roles
|
|
|
|
|
|
class CoreDataPermission(BasePermission):
|
|
"""Kerngegevens: schrijven per rol, lezen rolbewust."""
|
|
|
|
message = "Je hebt geen rechten voor deze roostergegevens."
|
|
|
|
def has_permission(self, request, view):
|
|
if not request.user or not request.user.is_authenticated:
|
|
return False
|
|
if is_admin_user(request.user):
|
|
return True
|
|
if request.method in SAFE_METHODS:
|
|
return True
|
|
return has_view_write_role(request.user, view)
|
|
|
|
def has_object_permission(self, request, view, obj):
|
|
if is_admin_user(request.user):
|
|
return True
|
|
if request.method not in SAFE_METHODS:
|
|
return has_view_write_role(request.user, view)
|
|
role = user_role(request.user)
|
|
person = linked_person(request.user)
|
|
if role in ("leerling", "ouder") and person is not None:
|
|
if obj.__class__.__name__ == "Persoon":
|
|
return obj.pk == person.pk
|
|
if hasattr(obj, "persoon_id"):
|
|
return obj.persoon_id == person.pk
|
|
return role in INTERNAL_READ_ROLES
|
|
|
|
|
|
class StaffDataPermission(BasePermission):
|
|
"""Rapportages: interne rollen mogen lezen, beheerders/rolhouders schrijven."""
|
|
|
|
message = "Je hebt geen rechten voor deze rapportage."
|
|
|
|
def has_permission(self, request, view):
|
|
if not request.user or not request.user.is_authenticated:
|
|
return False
|
|
if is_admin_user(request.user):
|
|
return True
|
|
if request.method in SAFE_METHODS:
|
|
return user_role(request.user) in INTERNAL_READ_ROLES
|
|
return has_view_write_role(request.user, view)
|
|
|
|
|
|
class AdminRolePermission(BasePermission):
|
|
"""Beheerder via Django staff of via de applicatierol beheerder."""
|
|
|
|
message = "Je hebt beheerdersrechten nodig."
|
|
|
|
def has_permission(self, request, view):
|
|
return is_admin_user(request.user)
|
|
|
|
|
|
def restrict_core_queryset(request, queryset):
|
|
"""Filter gevoelige lijsten voor leerling/ouderaccounts met gekoppelde persoon."""
|
|
user = request.user
|
|
if is_admin_user(user) or user_role(user) in INTERNAL_READ_ROLES:
|
|
return queryset
|
|
person = linked_person(user)
|
|
if person is None:
|
|
return queryset.none()
|
|
model_name = queryset.model.__name__
|
|
if model_name == "Groep":
|
|
return queryset.filter(pk=person.groep_id) if getattr(person, "groep_id", None) else queryset.none()
|
|
if model_name == "Subgroep":
|
|
return queryset.filter(leden=person).distinct()
|
|
if model_name == "Persoon":
|
|
return queryset.filter(pk=person.pk)
|
|
if model_name == "Afwezigheid":
|
|
return queryset.filter(persoon=person)
|
|
if model_name == "Roosterblok":
|
|
qs = queryset.filter(leerling=person)
|
|
if getattr(person, "groep_id", None):
|
|
qs = qs | queryset.filter(groep_id=person.groep_id)
|
|
qs = qs | queryset.filter(subgroep__leden=person)
|
|
return qs.distinct()
|
|
if model_name == "BlokUitzondering":
|
|
qs = queryset.filter(roosterblok__leerling=person)
|
|
if getattr(person, "groep_id", None):
|
|
qs = qs | queryset.filter(roosterblok__groep_id=person.groep_id)
|
|
qs = qs | queryset.filter(roosterblok__subgroep__leden=person)
|
|
return qs.distinct()
|
|
return queryset
|
|
|
|
|
|
def module_permission_class(module_key):
|
|
"""Maak een DRF-permissieklasse die een module-aan/uit vlag afdwingt."""
|
|
|
|
class IsModuleEnabled(BasePermission):
|
|
message = f"Module '{module_key}' is uitgeschakeld."
|
|
|
|
def has_permission(self, request, view):
|
|
from plugins import services
|
|
|
|
return services.is_enabled(module_key)
|
|
|
|
IsModuleEnabled.__name__ = f"IsModuleEnabled_{module_key}"
|
|
return IsModuleEnabled
|