Merge branch 'devel' into gandi-sponsor

This commit is contained in:
Oliver Falk
2021-09-10 11:45:18 +02:00
12 changed files with 125 additions and 18 deletions

View File

@@ -5,6 +5,11 @@ omit =
node_modules/*
.virtualenv/*
import_libravatar.py
requirements.txt
static/admin/*
static/humans.txt
static/img/robots.txt
[html]
extra_css = coverage_extra_style.css

View File

@@ -1,4 +1,6 @@
image: docker.io/ofalk/fedora31-python3
image:
name: quay.io/rhn_support_ofalk/fedora34-python3
entrypoint: [ '/bin/sh', '-c' ]
before_script:
- virtualenv -p python3 /tmp/.virtualenv

View File

@@ -23,6 +23,7 @@ cd ivatar
virtualenv -p python3 .virtualenv
source .virtualenv/bin/activate
pip install -r requirements.txt
pip install pillow
~~~~
## (SQL) Migrations

View File

@@ -0,0 +1,23 @@
# Generated by Django 3.1.7 on 2021-04-13 09:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ivataraccount', '0015_auto_20200225_0934'),
]
operations = [
migrations.AddField(
model_name='unconfirmedemail',
name='last_send_date',
field=models.DateTimeField(blank=True, null=True),
),
migrations.AddField(
model_name='unconfirmedemail',
name='last_status',
field=models.TextField(blank=True, max_length=2047, null=True),
),
]

View File

@@ -0,0 +1,48 @@
# Generated by Django 3.2.3 on 2021-05-28 13:14
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ivataraccount', '0016_auto_20210413_0904'),
]
operations = [
migrations.AlterField(
model_name='confirmedemail',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='confirmedopenid',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='openidassociation',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='openidnonce',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='photo',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='unconfirmedemail',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterField(
model_name='unconfirmedopenid',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
]

View File

@@ -347,6 +347,8 @@ class UnconfirmedEmail(BaseAccountModel):
'''
email = models.EmailField(max_length=MAX_LENGTH_EMAIL)
verification_key = models.CharField(max_length=64)
last_send_date = models.DateTimeField(null=True, blank=True)
last_status = models.TextField(max_length=2047, null=True, blank=True)
class Meta: # pylint: disable=too-few-public-methods
'''
@@ -357,6 +359,7 @@ class UnconfirmedEmail(BaseAccountModel):
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
if not self.verification_key:
hash_object = hashlib.new('sha256')
hash_object.update(
urandom(1024) + self.user.username.encode('utf-8') # pylint: disable=no-member
@@ -382,11 +385,17 @@ class UnconfirmedEmail(BaseAccountModel):
'verification_link': link,
'site_name': SITE_NAME,
})
self.last_send_date = timezone.now()
self.last_status = 'OK'
# if settings.DEBUG:
# print('DEBUG: %s' % link)
try:
send_mail(
email_subject, email_body, DEFAULT_FROM_EMAIL,
[self.email])
except Exception as e:
self.last_status = "%s" % e
self.save()
return True
def __str__(self):

View File

@@ -998,7 +998,7 @@ class PasswordResetView(PasswordResetViewOriginal):
# ResetPasswordView class will silently ignore the password
# reset request
if user:
if not user.password or user.password == '!':
if not user.password or user.password.startswith('!'):
random_pass = User.objects.make_random_password()
user.set_password(random_pass)
user.save()

View File

@@ -118,4 +118,6 @@ PROJECT_ROOT = os.path.abspath(
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
from config import * # pylint: disable=wildcard-import,wrong-import-position,unused-wildcard-import

View File

@@ -7,7 +7,7 @@ from django.conf.urls import url
from django.conf.urls.static import static
from django.views.generic import TemplateView, RedirectView
from ivatar import settings
from . views import AvatarImageView, GravatarProxyView
from . views import AvatarImageView, GravatarProxyView, StatsView
urlpatterns = [ # pylint: disable=invalid-name
path('admin/', admin.site.urls),
@@ -36,6 +36,7 @@ urlpatterns = [ # pylint: disable=invalid-name
url('privacy/', TemplateView.as_view(template_name='privacy.html'), name='privacy'),
url('contact/', TemplateView.as_view(template_name='contact.html'), name='contact'),
path('talk_to_us/', RedirectView.as_view(url='/contact'), name='talk_to_us'),
url('stats/', StatsView.as_view(), name='stats'),
]
MAINTENANCE = False

View File

@@ -8,12 +8,14 @@ from urllib.request import urlopen
from urllib.error import HTTPError, URLError
from ssl import SSLError
from django.views.generic.base import TemplateView, View
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseNotFound
from django.http import HttpResponse, HttpResponseRedirect
from django.http import HttpResponseNotFound, JsonResponse
from django.core.exceptions import ObjectDoesNotExist
from django.core.cache import cache, caches
from django.utils.translation import ugettext_lazy as _
from django.urls import reverse_lazy
from django.db.models import Q
from django.contrib.auth.models import User
from PIL import Image
@@ -23,7 +25,8 @@ from pydenticon5 import Pydenticon5
import pagan
from robohash import Robohash
from ivatar.settings import AVATAR_MAX_SIZE, JPEG_QUALITY, DEFAULT_AVATAR_SIZE, CACHE_RESPONSE
from ivatar.settings import AVATAR_MAX_SIZE, JPEG_QUALITY, DEFAULT_AVATAR_SIZE
from ivatar.settings import CACHE_RESPONSE
from ivatar.settings import CACHE_IMAGES_MAX_AGE
from . ivataraccount.models import ConfirmedEmail, ConfirmedOpenId
from . ivataraccount.models import pil_format, file_format
@@ -60,7 +63,8 @@ class CachingHttpResponse(HttpResponse):
'''
Handle caching of response
'''
def __init__(self, uri, content=b'', content_type=None, status=200, reason=None, charset=None): # pylint: disable=too-many-arguments
def __init__(self, uri, content=b'', content_type=None, status=200, # pylint: disable=too-many-arguments
reason=None, charset=None):
if CACHE_RESPONSE:
caches['filesystem'].set(uri, {
'content': content,
@@ -394,3 +398,17 @@ class GravatarProxyView(View):
# We shouldn't reach this point... But make sure we do something
return redir_default(default)
class StatsView(TemplateView, JsonResponse):
'''
Return stats
'''
def get(self, request, *args, **kwargs): # pylint: disable=too-many-branches,too-many-statements,too-many-locals,no-self-use,unused-argument,too-many-return-statements
retval = {
'users': User.objects.all().count(),
'mails': ConfirmedEmail.objects.all().count(),
'openids': ConfirmedOpenId.objects.all().count(), # pylint: disable=no-member
}
return JsonResponse(retval)

View File

@@ -1,7 +1,7 @@
autopep8
bcrypt
defusedxml
Django<3.2
Django
django-auth-ldap
django-bootstrap4
django-coverage-plugin

View File

@@ -14,9 +14,7 @@
There are a few ways to get in touch with the ivatar/libravatar developers:
<h4 style="margin-top: 2rem;margin-bottom: 1rem;">IRC</h4>
If you have an IRC client already, you can join #libravatar on chat.freenode.net.
<br/>
Otherwise, you can use this <a href="http://webchat.freenode.net/?channels=libravatar" title="http://webchat.freenode.net/?channels=libravatar">simple web interface</a>.
You can join the Libravatar community chat at <a href="https://matrix.to/#/#libravatar:matrix.org?via=shivering-isles.com&via=matrix.org&via=foad.me.uk" title="Libravatar on Matrix">#libravatar:matrix.org</a>. It is also bridged to #libravatar on irc.<a href="https://libera.chat/">libera.chat</a> for those prefering IRC.
<br/>
Please keep in mind that you may live in a different timezone than most of the developers. So if you do not get a response, it's not because we're ignoring you, it's probably because we're sleeping :)