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.')