Merge branch 'small' into 'master'
[mailman-postorious.git] / src / postorius / views / generic.py
blob02406f2a1e2641600bdcb783f04ba5f36c3343b0
1 # -*- coding: utf-8 -*-
2 # Copyright (C) 1998-2022 by the Free Software Foundation, Inc.
4 # This file is part of Postorius.
6 # Postorius is free software: you can redistribute it and/or modify it under
7 # the terms of the GNU General Public License as published by the Free
8 # Software Foundation, either version 3 of the License, or (at your option)
9 # any later version.
11 # Postorius is distributed in the hope that it will be useful, but WITHOUT
12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 # more details.
16 # You should have received a copy of the GNU General Public License along with
17 # Postorius. If not, see <http://www.gnu.org/licenses/>.
20 from urllib.error import HTTPError
22 from django.contrib import messages
23 from django.http import HttpResponse
24 from django.shortcuts import redirect, render
25 from django.urls import reverse
26 from django.utils.translation import gettext as _
27 from django.views.generic import TemplateView
29 from django_mailman3.lib.mailman import get_mailman_client
30 from django_mailman3.lib.paginator import paginate
32 from postorius.auth.utils import set_list_access_props
33 from postorius.forms import AddBanForm
34 from postorius.models import List
37 class MailmanClientMixin(object):
39 """Adds a mailmanclient.Client instance."""
41 def client(self):
42 if getattr(self, '_client', None) is None:
43 self._client = get_mailman_client()
44 return self._client
47 class MailingListView(TemplateView, MailmanClientMixin):
49 """A generic view for everything based on a mailman.client
50 list object.
52 Sets self.mailing_list to list object if list_id is in **kwargs.
53 """
54 def get(self, request, *args, **kwargs):
55 # This should be overridden by the subclass.
56 return HttpResponse(status=405)
58 def post(self, request, *args, **kwargs):
59 # This should be overridden by the subclass.
60 return HttpResponse(status=405)
62 def _get_list(self, list_id, page):
63 return List.objects.get_or_404(fqdn_listname=list_id)
65 def dispatch(self, request, *args, **kwargs):
66 # get the list object.
67 if 'list_id' in kwargs:
68 self.mailing_list = self._get_list(kwargs['list_id'],
69 int(kwargs.get('page', 1)))
70 set_list_access_props(request.user, self.mailing_list)
71 # set the template
72 if 'template' in kwargs:
73 self.template = kwargs['template']
74 return super(MailingListView, self).dispatch(request, *args, **kwargs)
76 def _has_pending_unsub_req(self, email):
77 """Check if there is a pending unsubscription request for email."""
78 for req in self.mailing_list.get_requests(
79 token_owner='moderator', request_type='unsubscription'):
80 if req.get('email') == email:
81 return req
82 return False
85 def bans_view(request, template, list_id=None):
86 """Ban or unban email addresses.
88 This is a reusable view which works for both global and list specific bans.
89 Whether a MailingList ban is updated or a Global one depends on list_id
90 being passed in.
92 :list_id: MailingList Id if this is a List ban, None otherwise.
94 """
95 if list_id:
96 m_list = List.objects.get_or_404(fqdn_listname=list_id)
97 url = reverse('list_bans', args=[list_id])
98 ban_list = m_list.bans
99 else:
100 ban_list = get_mailman_client().bans
101 url = reverse('global_bans')
102 m_list = None
104 # Process form submission.
105 if request.method == 'POST':
106 if 'add' in request.POST:
107 addban_form = AddBanForm(request.POST)
108 if addban_form.is_valid():
109 try:
110 ban_list.add(addban_form.cleaned_data['email'])
111 messages.success(request, _(
112 'The email {} has been banned.').format(
113 addban_form.cleaned_data['email']))
114 except HTTPError as e:
115 messages.error(
116 request, _('An error occurred: %s') % e.reason)
117 except ValueError as e:
118 messages.error(request, _('Invalid data: %s') % e)
119 return redirect(url)
120 elif 'del' in request.POST:
121 try:
122 ban_list.remove(request.POST['email'])
123 messages.success(request, _(
124 'The email {} has been un-banned').format(
125 request.POST['email']))
126 except HTTPError as e:
127 messages.error(request, _('An error occurred: %s') % e.reason)
128 except ValueError as e:
129 messages.error(request, _('Invalid data: %s') % e)
130 return redirect(url)
131 else:
132 addban_form = AddBanForm(initial=request.GET)
133 banned_addresses = paginate(
134 list(ban_list), request.GET.get('page'), request.GET.get('count'))
136 context = {
137 'addban_form': addban_form,
138 'banned_addresses': banned_addresses,
141 if list_id:
142 context['list'] = m_list
144 return render(request, template, context)