diff --git a/froide_govplan/admin.py b/froide_govplan/admin.py index bf7e0d4..7541d0e 100644 --- a/froide_govplan/admin.py +++ b/froide_govplan/admin.py @@ -1,5 +1,5 @@ from django import forms -from django.contrib import admin +from django.contrib import admin, auth from django.urls import reverse_lazy from tinymce.widgets import TinyMCE @@ -8,6 +8,8 @@ from froide.helper.widgets import TagAutocompleteWidget from .models import Government, GovernmentPlan, GovernmentPlanUpdate +User = auth.get_user_model() + class GovernmentPlanAdminForm(forms.ModelForm): class Meta: @@ -24,9 +26,7 @@ class GovernmentPlanUpdateAdminForm(forms.ModelForm): class Meta: model = GovernmentPlanUpdate fields = "__all__" - widgets = { - "content": TinyMCE(attrs={'cols': 80, 'rows': 30}) - } + widgets = {"content": TinyMCE(attrs={"cols": 80, "rows": 30})} class GovernmentAdmin(admin.ModelAdmin): @@ -54,9 +54,10 @@ class GovernmentPlanUpdateAdmin(admin.ModelAdmin): form = GovernmentPlanUpdateAdminForm raw_id_fields = ("user", "foirequest") list_display = ( + "title", + "timestamp", "plan", "user", - "timestamp", "status", "rating", "public", @@ -65,7 +66,10 @@ class GovernmentPlanUpdateAdmin(admin.ModelAdmin): "status", "public", ) - search_fields = ("title", "plan__title",) + search_fields = ( + "title", + "plan__title", + ) date_hierarchy = "timestamp" def get_queryset(self, request): @@ -74,8 +78,75 @@ class GovernmentPlanUpdateAdmin(admin.ModelAdmin): "plan", "user", ) + if self.has_limited_access(request.user): + qs = qs.filter(plan__in=self.get_allowed_plans(request)) return qs + def save_model(self, request, obj, form, change): + limited = self.has_limited_access(request.user) + if not change and limited: + # When added by a limited user, + # autofill user and organization + obj.user = request.user + if obj.plan.organization: + user_has_org = request.user.organization_set.all().filter(pk=1).exists() + if user_has_org: + obj.organization = obj.plan.organization + + res = super().save_model(request, obj, form, change) + + obj.plan.update_from_updates() + + return res + + def has_limited_access(self, user): + return not user.has_perm("froide_gov.change_governmentplanupdate") + + def get_allowed_plans(self, request): + if not self.has_limited_access(request.user): + return GovernmentPlan.objects.all() + groups = request.user.groups.all() + return GovernmentPlan.objects.filter(group__in=groups).distinct() + + def get_fields(self, request, obj=None): + if self.has_limited_access(request.user): + return ( + "plan", + "title", + "timestamp", + "content", + "url", + "status", + "rating", + "public", + ) + return super().get_fields(request, obj=obj) + + def formfield_for_foreignkey(self, db_field, request, **kwargs): + if db_field.name == "plan": + if self.has_limited_access(request.user): + kwargs["queryset"] = self.get_allowed_plans(request) + return super().formfield_for_foreignkey(db_field, request, **kwargs) + + def user_in_obj_group(self, request, obj): + if not obj.plan.group_id: + return False + user = request.user + return User.objects.filter(pk=user.pk, groups=obj.plan.group_id).exists() + + def has_view_permission(self, request, obj=None): + if obj and self.user_in_obj_group(request, obj): + return True + return super().has_view_permission(request, obj=obj) + + def has_add_permission(self, request): + return super().has_add_permission(request) + + def has_change_permission(self, request, obj=None): + if obj and self.user_in_obj_group(request, obj): + return True + return super().has_change_permission(request, obj=obj) + admin.site.register(Government, GovernmentAdmin) admin.site.register(GovernmentPlan, GovernmentPlanAdmin) diff --git a/froide_govplan/models.py b/froide_govplan/models.py index 466b4ee..ac325f3 100644 --- a/froide_govplan/models.py +++ b/froide_govplan/models.py @@ -109,13 +109,12 @@ class GovernmentPlan(models.Model): verbose_name_plural = _("Government plans") def __str__(self): - return 'GovernmentPlan "%s" (#%s)' % (self.title, self.pk) + return self.title def get_absolute_url(self): - return reverse("govplan:plan", kwargs={ - "gov": self.government.slug, - "plan": self.slug - }) + return reverse( + "govplan:plan", kwargs={"gov": self.government.slug, "plan": self.slug} + ) def get_absolute_domain_url(self): return settings.SITE_URL + self.get_absolute_url() @@ -123,10 +122,21 @@ class GovernmentPlan(models.Model): def get_reference_link(self): if self.reference.startswith("https://"): return self.reference - return "{}#{}".format( - self.government.planning_document, - self.reference + return "{}#{}".format(self.government.planning_document, self.reference) + + def update_from_updates(self): + last_status_update = ( + self.updates.all().filter(public=True).exclude(status="").first() ) + if last_status_update: + self.status = last_status_update.status + last_rating_update = ( + self.updates.all().filter(public=True).exclude(rating=None).first() + ) + if last_rating_update: + self.rating = last_rating_update.rating + if last_status_update or last_rating_update: + self.save() class GovernmentPlanUpdate(models.Model): @@ -161,7 +171,7 @@ class GovernmentPlanUpdate(models.Model): verbose_name_plural = _("Plan updates") def __str__(self): - return "Plan Update (%s)" % (self.pk,) + return "{} - {} ({})".format(self.title, self.timestamp, self.plan) if CMSPlugin: @@ -175,7 +185,9 @@ if CMSPlugin: CMS Plugin for displaying latest articles """ - government = models.ForeignKey(Government, null=True, blank=True, on_delete=models.SET_NULL) + government = models.ForeignKey( + Government, null=True, blank=True, on_delete=models.SET_NULL + ) categories = models.ManyToManyField( Category, verbose_name=_("categories"), blank=True ) @@ -235,9 +247,7 @@ if CMSPlugin: filters["categories__in"] = cat_list plans = plans.filter(**filters).distinct() - plans = plans.prefetch_related( - "categories", "government", "organization" - ) + plans = plans.prefetch_related("categories", "government", "organization") if self.count == 0: - return plans[self.offset:] + return plans[self.offset :] return plans[self.offset : self.offset + self.count]