mirror of
https://git.linux-kernel.at/oliver/ivatar.git
synced 2025-11-17 05:28:03 +00:00
WIP: Happy lint
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
Default: useful variables for the base page templates.
|
||||
'''
|
||||
|
||||
from ivatar.settings import IVATAR_VERSION, SITE_NAME
|
||||
from ipware import get_client_ip
|
||||
from ivatar.settings import IVATAR_VERSION, SITE_NAME
|
||||
|
||||
|
||||
def basepage(request):
|
||||
@@ -15,7 +15,7 @@ def basepage(request):
|
||||
if 'openid_identifier' in request.GET:
|
||||
context['openid_identifier'] = \
|
||||
request.GET['openid_identifier'] # pragma: no cover
|
||||
client_ip, is_routable = get_client_ip(request)
|
||||
client_ip = get_client_ip(request)[0]
|
||||
context['client_ip'] = client_ip
|
||||
context['ivatar_version'] = IVATAR_VERSION
|
||||
context['site_name'] = SITE_NAME
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
'''
|
||||
Register models in admin
|
||||
'''
|
||||
from django.contrib import admin
|
||||
|
||||
from . models import Photo, ConfirmedEmail, UnconfirmedEmail
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
'''
|
||||
Classes for our ivatar.ivataraccount.forms
|
||||
'''
|
||||
from urllib.parse import urlsplit, urlunsplit
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.urls import reverse
|
||||
from django.template.loader import render_to_string
|
||||
from django.core.mail import send_mail
|
||||
|
||||
from urllib.parse import urlsplit, urlunsplit
|
||||
from ipware import get_client_ip
|
||||
|
||||
from ivatar import settings
|
||||
from . models import UnconfirmedEmail, ConfirmedEmail, Photo
|
||||
from . models import UnconfirmedOpenId, ConfirmedOpenId
|
||||
|
||||
from ivatar.settings import MAX_LENGTH_EMAIL
|
||||
from ivatar.ivataraccount.models import MAX_LENGTH_URL
|
||||
|
||||
from ipware import get_client_ip
|
||||
from . models import UnconfirmedEmail, ConfirmedEmail, Photo
|
||||
from . models import UnconfirmedOpenId, ConfirmedOpenId
|
||||
|
||||
MAX_NUM_UNCONFIRMED_EMAILS_DEFAULT = 5
|
||||
|
||||
@@ -54,7 +56,7 @@ class AddEmailForm(forms.Form):
|
||||
|
||||
# Check whether or not a confirmation email has been
|
||||
# sent by this user already
|
||||
if UnconfirmedEmail.objects.filter(
|
||||
if UnconfirmedEmail.objects.filter( # pylint: disable=no-member
|
||||
user=user, email=self.cleaned_data['email']).exists():
|
||||
self.add_error('email', _('Address already added, currently unconfirmed'))
|
||||
return False
|
||||
@@ -112,7 +114,8 @@ class UploadPhotoForm(forms.Form):
|
||||
distribute photos to third parties.')
|
||||
})
|
||||
|
||||
def save(self, request, data):
|
||||
@staticmethod
|
||||
def save(request, data):
|
||||
'''
|
||||
Save the model and assign it to the current user
|
||||
'''
|
||||
@@ -122,7 +125,7 @@ class UploadPhotoForm(forms.Form):
|
||||
photo.ip_address = get_client_ip(request)
|
||||
photo.data = data.read()
|
||||
photo.save()
|
||||
if not photo.id:
|
||||
if not photo.pk:
|
||||
return None
|
||||
return photo
|
||||
|
||||
@@ -151,19 +154,18 @@ class AddOpenIDForm(forms.Form):
|
||||
url.query, url.fragment))
|
||||
|
||||
# TODO: Domain restriction as in libravatar?
|
||||
|
||||
return data
|
||||
|
||||
def save(self, user):
|
||||
'''
|
||||
Save the model, ensuring some safety
|
||||
'''
|
||||
if ConfirmedOpenId.objects.filter(
|
||||
if ConfirmedOpenId.objects.filter( # pylint: disable=no-member
|
||||
openid=self.cleaned_data['openid']).exists():
|
||||
self.add_error('openid', _('OpenID already added and confirmed!'))
|
||||
return False
|
||||
|
||||
if UnconfirmedOpenId.objects.filter(
|
||||
if UnconfirmedOpenId.objects.filter( # pylint: disable=no-member
|
||||
openid=self.cleaned_data['openid']).exists():
|
||||
self.add_error('openid', _('OpenID already added, but not confirmed yet!'))
|
||||
return False
|
||||
@@ -173,4 +175,4 @@ class AddOpenIDForm(forms.Form):
|
||||
unconfirmed.user = user
|
||||
unconfirmed.save()
|
||||
|
||||
return unconfirmed.id
|
||||
return unconfirmed.pk
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
'''
|
||||
Helper method to fetch Gravatar image
|
||||
'''
|
||||
from ssl import SSLError
|
||||
from urllib.request import urlopen, HTTPError, URLError
|
||||
import hashlib
|
||||
@@ -21,18 +24,18 @@ def get_photo(email):
|
||||
|
||||
try:
|
||||
urlopen(image_url, timeout=URL_TIMEOUT)
|
||||
except HTTPError as e:
|
||||
except HTTPError as e: # pylint: disable=invalid-name
|
||||
if e.code != 404 and e.code != 503:
|
||||
print( # pragma: no cover
|
||||
'Gravatar fetch failed with an unexpected %s HTTP error' %
|
||||
e.code)
|
||||
return False
|
||||
except URLError as e: # pragma: no cover
|
||||
except URLError as e: # pragma: no cover # pylint: disable=invalid-name
|
||||
print(
|
||||
'Gravatar fetch failed with URL error: %s' %
|
||||
e.reason) # pragma: no cover
|
||||
return False # pragma: no cover
|
||||
except SSLError as e: # pragma: no cover
|
||||
except SSLError as e: # pragma: no cover # pylint: disable=invalid-name
|
||||
print(
|
||||
'Gravatar fetch failed with SSL error: %s' %
|
||||
e.reason) # pragma: no cover
|
||||
|
||||
@@ -19,10 +19,10 @@ from django.utils import timezone
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from openid.association import Association as OIDAssociation
|
||||
from openid.store import nonce as oidnonce
|
||||
from openid.store.interface import OpenIDStore
|
||||
from ipware import get_client_ip
|
||||
|
||||
from ivatar.settings import MAX_LENGTH_EMAIL, logger
|
||||
from ivatar.settings import MAX_PIXELS, AVATAR_MAX_SIZE, JPEG_QUALITY
|
||||
@@ -42,6 +42,7 @@ def file_format(image_type):
|
||||
return 'png'
|
||||
elif image_type == 'GIF':
|
||||
return 'gif'
|
||||
return None
|
||||
|
||||
def pil_format(image_type):
|
||||
'''
|
||||
@@ -54,7 +55,7 @@ def pil_format(image_type):
|
||||
elif image_type == 'gif':
|
||||
return 'GIF'
|
||||
|
||||
logger.info('Unsupported file format: %s' % image_type)
|
||||
logger.info('Unsupported file format: %s', image_type)
|
||||
return None
|
||||
|
||||
|
||||
@@ -69,7 +70,7 @@ class BaseAccountModel(models.Model):
|
||||
ip_address = models.GenericIPAddressField(unpack_ipv4=True, null=True)
|
||||
add_date = models.DateTimeField(default=timezone.now)
|
||||
|
||||
class Meta:
|
||||
class Meta: # pylint: disable=too-few-public-methods
|
||||
'''
|
||||
Class attributes
|
||||
'''
|
||||
@@ -84,7 +85,7 @@ class Photo(BaseAccountModel):
|
||||
data = models.BinaryField()
|
||||
format = models.CharField(max_length=3)
|
||||
|
||||
class Meta:
|
||||
class Meta: # pylint: disable=too-few-public-methods
|
||||
'''
|
||||
Class attributes
|
||||
'''
|
||||
@@ -92,6 +93,9 @@ class Photo(BaseAccountModel):
|
||||
verbose_name_plural = _('photos')
|
||||
|
||||
def import_image(self, service_name, email_address):
|
||||
'''
|
||||
Allow to import image from other (eg. Gravatar) service
|
||||
'''
|
||||
image_url = False
|
||||
|
||||
if service_name == 'Gravatar':
|
||||
@@ -104,12 +108,12 @@ class Photo(BaseAccountModel):
|
||||
try:
|
||||
image = urlopen(image_url)
|
||||
# No idea how to test this
|
||||
except HTTPError as e: # pragma: no cover
|
||||
except HTTPError as e: # pragma: no cover # pylint: disable=invalid-name
|
||||
print('%s import failed with an HTTP error: %s' %
|
||||
(service_name, e.code))
|
||||
return False
|
||||
# No idea how to test this
|
||||
except URLError as e: # pragma: no cover
|
||||
except URLError as e: # pragma: no cover # pylint: disable=invalid-name
|
||||
print('%s import failed: %s' % (service_name, e.reason))
|
||||
return False
|
||||
data = image.read()
|
||||
@@ -128,7 +132,8 @@ class Photo(BaseAccountModel):
|
||||
super().save()
|
||||
return True
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
'''
|
||||
Override save from parent, taking care about the image
|
||||
'''
|
||||
@@ -136,7 +141,7 @@ class Photo(BaseAccountModel):
|
||||
try:
|
||||
img = Image.open(BytesIO(self.data))
|
||||
# Testing? Ideas anyone?
|
||||
except Exception as e: # pylint: disable=unused-variable
|
||||
except Exception as e: # pylint: disable=invalid-name,broad-except
|
||||
# For debugging only
|
||||
print('Exception caught: %s' % e)
|
||||
return False
|
||||
@@ -144,18 +149,21 @@ class Photo(BaseAccountModel):
|
||||
if not self.format:
|
||||
print('Format not recognized')
|
||||
return False
|
||||
return super().save(*args, **kwargs)
|
||||
return super().save(force_insert, force_update, using, update_fields)
|
||||
|
||||
def perform_crop(self, request, dimensions, email, openid):
|
||||
'''
|
||||
Helper to crop the image
|
||||
'''
|
||||
if request.user.photo_set.count() == 1:
|
||||
# This is the first photo, assign to all confirmed addresses
|
||||
for email in request.user.confirmedemail_set.all():
|
||||
email.photo = self
|
||||
email.save()
|
||||
for addr in request.user.confirmedemail_set.all():
|
||||
addr.photo = self
|
||||
addr.save()
|
||||
|
||||
for openid in request.user.confirmedopenid_set.all():
|
||||
openid.photo = self
|
||||
openid.save()
|
||||
for addr in request.user.confirmedopenid_set.all():
|
||||
addr.photo = self
|
||||
addr.save()
|
||||
|
||||
if email:
|
||||
# Explicitely asked
|
||||
@@ -171,25 +179,30 @@ class Photo(BaseAccountModel):
|
||||
img = Image.open(BytesIO(self.data))
|
||||
|
||||
# This should be anyway checked during save...
|
||||
a, b = img.size
|
||||
if a > MAX_PIXELS or b > MAX_PIXELS:
|
||||
messages.error(request, _('Image dimensions are too big(max: %s x %s' % (MAX_PIXELS, MAX_PIXELS)))
|
||||
dimensions['a'], dimensions['b'] = img.size # pylint: disable=invalid-name
|
||||
if dimensions['a'] > MAX_PIXELS or dimensions['b'] > MAX_PIXELS:
|
||||
messages.error(
|
||||
request,
|
||||
_('Image dimensions are too big(max: %s x %s' %
|
||||
(MAX_PIXELS, MAX_PIXELS)))
|
||||
return HttpResponseRedirect(reverse_lazy('profile'))
|
||||
|
||||
w = dimensions['w']
|
||||
h = dimensions['h']
|
||||
x = dimensions['x']
|
||||
y = dimensions['y']
|
||||
|
||||
if w == 0 and h == 0:
|
||||
w, h = a, b
|
||||
i = min(w, h)
|
||||
w, h = i, i
|
||||
elif w < 0 or (x + w) > a or h < 0 or (y + h) > b:
|
||||
if dimensions['w'] == 0 and dimensions['h'] == 0:
|
||||
dimensions['w'], dimensions['h'] = dimensions['a'], dimensions['b']
|
||||
min_from_w_h = min(dimensions['w'], dimensions['h'])
|
||||
dimensions['w'], dimensions['h'] = min_from_w_h, min_from_w_h
|
||||
elif dimensions['w'] < 0 or \
|
||||
(dimensions['x'] + dimensions['w']) > dimensions['a'] or \
|
||||
dimensions['h'] < 0 or \
|
||||
(dimensions['y'] + dimensions['h']) > dimensions['b']:
|
||||
messages.error(request, _('Crop outside of original image bounding box'))
|
||||
return HttpResponseRedirect(reverse_lazy('profile'))
|
||||
|
||||
cropped = img.crop((x, y, x + w, y + h))
|
||||
cropped = img.crop((
|
||||
dimensions['x'],
|
||||
dimensions['y'],
|
||||
dimensions['x'] + dimensions['w'],
|
||||
dimensions['y'] + dimensions['h']))
|
||||
# cropped.load()
|
||||
# Resize the image only if it's larger than the specified max width.
|
||||
cropped_w, cropped_h = cropped.size
|
||||
@@ -200,12 +213,6 @@ class Photo(BaseAccountModel):
|
||||
data = BytesIO()
|
||||
cropped.save(data, pil_format(self.format), quality=JPEG_QUALITY)
|
||||
data.seek(0)
|
||||
# Create new photo?
|
||||
# photo = Photo()
|
||||
# photo.user = request.user
|
||||
# photo.ip_address = get_client_ip(request)
|
||||
# photo.data = data.read()
|
||||
# photo.save()
|
||||
|
||||
# Overwrite the existing image
|
||||
self.data = data.read()
|
||||
@@ -214,12 +221,13 @@ class Photo(BaseAccountModel):
|
||||
return HttpResponseRedirect(reverse_lazy('profile'))
|
||||
|
||||
|
||||
class ConfirmedEmailManager(models.Manager):
|
||||
class ConfirmedEmailManager(models.Manager): # pylint: disable=too-few-public-methods
|
||||
'''
|
||||
Manager for our confirmed email addresses model
|
||||
'''
|
||||
|
||||
def create_confirmed_email(self, user, email_address, is_logged_in):
|
||||
@staticmethod
|
||||
def create_confirmed_email(user, email_address, is_logged_in):
|
||||
'''
|
||||
Helper method to create confirmed email address
|
||||
'''
|
||||
@@ -254,7 +262,7 @@ class ConfirmedEmail(BaseAccountModel):
|
||||
digest = models.CharField(max_length=64)
|
||||
objects = ConfirmedEmailManager()
|
||||
|
||||
class Meta:
|
||||
class Meta: # pylint: disable=too-few-public-methods
|
||||
'''
|
||||
Class attributes
|
||||
'''
|
||||
@@ -268,14 +276,15 @@ class ConfirmedEmail(BaseAccountModel):
|
||||
self.photo = photo
|
||||
self.save()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
'''
|
||||
Override save from parent, add digest
|
||||
'''
|
||||
self.digest = hashlib.md5(
|
||||
self.email.strip().lower().encode('utf-8')
|
||||
).hexdigest()
|
||||
return super().save(*args, **kwargs)
|
||||
return super().save(force_insert, force_update, using, update_fields)
|
||||
|
||||
|
||||
class UnconfirmedEmail(BaseAccountModel):
|
||||
@@ -285,18 +294,19 @@ class UnconfirmedEmail(BaseAccountModel):
|
||||
email = models.EmailField(max_length=MAX_LENGTH_EMAIL)
|
||||
verification_key = models.CharField(max_length=64)
|
||||
|
||||
class Meta:
|
||||
class Meta: # pylint: disable=too-few-public-methods
|
||||
'''
|
||||
Class attributes
|
||||
'''
|
||||
verbose_name = _('unconfirmed_email')
|
||||
verbose_name_plural = _('unconfirmed_emails')
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
hash_object = hashlib.new('sha256')
|
||||
hash_object.update(urandom(1024) + self.user.username.encode('utf-8'))
|
||||
hash_object.update(urandom(1024) + self.user.username.encode('utf-8')) # pylint: disable=no-member
|
||||
self.verification_key = hash_object.hexdigest()
|
||||
super(UnconfirmedEmail, self).save(*args, **kwargs)
|
||||
super(UnconfirmedEmail, self).save(force_insert, force_update, using, update_fields)
|
||||
|
||||
|
||||
class UnconfirmedOpenId(BaseAccountModel):
|
||||
@@ -305,7 +315,10 @@ class UnconfirmedOpenId(BaseAccountModel):
|
||||
'''
|
||||
openid = models.URLField(unique=False, max_length=MAX_LENGTH_URL)
|
||||
|
||||
class Meta:
|
||||
class Meta: # pylint: disable=too-few-public-methods
|
||||
'''
|
||||
Meta class
|
||||
'''
|
||||
verbose_name = _('unconfirmed OpenID')
|
||||
verbose_name_plural = ('unconfirmed_OpenIDs')
|
||||
|
||||
@@ -325,15 +338,22 @@ class ConfirmedOpenId(BaseAccountModel):
|
||||
)
|
||||
digest = models.CharField(max_length=64)
|
||||
|
||||
class Meta:
|
||||
class Meta: # pylint: disable=too-few-public-methods
|
||||
'''
|
||||
Meta class
|
||||
'''
|
||||
verbose_name = _('confirmed OpenID')
|
||||
verbose_name_plural = _('confirmed OpenIDs')
|
||||
|
||||
def set_photo(self, photo):
|
||||
'''
|
||||
Helper method to save photo
|
||||
'''
|
||||
self.photo = photo
|
||||
self.save()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
def save(self, force_insert=False, force_update=False, using=None,
|
||||
update_fields=None):
|
||||
url = urlsplit(self.openid)
|
||||
if url.username: # pragma: no cover
|
||||
password = url.password or ''
|
||||
@@ -344,7 +364,7 @@ class ConfirmedOpenId(BaseAccountModel):
|
||||
(url.scheme.lower(), netloc, url.path, url.query, url.fragment)
|
||||
)
|
||||
self.digest = hashlib.sha256(lowercase_url.encode('utf-8')).hexdigest()
|
||||
return super().save(*args, **kwargs)
|
||||
return super().save(force_insert, force_update, using, update_fields)
|
||||
|
||||
|
||||
class OpenIDNonce(models.Model):
|
||||
@@ -383,7 +403,7 @@ class DjangoOpenIDStore(OpenIDStore):
|
||||
assoc = OpenIDAssociation(
|
||||
server_url=server_url,
|
||||
handle=association.handle,
|
||||
secret=base64.encodestring(association.secret),
|
||||
secret=base64.encodebytes(association.secret),
|
||||
issued=association.issued,
|
||||
lifetime=association.issued,
|
||||
assoc_type=association.assoc_type)
|
||||
@@ -395,25 +415,25 @@ class DjangoOpenIDStore(OpenIDStore):
|
||||
'''
|
||||
assocs = []
|
||||
if handle is not None:
|
||||
assocs = OpenIDAssociation.objects.filter(
|
||||
assocs = OpenIDAssociation.objects.filter( # pylint: disable=no-member
|
||||
server_url=server_url, handle=handle)
|
||||
else:
|
||||
assocs = OpenIDAssociation.objects.filter(server_url=server_url)
|
||||
assocs = OpenIDAssociation.objects.filter(server_url=server_url) # pylint: disable=no-member
|
||||
if not assocs:
|
||||
return None
|
||||
associations = []
|
||||
for assoc in assocs:
|
||||
if type(assoc.secret) is str:
|
||||
if isinstance(assoc.secret, str):
|
||||
assoc.secret = assoc.secret.split("b'")[1].split("'")[0]
|
||||
assoc.secret = bytes(assoc.secret, 'utf-8')
|
||||
association = OIDAssociation(assoc.handle,
|
||||
base64.decodestring(assoc.secret),
|
||||
base64.decodebytes(assoc.secret),
|
||||
assoc.issued, assoc.lifetime,
|
||||
assoc.assoc_type)
|
||||
expires = 0
|
||||
try:
|
||||
expires = association.getExpiresIn()
|
||||
except Exception as e:
|
||||
expires = association.getExpiresIn() # pylint: disable=no-member
|
||||
except Exception as e: # pylint: disable=invalid-name,broad-except,unused-variable
|
||||
expires = association.expiresIn
|
||||
if expires == 0:
|
||||
self.removeAssociation(server_url, assoc.handle)
|
||||
@@ -429,7 +449,7 @@ class DjangoOpenIDStore(OpenIDStore):
|
||||
TODO: Could be moved to classmethod
|
||||
'''
|
||||
assocs = list(
|
||||
OpenIDAssociation.objects.filter(
|
||||
OpenIDAssociation.objects.filter( # pylint: disable=no-member
|
||||
server_url=server_url, handle=handle))
|
||||
assocs_exist = len(assocs) > 0
|
||||
for assoc in assocs:
|
||||
@@ -445,12 +465,12 @@ class DjangoOpenIDStore(OpenIDStore):
|
||||
if abs(timestamp - time.time()) > oidnonce.SKEW:
|
||||
return False
|
||||
try:
|
||||
nonce = OpenIDNonce.objects.get(
|
||||
nonce = OpenIDNonce.objects.get( # pylint: disable=no-member
|
||||
server_url__exact=server_url,
|
||||
timestamp__exact=timestamp,
|
||||
salt__exact=salt)
|
||||
except OpenIDNonce.DoesNotExist:
|
||||
nonce = OpenIDNonce.objects.create(
|
||||
except ObjectDoesNotExist:
|
||||
nonce = OpenIDNonce.objects.create( # pylint: disable=no-member
|
||||
server_url=server_url, timestamp=timestamp, salt=salt)
|
||||
return True
|
||||
nonce.delete()
|
||||
@@ -462,12 +482,12 @@ class DjangoOpenIDStore(OpenIDStore):
|
||||
TODO: Could be moved to classmethod
|
||||
'''
|
||||
timestamp = int(time.time()) - oidnonce.SKEW
|
||||
OpenIDNonce.objects.filter(timestamp__lt=timestamp).delete()
|
||||
OpenIDNonce.objects.filter(timestamp__lt=timestamp).delete() # pylint: disable=no-member
|
||||
|
||||
def cleanupAssociations(self): # pragma: no cover
|
||||
'''
|
||||
Helper method to cleanup associations
|
||||
TODO: Could be moved to classmethod
|
||||
'''
|
||||
OpenIDAssociation.objects.extra(
|
||||
OpenIDAssociation.objects.extra( # pylint: disable=no-member
|
||||
where=['issued + lifetimeint < (%s)' % time.time()]).delete()
|
||||
|
||||
@@ -410,7 +410,7 @@ class Tester(TestCase):
|
||||
follow=True,
|
||||
) # Create test addresses + 1 too much
|
||||
self.assertFormError(response, 'form', None,
|
||||
'Too many unconfirmed mail addresses!')
|
||||
'Too many unconfirmed mail addresses!')
|
||||
|
||||
def test_add_mail_address_twice(self):
|
||||
'''
|
||||
|
||||
@@ -17,7 +17,7 @@ from . views import CropPhotoView
|
||||
# Define URL patterns, self documenting
|
||||
# To see the fancy, colorful evaluation of these use:
|
||||
# ./manager show_urls
|
||||
urlpatterns = [
|
||||
urlpatterns = [ # pylint: disable=invalid-name
|
||||
path('new/', CreateView.as_view(), name='new_account'),
|
||||
path('login/', LoginView.as_view(template_name='login.html'),
|
||||
name='login'),
|
||||
@@ -38,39 +38,39 @@ urlpatterns = [
|
||||
path('upload_photo/', UploadPhotoView.as_view(), name='upload_photo'),
|
||||
path('password_set/', PasswordSetView.as_view(), name='password_set'),
|
||||
url(
|
||||
'remove_unconfirmed_openid/(?P<openid_id>\d+)',
|
||||
r'remove_unconfirmed_openid/(?P<openid_id>\d+)',
|
||||
RemoveUnconfirmedOpenIDView.as_view(),
|
||||
name='remove_unconfirmed_openid'),
|
||||
url(
|
||||
'remove_confirmed_openid/(?P<openid_id>\d+)',
|
||||
r'remove_confirmed_openid/(?P<openid_id>\d+)',
|
||||
RemoveConfirmedOpenIDView.as_view(), name='remove_confirmed_openid'),
|
||||
url(
|
||||
'openid_redirection/(?P<openid_id>\d+)',
|
||||
r'openid_redirection/(?P<openid_id>\d+)',
|
||||
RedirectOpenIDView.as_view(), name='openid_redirection'),
|
||||
url(
|
||||
'confirm_openid/(?P<openid_id>\w+)',
|
||||
r'confirm_openid/(?P<openid_id>\w+)',
|
||||
ConfirmOpenIDView.as_view(), name='confirm_openid'),
|
||||
url(
|
||||
'confirm_email/(?P<verification_key>\w+)',
|
||||
r'confirm_email/(?P<verification_key>\w+)',
|
||||
ConfirmEmailView.as_view(), name='confirm_email'),
|
||||
url(
|
||||
'remove_unconfirmed_email/(?P<email_id>\d+)',
|
||||
r'remove_unconfirmed_email/(?P<email_id>\d+)',
|
||||
RemoveUnconfirmedEmailView.as_view(), name='remove_unconfirmed_email'),
|
||||
url(
|
||||
'remove_confirmed_email/(?P<email_id>\d+)',
|
||||
r'remove_confirmed_email/(?P<email_id>\d+)',
|
||||
RemoveConfirmedEmailView.as_view(), name='remove_confirmed_email'),
|
||||
url(
|
||||
'assign_photo_email/(?P<email_id>\d+)',
|
||||
r'assign_photo_email/(?P<email_id>\d+)',
|
||||
AssignPhotoEmailView.as_view(), name='assign_photo_email'),
|
||||
url(
|
||||
'assign_photo_openid/(?P<openid_id>\d+)',
|
||||
r'assign_photo_openid/(?P<openid_id>\d+)',
|
||||
AssignPhotoOpenIDView.as_view(), name='assign_photo_openid'),
|
||||
url(
|
||||
'import_photo/(?P<email_id>\d+)',
|
||||
r'import_photo/(?P<email_id>\d+)',
|
||||
ImportPhotoView.as_view(), name='import_photo'),
|
||||
url(
|
||||
'delete_photo/(?P<pk>\d+)',
|
||||
r'delete_photo/(?P<pk>\d+)',
|
||||
DeletePhotoView.as_view(), name='delete_photo'),
|
||||
url('raw_image/(?P<pk>\d+)', RawImageView.as_view(), name='raw_image'),
|
||||
url('crop_photo/(?P<pk>\d+)', CropPhotoView.as_view(), name='crop_photo'),
|
||||
url(r'raw_image/(?P<pk>\d+)', RawImageView.as_view(), name='raw_image'),
|
||||
url(r'crop_photo/(?P<pk>\d+)', CropPhotoView.as_view(), name='crop_photo'),
|
||||
]
|
||||
|
||||
@@ -5,15 +5,14 @@ Django settings for ivatar project.
|
||||
import os
|
||||
import logging
|
||||
|
||||
log_level = logging.DEBUG
|
||||
logger = logging.getLogger('ivatar')
|
||||
log_level = logging.DEBUG # pylint: disable=invalid-name
|
||||
logger = logging.getLogger('ivatar') # pylint: disable=invalid-name
|
||||
logger.setLevel(log_level)
|
||||
|
||||
PACKAGE_ROOT = os.path.abspath(os.path.dirname(__file__))
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
# TODO: Changeme
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = '=v(+-^t#ahv^a&&e)uf36g8algj$d1@6ou^w(r0@%)#8mlc*zk'
|
||||
|
||||
@@ -119,4 +118,4 @@ PROJECT_ROOT = os.path.abspath(
|
||||
STATIC_URL = '/static/'
|
||||
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
|
||||
|
||||
from config import * # noqa
|
||||
from config import * # pylint: disable=wildcard-import,wrong-import-position,unused-wildcard-import
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
'''
|
||||
Unit tests for WSGI
|
||||
'''
|
||||
import unittest
|
||||
|
||||
import os
|
||||
@@ -7,7 +10,13 @@ django.setup()
|
||||
|
||||
|
||||
class TestCase(unittest.TestCase):
|
||||
'''
|
||||
Simple testcase to see if WSGI loads correctly
|
||||
'''
|
||||
def test_run_wsgi(self):
|
||||
'''
|
||||
Run wsgi import
|
||||
'''
|
||||
import ivatar.wsgi
|
||||
self.assertEqual(ivatar.wsgi.application.__class__,
|
||||
django.core.handlers.wsgi.WSGIHandler)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'''
|
||||
ivatar URL Configuration
|
||||
ivatar URL configuration
|
||||
'''
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
@@ -9,15 +9,15 @@ from django.views.generic import TemplateView
|
||||
from ivatar import settings
|
||||
from . views import AvatarImageView
|
||||
|
||||
urlpatterns = [
|
||||
urlpatterns = [ # pylint: disable=invalid-name
|
||||
path('admin/', admin.site.urls),
|
||||
url('openid/', include('django_openid_auth.urls')),
|
||||
url('accounts/', include('ivatar.ivataraccount.urls')),
|
||||
url(
|
||||
'avatar/(?P<digest>\w{64})',
|
||||
r'avatar/(?P<digest>\w{64})',
|
||||
AvatarImageView.as_view(), name='avatar_view'),
|
||||
url(
|
||||
'avatar/(?P<digest>\w{32})',
|
||||
r'avatar/(?P<digest>\w{32})',
|
||||
AvatarImageView.as_view(), name='avatar_view'),
|
||||
url('', TemplateView.as_view(template_name='home.html')),
|
||||
]
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
'''
|
||||
Simple module providing reusable random_string function
|
||||
'''
|
||||
import random
|
||||
import string
|
||||
|
||||
|
||||
def random_string(len=10):
|
||||
def random_string(length=10):
|
||||
'''
|
||||
Return some random string with default length 10
|
||||
'''
|
||||
return ''.join(random.SystemRandom().choice(
|
||||
string.ascii_lowercase + string.digits) for _ in range(10))
|
||||
string.ascii_lowercase + string.digits) for _ in range(length))
|
||||
|
||||
@@ -5,6 +5,7 @@ import io
|
||||
from django.views.generic.base import TemplateView
|
||||
from django.http import HttpResponse
|
||||
from . ivataraccount.models import ConfirmedEmail, ConfirmedOpenId
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
||||
|
||||
class AvatarImageView(TemplateView):
|
||||
@@ -29,13 +30,14 @@ class AvatarImageView(TemplateView):
|
||||
|
||||
try:
|
||||
obj = model.objects.get(digest=kwargs['digest'])
|
||||
except model.DoesNotExist:
|
||||
except ObjectDoesNotExist:
|
||||
# TODO: Use default!?
|
||||
raise Exception('Mail/openid ("%s") does not exist"' %
|
||||
kwargs['digest'])
|
||||
if not obj.photo:
|
||||
# That is hacky, but achieves what we want :-)
|
||||
attr = getattr(obj, 'email', obj.openid)
|
||||
# TODO: Use default!?
|
||||
raise Exception('No photo assigned to "%s"' % attr)
|
||||
|
||||
return HttpResponse(
|
||||
|
||||
@@ -13,4 +13,4 @@ from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ivatar.settings")
|
||||
|
||||
application = get_wsgi_application()
|
||||
application = get_wsgi_application() # pylint: disable=invalid-name
|
||||
|
||||
Reference in New Issue
Block a user