diff --git a/rest_condition/mixins.py b/rest_condition/mixins.py new file mode 100644 index 0000000..4bf3b7e --- /dev/null +++ b/rest_condition/mixins.py @@ -0,0 +1,35 @@ +__all__ = ('UpdatedPermissionChecksMixin',) + +class UpdatedPermissionChecksMixin(object): + """ + Updated permission checks mixin. + """ + def check_permissions(self, request): + """ + Check if the request should be permitted. + Raises an appropriate exception if the request is not permitted. + """ + for permission in self.get_permissions(): + has_perm = permission.has_permission(request, self) + if not has_perm: + message = has_perm.message \ + if hasattr(has_perm, 'message') and has_perm.message \ + else getattr(permission, 'message', None) + self.permission_denied( + request, message=message + ) + + def check_object_permissions(self, request, obj): + """ + Check if the request should be permitted for a given object. + Raises an appropriate exception if the request is not permitted. + """ + for permission in self.get_permissions(): + has_perm = permission.has_object_permission(request, self, obj) + if not has_perm: + message = has_perm.message \ + if hasattr(has_perm, 'message') and has_perm.message \ + else getattr(permission, 'message', None) + self.permission_denied( + request, message=message + ) diff --git a/rest_condition/permissions.py b/rest_condition/permissions.py index df3f11c..6c14a5f 100644 --- a/rest_condition/permissions.py +++ b/rest_condition/permissions.py @@ -5,6 +5,9 @@ import operator from rest_framework import permissions +# Import from rest_framework.types once the pull request is merged +from .types import Boolean + __all__ = ['ConditionalPermission', 'Condition', 'C', 'And', 'Or', 'Not'] _NONE = object() @@ -82,6 +85,7 @@ def __init__(self, *perms_or_conds, **kwargs): def evaluate_permissions(self, permission_name, *args, **kwargs): reduced_result = _NONE + messages = [] for condition in self.perms_or_conds: if hasattr(condition, 'evaluate_permissions'): @@ -91,6 +95,13 @@ def evaluate_permissions(self, permission_name, *args, **kwargs): condition = condition() result = getattr(condition, permission_name)(*args, **kwargs) + message = result.message \ + if hasattr(result, 'message') and result.message \ + else None + + if message: + messages.append(message) + if reduced_result is _NONE: reduced_result = result else: @@ -100,9 +111,10 @@ def evaluate_permissions(self, permission_name, *args, **kwargs): break if reduced_result is not _NONE: - return not reduced_result if self.negated else reduced_result + ret = not reduced_result if self.negated else reduced_result + return Boolean(ret, '; '.join(messages)) - return False + return Boolean(False, '; '.join(messages)) def has_object_permission(self, request, view, obj): return self.evaluate_permissions('has_object_permission', diff --git a/rest_condition/types.py b/rest_condition/types.py new file mode 100644 index 0000000..2e1d283 --- /dev/null +++ b/rest_condition/types.py @@ -0,0 +1,7 @@ +__all__ = ('Boolean',) + +class Boolean(int): + def __new__(cls, x, message): + obj = int.__new__(cls, x) + obj.message = message + return obj