#19 Tests
* refactors CheckableMixin and RecordableMixin into CheckableObject and RecordableObject * adds ShareableObject for wrapping share related fields and functionality * adds share functionality to EcoAccount and EMA, just like Intervention
This commit is contained in:
@@ -21,6 +21,7 @@ from compensation.settings import COMPENSATION_IDENTIFIER_TEMPLATE, COMPENSATION
|
||||
from ema.settings import EMA_ACCOUNT_IDENTIFIER_LENGTH, EMA_ACCOUNT_IDENTIFIER_TEMPLATE
|
||||
from intervention.settings import INTERVENTION_IDENTIFIER_LENGTH, INTERVENTION_IDENTIFIER_TEMPLATE
|
||||
from konova.settings import INTERVENTION_REVOCATION_DOC_PATH
|
||||
from konova.utils import generators
|
||||
from konova.utils.generators import generate_random_string
|
||||
from user.models import UserActionLogEntry, UserAction
|
||||
|
||||
@@ -315,12 +316,23 @@ class Geometry(BaseResource):
|
||||
geom = MultiPolygonField(null=True, blank=True, srid=DEFAULT_SRID)
|
||||
|
||||
|
||||
class RecordableMixin:
|
||||
""" Mixin to be combined with BaseObject class
|
||||
|
||||
Provides functionality related to un/recording of data
|
||||
class RecordableObject(models.Model):
|
||||
""" Wraps record related fields and functionality
|
||||
|
||||
"""
|
||||
# Refers to "verzeichnen"
|
||||
recorded = models.OneToOneField(
|
||||
UserActionLogEntry,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Holds data on user and timestamp of this action",
|
||||
related_name="+"
|
||||
)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def set_unrecorded(self, user: User):
|
||||
""" Perform unrecording
|
||||
|
||||
@@ -370,12 +382,19 @@ class RecordableMixin:
|
||||
self.set_unrecorded(user)
|
||||
|
||||
|
||||
class CheckableMixin:
|
||||
""" Mixin to be combined with BaseObject class
|
||||
class CheckableObject(models.Model):
|
||||
# Checks - Refers to "Genehmigen" but optional
|
||||
checked = models.OneToOneField(
|
||||
UserActionLogEntry,
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Holds data on user and timestamp of this action",
|
||||
related_name="+"
|
||||
)
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
Provides functionality related to un/checking of data
|
||||
|
||||
"""
|
||||
def set_unchecked(self, user: User):
|
||||
""" Perform unrecording
|
||||
|
||||
@@ -417,3 +436,53 @@ class CheckableMixin:
|
||||
self.set_checked(user)
|
||||
else:
|
||||
self.set_unchecked(user)
|
||||
|
||||
|
||||
class ShareableObject(models.Model):
|
||||
# Users having access on this object
|
||||
users = models.ManyToManyField(User, help_text="Users having access (data shared with)")
|
||||
access_token = models.CharField(
|
||||
max_length=255,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Used for sharing access",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def generate_access_token(self, make_unique: bool = False, rec_depth: int = 5):
|
||||
""" Creates a new access token for the data
|
||||
|
||||
Tokens are not used for identification of a table row. The share logic checks the intervention id as well
|
||||
as the given token. Therefore two different interventions can hold the same access_token without problems.
|
||||
For (possible) future changes to the share logic, the make_unique parameter may be used for checking whether
|
||||
the access_token is already used in any intervention. If so, tokens will be generated as long as a free token
|
||||
can be found.
|
||||
|
||||
Args:
|
||||
make_unique (bool): Perform check on uniqueness over all intervention entries
|
||||
rec_depth (int): How many tries for generating a free random token (only if make_unique)
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
# Make sure we won't end up in an infinite loop of trying to generate access_tokens
|
||||
rec_depth = rec_depth - 1
|
||||
if rec_depth < 0 and make_unique:
|
||||
raise RuntimeError(
|
||||
"Access token generating for {} does not seem to find a free random token! Aborted!".format(self.id)
|
||||
)
|
||||
|
||||
# Create random token
|
||||
token = generators.generate_random_string(15, True, True, False)
|
||||
# Check dynamically wheter there is another instance of that model, which holds this random access token
|
||||
_model = self._meta.concrete_model
|
||||
token_used_in = _model.objects.filter(access_token=token)
|
||||
# Make sure the token is not used anywhere as access_token, yet.
|
||||
# Make use of QuerySet lazy method for checking if it exists or not.
|
||||
if token_used_in and make_unique:
|
||||
self.generate_access_token(make_unique, rec_depth)
|
||||
else:
|
||||
self.access_token = token
|
||||
self.save()
|
||||
|
||||
Reference in New Issue
Block a user