diff --git a/src/c3nav/control/forms.py b/src/c3nav/control/forms.py index 21ddd0c7..1a3163a1 100644 --- a/src/c3nav/control/forms.py +++ b/src/c3nav/control/forms.py @@ -23,6 +23,10 @@ from c3nav.site.models import Announcement class UserPermissionsForm(ModelForm): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields['review_group_reports'].label_from_instance = lambda obj: obj.title + class Meta: model = UserPermissions exclude = ('user', 'max_changeset_changes', 'api_secret') diff --git a/src/c3nav/control/migrations/0008_userpermissions_reports.py b/src/c3nav/control/migrations/0008_userpermissions_reports.py new file mode 100644 index 00000000..1bd60de0 --- /dev/null +++ b/src/c3nav/control/migrations/0008_userpermissions_reports.py @@ -0,0 +1,24 @@ +# Generated by Django 2.2.8 on 2019-12-24 16:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mapdata', '0078_reports'), + ('control', '0007_userpermissions_manage_map_updates'), + ] + + operations = [ + migrations.AddField( + model_name='userpermissions', + name='review_all_reports', + field=models.BooleanField(default=False, verbose_name='can review reports'), + ), + migrations.AddField( + model_name='userpermissions', + name='review_group_reports', + field=models.ManyToManyField(limit_choices_to={'access_restriction': None}, related_name='permissions', to='mapdata.LocationGroup', verbose_name='can review reports belonging to'), + ), + ] diff --git a/src/c3nav/control/models.py b/src/c3nav/control/models.py index ec68fe83..e5ec2b7b 100644 --- a/src/c3nav/control/models.py +++ b/src/c3nav/control/models.py @@ -5,7 +5,7 @@ from django.conf import settings from django.contrib.auth.models import User from django.core.cache import cache from django.db import models, transaction -from django.utils.functional import lazy +from django.utils.functional import cached_property, lazy from django.utils.translation import ugettext_lazy as _ from c3nav.mapdata.models import Space @@ -29,6 +29,12 @@ class UserPermissions(models.Model): manage_announcements = models.BooleanField(default=False, verbose_name=_('manage announcements')) grant_all_access = models.BooleanField(default=False, verbose_name=_('can grant access to everything')) grant_space_access = models.BooleanField(default=False, verbose_name=_('can grant space access')) + + review_all_reports = models.BooleanField(default=False, verbose_name=_('can review reports')) + review_group_reports = models.ManyToManyField('mapdata.LocationGroup', + limit_choices_to={'access_restriction': None}, + verbose_name=_('can review reports belonging to')) + api_secret = models.CharField(null=True, blank=True, max_length=64, verbose_name=_('API secret')) class Meta: @@ -47,6 +53,12 @@ class UserPermissions(models.Model): def get_cache_key(pk): return 'control:permissions:%d' % pk + @cached_property + def review_group_ids(self): + if self.pk is None: + return () + return tuple(self.review_group_reports.values_list('pk', flat=True)) + @classmethod @contextmanager def lock(cls, pk): diff --git a/src/c3nav/control/templates/control/user.html b/src/c3nav/control/templates/control/user.html index b0061fc7..fc85249f 100644 --- a/src/c3nav/control/templates/control/user.html +++ b/src/c3nav/control/templates/control/user.html @@ -12,7 +12,11 @@
{% csrf_token %} {% for field in user_permissions_form %} -
+ {% if field.name == 'review_group_reports' %} + {{ field.label_tag }} {{ field }} + {% else %} +
+ {% endif %} {% endfor %}
diff --git a/src/c3nav/mapdata/models/report.py b/src/c3nav/mapdata/models/report.py index 0ceeed71..da374a18 100644 --- a/src/c3nav/mapdata/models/report.py +++ b/src/c3nav/mapdata/models/report.py @@ -3,6 +3,7 @@ import string from django.conf import settings from django.core.exceptions import ObjectDoesNotExist from django.db import models +from django.db.models import Q from django.utils.crypto import get_random_string from django.utils.translation import ugettext_lazy as _ @@ -94,11 +95,14 @@ class Report(models.Model): @classmethod def qs_for_request(cls, request): - if request.user.is_superuser: - # todo: permissions! + if request.user_permissions.review_all_reports: return cls.objects.all() elif request.user.is_authenticated: - return cls.objects.filter(author=request.user) + return cls.objects.filter( + Q(author=request.user) | + Q(location__group__in=request.user_permissions.review_group_ids) | + Q(created_groups__in=request.user_permissions.review_group_ids) + ) else: return cls.objects.none() diff --git a/src/c3nav/site/static/site/css/c3nav.scss b/src/c3nav/site/static/site/css/c3nav.scss index 9d669e97..660ad828 100644 --- a/src/c3nav/site/static/site/css/c3nav.scss +++ b/src/c3nav/site/static/site/css/c3nav.scss @@ -1233,6 +1233,11 @@ main.control h4 { main.control form tr > * { white-space: nowrap; } +main.control select { + display: block; + width: 300px; + height: 100px; +} .button-cell { padding-top: 4px; padding-bottom: 4px;