feat: Add PermissionCacheMixin and cache permission methods results

This commit is contained in:
Ehsan200 2023-06-10 14:35:19 +03:30
parent 376a5cbbba
commit c992532552

View File

@ -1,6 +1,8 @@
""" """
Provides a set of pluggable permission policies. Provides a set of pluggable permission policies.
""" """
from functools import lru_cache
from django.http import Http404 from django.http import Http404
from rest_framework import exceptions from rest_framework import exceptions
@ -8,6 +10,16 @@ from rest_framework import exceptions
SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS') SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS')
class PermissionCacheMixin:
@lru_cache
def has_permission_value(self, request, view):
return self.has_permission(request, view)
@lru_cache
def has_object_permission_value(self, request, view, obj):
return self.has_object_permission(request, view, obj)
class OperationHolderMixin: class OperationHolderMixin:
def __and__(self, other): def __and__(self, other):
return OperandHolder(AND, self, other) return OperandHolder(AND, self, other)
@ -55,61 +67,61 @@ class OperandHolder(OperationHolderMixin):
) )
class AND: class AND(PermissionCacheMixin):
def __init__(self, op1, op2): def __init__(self, op1, op2):
self.op1 = op1 self.op1 = op1
self.op2 = op2 self.op2 = op2
def has_permission(self, request, view): def has_permission(self, request, view):
return ( return (
self.op1.has_permission(request, view) and self.op1.has_permission_value(request, view) and
self.op2.has_permission(request, view) self.op2.has_permission_value(request, view)
) )
def has_object_permission(self, request, view, obj): def has_object_permission(self, request, view, obj):
return ( return (
self.op1.has_object_permission(request, view, obj) and self.op1.has_object_permission_value(request, view, obj) and
self.op2.has_object_permission(request, view, obj) self.op2.has_object_permission_value(request, view, obj)
) )
class OR: class OR(PermissionCacheMixin):
def __init__(self, op1, op2): def __init__(self, op1, op2):
self.op1 = op1 self.op1 = op1
self.op2 = op2 self.op2 = op2
def has_permission(self, request, view): def has_permission(self, request, view):
return ( return (
self.op1.has_permission(request, view) or self.op1.has_permission_value(request, view) or
self.op2.has_permission(request, view) self.op2.has_permission_value(request, view)
) )
def has_object_permission(self, request, view, obj): def has_object_permission(self, request, view, obj):
return ( return (
self.op1.has_permission(request, view) self.op1.has_permission_value(request, view)
and self.op1.has_object_permission(request, view, obj) and self.op1.has_object_permission_value(request, view, obj)
) or ( ) or (
self.op2.has_permission(request, view) self.op2.has_permission_value(request, view)
and self.op2.has_object_permission(request, view, obj) and self.op2.has_object_permission_value(request, view, obj)
) )
class NOT: class NOT(PermissionCacheMixin):
def __init__(self, op1): def __init__(self, op1):
self.op1 = op1 self.op1 = op1
def has_permission(self, request, view): def has_permission(self, request, view):
return not self.op1.has_permission(request, view) return not self.op1.has_permission_value(request, view)
def has_object_permission(self, request, view, obj): def has_object_permission(self, request, view, obj):
return not self.op1.has_object_permission(request, view, obj) return not self.op1.has_object_permission_value(request, view, obj)
class BasePermissionMetaclass(OperationHolderMixin, type): class BasePermissionMetaclass(OperationHolderMixin, type):
pass pass
class BasePermission(metaclass=BasePermissionMetaclass): class BasePermission(PermissionCacheMixin, metaclass=BasePermissionMetaclass):
""" """
A base class from which all permission classes should inherit. A base class from which all permission classes should inherit.
""" """