From 1d4703f86fa90946cd6d13cb904b0ee25f11ec41 Mon Sep 17 00:00:00 2001 From: Gwendolyn Date: Wed, 20 Dec 2023 23:56:32 +0100 Subject: [PATCH] access restrictions can be set to public to make them available to everyone (even not logged in users) public access restrictions do not count to the unlocked areas count --- src/c3nav/editor/forms.py | 2 +- .../0093_public_accessrestriction.py | 24 +++++++++++ src/c3nav/mapdata/models/access.py | 41 ++++++++++++------- src/c3nav/mapdata/utils/user.py | 4 +- 4 files changed, 53 insertions(+), 18 deletions(-) create mode 100644 src/c3nav/mapdata/migrations/0093_public_accessrestriction.py diff --git a/src/c3nav/editor/forms.py b/src/c3nav/editor/forms.py index a89f5f72..4c28d8cc 100644 --- a/src/c3nav/editor/forms.py +++ b/src/c3nav/editor/forms.py @@ -308,7 +308,7 @@ def create_editor_form(editor_model): 'level_change_description', 'base_mapdata_accessible', 'can_report_missing', 'label_settings', 'label_override', 'min_zoom', 'max_zoom', 'font_size', 'allow_levels', 'allow_spaces', 'allow_areas', 'allow_pois', 'allow_dynamic_locations', - 'left', 'top', 'right', 'bottom'] + 'left', 'top', 'right', 'bottom', 'public'] field_names = [field.name for field in editor_model._meta.get_fields() if not field.one_to_many] existing_fields = [name for name in possible_fields if name in field_names] diff --git a/src/c3nav/mapdata/migrations/0093_public_accessrestriction.py b/src/c3nav/mapdata/migrations/0093_public_accessrestriction.py new file mode 100644 index 00000000..b2066cd8 --- /dev/null +++ b/src/c3nav/mapdata/migrations/0093_public_accessrestriction.py @@ -0,0 +1,24 @@ +# Generated by Django 4.2.7 on 2023-12-20 22:25 + +import c3nav.mapdata.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mapdata', '0092_accesspermission_by_group'), + ] + + operations = [ + migrations.RenameField( + model_name='accessrestriction', + old_name='open', + new_name='public', + ), + migrations.AlterField( + model_name='accessrestriction', + name='public', + field=models.BooleanField(default=False, verbose_name='public'), + ), + ] diff --git a/src/c3nav/mapdata/models/access.py b/src/c3nav/mapdata/models/access.py index 3ed48e05..da56212a 100644 --- a/src/c3nav/mapdata/models/access.py +++ b/src/c3nav/mapdata/models/access.py @@ -20,7 +20,7 @@ class AccessRestriction(TitledMixin, models.Model): """ An access restriction """ - open = models.BooleanField(default=False, verbose_name=_('open')) + public = models.BooleanField(default=False, verbose_name=_('public')) groups = models.ManyToManyField('mapdata.AccessRestrictionGroup', verbose_name=_('Groups'), blank=True) class Meta: @@ -41,6 +41,26 @@ class AccessRestriction(TitledMixin, models.Model): def q_for_request(cls, request): return Q(pk__in=AccessPermission.get_for_request(request)) + @staticmethod + def get_all() -> set[int]: + cache_key = 'all_access_restrictions:%s' % MapUpdate.current_cache_key() + access_restriction_ids = cache.get(cache_key, None) + if access_restriction_ids is None: + access_restriction_ids = set(AccessRestriction.objects.values_list('pk', flat=True)) + cache.set(cache_key, access_restriction_ids, 300) + return access_restriction_ids + + @staticmethod + def get_all_public() -> set[int]: + cache_key = 'public_access_restrictions:%s' % MapUpdate.current_cache_key() + access_restriction_ids = cache.get(cache_key, None) + if access_restriction_ids is None: + access_restriction_ids = set(AccessRestriction.objects.filter(public=True) + .values_list('pk', flat=True)) + cache.set(cache_key, access_restriction_ids, 300) + return access_restriction_ids + + class AccessRestrictionGroup(TitledMixin, models.Model): """ @@ -59,7 +79,7 @@ class AccessRestrictionGroup(TitledMixin, models.Model): def q_for_request(cls, request): if request.user.is_authenticated and request.user.is_superuser: return Q() - all_permissions = AccessPermission.get_all_access_restrictions() + all_permissions = AccessRestriction.get_all() permissions = AccessPermission.get_for_request(request) # now we filter out groups where the user doesn't have a permission for all members filter_perms = all_permissions - permissions @@ -184,7 +204,7 @@ class AccessPermission(models.Model): return {} if request.user_permissions.grant_all_access: - return {pk: None for pk in cls.get_all_access_restrictions()} + return {pk: None for pk in AccessRestriction.get_all()} result = tuple( cls.queryset_for_user(request.user, can_grant).select_related( @@ -208,22 +228,13 @@ class AccessPermission(models.Model): } return permissions - @staticmethod - def get_all_access_restrictions() -> set[int]: - cache_key = 'all_access_restrictions:%s' % MapUpdate.current_cache_key() - access_restriction_ids = cache.get(cache_key, None) - if access_restriction_ids is None: - access_restriction_ids = set(AccessRestriction.objects.values_list('pk', flat=True)) - cache.set(cache_key, access_restriction_ids, 300) - return access_restriction_ids - @classmethod def get_for_request(cls, request) -> set[int]: if not request or not request.user.is_authenticated: - return set() + return AccessRestriction.get_all_public() if request.user_permissions.grant_all_access: - return cls.get_all_access_restrictions() + return AccessRestriction.get_all() cache_key = cls.user_access_permission_key(request.user.pk) access_restriction_ids = cache.get(cache_key, None) @@ -234,7 +245,7 @@ class AccessPermission(models.Model): expire_date = min((e for e in permissions.values() if e), default=timezone.now()+timedelta(seconds=120)) cache.set(cache_key, access_restriction_ids, max(0.0, (expire_date-timezone.now()).total_seconds())) - return set(access_restriction_ids) + return set(access_restriction_ids) | AccessRestriction.get_all_public() @classmethod def cache_key_for_request(cls, request, with_update=True): diff --git a/src/c3nav/mapdata/utils/user.py b/src/c3nav/mapdata/utils/user.py index 2e5d402d..e21fc14e 100644 --- a/src/c3nav/mapdata/utils/user.py +++ b/src/c3nav/mapdata/utils/user.py @@ -3,12 +3,12 @@ from django.utils.functional import lazy from django.utils.translation import gettext_lazy as _ from django.utils.translation import ngettext_lazy -from c3nav.mapdata.models.access import AccessPermission +from c3nav.mapdata.models.access import AccessPermission, AccessRestriction from c3nav.mapdata.models.locations import Position def get_user_data(request): - permissions = AccessPermission.get_for_request(request) + permissions = AccessPermission.get_for_request(request) - AccessRestriction.get_all_public() result = { 'logged_in': bool(request.user.is_authenticated), 'allow_editor': can_access_editor(request),