diff --git a/ivatar/ivataraccount/models.py b/ivatar/ivataraccount/models.py index 12d365e..5563551 100644 --- a/ivatar/ivataraccount/models.py +++ b/ivatar/ivataraccount/models.py @@ -24,6 +24,8 @@ from openid.association import Association as OIDAssociation from openid.store import nonce as oidnonce from openid.store.interface import OpenIDStore +from libravatar import libravatar_url + from ivatar.settings import MAX_LENGTH_EMAIL, logger from ivatar.settings import MAX_PIXELS, AVATAR_MAX_SIZE, JPEG_QUALITY from ivatar.settings import MAX_LENGTH_URL @@ -128,6 +130,9 @@ class Photo(BaseAccountModel): if gravatar: image_url = gravatar['image_url'] + if service_name == 'Libravatar': + image_url = libravatar_url(email_address) + if not image_url: return False # pragma: no cover try: diff --git a/ivatar/ivataraccount/templates/_import_photo_form.html b/ivatar/ivataraccount/templates/_import_photo_form.html new file mode 100644 index 0000000..d5fcf56 --- /dev/null +++ b/ivatar/ivataraccount/templates/_import_photo_form.html @@ -0,0 +1,37 @@ +{% load i18n %} +{% load bootstrap4 %} + +{% if not user.is_anonymous %} + {% if photos %} +

{% trans 'Would you like to import some of these externally hosted photos?' %}

+ {% if email_id %} +
{% csrf_token %} + + {% else %} + {% csrf_token %} + + {% endif %} + +

+ {% buttons %} + + {% endbuttons %} +

+
+ {% endif %} +{% endif %} diff --git a/ivatar/ivataraccount/templates/assign_photo_email.html b/ivatar/ivataraccount/templates/assign_photo_email.html index d5961e7..472adbb 100644 --- a/ivatar/ivataraccount/templates/assign_photo_email.html +++ b/ivatar/ivataraccount/templates/assign_photo_email.html @@ -37,7 +37,12 @@ -

{% blocktrans %}upload a new one{% endblocktrans %}

+

+
+ {% blocktrans %}Upload a new one{% endblocktrans %} +
+ {% blocktrans %}Import from other services{% endblocktrans %} +

{% endif %} diff --git a/ivatar/ivataraccount/templates/email_confirmed.html b/ivatar/ivataraccount/templates/email_confirmed.html index 2d54ec5..8f7aec7 100644 --- a/ivatar/ivataraccount/templates/email_confirmed.html +++ b/ivatar/ivataraccount/templates/email_confirmed.html @@ -9,31 +9,8 @@

{% trans 'Your email address was successfully confirmed!' %}

-{% if not user.is_anonymous %} -{% if photos %} - -

{% trans 'Would you like to import some of these externally hosted photos?' %}

-
{% csrf_token %} - - - -

-
-{% endif %} +{% include '_import_photo_form.html' %}

{% trans 'Back to your profile' %}

-{% endif %} {% endblock content %} diff --git a/ivatar/ivataraccount/templates/import_photo.html b/ivatar/ivataraccount/templates/import_photo.html new file mode 100644 index 0000000..104c985 --- /dev/null +++ b/ivatar/ivataraccount/templates/import_photo.html @@ -0,0 +1,33 @@ +{% extends 'base.html' %} +{% load i18n %} +{% load bootstrap4 %} + +{% block title %}{% trans 'Import photo' %} - Libravatar{% endblock title %} + +{% block content %} + +

{% trans 'Import photo' %}

+ +{% include '_import_photo_form.html' %} + +{% if not email_id %} +
+ + + {% buttons %} + + {% endbuttons %} +
+ + +{% endif %} + +

{% trans 'Back to your profile' %}

+ +{% endblock content %} diff --git a/ivatar/ivataraccount/templates/profile.html b/ivatar/ivataraccount/templates/profile.html index ad2d4f5..8e0488a 100644 --- a/ivatar/ivataraccount/templates/profile.html +++ b/ivatar/ivataraccount/templates/profile.html @@ -79,7 +79,11 @@ {% endif %} {% if not max_photos %} -

{% trans 'Upload a new photo' %}

+

+
+ {% trans 'Upload a new photo' %}
+ {% trans 'Import photo from other services' %} +

{% endif %}

{% trans 'Account settings' %}

diff --git a/ivatar/ivataraccount/test_views.py b/ivatar/ivataraccount/test_views.py index aaf1994..150bf95 100644 --- a/ivatar/ivataraccount/test_views.py +++ b/ivatar/ivataraccount/test_views.py @@ -333,7 +333,7 @@ class Tester(TestCase): # pylint: disable=too-many-public-methods 'unable to import photo from Gravatar?') self.assertEqual( str(list(response.context[0]['messages'])[0]), - 'Image successfully imported', + 'Gravatar image successfully imported', 'Importing gravatar photo did not work?') self.assertIsInstance( self.user.photo_set.first(), @@ -1162,8 +1162,6 @@ class Tester(TestCase): # pylint: disable=too-many-public-methods ) url = '%s?%s' % (urlobj.path, urlobj.query) response = self.client.get(url, follow=False) - print(response) - print(response.content) self.assertRedirects( response=response, expected_url=default, diff --git a/ivatar/ivataraccount/urls.py b/ivatar/ivataraccount/urls.py index 5ffb225..9c14baa 100644 --- a/ivatar/ivataraccount/urls.py +++ b/ivatar/ivataraccount/urls.py @@ -69,6 +69,12 @@ urlpatterns = [ # pylint: disable=invalid-name url( r'assign_photo_openid/(?P\d+)', AssignPhotoOpenIDView.as_view(), name='assign_photo_openid'), + url( + r'import_photo/$', + ImportPhotoView.as_view(), name='import_photo'), + url( + r'import_photo/(?P[\w.]+@[\w.]+.[\w.]+)', + ImportPhotoView.as_view(), name='import_photo'), url( r'import_photo/(?P\d+)', ImportPhotoView.as_view(), name='import_photo'), diff --git a/ivatar/ivataraccount/views.py b/ivatar/ivataraccount/views.py index f96eca9..8e968eb 100644 --- a/ivatar/ivataraccount/views.py +++ b/ivatar/ivataraccount/views.py @@ -2,6 +2,7 @@ View classes for ivatar/ivataraccount/ ''' import io +from urllib.request import urlopen from django.contrib.auth.decorators import login_required from django.utils.decorators import method_decorator @@ -16,6 +17,7 @@ from django.utils.translation import ugettext_lazy as _ from django.http import HttpResponseRedirect, HttpResponse 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 @@ -23,6 +25,9 @@ from openid.consumer import consumer from ipware import get_client_ip +from libravatar import libravatar_url +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 @@ -272,39 +277,111 @@ class AssignPhotoOpenIDView(SuccessMessageMixin, TemplateView): @method_decorator(login_required, name='dispatch') -class ImportPhotoView(SuccessMessageMixin, View): +class ImportPhotoView(SuccessMessageMixin, TemplateView): ''' View class to import a photo from another service Currently only Gravatar is supported ''' + template_name = 'import_photo.html' - @staticmethod - def post(request, *args, **kwargs): # pylint: disable=unused-argument + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['photos'] = [] + addr = None + if 'email_id' in kwargs: + try: + addr = ConfirmedEmail.objects.get(pk=kwargs['email_id']).email + except: + messages.error( + self.request, + _('Address does not exist')) + return context + + if 'email_addr' in kwargs: + addr = kwargs['email_addr'] + + if addr: + gravatar = get_gravatar_photo(addr) + if gravatar: + context['photos'].append(gravatar) + + libravatar_service_url = libravatar_url( + email=addr, + default=404, + ) + try: + if libravatar_service_url: + response = urlopen(libravatar_service_url) + context['photos'].append({ + 'service_url': libravatar_service_url, + 'thumbnail_url': libravatar_service_url + '?s=80', + 'image_url': libravatar_service_url + '?s=512', + 'width': 80, + 'height': 80, + 'service_name': 'Libravatar', + }) + except Exception: + pass + + return context + + def post(self, request, *args, **kwargs): # pylint: disable=no-self-use,unused-argument ''' - Handle post - import photo + Handle post to photo import ''' - try: - email = ConfirmedEmail.objects.get( - id=kwargs['email_id'], user=request.user) - except Exception: # pylint: disable=broad-except - messages.error( - request, - _('Address does not exist')) - return HttpResponseRedirect(reverse_lazy('profile')) + + addr = None + email_id = None + imported = None + + if 'email_id' in kwargs: + email_id = kwargs['email_id'] + if 'email_id' in request.POST: + email_id = request.POST['email_id'] + if 'email_addr' in kwargs: + addr = kwargs['email_addr'] + if 'email_addr' in request.POST: + addr = request.POST['email_addr'] + + if email_id: + email = ConfirmedEmail.objects.filter( + id=email_id, user=request.user) + if email.count() > 0: + addr = email.first().email + else: + messages.error( + request, + _('Address does not exist')) + return HttpResponseRedirect(reverse_lazy('profile')) if 'photo_Gravatar' in request.POST: photo = Photo() photo.user = request.user - photo.ip_address = get_client_ip(request)[0] - if photo.import_image('Gravatar', email.email): + photo.ip_address = get_client_ip(request) + if photo.import_image('Gravatar', addr): messages.success(request, - _('Image successfully imported')) + _('Gravatar image successfully imported')) else: # Honestly, I'm not sure how to test this... messages.error( request, - _('Image import not successful')) # pragma: no cover - else: + _('Gravatar image import not successful')) # pragma: no cover + imported = True + + if 'photo_Libravatar' in request.POST: + photo = Photo() + photo.user = request.user + photo.ip_address = get_client_ip(request) + if photo.import_image('Libravatar', addr): + messages.success(request, + _('Libravatar image successfully imported')) + else: + # Honestly, I'm not sure how to test this... + messages.error( + request, + _('Libravatar image import not successful')) # pragma: no cover + imported = True + if not imported: messages.warning(request, _('Nothing importable')) return HttpResponseRedirect(reverse_lazy('profile')) diff --git a/ivatar/views.py b/ivatar/views.py index 1568048..35753d5 100644 --- a/ivatar/views.py +++ b/ivatar/views.py @@ -5,8 +5,10 @@ from io import BytesIO from os import path from PIL import Image from django.views.generic.base import TemplateView -from django.http import HttpResponse, HttpResponseRedirect +from django.http import HttpResponse, HttpResponseRedirect, HttpResponseNotFound from django.core.exceptions import ObjectDoesNotExist +from django.utils.translation import ugettext_lazy as _ + from ivatar.settings import AVATAR_MAX_SIZE, JPEG_QUALITY from . ivataraccount.models import ConfirmedEmail, ConfirmedOpenId from . ivataraccount.models import pil_format @@ -58,10 +60,12 @@ class AvatarImageView(TemplateView): # If that mail/openid doesn't exist, or has no photo linked to it if not obj or not obj.photo: - # Return the default URL, as specified + # Return the default URL, as specified, or 404 Not Found, if default=404 if default: + if str(default) == str(404): + return HttpResponseNotFound(_('

Image not found

')) return HttpResponseRedirect(default) - # Return our default URl + # Return our default URL else: static_img = path.join('static', 'img', 'mm', '%s%s' % (str(size), '.png')) if not path.isfile(static_img):