Add moderation for mailing lists

This commit is contained in:
Antoine Bartuccio 2017-08-21 19:53:17 +02:00
parent fe187dae38
commit 470680e760
10 changed files with 119 additions and 24 deletions

View File

@ -58,6 +58,6 @@ def FetchMailingLists(request):
if key != settings.SITH_MAILING_FETCH_KEY:
raise PermissionDenied
data = ''
for mailing in Mailing.objects.all():
for mailing in Mailing.objects.filter(is_moderated=True).all():
data += mailing.fetch_format()
return Response(data)

View File

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('club', '0010_auto_20170817_1537'),
]
operations = [
migrations.AddField(
model_name='mailing',
name='is_moderated',
field=models.BooleanField(default=False, verbose_name='is moderated'),
),
migrations.AddField(
model_name='mailing',
name='moderator',
field=models.ForeignKey(related_name='moderated_mailings', to=settings.AUTH_USER_MODEL, null=True, verbose_name='moderator'),
),
]

View File

@ -27,12 +27,12 @@ from django.db import models
from django.core import validators
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ValidationError
from django.core.exceptions import ValidationError, ObjectDoesNotExist
from django.db import transaction
from django.core.urlresolvers import reverse
from django.utils import timezone
from core.models import User, MetaGroup, Group, SithFile
from core.models import User, MetaGroup, Group, SithFile, RealGroup, Notification
# Create your models here.
@ -230,12 +230,19 @@ class Mailing(models.Model):
"""
club = models.ForeignKey(Club, verbose_name=_('Club'), related_name="mailings", null=False, blank=False)
email = models.EmailField(_('Email address'), unique=True)
is_moderated = models.BooleanField(_('is moderated'), default=False)
moderator = models.ForeignKey(User, related_name="moderated_mailings", verbose_name=_("moderator"), null=True)
def clean(self):
if '@' + settings.SITH_MAILING_DOMAIN not in self.email:
raise ValidationError(_('Unothorized mailing domain'))
if self.can_moderate(self.moderator):
self.is_moderated = True
else:
self.moderator = None
super(Mailing, self).clean()
def can_moderate(self, user):
return user.is_root or user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID)
def is_owned_by(self, user):
return user.is_in_group(self) or user.is_root or user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID)
@ -256,6 +263,13 @@ class Mailing(models.Model):
resp += sub.fetch_format()
return resp
def save(self):
if not self.is_moderated:
for user in RealGroup.objects.filter(id=settings.SITH_GROUP_COM_ADMIN_ID).first().users.all():
if not user.notifications.filter(type="MAILING_MODERATION", viewed=False).exists():
Notification(user=user, url=reverse('com:mailing_admin'), type="MAILING_MODERATION").save()
super(Mailing, self).save()
def __str__(self):
return "%s - %s" % (self.club, self.email)
@ -274,10 +288,13 @@ class MailingSubscription(models.Model):
def clean(self):
if not self.user and not self.email:
raise ValidationError(_("At least user or email is required"))
try:
if self.user and not self.email:
self.email = self.user.email
if MailingSubscription.objects.filter(mailing=self.mailing, email=self.email).exists():
raise ValidationError(_("This email is already suscribed in this mailing"))
except ObjectDoesNotExist:
pass
super(MailingSubscription, self).clean()
def is_owned_by(self, user):

View File

@ -7,9 +7,10 @@
{% block content %}
{% if has_objects %}
{% trans %}Remember : mailing lists need to be validated by the school to work, please inform us about any new mailing list created{% endtrans %}
<b>{% trans %}Remember : mailing lists need to be moderated, if your new created list is not shown wait until moderation takes action{% endtrans %}</b>
{% for mailing in object_list %}
{% if mailing.is_moderated %}
<h2>{% trans %}Mailing{% endtrans %} {{ mailing.email }}
{%- if user.is_owner(mailing) -%}
<a href="{{ url('club:mailing_delete', mailing_id=mailing.id) }}"> - {% trans %}Delete{% endtrans %}</a>
@ -33,6 +34,7 @@
</tr>
{% endfor %}
</table>
{% endif %}
{% endfor %}
{% else %}

View File

@ -43,6 +43,7 @@ from core.views.forms import SelectDate, SelectDateTime
from club.models import Club, Membership, Mailing, MailingSubscription
from sith.settings import SITH_MAXIMUM_FREE_ROLE
from counter.models import Selling, Counter
from core.models import User
from django.conf import settings
@ -52,7 +53,7 @@ from django.conf import settings
class MailingForm(forms.ModelForm):
class Meta:
model = Mailing
fields = ('email', 'club')
fields = ('email', 'club', 'moderator')
email = forms.CharField(
label=_('Email address'),
@ -66,11 +67,16 @@ class MailingForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
club_id = kwargs.pop('club_id', None)
user_id = kwargs.pop('user_id', -1) # Remember 0 is treated as None
super(MailingForm, self).__init__(*args, **kwargs)
if club_id:
self.fields['club'].queryset = Club.objects.filter(id=club_id)
self.fields['club'].initial = club_id
self.fields['club'].widget = forms.HiddenInput()
if user_id >= 0:
self.fields['moderator'].queryset = User.objects.filter(id=user_id)
self.fields['moderator'].initial = user_id
self.fields['moderator'].widget = forms.HiddenInput()
def clean(self):
cleaned_data = super(MailingForm, self).clean()
@ -85,11 +91,12 @@ class MailingSubscriptionForm(forms.ModelForm):
fields = ('mailing', 'user', 'email')
def __init__(self, *args, **kwargs):
kwargs.pop('user_id', None) # For standart interface
club_id = kwargs.pop('club_id', None)
super(MailingSubscriptionForm, self).__init__(*args, **kwargs)
self.fields['email'].required = False
if club_id:
self.fields['mailing'].queryset = Mailing.objects.filter(club__id=club_id)
self.fields['mailing'].queryset = Mailing.objects.filter(club__id=club_id, is_moderated=True)
user = AutoCompleteSelectField('users', label=_('User'), help_text=None, required=False)
@ -419,7 +426,7 @@ class ClubMailingView(ClubTabsMixin, ListView):
if not self.authorized():
raise PermissionDenied
self.member_form = MailingSubscriptionForm(club_id=self.club.id)
self.mailing_form = MailingForm(club_id=self.club.id)
self.mailing_form = MailingForm(club_id=self.club.id, user_id=self.user.id)
return super(ClubMailingView, self).dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
@ -464,6 +471,7 @@ class MailingGenericCreateView(CreateView, SingleObjectMixin):
def get_form_kwargs(self):
kwargs = super(MailingGenericCreateView, self).get_form_kwargs()
kwargs['club_id'] = self.list_view.club.id
kwargs['user_id'] = self.list_view.user.id
return kwargs
def dispatch(self, request, *args, **kwargs):
@ -481,12 +489,16 @@ class MailingDeleteView(CanEditMixin, DeleteView):
model = Mailing
template_name = 'core/delete_confirm.jinja'
pk_url_kwarg = "mailing_id"
redirect_page = None
def dispatch(self, request, *args, **kwargs):
self.club_id = self.get_object().club.id
return super(MailingDeleteView, self).dispatch(request, *args, **kwargs)
def get_success_url(self, **kwargs):
if self.redirect_page:
return reverse_lazy(self.redirect_page)
else:
return reverse_lazy('club:mailing', kwargs={'club_id': self.club_id})

View File

@ -4,22 +4,37 @@
{% trans %}Mailing lists administration{% endtrans %}
{% endblock %}
{% block content %}
<h1>{% trans %}This page lists all existing mailing lists{% endtrans %}</h1>
{% if has_objects %}
{% macro display_mailings(list) %}
<table>
<tr>
<th>{% trans %}Email{% endtrans %}</th>
<th>{% trans %}Club{%endtrans%}</th>
<th>{% trans %}Actions{% endtrans %}</th>
</tr>
{% for mailing in object_list %}
{% for mailing in list %}
<tr>
<td>{{ mailing.email }}</td>
<td><a href="{{ url('club:mailing', club_id=mailing.club.id) }}">{{ mailing.club }}</a> <a href="{{ url('club:mailing_delete', mailing_id=mailing.id) }}">{% trans %}Delete{% endtrans %}</a></td>
<td><a href="{{ url('club:mailing', club_id=mailing.club.id) }}">{{ mailing.club }}</a></td>
<td>
<a href="{{ url('com:mailing_delete', mailing_id=mailing.id) }}">{% trans %}Delete{% endtrans %}</a> - {% if not mailing.is_moderated %}<a href="{{ url('com:mailing_moderate', mailing_id=mailing.id) }}">{% trans %}Moderate{% endtrans %}</a>{% else %}{% trans user=mailing.moderator %}Moderated by {{ user }}{% endtrans %}{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% endmacro %}
{% block content %}
<h1>{% trans %}This page lists all mailing lists{% endtrans %}</h1>
{% if has_unmoderated %}
<h2>{% trans %}Not moderated mailing lists{% endtrans %}</h2>
{{ display_mailings(unmoderated) }}
{% endif %}
<h2>{% trans %}Moderated mailing lists{% endtrans %}</h2>
{% if has_moderated %}
{{ display_mailings(moderated) }}
{% else %}
<p>{% trans %}No mailing list existing{% endtrans %}</p>
{% endif %}

View File

@ -25,6 +25,7 @@
from django.conf.urls import url
from com.views import *
from club.views import MailingDeleteView
urlpatterns = [
url(r'^sith/edit/alert$', AlertMsgEditView.as_view(), name='alert_edit'),
@ -43,5 +44,7 @@ urlpatterns = [
url(r'^news/(?P<news_id>[0-9]+)/edit$', NewsEditView.as_view(), name='news_edit'),
url(r'^news/(?P<news_id>[0-9]+)$', NewsDetailView.as_view(), name='news_detail'),
url(r'^mailings$', MailingListAdminView.as_view(), name='mailing_admin'),
url(r'^mailings/(?P<mailing_id>[0-9]+)/moderate$', MailingModerateView.as_view(), name='mailing_moderate'),
url(r'^mailings/(?P<mailing_id>[0-9]+)/delete$', MailingDeleteView.as_view(redirect_page='com:mailing_admin'), name='mailing_delete'),
]

View File

@ -25,7 +25,7 @@
from django.shortcuts import redirect, get_object_or_404
from django.http import HttpResponseRedirect
from django.views.generic import ListView, DetailView
from django.views.generic import ListView, DetailView, View
from django.views.generic.edit import UpdateView, CreateView, DeleteView
from django.views.generic.detail import SingleObjectMixin
from django.utils.translation import ugettext_lazy as _
@ -429,11 +429,27 @@ class MailingListAdminView(ComTabsMixin, ListView):
current_tab = "mailings"
def dispatch(self, request, *args, **kwargs):
if not request.user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) or request.user.is_root:
if not (request.user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) or request.user.is_root):
raise PermissionDenied
return super(MailingListAdminView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
kwargs = super(MailingListAdminView, self).get_context_data(**kwargs)
kwargs['has_objects'] = len(kwargs['object_list']) > 0
kwargs['moderated'] = self.get_queryset().filter(is_moderated=True).all()
kwargs['unmoderated'] = self.get_queryset().filter(is_moderated=False).all()
kwargs['has_moderated'] = len(kwargs['moderated']) > 0
kwargs['has_unmoderated'] = len(kwargs['unmoderated']) > 0
return kwargs
class MailingModerateView(View):
def get(self, request, *args, **kwargs):
mailing = get_object_or_404(Mailing, pk=kwargs['mailing_id'])
if mailing.can_moderate(request.user):
mailing.is_moderated = True
mailing.moderator = request.user
mailing.save()
return redirect('com:mailing_admin')
raise PermissionDenied

View File

@ -1346,6 +1346,8 @@ def migrate_mailings():
SELECT * FROM mailing
""")
moderator = User.objects.get(id=0)
for mailing in cur:
club = Club.objects.filter(id=mailing['id_asso_parent'])
if club.exists():
@ -1353,7 +1355,8 @@ def migrate_mailings():
club = club.first()
if mailing['nom']:
mailing['nom'] = '.' + mailing['nom']
Mailing(id=mailing['id_mailing'], club=club, email=to_unicode(club.unix_name + mailing['nom'] + '@utbm.fr')).save()
Mailing(id=mailing['id_mailing'], club=club, email=to_unicode(club.unix_name + mailing['nom'] + '@utbm.fr'),
moderator=moderator, is_moderated=(mailing['is_valid'] > 0)).save()
print("-------------------")
cur.execute("""

View File

@ -543,6 +543,7 @@ SITH_LAUNDERETTE_PRICES = {
}
SITH_NOTIFICATIONS = [
('MAILING_MODERATION', _("A new mailing list neet to be moderated")),
('NEWS_MODERATION', _("A fresh new to be moderated")),
('FILE_MODERATION', _("New files to be moderated")),
('SAS_MODERATION', _("New pictures/album to be moderated in the SAS")),