Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Newsletter owner groups #265

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 115 additions & 10 deletions newsletter/admin.py
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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,
Expand All @@ -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),
Expand All @@ -89,6 +99,7 @@ def admin_submissions(self, obj):


class NewsletterAdminLinkMixin(object):

def admin_newsletter(self, obj):
opts = Newsletter._meta
newsletter = obj.newsletter
Expand All @@ -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('<a href="{}/">{}</a>', obj.id, obj.message.title)
admin_message.short_description = _('submission')
Expand Down Expand Up @@ -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)

Expand All @@ -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()

Expand Down Expand Up @@ -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('<a href="{}/">{}</a>', obj.id, obj.title)
admin_title.short_description = _('message')
Expand All @@ -259,6 +332,7 @@ def admin_preview(self, obj):
admin_preview.short_description = ''

""" Views """

def preview(self, request, object_id):
return render(
request,
Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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 = '<img src="{}" width="10" height="10" alt="{}"/>'
alt_txt = self.admin_status_text(obj)
Expand Down Expand Up @@ -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(
Expand All @@ -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()
Expand Down Expand Up @@ -501,6 +604,7 @@ def subscribers_import_confirm(self, request):
)

""" URLs """

def get_urls(self):
urls = super(SubscriptionAdmin, self).get_urls()

Expand All @@ -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(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rebase on current master (this was fixed slightly different in another PR)

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

Expand Down
11 changes: 11 additions & 0 deletions newsletter/admin_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
21 changes: 21 additions & 0 deletions newsletter/migrations/0005_newsletter_groups.py
Original file line number Diff line number Diff line change
@@ -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'),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an unrelated migration - please remove it from this PR

('newsletter', '0004_auto_20180407_1043'),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please create a completely new migration based from the current master?

]

operations = [
migrations.AddField(
model_name='newsletter',
name='groups',
field=models.ManyToManyField(blank=True, related_name='groups', to='auth.Group', verbose_name='Groups'),
),
]
6 changes: 6 additions & 0 deletions newsletter/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down