From 973437f923735b55bf825777e067a4b48e88a612 Mon Sep 17 00:00:00 2001 From: Oliver Falk Date: Fri, 13 Jul 2018 12:23:58 +0200 Subject: [PATCH] Add extra page after libravatar export upload, where user can choose what to import --- ivatar/ivataraccount/forms.py | 40 --------- .../ivataraccount/read_libravatar_export.py | 10 ++- .../templates/choose_libravatar_export.html | 40 +++++++++ ivatar/ivataraccount/urls.py | 2 + ivatar/ivataraccount/views.py | 85 ++++++++++++++++--- 5 files changed, 122 insertions(+), 55 deletions(-) create mode 100644 ivatar/ivataraccount/templates/choose_libravatar_export.html diff --git a/ivatar/ivataraccount/forms.py b/ivatar/ivataraccount/forms.py index ad82553..051b4f7 100644 --- a/ivatar/ivataraccount/forms.py +++ b/ivatar/ivataraccount/forms.py @@ -209,43 +209,3 @@ class UploadLibravatarExportForm(forms.Form): _('This field must be checked since we need to be able to\ distribute photos to third parties.') }) - - @staticmethod - def save(request, data): - ''' - Save the models and assign it to the current user - ''' - items = libravatar_read_gzdata(data.read()) - for email in items['emails']: - if not ConfirmedEmail.objects.filter(email=email) and \ - not UnconfirmedEmail.objects.filter(email=email): # pylint: disable=no-member - try: - unconfirmed = UnconfirmedEmail.objects.create( # pylint: disable=no-member - user=request.user, - email=email - ) - unconfirmed.save() - unconfirmed.send_confirmation_mail(url=request.build_absolute_uri('/')[:-1]) - except Exception as e: # pylint: disable=broad-except,invalid-name - # Debugging only - print('Exception while trying to import mail addresses: %s' % e) - if 'openids' in items: - messages.warning( - request, - _('You have OpenIDs in your export file, but we cannot\ - import those at the moment')) - - for pilobj in items['photos']: - # Is there a reasonable way to check if that photo already exists!? - try: - data = BytesIO() - pilobj.save(data, pilobj.format, quality=JPEG_QUALITY) - data.seek(0) - photo = Photo() - photo.user = request.user - photo.ip_address = get_client_ip(request)[0] - photo.format = file_format(pilobj.format) - photo.data = data.read() - photo.save() - except Exception: # pylint: disable=broad-except - pass diff --git a/ivatar/ivataraccount/read_libravatar_export.py b/ivatar/ivataraccount/read_libravatar_export.py index 775bb5f..b99f11d 100644 --- a/ivatar/ivataraccount/read_libravatar_export.py +++ b/ivatar/ivataraccount/read_libravatar_export.py @@ -49,14 +49,18 @@ def read_gzdata(gzdata=None): photo.attrib['encoding'], photo.attrib['format'], e)) continue try: - img = Image.open(BytesIO(data)) + Image.open(BytesIO(data)) + # If it is a working image, we can use it + photo.text.replace('\n', '') + photos.append({ + 'data': photo.text, + 'format': photo.attrib['format'], + }) except Exception as e: # pylint: disable=broad-except,invalid-name print('Cannot decode photo; Encoding: %s, Format: %s: %s' % ( photo.attrib['encoding'], photo.attrib['format'], e)) continue - photos.append(img) - return { 'emails': emails, 'openids': openids, diff --git a/ivatar/ivataraccount/templates/choose_libravatar_export.html b/ivatar/ivataraccount/templates/choose_libravatar_export.html new file mode 100644 index 0000000..cbc5f9d --- /dev/null +++ b/ivatar/ivataraccount/templates/choose_libravatar_export.html @@ -0,0 +1,40 @@ +{% extends 'base.html' %} +{% load i18n %} +{% load static %} +{% load bootstrap4 %} + +{% block title %}{% trans 'Choose items to be uploaded' %}{% endblock title %} + +{% block content %} +

{% trans 'Choose items to be imported' %}

+ +
+
{% csrf_token %} + {% if emails %} +

+ {% trans 'Email addresses we found in the export - existing ones will not be re-added' %}: +

+ {% for email in emails %} + {{ email }}
+ {% endfor %} + {% endif %} +

+ {% if photos %} +

+ {% trans 'Photos we found in the export' %}: +

+ {% for photo in photos %} + + + +
+ {% endfor %} + {% endif %} +
+ {% buttons %} + + + {% endbuttons %} +
+
+{% endblock content %} diff --git a/ivatar/ivataraccount/urls.py b/ivatar/ivataraccount/urls.py index cd6c901..5e2f1b2 100644 --- a/ivatar/ivataraccount/urls.py +++ b/ivatar/ivataraccount/urls.py @@ -85,4 +85,6 @@ urlpatterns = [ # pylint: disable=invalid-name url(r'crop_photo/(?P\d+)', CropPhotoView.as_view(), name='crop_photo'), url(r'pref/$', UserPreferenceView.as_view(), name='user_preference'), url(r'upload_export/$', UploadLibravatarExportView.as_view(), name='upload_export'), + url(r'upload_export/(?Psave)$', + UploadLibravatarExportView.as_view(), name='upload_export'), ] diff --git a/ivatar/ivataraccount/views.py b/ivatar/ivataraccount/views.py index 9b94dec..4c18447 100644 --- a/ivatar/ivataraccount/views.py +++ b/ivatar/ivataraccount/views.py @@ -1,8 +1,11 @@ ''' View classes for ivatar/ivataraccount/ ''' -import io +from io import BytesIO from urllib.request import urlopen +import base64 + +from PIL import Image from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User @@ -20,22 +23,22 @@ from django.urls import reverse_lazy, reverse from django.shortcuts import render from django_openid_auth.models import UserOpenID -from django_openid_auth.models import UserOpenID from openid import oidutil from openid.consumer import consumer from ipware import get_client_ip from libravatar import libravatar_url +from ivatar.settings import MAX_NUM_PHOTOS, MAX_PHOTO_SIZE, JPEG_QUALITY from .gravatar import get_photo as get_gravatar_photo -from ivatar.settings import MAX_NUM_PHOTOS, MAX_PHOTO_SIZE - from .forms import AddEmailForm, UploadPhotoForm, AddOpenIDForm from .forms import UpdatePreferenceForm, UploadLibravatarExportForm from .models import UnconfirmedEmail, ConfirmedEmail, Photo from .models import UnconfirmedOpenId, ConfirmedOpenId, DjangoOpenIDStore from .models import UserPreference +from .models import file_format +from . read_libravatar_export import read_gzdata as libravatar_read_gzdata def openid_logging(message, level=0): @@ -295,7 +298,7 @@ class ImportPhotoView(SuccessMessageMixin, TemplateView): if 'email_id' in kwargs: try: addr = ConfirmedEmail.objects.get(pk=kwargs['email_id']).email - except: + except Exception: # pylint: disable=broad-except messages.error( self.request, _('Address does not exist')) @@ -315,7 +318,8 @@ class ImportPhotoView(SuccessMessageMixin, TemplateView): ) try: if libravatar_service_url: - response = urlopen(libravatar_service_url) + # if it doesn't work, it will be catched by except + urlopen(libravatar_service_url) context['photos'].append({ 'service_url': libravatar_service_url, 'thumbnail_url': libravatar_service_url + '?s=80', @@ -324,12 +328,13 @@ class ImportPhotoView(SuccessMessageMixin, TemplateView): 'height': 80, 'service_name': 'Libravatar', }) - except Exception: + except Exception as e: # pylint: disable=broad-except,invalid-name + print('Exception caught during photo import: %s' % e) pass return context - def post(self, request, *args, **kwargs): # pylint: disable=no-self-use,unused-argument + def post(self, request, *args, **kwargs): # pylint: disable=no-self-use,unused-argument,too-many-branches ''' Handle post to photo import ''' @@ -400,7 +405,7 @@ class RawImageView(DetailView): def get(self, request, *args, **kwargs): photo = self.model.objects.get(pk=kwargs['pk']) # pylint: disable=no-member return HttpResponse( - io.BytesIO(photo.data), content_type='image/%s' % photo.format) + BytesIO(photo.data), content_type='image/%s' % photo.format) @method_decorator(login_required, name='dispatch') @@ -717,8 +722,64 @@ class UploadLibravatarExportView(SuccessMessageMixin, FormView): success_url = reverse_lazy('profile') model = User + def post(self, request, *args, **kwargs): # pylint: disable=unused-argument + ''' + Handle post request - choose items to import + ''' + if 'save' in kwargs: # pylint: disable=too-many-nested-blocks + if kwargs['save'] == 'save': + for arg in request.POST: + if arg.startswith('email_'): + email = request.POST[arg] + if not ConfirmedEmail.objects.filter(email=email) and \ + not UnconfirmedEmail.objects.filter(email=email): # pylint: disable=no-member + try: + unconfirmed = UnconfirmedEmail.objects.create( # pylint: disable=no-member + user=request.user, + email=email + ) + unconfirmed.save() + unconfirmed.send_confirmation_mail( + url=request.build_absolute_uri('/')[:-1]) + messages.info( + request, + '%s: %s' %( + email, + _('address added successfully,\ + confirmation mail sent'))) + except Exception as e: # pylint: disable=broad-except,invalid-name + # DEBUG + print('Exception during adding mail address (%s): %s' % (email, e)) + + if arg.startswith('photo'): + try: + data = base64.decodebytes(bytes(request.POST[arg], 'utf-8')) + except Exception as e: # pylint: disable=broad-except,invalid-name + print('Cannot decode photo: %s' % e) + continue + try: + pilobj = Image.open(BytesIO(data)) + out = BytesIO() + pilobj.save(out, pilobj.format, quality=JPEG_QUALITY) + out.seek(0) + photo = Photo() + photo.user = request.user + photo.ip_address = get_client_ip(request)[0] + photo.format = file_format(pilobj.format) + photo.data = out.read() + photo.save() + except Exception as e: # pylint: disable=broad-except,invalid-name + print('Exception during save: %s' % e) + continue + + return HttpResponseRedirect(reverse_lazy('profile')) + return super().post(request, args, kwargs) + def form_valid(self, form): data = self.request.FILES['export_file'] - - form.save(self.request, data) - return super().form_valid(form) + items = libravatar_read_gzdata(data.read()) + # DEBUG print(items) + return render(self.request, 'choose_libravatar_export.html', { + 'emails': items['emails'], + 'photos': items['photos'], + })