welco/welco/sources/mail/views.py

196 lines
7.0 KiB
Python

# welco - multichannel request processing
# Copyright (C) 2018 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import json
import logging
from django import template
from django.contrib.auth.decorators import login_required
from django.contrib.contenttypes.models import ContentType
from django.contrib import messages
from django.urls import reverse
from django.template import RequestContext
from django.http import HttpResponse, HttpResponseRedirect
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import TemplateView
from django.db.transaction import atomic
from rest_framework import authentication, serializers, permissions, status
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from welco.utils import response_for_json
from .models import Mail
from .forms import MailQualificationForm
from .utils import get_maarch, MaarchError
logger = logging.getLogger(__name__)
def viewer(request, *args, **kwargs):
if not 'file' in request.GET:
return HttpResponseRedirect('?file=')
body = template.loader.get_template('welco/mail_viewer.html').render(
request=request)
return HttpResponse(body)
class Feeder(TemplateView):
template_name = 'welco/mail_feeder.html'
def post(self, request):
for upload in request.FILES.getlist('mail'):
mail = Mail(content=upload)
mail.save()
messages.info(request, _('%d files uploaded successfully.') %
len(request.FILES.getlist('mail')))
return HttpResponseRedirect(reverse('mail-feeder'))
feeder = login_required(csrf_exempt(Feeder.as_view()))
class Home(object):
source_key = 'mail'
display_filter = True
allow_reject = True
def __init__(self, request, **kwargs):
self.request = request
self.kwargs = kwargs
def get_queryset(self):
return Mail.objects.exclude(status__startswith='done-')
def get_template(self):
return 'welco/mail_home.html'
def render(self):
context = {}
context['mails'] = self.get_queryset().order_by('creation_timestamp')
context['source_type'] = ContentType.objects.get_for_model(Mail)
context['form'] = MailQualificationForm()
context['source_form_url'] = Mail.get_qualification_form_submit_url()
if self.allow_reject:
context['reject_url'] = reverse('mail-reject')
context['display_filter'] = self.display_filter
tmpl = template.loader.get_template(self.get_template())
return tmpl.render(context, request=self.request)
@csrf_exempt
def qualification_save(request, *args, **kwargs):
mail = Mail.objects.get(id=request.POST['source_pk'])
form = MailQualificationForm(request.POST)
if form.is_valid():
mail.post_date = form.cleaned_data['post_date']
mail.registered_mail_number = form.cleaned_data['registered_mail_number']
mail.reference = form.cleaned_data['reference']
mail.subject = form.cleaned_data['subject']
mail.save()
return HttpResponseRedirect(reverse('qualif-zone') +
'?source_type=%s&source_pk=%s' % (request.POST['source_type'],
request.POST['source_pk']))
class EditNote(TemplateView):
template_name = 'welco/mail_edit_note.html'
def get_context_data(self, **kwargs):
context = super(EditNote, self).get_context_data(**kwargs)
context['mail'] = Mail.objects.get(id=self.request.GET['mail'])
return context
def post(self, request, *args, **kwargs):
mail = Mail.objects.get(id=self.request.GET['mail'])
mail.note = self.request.POST['note']
mail.save()
return HttpResponse(json.dumps({'result': 'ok'}))
edit_note = login_required(csrf_exempt(EditNote.as_view()))
@login_required
def note(request, *args, **kwargs):
mail = Mail.objects.get(id=kwargs['pk'])
if not mail.note:
mail.note = '+'
return HttpResponse(mail.html_note())
@login_required
@csrf_exempt
def reject(request, *args, **kwargs):
maarch = get_maarch()
mail = Mail.objects.filter(id=request.POST['source_pk']).first()
if mail:
try:
with atomic():
if maarch and mail.external_id and mail.external_id.startswith('maarch-'):
mail_pk = mail.external_id.split('-', 1)[1]
maarch.set_grc_refused_status(mail_pk)
mail.delete()
except Exception:
logger.exception('rejection request to maarch failed')
messages.error(request, _('Rejection request to Maarch failed'))
return HttpResponse()
@login_required
def mail_count(request, *args, **kwargs):
count = Mail.objects.exclude(status__startswith='done-').count()
return response_for_json(request, {'count': count})
class NotificationSerializer(serializers.Serializer):
mail_id = serializers.CharField()
content = serializers.CharField()
class MailResponseAPIView(GenericAPIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = NotificationSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
if not serializer.is_valid():
response = {'err': 1, 'err_desc': serializer.errors}
return Response(response, status.HTTP_400_BAD_REQUEST)
mail_id = serializer.validated_data['mail_id']
content = serializer.validated_data['content']
# for now, we only support maarch
if not mail_id.startswith('maarch-'):
response = {'err': 1, 'err_desc': 'only maarch is supported'}
return Response(response)
mail = Mail.objects.filter(external_id=mail_id).first()
if not mail:
response = {'err': 1, 'err_desc': 'unknown mail_id'}
return Response(response, status.HTTP_404_NOT_FOUND)
return self.maarch_response(mail, content)
def maarch_response(self, mail, content):
maarch = get_maarch()
if not maarch:
return Response({'err': 1, 'err_desc': 'maarch is unconfigured'})
mail_pk = int(mail.external_id.split('-', 1)[1])
try:
maarch.set_grc_response_status(mail_pk, content)
except MaarchError as e:
return Response({'err': 1, 'err_desc': str(e)})
return Response({'err': 0})
mail_response = MailResponseAPIView.as_view()