-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathbase.py
60 lines (43 loc) · 1.83 KB
/
base.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
"""
Base service and permission decorators
"""
from functools import wraps
from typing import TypeVar, Callable, Any
from django.core.exceptions import PermissionDenied
T = TypeVar("T")
def requires_permission(permission_type: str, obj_param: str = "instance"):
"""
Permission decorator for service methods.
Args:
permission_type: Type of permission to check (view/edit/delete)
obj_param: Name of the parameter that contains the object to check permissions against
"""
def decorator(func: Callable) -> Callable:
@wraps(func)
def wrapper(service: Any, user: Any, *args, **kwargs) -> Any:
# Get the object to check permissions against
obj = kwargs.get(obj_param) or (args[0] if args else None)
if not obj:
raise ValueError(f"Could not find object parameter: {obj_param}")
# Get the permission check method
check_method = getattr(service, f"can_{permission_type}")
if not check_method:
raise ValueError(f"Service does not implement: can_{permission_type}")
# Check permission
if not check_method(user, obj):
raise PermissionDenied(
f"User does not have {permission_type} permission for {obj}"
)
return func(service, user, *args, **kwargs)
return wrapper
return decorator
class BasePermissionService:
"""Base service class with permission checks"""
def can_view(self, user: Any, instance: Any) -> bool:
raise NotImplementedError
def can_edit(self, user: Any, instance: Any) -> bool:
raise NotImplementedError
def can_delete(self, user: Any, instance: Any) -> bool:
raise NotImplementedError
def can_create(self, user: Any) -> bool:
raise NotImplementedError