Commit a81b6315 authored by Joost Rijneveld's avatar Joost Rijneveld
Browse files

Merge branch 'feature/mailinglist-json-api' into 'master'

Mailinglist JSON API

Closes #29 and #475

See merge request !545
parents a8052126 ce074154
import hashlib
from rest_framework import permissions
class MailingListPermission(permissions.BasePermission):
Permission check for mailing list secret key
def has_permission(self, request, view):
if request.user.is_superuser:
return True
if 'secret' in request.GET:
apihash = hashlib.sha1(request.GET['secret']
return apihash == '356a192b7913b04c54574d18c28d46e6395428ab'
return False
from rest_framework import serializers
from mailinglists.models import MailingList
class MailingListSerializer(serializers.ModelSerializer):
class Meta:
model = MailingList
fields = ('names', 'prefix', 'archived', 'moderated', 'addresses')
names = serializers.SerializerMethodField('_names')
addresses = serializers.SerializerMethodField('_addresses')
def _names(self, instance):
return [] + [x.alias for x in instance.aliasses.all()]
def _addresses(self, instance):
return instance.all_addresses()
from rest_framework import routers
from mailinglists.api import viewsets
router = routers.SimpleRouter()
router.register(r'mailinglists', viewsets.MailingListViewset)
urlpatterns = router.urls
from rest_framework import viewsets
from mailinglists import services
from mailinglists.api.permissions import MailingListPermission
from mailinglists.api.serializers import MailingListSerializer
from mailinglists.models import MailingList
class MailingListViewset(viewsets.ReadOnlyModelViewSet):
permission_classes = [MailingListPermission]
queryset = MailingList.objects.all()
serializer_class = MailingListSerializer
def list(self, request, *args, **kwargs):
response = super().list(request, *args, **kwargs)
automatic_lists = services.get_automatic_lists()
if automatic_lists is not None: = list( + automatic_lists
return response
from django.contrib.auth.models import User
from django.utils import timezone
from activemembers.models import CommitteeMembership, Mentorship
from members.models import Member
from thaliawebsite.settings import settings
from utils.snippets import datetime_to_lectureyear
def get_automatic_lists():
memberships = (CommitteeMembership.active_memberships
committee_chairs = [x.member for x in memberships] + [Member(
active_committee_memberships = (CommitteeMembership.active_memberships
active_members = [x.member for x in active_committee_memberships]
active_mentorships = Mentorship.objects.filter(
mentors = [x.member for x in active_mentorships]
lists = []
lists += _create_automatic_list(
['leden', 'members'], '[THALIA]',
Member.all_with_membership('member', 'user'), True, True, True)
lists += _create_automatic_list(
['begunstigers', 'supporters'], '[THALIA]', Member.all_with_membership(
'supporter', 'user'), multilingual=True)
lists += _create_automatic_list(
['ereleden', 'honorary'], '[THALIA]', Member.all_with_membership(
'honorary', 'user'), multilingual=True)
lists += _create_automatic_list(
['mentors'], '[THALIA] [MENTORS]', mentors, moderated=False)
lists += _create_automatic_list(
['activemembers'], '[THALIA] [COMMITTEES]',
lists += _create_automatic_list(
['commissievoorzitters', 'committeechairs'], '[THALIA] [CHAIRS]',
committee_chairs, moderated=False)
lists += _create_automatic_list(
['optin'], '[THALIA] [OPTIN]', Member.active_members.filter(
return lists
def _create_automatic_list(names, prefix, members,
archived=True, moderated=True, multilingual=False):
data = {
'names': names,
'prefix': prefix,
'archived': archived,
'moderated': moderated,
if multilingual:
data['addresses'] = [ for member in members]
yield data # this is the complete list, e.g. leden@
for language in settings.LANGUAGES:
localized_data = data.copy()
localized_data['addresses'] = [ for member in members
if member.language == language[0]]
localized_data['names'] = [
'{}-{}'.format(n, language[0]) for n in names]
yield localized_data # these are localized lists, e.g. leden-nl@
data['addresses'] = [ for member in members]
yield data
from django.conf.urls import include, url
from . import views
app_name = "mailinglists"
urlpatterns = [
url('^', views.index, name='index'),
import hashlib
from django.core.exceptions import PermissionDenied
from django.http import Http404
from django.shortcuts import get_object_or_404, render
from activemembers.models import CommitteeMembership
from members.models import Member
from .models import MailingList
# Consider replacing this completely;
# - either by a cronjob Python script that queries the database directly
# - or by a __save__ handler that updates mailman when MailingList changes
# - or at least by a more nicely separated API with less GET variables
# see issue #29
def index(request):
if 'apikey' not in request.GET:
raise PermissionDenied
apihash = hashlib.sha1(request.GET['apikey'].encode('utf-8')).hexdigest()
if apihash != 'cb004452d9c80e295bebfc778871b3b082d70ad8':
raise PermissionDenied
if 'lists' in request.GET:
context = {'lists': MailingList.objects.all()
return render(request, 'mailinglists/lists.txt', context,
elif 'list' in request.GET:
pk = request.GET['list'].split('_') # could be id_aliasname
mailinglist = get_object_or_404(MailingList, pk=int(pk[0]))
if len(pk) > 1 and mailinglist.aliasses.filter(alias=pk[1]): = pk[1]
return render(request, 'mailinglists/list_data.txt',
{'list': mailinglist}, content_type='text/plain')
elif 'membership_type' in request.GET:
membership_type = {"Current Members": "member",
"Benefactor": "supporter",
"Honorary Member": "honorary"
members = Member.all_with_membership(membership_type, 'user')
elif 'custom' in request.GET:
if request.GET['custom'] == 'commissievoorzitters':
memberships = (CommitteeMembership.active_memberships
members = [x.member for x in memberships]
# The intern is always included; we mock an object with a .email
members += [{'user': {'email': ''}}]
elif request.GET['custom'] == 'optin':
members = (Member.objects.filter(receive_optin=True)
return render(request, 'mailinglists/custom_list.txt',
{'members': members}, content_type='text/plain')
except NameError:
raise Http404("Insufficient arguments")
......@@ -65,7 +65,6 @@ thalia_sitemap.update(events_sitemap)
urlpatterns = [
url(r'^$', TemplateView.as_view(template_name='index.html'), name='index'),
url(r'^mailinglists/', include('mailinglists.urls')),
url(r'^members/', include('members.urls')),
url(r'^account/$', members.views.account, name='account'),
url(r'^events/', include('events.urls')),
......@@ -106,6 +105,7 @@ urlpatterns = [
url(r'^', include('events.api.urls')),
url(r'^', include('members.api.urls')),
url(r'^', include('partners.api.urls')),
url(r'^', include('mailinglists.api.urls')),
], namespace='v1')),
url(r'^education/', include('education.urls')),
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment