2016-03-02 00:46:19 +01:00
|
|
|
from django.dispatch import Signal
|
|
|
|
|
|
|
|
from .dispatch import SignalConnectMetaClass
|
|
|
|
|
|
|
|
|
|
|
|
class BaseAccessPermissions(object, metaclass=SignalConnectMetaClass):
|
2016-02-11 22:58:32 +01:00
|
|
|
"""
|
|
|
|
Base access permissions container.
|
2016-03-02 00:46:19 +01:00
|
|
|
|
|
|
|
Every app which has autoupdate models has to create classes subclassing
|
|
|
|
from this base class for every autoupdate root model. Each subclass has
|
|
|
|
to have a globally unique name. The metaclass (SignalConnectMetaClass)
|
|
|
|
does the rest of the magic.
|
2016-02-11 22:58:32 +01:00
|
|
|
"""
|
2016-03-02 00:46:19 +01:00
|
|
|
signal = Signal()
|
|
|
|
|
|
|
|
def __init__(self, **kwargs):
|
|
|
|
"""
|
|
|
|
Initializes the access permission instance. This is done when the
|
|
|
|
signal is sent.
|
|
|
|
|
|
|
|
Because of Django's signal API, we have to take wildcard keyword
|
|
|
|
arguments. But they are not used here.
|
|
|
|
"""
|
|
|
|
pass
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def get_dispatch_uid(cls):
|
|
|
|
"""
|
|
|
|
Returns the classname as a unique string for each class. Returns None
|
|
|
|
for the base class so it will not be connected to the signal.
|
|
|
|
"""
|
|
|
|
if not cls.__name__ == 'BaseAccessPermissions':
|
|
|
|
return cls.__name__
|
|
|
|
|
2016-02-11 22:58:32 +01:00
|
|
|
def can_retrieve(self, user):
|
|
|
|
"""
|
2016-03-02 00:46:19 +01:00
|
|
|
Returns True if the user has read access to model instances.
|
2016-02-11 22:58:32 +01:00
|
|
|
"""
|
|
|
|
return False
|
|
|
|
|
2016-03-02 00:46:19 +01:00
|
|
|
def get_serializer_class(self, user=None):
|
2016-02-11 22:58:32 +01:00
|
|
|
"""
|
|
|
|
Returns different serializer classes according to users permissions.
|
2016-03-02 00:46:19 +01:00
|
|
|
|
|
|
|
This should return the serializer for full data access if user is
|
|
|
|
None. See get_full_data().
|
2016-02-11 22:58:32 +01:00
|
|
|
"""
|
|
|
|
raise NotImplementedError(
|
2016-03-02 00:46:19 +01:00
|
|
|
"You have to add the method 'get_serializer_class' to your "
|
2016-02-11 22:58:32 +01:00
|
|
|
"access permissions class.".format(self))
|
|
|
|
|
2016-03-02 00:46:19 +01:00
|
|
|
def get_full_data(self, instance):
|
2016-02-11 22:58:32 +01:00
|
|
|
"""
|
2016-03-02 00:46:19 +01:00
|
|
|
Returns all possible serialized data for the given instance.
|
|
|
|
"""
|
|
|
|
return self.get_serializer_class(user=None)(instance).data
|
|
|
|
|
|
|
|
def get_restricted_data(self, full_data, user):
|
|
|
|
"""
|
|
|
|
Returns the restricted serialized data for the instance prepared
|
|
|
|
for the user.
|
|
|
|
|
|
|
|
Returns None if the user has no read access. Returns reduced data
|
|
|
|
if the user has limited access. Default: Returns full data if the
|
|
|
|
user has read access to model instances.
|
2016-02-11 22:58:32 +01:00
|
|
|
|
2016-03-02 00:46:19 +01:00
|
|
|
Hint: You should override this method if your
|
|
|
|
get_serializer_class() method may return different serializer for
|
|
|
|
different users or if you have access restrictions in your view or
|
|
|
|
viewset in methods like retrieve() or check_object_permissions().
|
2016-02-11 22:58:32 +01:00
|
|
|
"""
|
|
|
|
if self.can_retrieve(user):
|
2016-03-02 00:46:19 +01:00
|
|
|
data = full_data
|
2016-02-11 22:58:32 +01:00
|
|
|
else:
|
|
|
|
data = None
|
|
|
|
return data
|