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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
| from rest_framework import permissions class CodePermission(permissions.BasePermission): REQUEST_METHOD_MAP = { 'list': 'GET', 'create': 'POST', 'destroy': 'DELETE', 'delete': 'DELETE', 'retrieve': 'GET', 'put': 'PUT', 'get': 'GET', 'post': 'POST', 'patch': 'PATCH' }
def check_permission_format(self, permission_code, permission_code_by_method, view): """检查配置的权限是否合法,不满足格式要求会抛异常""" module_path = "{}.{}".format(view.__module__, view.__name__) if permission_code and permission_code is not None and not isinstance(permission_code, (int, list)): raise TypeError( '<%s> permission_code type was not int or list' % module_path ) else: if isinstance(permission_code, list): for action_code in permission_code: if not isinstance(action_code, int): raise TypeError( '<%s> permission_code list value "%s" type was not int!' % (module_path, action_code) ) if permission_code_by_method and permission_code_by_method is not None: """""" if not isinstance(permission_code_by_method, dict): raise TypeError( '<%s> permission_code_by_method type must dict!' % module_path ) for action in permission_code_by_method: if str(action).lower() not in self.REQUEST_METHOD_MAP: raise TypeError( '<%s> permission_code_by_method: action "%s" not support, allow:[%s]' % ( module_path, action, ",".join(self.REQUEST_METHOD_MAP.keys()) ) ) if not hasattr(view, action): raise AttributeError( '<%s> permission_code_by_method: method "%s" is undefined in this class.' % ( module_path, action ) ) if not isinstance(permission_code_by_method.get(action, None), (int, list)): raise TypeError( '<%s> permission_code_by_method: "%s" permission_code type must int or list, not %s.' % (module_path, action, type(permission_code_by_method.get(action, None)).__name__) ) else: if isinstance(action_list := permission_code_by_method.get(action, None), list): for action_code in action_list: if not isinstance(action_code, int): raise TypeError( '<%s> permission_code_by_method: "%s" code list value "%s" type was not int' % ( module_path, action, action_code ) )
def get_permission(self, view) -> tuple: """获取配置的权限""" return getattr(view, 'permission_code') if hasattr(view, 'permission_code') else None, \ getattr(view, 'permission_code_by_method') if hasattr(view, 'permission_code_by_method') else None
def is_require_permission(self, view) -> bool: """检查类是否需要权限访问""" permission_code, permission_code_by_method = self.get_permission(view)
if permission_code or permission_code_by_method: return True return False
@staticmethod def query_permission(role_id, code) -> bool: """查询权限code,True为满足所有,False为任一不满足。None视为不需要权限,返回True""" if isinstance(code, int): code = [code] elif role_id is None: return True
from apps.user.models import PermissionCodeRoleRelation for c in code: if isinstance(c, list): if not CodePermission.query_permission(role_id=role_id, code=c): return False continue if PermissionCodeRoleRelation.objects.filter(role_id=role_id, code=c).count() == 0: return False return True
def has_permission(self, request, view): if self.is_require_permission(view): if not request.user.role_id: return False
permission_code, permission_code_by_method = self.get_permission(view) self.check_permission_format(permission_code, permission_code_by_method, view) if permission_code_by_method and isinstance(permission_code_by_method, dict): permission_action = list( set(permission_code_by_method.keys()) & set([r for r in self.REQUEST_METHOD_MAP if self.REQUEST_METHOD_MAP[r] == request.method]) ) permission_action_code = [permission_code_by_method[k] for k in permission_code_by_method if k in permission_action and permission_code_by_method[k]] else: permission_action_code = [] return self.query_permission(role_id=request.user.role_id, code=permission_code) & self.query_permission( role_id=request.user.role_id, code=permission_action_code ) else: return True
|