Ability to import from libravatar + import by email; Forms are WIP!

This commit is contained in:
Oliver Falk
2018-07-10 14:46:30 +02:00
parent 4cf9e72c93
commit 96237bb47e
6 changed files with 119 additions and 20 deletions

View File

@@ -24,6 +24,8 @@ from openid.association import Association as OIDAssociation
from openid.store import nonce as oidnonce from openid.store import nonce as oidnonce
from openid.store.interface import OpenIDStore from openid.store.interface import OpenIDStore
from libravatar import libravatar_url
from ivatar.settings import MAX_LENGTH_EMAIL, logger from ivatar.settings import MAX_LENGTH_EMAIL, logger
from ivatar.settings import MAX_PIXELS, AVATAR_MAX_SIZE, JPEG_QUALITY from ivatar.settings import MAX_PIXELS, AVATAR_MAX_SIZE, JPEG_QUALITY
from ivatar.settings import MIN_LENGTH_URL, MAX_LENGTH_URL from ivatar.settings import MIN_LENGTH_URL, MAX_LENGTH_URL
@@ -127,6 +129,9 @@ class Photo(BaseAccountModel):
if gravatar: if gravatar:
image_url = gravatar['image_url'] image_url = gravatar['image_url']
if service_name == 'Libravatar':
image_url = libravatar_url(email_address)
if not image_url: if not image_url:
return False # pragma: no cover return False # pragma: no cover
try: try:

View File

@@ -4,12 +4,20 @@
{% if not user.is_anonymous %} {% if not user.is_anonymous %}
{% if photos %} {% if photos %}
<p>{% trans 'Would you like to import some of these externally hosted photos?' %}</p> <p>{% trans 'Would you like to import some of these externally hosted photos?' %}</p>
{% if email_id %}
<form action="{% url 'import_photo' email_id %}" method="post">{% csrf_token %} <form action="{% url 'import_photo' email_id %}" method="post">{% csrf_token %}
<input type="hidden" name="email_id" value="{{ email_id }}"> <input type="hidden" name="email_id" value="{{ email_id }}">
{% else %}
<form action="{% url 'import_photo' %}" method="post">{% csrf_token %}
<input type="hidden" name="email_addr" value="{{ email_addr }}">
{% endif %}
<ul class="horizontal-list imported-list centered"> <ul class="horizontal-list imported-list centered">
{% for photo in photos %} {% for photo in photos %}
<li><input type="checkbox" name="photo_{{photo.service_name}}" id="photo_{{photo.service_name}}" checked="checked"> <li><input type="checkbox" name="photo_{{photo.service_name}}" id="photo_{{photo.service_name}}" checked="checked">
<br/><label for="photo_{{photo.service_name}}"><img src="{{ photo.thumbnail_url }}" class="thumbnail" alt="{{photo.service_name}} image"></label> <br/>
<label for="photo_{{photo.service_name}}">
<img src="{{ photo.thumbnail_url }}" class="thumbnail" alt="{{ photo.service_name }} image">
</label>
<br/> <br/>
{% if photo.service_url %} {% if photo.service_url %}
<a href="{{ photo.service_url }}">{{ photo.service_name }}</a> <a href="{{ photo.service_url }}">{{ photo.service_name }}</a>
@@ -25,5 +33,7 @@
{% endbuttons %} {% endbuttons %}
</p> </p>
</form> </form>
{% else %}
<p>{% trans 'Nothing importable found' %}</p>
{% endif %} {% endif %}
{% endif %} {% endif %}

View File

@@ -1,5 +1,6 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n %} {% load i18n %}
{% load bootstrap4 %}
{% block title %}{% trans 'Import photo' %} - Libravatar{% endblock title %} {% block title %}{% trans 'Import photo' %} - Libravatar{% endblock title %}
@@ -9,6 +10,18 @@
{% include '_import_photo_form.html' %} {% include '_import_photo_form.html' %}
{# Code not ready yet
{% if not email_id %}
<form action="{% url 'import_photo' %}" method="post">{% csrf_token %}
<label for="email_addr">{% trans 'Email Address' %}</label>
<input type="text" name="email_addr" value="{{ email_addr }}">
{% buttons %}
<button type="submit" class="btn btn-primary">{% trans 'Check' %}</button>
{% endbuttons %}
</form>
{% endif %}
#}
<p><a href="{% url 'profile' %}">{% trans 'Back to your profile' %}</a></p> <p><a href="{% url 'profile' %}">{% trans 'Back to your profile' %}</a></p>
{% endblock content %} {% endblock content %}

View File

@@ -66,6 +66,12 @@ urlpatterns = [ # pylint: disable=invalid-name
url( url(
r'assign_photo_openid/(?P<openid_id>\d+)', r'assign_photo_openid/(?P<openid_id>\d+)',
AssignPhotoOpenIDView.as_view(), name='assign_photo_openid'), AssignPhotoOpenIDView.as_view(), name='assign_photo_openid'),
url(
r'import_photo/$',
ImportPhotoView.as_view(), name='import_photo'),
url(
r'import_photo/(?P<email_addr>[\w.]+@[\w.]+.[\w.]+)',
ImportPhotoView.as_view(), name='import_photo'),
url( url(
r'import_photo/(?P<email_id>\d+)', r'import_photo/(?P<email_id>\d+)',
ImportPhotoView.as_view(), name='import_photo'), ImportPhotoView.as_view(), name='import_photo'),

View File

@@ -3,6 +3,7 @@ View classes for ivatar/ivataraccount/
''' '''
import io import io
from urllib.request import urlopen
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
@@ -24,6 +25,8 @@ from openid.consumer import consumer
from ipware import get_client_ip from ipware import get_client_ip
from libravatar import libravatar_url
from ivatar.settings import MAX_NUM_PHOTOS, MAX_PHOTO_SIZE from ivatar.settings import MAX_NUM_PHOTOS, MAX_PHOTO_SIZE
from .forms import AddEmailForm, UploadPhotoForm, AddOpenIDForm from .forms import AddEmailForm, UploadPhotoForm, AddOpenIDForm
@@ -271,19 +274,62 @@ class ImportPhotoView(SuccessMessageMixin, TemplateView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context['photos'] = [] context['photos'] = []
gravatar = get_gravatar_photo(ConfirmedEmail.objects.get(pk=kwargs['email_id']).email) addr = None
if 'email_id' in kwargs:
addr = ConfirmedEmail.objects.get(pk=kwargs['email_id']).email
if 'email_addr' in kwargs:
addr = kwargs['email_addr']
if addr:
gravatar = get_gravatar_photo(addr)
if gravatar: if gravatar:
context['photos'].append(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 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
''' '''
Handle post to photo import Handle post to photo import
''' '''
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:
try: try:
email = ConfirmedEmail.objects.get( email = ConfirmedEmail.objects.filter(
id=kwargs['email_id'], user=request.user) id=email_id, user=request.user)
except ConfirmedEmail.DoesNotExist as e: # pylint: disable=no-member if email.count() > 0:
addr = email.first().email
except ConfirmedEmail.DoesNotExist: # pylint: disable=no-member
messages.error( messages.error(
request, request,
_('Address does not exist')) _('Address does not exist'))
@@ -293,15 +339,30 @@ class ImportPhotoView(SuccessMessageMixin, TemplateView):
photo = Photo() photo = Photo()
photo.user = request.user photo.user = request.user
photo.ip_address = get_client_ip(request) photo.ip_address = get_client_ip(request)
if photo.import_image('Gravatar', email.email): if photo.import_image('Gravatar', addr):
messages.success(request, messages.success(request,
_('Image successfully imported')) _('Gravatar image successfully imported'))
else: else:
# Honestly, I'm not sure how to test this... # Honestly, I'm not sure how to test this...
messages.error( messages.error(
request, request,
_('Image import not successful')) # pragma: no cover _('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 successfully imported'))
else: 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')) messages.warning(request, _('Nothing importable'))
return HttpResponseRedirect(reverse_lazy('profile')) return HttpResponseRedirect(reverse_lazy('profile'))

View File

@@ -5,8 +5,10 @@ from io import BytesIO
from os import path from os import path
from PIL import Image from PIL import Image
from django.views.generic.base import TemplateView 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.core.exceptions import ObjectDoesNotExist
from django.utils.translation import ugettext_lazy as _
from ivatar.settings import AVATAR_MAX_SIZE, JPEG_QUALITY from ivatar.settings import AVATAR_MAX_SIZE, JPEG_QUALITY
from . ivataraccount.models import ConfirmedEmail, ConfirmedOpenId from . ivataraccount.models import ConfirmedEmail, ConfirmedOpenId
from . ivataraccount.models import pil_format 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 that mail/openid doesn't exist, or has no photo linked to it
if not obj or not obj.photo: 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 default:
if str(default) == str(404):
return HttpResponseNotFound(_('<h1>Image not found</h1>'))
return HttpResponseRedirect(default) return HttpResponseRedirect(default)
# Return our default URl # Return our default URL
else: else:
static_img = path.join('static', 'img', 'mm', '%s%s' % (str(size), '.png')) static_img = path.join('static', 'img', 'mm', '%s%s' % (str(size), '.png'))
if not path.isfile(static_img): if not path.isfile(static_img):