Louis Mazin 4db822aebe big maj
2026-10-05 17:52:28 +02:00

106 lines
3.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from rest_framework.exceptions import PermissionDenied
from .models import DelegatedPermission, PermissionDefaults, UserPermissions
PERMISSION_NAMES = ('request_leave', 'create_personal_event', 'create_publication')
MANAGEMENT_PERMISSION_NAMES = tuple(value for value, _label in DelegatedPermission.Code.choices)
DENIAL_MESSAGES = {
'request_leave': 'Les demandes de congés ne sont pas activées pour ton compte. Contacte un responsable.',
'create_personal_event': 'L’ajout d’événements personnels n’est pas activé pour ton compte. Contacte un responsable.',
'create_publication': 'La création de publications n’est pas activée pour ton compte. Contacte un responsable.',
}
def is_admin(user):
return bool(user.is_authenticated and user.is_active and (user.is_staff or user.is_superuser))
def default_permissions():
row = PermissionDefaults.objects.filter(pk=1).first()
return {key: getattr(row, key, True) for key in PERMISSION_NAMES}
def effective_permissions(user, defaults=None):
if not user.is_authenticated or not user.is_active:
return dict.fromkeys(PERMISSION_NAMES, False)
if is_admin(user):
return dict.fromkeys(PERMISSION_NAMES, True)
values = dict(defaults) if defaults is not None else default_permissions()
# Ne pas réutiliser une relation mise en cache après un changement de droits.
overrides = UserPermissions.objects.filter(user_id=user.pk).values(*PERMISSION_NAMES).first()
if overrides:
for key in PERMISSION_NAMES:
value = overrides[key]
if value is not None:
values[key] = value
return values
def require_permission(user, name):
if not effective_permissions(user)[name]:
raise PermissionDenied(DENIAL_MESSAGES[name])
def management_permissions(user):
"""Retourne les responsabilités de gestion exposées au frontend."""
if not getattr(user, 'is_authenticated', False) or not user.is_active:
return {
key: {'enabled': False, 'all_users': False, 'user_ids': []}
for key in MANAGEMENT_PERMISSION_NAMES
}
if is_admin(user):
return {
key: {'enabled': True, 'all_users': True, 'user_ids': []}
for key in MANAGEMENT_PERMISSION_NAMES
}
rows = {
row.code: row
for row in DelegatedPermission.objects.filter(user_id=user.pk).prefetch_related('targets')
}
result = {}
for key in MANAGEMENT_PERMISSION_NAMES:
row = rows.get(key)
user_ids = sorted(target.pk for target in row.targets.all()) if row and not row.all_users else []
result[key] = {
'enabled': bool(row and (row.all_users or user_ids)),
'all_users': bool(row and row.all_users),
'user_ids': user_ids,
}
return result
def management_target_ids(user, name):
"""
None = accès illimité (admin ou délégation « toute l'équipe »).
set() = aucun accès.
Sinon, ids des utilisateurs autorisés.
"""
if name not in MANAGEMENT_PERMISSION_NAMES:
raise ValueError(f'Permission de gestion inconnue : {name}')
if not getattr(user, 'is_authenticated', False) or not user.is_active:
return set()
if is_admin(user):
return None
row = DelegatedPermission.objects.filter(user_id=user.pk, code=name).first()
if row is None:
return set()
if row.all_users:
return None
return set(row.targets.values_list('pk', flat=True))
def has_management_permission(user, name, target_user_id=None):
targets = management_target_ids(user, name)
if targets is None:
return True
if target_user_id is None:
return bool(targets)
return int(target_user_id) in targets
def require_management_permission(user, name, target_user_id=None, message=None):
if not has_management_permission(user, name, target_user_id):
raise PermissionDenied(message or 'Vous n’avez pas l’autorisation d’effectuer cette action.')