diff --git a/src/c3nav/editor/forms.py b/src/c3nav/editor/forms.py index 8e1cdc7c..73880b4a 100644 --- a/src/c3nav/editor/forms.py +++ b/src/c3nav/editor/forms.py @@ -10,6 +10,7 @@ from django.core.cache import cache from django.core.exceptions import FieldDoesNotExist from django.core.serializers.json import DjangoJSONEncoder from django.db.models import Prefetch, Q +from django.db.models.fields.reverse_related import ManyToManyRel from django.forms import (BooleanField, CharField, ChoiceField, DecimalField, Form, JSONField, ModelChoiceField, ModelForm, MultipleChoiceField, Select, ValidationError) from django.forms.widgets import HiddenInput, TextInput @@ -171,9 +172,9 @@ class EditorFormBase(I18nModelFormMixin, ModelForm): self.fields.move_to_end('copy_from', last=False) self.fields.move_to_end('name', last=False) - if self._meta.model.__name__ == 'AccessRestriction': - self.fields['groups'].label_from_instance = lambda obj: obj.title - self.fields['groups'].queryset = AccessRestrictionGroup.qs_for_request(self.request) + if self._meta.model.__name__ == 'AccessRestrictionGroup': + self.fields['members'].label_from_instance = lambda obj: obj.title + self.fields['members'].queryset = AccessRestriction.qs_for_request(self.request) elif 'groups' in self.fields: kwargs = {'allow_'+self._meta.model._meta.default_related_name: True} @@ -407,7 +408,7 @@ def create_editor_form(editor_model): 'extra_seconds', 'speed', 'can_report_missing', "can_report_mistake", 'description', 'speed_up', 'description_up', 'report_help_text', 'enter_description', 'level_change_description', 'base_mapdata_accessible', - 'label_settings', 'label_override', 'min_zoom', 'max_zoom', 'font_size', + 'label_settings', 'label_override', 'min_zoom', 'max_zoom', 'font_size', 'members', 'allow_levels', 'allow_spaces', 'allow_areas', 'allow_pois', 'allow_dynamic_locations', 'left', 'top', 'right', 'bottom', 'import_tag', 'import_block_data', 'import_block_geom', 'public', 'default', 'dark', 'high_contrast', 'funky', 'randomize_primary_color', 'color_logo', @@ -422,7 +423,8 @@ def create_editor_form(editor_model): 'stroke_color', 'stroke_width', 'fill_color', 'interactive', 'point_icon', 'extra_data', 'show_label', 'show_geometry', 'external_url', ] - field_names = [field.name for field in editor_model._meta.get_fields() if not field.one_to_many] + field_names = [field.name for field in editor_model._meta.get_fields() + if not field.one_to_many and not isinstance(field, ManyToManyRel)] existing_fields = [name for name in possible_fields if name in field_names] class EditorForm(EditorFormBase, ModelForm): diff --git a/src/c3nav/mapdata/migrations/0114_accessrestrictiongroup_members.py b/src/c3nav/mapdata/migrations/0114_accessrestrictiongroup_members.py new file mode 100644 index 00000000..1f15c3e1 --- /dev/null +++ b/src/c3nav/mapdata/migrations/0114_accessrestrictiongroup_members.py @@ -0,0 +1,41 @@ +# Generated by Django 5.0.8 on 2024-12-11 13:24 + +from django.db import migrations, models + + +def forwards_func(apps, schema_editor): + AccessRestrictionGroup = apps.get_model('mapdata', 'AccessRestrictionGroup') + for group in AccessRestrictionGroup.objects.prefetch_related("accessrestrictions").all(): + group.members.set(group.accessrestrictions.all()) + + +def backwards_func(apps, schema_editor): + AccessRestrictionGroup = apps.get_model('mapdata', 'AccessRestrictionGroup') + for group in AccessRestrictionGroup.objects.prefetch_related("members").all(): + group.accessrestrictions.set(group.members.all()) + + +class Migration(migrations.Migration): + + dependencies = [ + ('mapdata', '0113_locationgroup_can_report_mistake'), + ] + + operations = [ + migrations.AddField( + model_name='accessrestrictiongroup', + name='members', + field=models.ManyToManyField(blank=True, to='mapdata.accessrestriction', verbose_name='Access Restrictions'), + ), + migrations.RunPython(forwards_func, backwards_func), + migrations.RemoveField( + model_name='accessrestriction', + name='groups', + ), + migrations.AlterField( + model_name='accessrestrictiongroup', + name='members', + field=models.ManyToManyField(blank=True, related_name='groups', to='mapdata.accessrestriction', + verbose_name='Access Restrictions'), + ), + ] diff --git a/src/c3nav/mapdata/models/access.py b/src/c3nav/mapdata/models/access.py index e736fcba..d1e1d8ff 100644 --- a/src/c3nav/mapdata/models/access.py +++ b/src/c3nav/mapdata/models/access.py @@ -21,7 +21,6 @@ class AccessRestriction(TitledMixin, models.Model): An access restriction """ public = models.BooleanField(default=False, verbose_name=_('public')) - groups = models.ManyToManyField('mapdata.AccessRestrictionGroup', verbose_name=_('Groups'), blank=True) class Meta: verbose_name = _('Access Restriction') @@ -60,6 +59,9 @@ class AccessRestrictionGroup(TitledMixin, models.Model): """ An access restriction group """ + members = models.ManyToManyField('mapdata.AccessRestriction', verbose_name=_('Access Restrictions'), blank=True, + related_name="groups") + class Meta: verbose_name = _('Access Restriction Group') verbose_name_plural = _('Access Restriction Groups') @@ -77,7 +79,7 @@ class AccessRestrictionGroup(TitledMixin, models.Model): 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 - return ~Q(accessrestrictions__pk__in=filter_perms) + return ~Q(members__pk__in=filter_perms) @classmethod def qs_for_user(cls, user): @@ -91,7 +93,7 @@ class AccessRestrictionGroup(TitledMixin, models.Model): permissions = AccessPermission.get_for_user(user) # now we filter out groups where the user doesn't have a permission for all members filter_perms = all_permissions - permissions - return ~Q(accessrestrictions__pk__in=filter_perms) + return ~Q(members__pk__in=filter_perms) def default_valid_until(): @@ -288,7 +290,7 @@ class AccessPermission(models.Model): result = tuple( qs.select_related( 'access_restriction_group' - ).prefetch_related('access_restriction_group__accessrestrictions') + ).prefetch_related('access_restriction_group__members') ) # collect permissions (can be multiple for one restriction) @@ -297,7 +299,7 @@ class AccessPermission(models.Model): if permission.access_restriction_id: permissions.setdefault(permission.access_restriction_id, set()).add(permission.expire_date) if permission.access_restriction_group_id: - for member in permission.access_restriction_group.accessrestrictions.all(): + for member in permission.access_restriction_group.members.all(): permissions.setdefault(member.pk, set()).add(permission.expire_date) # get latest expire date for each permission