diff --git a/src/c3nav/control/templates/control/user.html b/src/c3nav/control/templates/control/user.html index c927a598..d55f36d5 100644 --- a/src/c3nav/control/templates/control/user.html +++ b/src/c3nav/control/templates/control/user.html @@ -46,7 +46,7 @@ {% if access_permission.expire_date %}{{ access_permission.expire_date }}{% else %}{% trans 'never' %}{% endif %} {% if access_permission.can_grant %}{% trans 'Yes' %}{% else %}{% trans 'No' %}{% endif %} - {{ access_permission. }}{% if access_permission.can_grant %}{% trans 'Yes' %}{% else %}{% trans 'No' %}{% endif %} + {% if access_permission.unique_key %}{{ access_permission.unique_key }}{% endif %} {% if request.user_permissions.grant_all_access or request.user == access_permission.author %} {% endif %} diff --git a/src/c3nav/mapdata/migrations/0064_access_permission_unique_key.py b/src/c3nav/mapdata/migrations/0064_access_permission_unique_key.py new file mode 100644 index 00000000..8c0b0267 --- /dev/null +++ b/src/c3nav/mapdata/migrations/0064_access_permission_unique_key.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.7 on 2017-12-19 11:10 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('mapdata', '0063_descriptions_unique_together'), + ] + + operations = [ + migrations.AlterModelOptions( + name='accesspermissiontoken', + options={'verbose_name': 'Access Permission Token', 'verbose_name_plural': 'Access Permission Tokens'}, + ), + migrations.AddField( + model_name='accesspermission', + name='unique_key', + field=models.CharField(max_length=32, null=True, verbose_name='unique key'), + ), + migrations.AddField( + model_name='accesspermissiontoken', + name='unique_key', + field=models.CharField(max_length=32, null=True, verbose_name='unique key'), + ), + migrations.AlterUniqueTogether( + name='accesspermission', + unique_together=set([('author', 'unique_key')]), + ), + ] diff --git a/src/c3nav/mapdata/models/access.py b/src/c3nav/mapdata/models/access.py index 815da566..05878a99 100644 --- a/src/c3nav/mapdata/models/access.py +++ b/src/c3nav/mapdata/models/access.py @@ -55,8 +55,14 @@ class AccessPermissionToken(models.Model): unlimited = models.BooleanField(default=False, db_index=True, verbose_name=_('unlimited')) redeemed = models.BooleanField(default=False, db_index=True, verbose_name=_('redeemed')) can_grant = models.BooleanField(default=False, db_index=True, verbose_name=_('can grant')) + unique_key = models.CharField(max_length=32, null=True, verbose_name=_('unique key')) data = models.BinaryField() + class Meta: + verbose_name = _('Access Permission Token') + verbose_name_plural = _('Access Permission Tokens') + default_related_name = 'accessrestriction_tokens' + @property def restrictions(self) -> Sequence[AccessPermissionTokenItem]: return pickle.loads(self.data) @@ -76,15 +82,19 @@ class AccessPermissionToken(models.Model): raise self.RedeemError('No longer valid.') if user: - for restriction in self.restrictions: - AccessPermission.objects.create( - user=user, - access_restriction_id=restriction.pk, - author_id=self.author_id, - expire_date=restriction.expire_date, - can_grant=self.can_grant, - token=self if self.pk else None, - ) + with transaction.atomic(): + if self.author_id and self.unique_key: + AccessPermission.objects.filter(author_id=self.author_id, unique_key=self.unique_key).delete() + for restriction in self.restrictions: + AccessPermission.objects.create( + user=user, + access_restriction_id=restriction.pk, + author_id=self.author_id, + expire_date=restriction.expire_date, + can_grant=self.can_grant, + unique_key=self.unique_key, + token=self if self.pk else None, + ) if self.pk and not self.unlimited: self.redeemed = True @@ -105,6 +115,7 @@ class AccessPermission(models.Model): can_grant = models.BooleanField(default=False, verbose_name=_('can grant')) author = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL, related_name='authored_access_permissions', verbose_name=_('Author')) + unique_key = models.CharField(max_length=32, null=True, verbose_name=_('unique key')) token = models.ForeignKey(AccessPermissionToken, null=True, on_delete=models.CASCADE, verbose_name=_('Access permission token')) @@ -112,6 +123,9 @@ class AccessPermission(models.Model): verbose_name = _('Access Permission') verbose_name_plural = _('Access Permissions') default_related_name = 'accesspermissions' + unique_together = ( + ('author', 'unique_key') + ) @staticmethod def user_access_permission_key(user_id):