diff --git a/newsletter/admin.py b/newsletter/admin.py index 20157f36..69cb634d 100644 --- a/newsletter/admin.py +++ b/newsletter/admin.py @@ -1,12 +1,7 @@ from __future__ import unicode_literals - -import logging -logger = logging.getLogger(__name__) - import six from django.db import models - from django.conf import settings from django.conf.urls import url @@ -50,6 +45,9 @@ from .settings import newsletter_settings +import logging +logger = logging.getLogger(__name__) + # Contsruct URL's for icons ICON_URLS = { 'yes': '%snewsletter/admin/img/icon-yes.gif' % settings.STATIC_URL, @@ -65,7 +63,19 @@ class NewsletterAdmin(admin.ModelAdmin): ) prepopulated_fields = {'slug': ('title',)} + # filter queryset by user group + def get_queryset(self, request): + qs = super(NewsletterAdmin, self).get_queryset(request) + if request.user.is_superuser: + return qs + newsqs = qs.filter( + groups__name__in=request.user.groups.values_list('name', flat=True) + ) + nogroupsqs = qs.filter(groups__isnull=True) + return newsqs | nogroupsqs + """ List extensions """ + def _admin_url(self, obj, model, text): url = reverse('admin:%s_%s_changelist' % (model._meta.app_label, model._meta.model_name), @@ -89,6 +99,7 @@ def admin_submissions(self, obj): class NewsletterAdminLinkMixin(object): + def admin_newsletter(self, obj): opts = Newsletter._meta newsletter = obj.newsletter @@ -111,7 +122,42 @@ class SubmissionAdmin(NewsletterAdminLinkMixin, ExtendibleModelAdminMixin, save_as = True filter_horizontal = ('subscriptions',) + """ restrict access by newsletter groups """ + + def get_form(self, request, *args, **kwargs): + form = super(SubmissionAdmin, self).get_form(request, *args, **kwargs) + form.current_user = request.user + return form + + def formfield_for_foreignkey(self, db_field, request, **kwargs): + if db_field.name == "message" and not request.user.is_superuser: + newsqs = Newsletter.objects.filter( + groups__name__in=request.user.groups.values_list( + 'name', flat=True) + ) + nogroupsqs = Newsletter.objects.filter(groups__isnull=True) + + kwargs["queryset"] = Message.objects.filter( + newsletter__in=(newsqs | nogroupsqs)) + return super(SubmissionAdmin, self).formfield_for_foreignkey( + db_field, request, **kwargs) + + # filter queryset by user group + + def get_queryset(self, request): + qs = super(SubmissionAdmin, self).get_queryset(request) + if request.user.is_superuser: + return qs + newsqs = Newsletter.objects.filter( + groups__name__in=request.user.groups.values_list('name', flat=True) + ) + nogroupsqs = Newsletter.objects.filter(groups__isnull=True) + listMessages = Message.objects.filter( + newsletter__in=(newsqs | nogroupsqs)) + return qs.filter(message__in=listMessages) + """ List extensions """ + def admin_message(self, obj): return format_html('{}', obj.id, obj.message.title) admin_message.short_description = _('submission') @@ -162,6 +208,7 @@ def admin_status_text(self, obj): admin_status_text.short_description = _('Status') """ Views """ + def submit(self, request, object_id): submission = self._getobj(request, object_id) @@ -181,6 +228,7 @@ def submit(self, request, object_id): return HttpResponseRedirect(changelist_url) """ URLs """ + def get_urls(self): urls = super(SubmissionAdmin, self).get_urls() @@ -247,7 +295,32 @@ class MessageAdmin(NewsletterAdminLinkMixin, ExtendibleModelAdminMixin, inlines = [ArticleInline, ] + # show only newsletter for user's groups + def formfield_for_foreignkey(self, db_field, request, **kwargs): + if db_field.name == "newsletter" and not request.user.is_superuser: + newsqs = Newsletter.objects.filter( + groups__name__in=request.user.groups.values_list( + 'name', flat=True) + ) + nogroupsqs = Newsletter.objects.filter(groups__isnull=True) + kwargs["queryset"] = newsqs | nogroupsqs + return super(MessageAdmin, self).formfield_for_foreignkey( + db_field, request, **kwargs) + + # filter queryset by user group + def get_queryset(self, request): + qs = super(MessageAdmin, self).get_queryset(request) + if request.user.is_superuser: + return qs + newsqs = Newsletter.objects.filter( + groups__name__in=request.user.groups.values_list('name', flat=True) + ) + nogroupsqs = Newsletter.objects.filter(groups__isnull=True) + + return qs.filter(newsletter__in=(newsqs | nogroupsqs)) + """ List extensions """ + def admin_title(self, obj): return format_html('{}', obj.id, obj.title) admin_title.short_description = _('message') @@ -259,6 +332,7 @@ def admin_preview(self, obj): admin_preview.short_description = '' """ Views """ + def preview(self, request, object_id): return render( request, @@ -320,6 +394,7 @@ def subscribers_json(self, request, object_id): return HttpResponse(json, content_type='application/json') """ URLs """ + def get_urls(self): urls = super(MessageAdmin, self).get_urls() @@ -366,7 +441,33 @@ class SubscriptionAdmin(NewsletterAdminLinkMixin, ExtendibleModelAdminMixin, actions = ['make_subscribed', 'make_unsubscribed'] exclude = ['unsubscribed'] + """ restrict access by newsletter groups """ + + def formfield_for_foreignkey(self, db_field, request, **kwargs): + if db_field.name == "newsletter" and not request.user.is_superuser: + newsqs = Newsletter.objects.filter( + groups__name__in=request.user.groups.values_list( + 'name', flat=True) + ) + nogroupsqs = Newsletter.objects.filter(groups__isnull=True) + kwargs["queryset"] = newsqs | nogroupsqs + return super(SubscriptionAdmin, self).formfield_for_foreignkey( + db_field, request, **kwargs) + + # filter queryset by user group + def get_queryset(self, request): + qs = super(SubscriptionAdmin, self).get_queryset(request) + if request.user.is_superuser: + return qs + newsqs = Newsletter.objects.filter( + groups__name__in=request.user.groups.values_list('name', flat=True) + ) + nogroupsqs = Newsletter.objects.filter(groups__isnull=True) + + return qs.filter(newsletter__in=(newsqs | nogroupsqs)) + """ List extensions """ + def admin_status(self, obj): img_tag = '{}' alt_txt = self.admin_status_text(obj) @@ -403,6 +504,7 @@ def admin_unsubscribe_date(self, obj): admin_unsubscribe_date.short_description = _("unsubscribe date") """ Actions """ + def make_subscribed(self, request, queryset): rows_updated = queryset.update(subscribed=True) self.message_user( @@ -428,6 +530,7 @@ def make_unsubscribed(self, request, queryset): make_unsubscribed.short_description = _("Unsubscribe selected users") """ Views """ + def subscribers_import(self, request): if not request.user.has_perm('newsletter.add_subscription'): raise PermissionDenied() @@ -501,6 +604,7 @@ def subscribers_import_confirm(self, request): ) """ URLs """ + def get_urls(self): urls = super(SubscriptionAdmin, self).get_urls() @@ -516,13 +620,14 @@ def get_urls(self): # only used in this part of the admin. For now, leave them here. if HAS_CBV_JSCAT: my_urls.append(url(r'^jsi18n/$', - JavaScriptCatalog.as_view(packages=('newsletter',)), - name='newsletter_js18n')) + JavaScriptCatalog.as_view( + packages=('newsletter',)), + name='newsletter_js18n')) else: my_urls.append(url(r'^jsi18n/$', - javascript_catalog, - {'packages': ('newsletter',)}, - name='newsletter_js18n')) + javascript_catalog, + {'packages': ('newsletter',)}, + name='newsletter_js18n')) return my_urls + urls diff --git a/newsletter/admin_forms.py b/newsletter/admin_forms.py index 59aa0c1c..c7967ffb 100644 --- a/newsletter/admin_forms.py +++ b/newsletter/admin_forms.py @@ -148,6 +148,17 @@ class Meta: model = Submission fields = '__all__' + def __init__(self, *args, **kwargs): + super(SubmissionAdminForm, self).__init__(*args, **kwargs) + if not self.current_user.is_superuser: + newsqs = Newsletter.objects.filter( + groups__name__in=self.current_user.groups.values_list( + 'name', flat=True) + ) + nogroupsqs = Newsletter.objects.filter(groups__isnull=True) + self.fields['subscriptions'].queryset = Subscription.objects.filter( + newsletter__in=(newsqs | nogroupsqs)) + def clean_publish(self): """ Make sure only one submission can be published for each message. diff --git a/newsletter/migrations/0005_newsletter_groups.py b/newsletter/migrations/0005_newsletter_groups.py new file mode 100644 index 00000000..e2304cd9 --- /dev/null +++ b/newsletter/migrations/0005_newsletter_groups.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.16 on 2018-11-23 13:34 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0008_alter_user_username_max_length'), + ('newsletter', '0004_auto_20180407_1043'), + ] + + operations = [ + migrations.AddField( + model_name='newsletter', + name='groups', + field=models.ManyToManyField(blank=True, related_name='groups', to='auth.Group', verbose_name='Groups'), + ), + ] diff --git a/newsletter/models.py b/newsletter/models.py index 9d2a7cd4..b8d2396b 100644 --- a/newsletter/models.py +++ b/newsletter/models.py @@ -3,6 +3,7 @@ import django from django.conf import settings +from django.contrib.auth.models import Group from django.contrib.sites.models import Site from django.contrib.sites.managers import CurrentSiteManager from django.core.mail import EmailMultiAlternatives @@ -53,6 +54,11 @@ class Newsletter(models.Model): help_text=_('Whether or not to send HTML versions of e-mails.') ) + groups = models.ManyToManyField( + Group, related_name='groups', verbose_name=_('Groups'), + blank=True + ) + objects = models.Manager() # Automatically filter the current site