mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-11-04 09:12:11 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			67 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			67 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Copyright (C) 2018-2025 by BDE ENS Paris-Saclay
 | 
						|
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
						|
 | 
						|
from rest_framework.permissions import DjangoObjectPermissions
 | 
						|
 | 
						|
from .backends import PermissionBackend
 | 
						|
 | 
						|
SAFE_METHODS = ('HEAD', 'OPTIONS', )
 | 
						|
 | 
						|
 | 
						|
class StrongDjangoObjectPermissions(DjangoObjectPermissions):
 | 
						|
    """
 | 
						|
    Default DjangoObjectPermissions grant view permission to all.
 | 
						|
    This is a simple patch of this class that controls view access.
 | 
						|
    """
 | 
						|
 | 
						|
    # The queryset is filtered, and permissions are more powerful than a simple check than just "can view this model"
 | 
						|
    perms_map = {
 | 
						|
        'GET': ['%(app_label)s.view_%(model_name)s'],
 | 
						|
        'OPTIONS': [],
 | 
						|
        'HEAD': [],
 | 
						|
        'POST': ['%(app_label)s.add_%(model_name)s'],
 | 
						|
        'PUT': [],      # ['%(app_label)s.change_%(model_name)s'],
 | 
						|
        'PATCH': [],    # ['%(app_label)s.change_%(model_name)s'],
 | 
						|
        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
 | 
						|
    }
 | 
						|
 | 
						|
    def get_required_object_permissions(self, method, model_cls):
 | 
						|
        kwargs = {
 | 
						|
            'app_label': model_cls._meta.app_label,
 | 
						|
            'model_name': model_cls._meta.model_name
 | 
						|
        }
 | 
						|
 | 
						|
        if method not in self.perms_map:
 | 
						|
            from rest_framework import exceptions
 | 
						|
            raise exceptions.MethodNotAllowed(method)
 | 
						|
 | 
						|
        return [perm % kwargs for perm in self.perms_map[method]]
 | 
						|
 | 
						|
    def has_object_permission(self, request, view, obj):
 | 
						|
        # authentication checks have already executed via has_permission
 | 
						|
        queryset = self._queryset(view)
 | 
						|
        model_cls = queryset.model
 | 
						|
        user = request.user
 | 
						|
 | 
						|
        perms = self.get_required_object_permissions(request.method, model_cls)
 | 
						|
        # if not user.has_perms(perms, obj):
 | 
						|
        if not all(PermissionBackend.check_perm(request, perm, obj) for perm in perms):
 | 
						|
            # If the user does not have permissions we need to determine if
 | 
						|
            # they have read permissions to see 403, or not, and simply see
 | 
						|
            # a 404 response.
 | 
						|
            from django.http import Http404
 | 
						|
 | 
						|
            if request.method in SAFE_METHODS:
 | 
						|
                # Read permissions already checked and failed, no need
 | 
						|
                # to make another lookup.
 | 
						|
                raise Http404
 | 
						|
 | 
						|
            read_perms = self.get_required_object_permissions('GET', model_cls)
 | 
						|
            if not user.has_perms(read_perms, obj):
 | 
						|
                raise Http404
 | 
						|
 | 
						|
            # Has read permissions.
 | 
						|
            return False
 | 
						|
 | 
						|
        return True
 |