106 lines
3.9 KiB
Python
106 lines
3.9 KiB
Python
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.')
|