[permission] Renamed Permission.permission and added description field

This commit is contained in:
Benjamin Graillot 2020-02-09 18:14:36 +01:00
parent 94c3a99447
commit 72955ae2d6
1 changed files with 37 additions and 31 deletions

View File

@ -57,11 +57,11 @@ class Permission(models.Model):
model = models.ForeignKey(ContentType, on_delete=models.CASCADE, related_name='+') model = models.ForeignKey(ContentType, on_delete=models.CASCADE, related_name='+')
# A json encoded Q object with the following grammar # A json encoded Q object with the following grammar
# permission -> [] | {} (the empty permission representing all objects) # query -> [] | {} (the empty query representing all objects)
# permission -> ['AND', permission, …] # query -> ['AND', query, …]
# -> ['OR', permission, …] # -> ['OR', query, …]
# -> ['NOT', permission] # -> ['NOT', query]
# permission -> {key: value, …} # query -> {key: value, …}
# key -> string # key -> string
# value -> int | string | bool | null # value -> int | string | bool | null
# -> [parameter] # -> [parameter]
@ -69,14 +69,16 @@ class Permission(models.Model):
# Examples: # Examples:
# Q(is_admin=True) := {'is_admin': ['TYPE', 'bool', 'True']} # Q(is_admin=True) := {'is_admin': ['TYPE', 'bool', 'True']}
# ~Q(is_admin=True) := ['NOT', {'is_admin': ['TYPE', 'bool', 'True']}] # ~Q(is_admin=True) := ['NOT', {'is_admin': ['TYPE', 'bool', 'True']}]
permission = models.TextField() query = models.TextField()
type = models.CharField(max_length=16, choices=PERMISSION_TYPES) type = models.CharField(max_length=15, choices=PERMISSION_TYPES)
field = models.CharField(max_length=256, blank=True) field = models.CharField(max_length=255, blank=True)
description = models.CharField(max_length=255, blank=True)
class Meta: class Meta:
unique_together = ('model', 'permission', 'type', 'field') unique_together = ('model', 'query', 'type', 'field')
def clean(self): def clean(self):
if self.field and self.type not in {'view', 'change'}: if self.field and self.type not in {'view', 'change'}:
@ -86,25 +88,25 @@ class Permission(models.Model):
self.full_clean() self.full_clean()
super().save() super().save()
def _about(_self, _permission, **kwargs): def _about(_self, _query, **kwargs):
self = _self self = _self
permission = _permission query = _query
if len(permission) == 0: if len(query) == 0:
# The permission is either [] or {} and # The query is either [] or {} and
# applies to all objects of the model # applies to all objects of the model
# to represent this we return None # to represent this we return None
return None return None
if isinstance(permission, list): if isinstance(query, list):
if permission[0] == 'AND': if query[0] == 'AND':
return functools.reduce(operator.and_, [self._about(permission, **kwargs) for permission in permission[1:]]) return functools.reduce(operator.and_, [self._about(query, **kwargs) for query in query[1:]])
elif permission[0] == 'OR': elif query[0] == 'OR':
return functools.reduce(operator.or_, [self._about(permission, **kwargs) for permission in permission[1:]]) return functools.reduce(operator.or_, [self._about(query, **kwargs) for query in query[1:]])
elif permission[0] == 'NOT': elif query[0] == 'NOT':
return ~self._about(permission[1], **kwargs) return ~self._about(query[1], **kwargs)
elif isinstance(permission, dict): elif isinstance(query, dict):
q_kwargs = {} q_kwargs = {}
for key in permission: for key in query:
value = permission[key] value = query[key]
if isinstance(value, list): if isinstance(value, list):
# It is a parameter we query its primary key # It is a parameter we query its primary key
q_kwargs[key] = kwargs[value[0]].pk q_kwargs[key] = kwargs[value[0]].pk
@ -113,18 +115,22 @@ class Permission(models.Model):
return Q(**q_kwargs) return Q(**q_kwargs)
else: else:
# TODO: find a better way to crash here # TODO: find a better way to crash here
raise Exception("Permission {} is wrong".format(self.permission)) raise Exception("query {} is wrong".format(self.query))
def about(self, **kwargs): def about(self, **kwargs):
permission = json.loads(self.permission) """
query = self._about(permission, **kwargs) Return an InstancedPermission with the parameters
replaced by their values and the query interpreted
"""
query = json.loads(self.query)
query = self._about(query, **kwargs)
return InstancedPermission(self.model, query, self.type, self.field) return InstancedPermission(self.model, query, self.type, self.field)
def __str__(self): def __str__(self):
if self.field: if self.field:
return _("Can {type} {model}.{field} in {permission}").format(type=self.type, model=self.model, field=self.field, permission=self.permission) return _("Can {type} {model}.{field} in {query}").format(type=self.type, model=self.model, field=self.field, query=self.query)
else: else:
return _("Can {type} {model} in {permission}").format(type=self.type, model=self.model, permission=self.permission) return _("Can {type} {model} in {query}").format(type=self.type, model=self.model, query=self.query)
class UserPermission(models.Model): class UserPermission(models.Model):