10 Commits

Author SHA1 Message Date
Oliver Falk
f359532c30 Merge branch 'devel' into 'master'
Include fix for #89

See merge request oliver/ivatar!215
2022-11-17 11:39:12 +00:00
Oliver Falk
a76d5b9225 Merge branch 'devel' into 'master'
Merge latest devel tree

See merge request oliver/ivatar!214
2022-11-17 10:54:20 +00:00
Oliver Falk
71d69dde53 Merge branch 'devel' into 'master'
v1.6.2

See merge request oliver/ivatar!213
2022-10-27 07:21:23 +00:00
Oliver Falk
0b5271424c Merge branch 'devel' into 'master'
v1.6.1: New trusted URLs handling + update security page

See merge request oliver/ivatar!212
2022-09-15 17:16:14 +00:00
Oliver Falk
a492995836 Merge branch 'devel' into 'master'
Quick fix: Add www.gravatar.com to the list of trusted URIs

See merge request oliver/ivatar!206
2022-07-15 13:21:00 +00:00
Oliver Falk
ad39324650 Merge branch 'devel' into 'master'
Additional tests to increase coverage (a bit)

See merge request oliver/ivatar!205
2022-06-28 08:57:20 +00:00
Oliver Falk
ef02feed3b Merge branch 'devel' into 'master'
Typo fix + coverage adaption

See merge request oliver/ivatar!204
2022-06-21 12:27:49 +00:00
Oliver Falk
1a10861d2f Merge branch 'devel' into 'master'
Update pre-commit + new stats

See merge request oliver/ivatar!203
2022-05-03 12:24:04 +00:00
Oliver Falk
b64f939344 Merge branch 'devel' into 'master'
Enhance stats + add tests

See merge request oliver/ivatar!201
2022-02-18 13:06:29 +00:00
Oliver Falk
ddaf6a6d8a Enhance stats + add tests 2022-02-18 13:06:29 +00:00
11 changed files with 90 additions and 172 deletions

View File

@@ -20,8 +20,6 @@ test_and_coverage:
- echo 'from ivatar.settings import TEMPLATES' > config_local.py - echo 'from ivatar.settings import TEMPLATES' > config_local.py
- echo 'TEMPLATES[0]["OPTIONS"]["debug"] = True' >> config_local.py - echo 'TEMPLATES[0]["OPTIONS"]["debug"] = True' >> config_local.py
- echo "DEBUG = True" >> config_local.py - echo "DEBUG = True" >> config_local.py
- echo "from config import CACHES" >> config_local.py
- echo "CACHES['default'] = CACHES['filesystem']" >> config_local.py
- python manage.py collectstatic --noinput - python manage.py collectstatic --noinput
- coverage run --source . manage.py test -v3 - coverage run --source . manage.py test -v3
- coverage report --fail-under=70 - coverage report --fail-under=70

View File

@@ -4,16 +4,16 @@ repos:
hooks: hooks:
- id: check-useless-excludes - id: check-useless-excludes
- repo: https://github.com/pre-commit/mirrors-prettier - repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.0.0-alpha.4 rev: v2.6.2
hooks: hooks:
- id: prettier - id: prettier
files: \.(css|js|md|markdown|json) files: \.(css|js|md|markdown|json)
- repo: https://github.com/python/black - repo: https://github.com/python/black
rev: 22.10.0 rev: 22.3.0
hooks: hooks:
- id: black - id: black
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0 rev: v4.2.0
hooks: hooks:
- id: check-added-large-files - id: check-added-large-files
- id: check-ast - id: check-ast
@@ -37,8 +37,8 @@ repos:
- id: requirements-txt-fixer - id: requirements-txt-fixer
- id: sort-simple-yaml - id: sort-simple-yaml
- id: trailing-whitespace - id: trailing-whitespace
- repo: https://github.com/PyCQA/flake8 - repo: https://gitlab.com/pycqa/flake8
rev: 5.0.4 rev: 3.9.2
hooks: hooks:
- id: flake8 - id: flake8
- repo: local - repo: local

View File

@@ -60,7 +60,7 @@ OPENID_CREATE_USERS = True
OPENID_UPDATE_DETAILS_FROM_SREG = True OPENID_UPDATE_DETAILS_FROM_SREG = True
SITE_NAME = os.environ.get("SITE_NAME", "libravatar") SITE_NAME = os.environ.get("SITE_NAME", "libravatar")
IVATAR_VERSION = "1.7.0" IVATAR_VERSION = "1.6.2"
SCHEMAROOT = "https://www.libravatar.org/schemas/export/0.2" SCHEMAROOT = "https://www.libravatar.org/schemas/export/0.2"
@@ -191,7 +191,7 @@ MESSAGE_TAGS = {
CACHES = { CACHES = {
"default": { "default": {
"BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache", "BACKEND": "django.core.cache.backends.memcached.MemcachedCache",
"LOCATION": [ "LOCATION": [
"127.0.0.1:11211", "127.0.0.1:11211",
], ],
@@ -238,7 +238,9 @@ TRUSTED_DEFAULT_URLS = [
"path_prefix": "/static/img/", "path_prefix": "/static/img/",
}, },
{ {
"schemes": ["http"], "schemes": [
"http",
],
"host_equals": "www.planet-libre.org", "host_equals": "www.planet-libre.org",
"path_prefix": "/themes/planetlibre/images/", "path_prefix": "/themes/planetlibre/images/",
}, },

View File

@@ -34,7 +34,7 @@ outline: inherit;
<button type="submit" name="photo{{ photo.id }}" class="nobutton"> <button type="submit" name="photo{{ photo.id }}" class="nobutton">
<div class="panel panel-tortin" style="width:132px;margin:0"> <div class="panel panel-tortin" style="width:132px;margin:0">
<div class="panel-heading"> <div class="panel-heading">
<h3 class="panel-title">{% if email.photo.id == photo.id %}<i class="fa fa-check"></i>{% endif %} {% trans 'Image' %} {{ forloop.counter }}</h3> <h3 class="panel-title">{% ifequal email.photo.id photo.id %}<i class="fa fa-check"></i>{% endifequal %} {% trans 'Image' %} {{ forloop.counter }}</h3>
</div> </div>
<div class="panel-body" style="height:130px"> <div class="panel-body" style="height:130px">
<center> <center>
@@ -49,7 +49,7 @@ outline: inherit;
<button type="submit" name="photoNone" class="nobutton"> <button type="submit" name="photoNone" class="nobutton">
<div class="panel panel-tortin" style="width:132px;margin:0"> <div class="panel panel-tortin" style="width:132px;margin:0">
<div class="panel-heading"> <div class="panel-heading">
<h3 class="panel-title">{% if email.photo.id == photo.id %}<i class="fa fa-check"></i>{% endif %} {% trans 'No image' %}</h3> <h3 class="panel-title">{% ifequal email.photo.id photo.id %}<i class="fa fa-check"></i>{% endifequal %} {% trans 'No image' %}</h3>
</div> </div>
<div class="panel-body" style="height:130px"> <div class="panel-body" style="height:130px">
<center> <center>

View File

@@ -34,7 +34,7 @@ outline: inherit;
<button type="submit" name="photo{{ photo.id }}" class="nobutton"> <button type="submit" name="photo{{ photo.id }}" class="nobutton">
<div class="panel panel-tortin" style="width:132px;margin:0"> <div class="panel panel-tortin" style="width:132px;margin:0">
<div class="panel-heading"> <div class="panel-heading">
<h3 class="panel-title">{% if openid.photo.id == photo.id %}<i class="fa fa-check"></i>{% endif %} {% trans 'Image' %} {{ forloop.counter }}</h3> <h3 class="panel-title">{% ifequal openid.photo.id photo.id %}<i class="fa fa-check"></i>{% endifequal %} {% trans 'Image' %} {{ forloop.counter }}</h3>
</div> </div>
<div class="panel-body" style="height:130px"> <div class="panel-body" style="height:130px">
<center> <center>
@@ -49,7 +49,7 @@ outline: inherit;
<button type="submit" name="photoNone" class="nobutton"> <button type="submit" name="photoNone" class="nobutton">
<div class="panel panel-tortin" style="width:132px;margin:0"> <div class="panel panel-tortin" style="width:132px;margin:0">
<div class="panel-heading"> <div class="panel-heading">
<h3 class="panel-title">{% if openid.photo.id == photo.id %}<i class="fa fa-check"></i>{% endif %} {% trans 'No image' %}</h3> <h3 class="panel-title">{% ifequal openid.photo.id photo.id %}<i class="fa fa-check"></i>{% endifequal %} {% trans 'No image' %}</h3>
</div> </div>
<div class="panel-body" style="height:130px"> <div class="panel-body" style="height:130px">
<center> <center>

View File

@@ -1292,37 +1292,16 @@ class Tester(TestCase): # pylint: disable=too-many-public-methods
# Simply delete it, then it's digest is 'correct', but # Simply delete it, then it's digest is 'correct', but
# the hash is no longer there # the hash is no longer there
addr = self.user.confirmedemail_set.first().email addr = self.user.confirmedemail_set.first().email
digest = hashlib.md5(addr.strip().lower().encode("utf-8")).hexdigest() hashlib.md5(addr.strip().lower().encode("utf-8")).hexdigest()
self.user.confirmedemail_set.first().delete() self.user.confirmedemail_set.first().delete()
url = "%s?%s" % (urlobj.path, urlobj.query) url = "%s?%s" % (urlobj.path, urlobj.query)
response = self.client.get(url, follow=True) response = self.client.get(url, follow=True)
self.assertEqual( self.assertRedirects(
response.redirect_chain[0][0], response=response,
"/gravatarproxy/%s?s=80" % digest, expected_url="/static/img/nobody/80.png",
"Doesn't redirect to Gravatar?", msg_prefix="Why does this not redirect to Gravatar?",
) )
self.assertEqual(
response.redirect_chain[0][1], 302, "Doesn't redirect with 302?"
)
self.assertEqual(
response.redirect_chain[1][0],
"/avatar/%s?s=80&forcedefault=y" % digest,
"Doesn't redirect with default forced on?",
)
self.assertEqual(
response.redirect_chain[1][1], 302, "Doesn't redirect with 302?"
)
self.assertEqual(
response.redirect_chain[2][0],
"/static/img/nobody/80.png",
"Doesn't redirect to static?",
)
# self.assertRedirects(
# response=response,
# expected_url="/static/img/nobody/80.png",
# msg_prefix="Why does this not redirect to Gravatar?",
# )
# Eventually one should check if the data is the same # Eventually one should check if the data is the same
def test_avatar_url_inexisting_mail_digest_gravatarproxy_disabled( def test_avatar_url_inexisting_mail_digest_gravatarproxy_disabled(
@@ -1344,17 +1323,11 @@ class Tester(TestCase): # pylint: disable=too-many-public-methods
self.user.confirmedemail_set.first().delete() self.user.confirmedemail_set.first().delete()
url = "%s?%s&gravatarproxy=n" % (urlobj.path, urlobj.query) url = "%s?%s&gravatarproxy=n" % (urlobj.path, urlobj.query)
response = self.client.get(url, follow=True) response = self.client.get(url, follow=True)
self.assertEqual( self.assertRedirects(
response.redirect_chain[0][0], response=response,
"/static/img/nobody/80.png", expected_url="/static/img/nobody/80.png",
"Doesn't redirect to static?", msg_prefix="Why does this not redirect to the default img?",
) )
# self.assertRedirects(
# response=response,
# expected_url="/static/img/nobody/80.png",
# msg_prefix="Why does this not redirect to the default img?",
# )
# Eventually one should check if the data is the same # Eventually one should check if the data is the same
def test_avatar_url_inexisting_mail_digest_w_default_mm( def test_avatar_url_inexisting_mail_digest_w_default_mm(
@@ -1388,17 +1361,11 @@ class Tester(TestCase): # pylint: disable=too-many-public-methods
) )
url = "%s?%s&gravatarproxy=n" % (urlobj.path, urlobj.query) url = "%s?%s&gravatarproxy=n" % (urlobj.path, urlobj.query)
response = self.client.get(url, follow=True) response = self.client.get(url, follow=True)
self.assertEqual( self.assertRedirects(
response.redirect_chain[0][0], response=response,
"/static/img/mm/80.png", expected_url="/static/img/mm/80.png",
"Doesn't redirect to static?", msg_prefix="Why does this not redirect to the default img?",
) )
# self.assertRedirects(
# response=response,
# expected_url="/static/img/mm/80.png",
# msg_prefix="Why does this not redirect to the default img?",
# )
# Eventually one should check if the data is the same # Eventually one should check if the data is the same
def test_avatar_url_inexisting_mail_digest_wo_default( def test_avatar_url_inexisting_mail_digest_wo_default(
@@ -1413,36 +1380,13 @@ class Tester(TestCase): # pylint: disable=too-many-public-methods
size=80, size=80,
) )
) )
digest = hashlib.md5("asdf@company.local".lower().encode("utf-8")).hexdigest()
url = "%s?%s" % (urlobj.path, urlobj.query) url = "%s?%s" % (urlobj.path, urlobj.query)
response = self.client.get(url, follow=True) response = self.client.get(url, follow=True)
self.assertEqual( self.assertRedirects(
response.redirect_chain[0][0], response=response,
"/gravatarproxy/%s?s=80" % digest, expected_url="/static/img/nobody/80.png",
"Doesn't redirect to Gravatar?", msg_prefix="Why does this not redirect to the default img?",
) )
self.assertEqual(
response.redirect_chain[0][1], 302, "Doesn't redirect with 302?"
)
self.assertEqual(
response.redirect_chain[1][0],
"/avatar/%s?s=80&forcedefault=y" % digest,
"Doesn't redirect with default forced on?",
)
self.assertEqual(
response.redirect_chain[1][1], 302, "Doesn't redirect with 302?"
)
self.assertEqual(
response.redirect_chain[2][0],
"/static/img/nobody/80.png",
"Doesn't redirect to static?",
)
# self.assertRedirects(
# response=response,
# expected_url="/static/img/nobody/80.png",
# msg_prefix="Why does this not redirect to the default img?",
# )
# Eventually one should check if the data is the same # Eventually one should check if the data is the same
def test_avatar_url_inexisting_mail_digest_wo_default_gravatarproxy_disabled( def test_avatar_url_inexisting_mail_digest_wo_default_gravatarproxy_disabled(
@@ -1459,26 +1403,17 @@ class Tester(TestCase): # pylint: disable=too-many-public-methods
) )
url = "%s?%s&gravatarproxy=n" % (urlobj.path, urlobj.query) url = "%s?%s&gravatarproxy=n" % (urlobj.path, urlobj.query)
response = self.client.get(url, follow=True) response = self.client.get(url, follow=True)
self.assertEqual( self.assertRedirects(
response.redirect_chain[0][0], response=response,
"/static/img/nobody/80.png", expected_url="/static/img/nobody/80.png",
"Doesn't redirect to static?", msg_prefix="Why does this not redirect to the default img?",
) )
# self.assertRedirects(
# response=response,
# expected_url="/static/img/nobody/80.png",
# msg_prefix="Why does this not redirect to the default img?",
# )
# Eventually one should check if the data is the same # Eventually one should check if the data is the same
def test_avatar_url_default(self): # pylint: disable=invalid-name def test_avatar_url_default(self): # pylint: disable=invalid-name
""" """
Test fetching avatar for not existing mail with default specified Test fetching avatar for not existing mail with default specified
""" """
# TODO - Find a new way
# Do not run this test, since static serving isn't allowed in testing mode
return
urlobj = urlsplit( urlobj = urlsplit(
libravatar_url( libravatar_url(
"xxx@xxx.xxx", "xxx@xxx.xxx",
@@ -1487,7 +1422,7 @@ class Tester(TestCase): # pylint: disable=too-many-public-methods
) )
) )
url = "%s?%s" % (urlobj.path, urlobj.query) url = "%s?%s" % (urlobj.path, urlobj.query)
response = self.client.get(url, follow=False) response = self.client.get(url, follow=True)
self.assertRedirects( self.assertRedirects(
response=response, response=response,
expected_url="/static/img/nobody.png", expected_url="/static/img/nobody.png",
@@ -1500,9 +1435,6 @@ class Tester(TestCase): # pylint: disable=too-many-public-methods
""" """
Test fetching avatar for not existing mail with default specified Test fetching avatar for not existing mail with default specified
""" """
# TODO - Find a new way
# Do not run this test, since static serving isn't allowed in testing mode
return
urlobj = urlsplit( urlobj = urlsplit(
libravatar_url( libravatar_url(
"xxx@xxx.xxx", "xxx@xxx.xxx",

View File

@@ -2,7 +2,8 @@
""" """
URLs for ivatar.ivataraccount URLs for ivatar.ivataraccount
""" """
from django.urls import path, re_path from django.urls import path
from django.conf.urls import url
from django.contrib.auth.views import LogoutView from django.contrib.auth.views import LogoutView
from django.contrib.auth.views import ( from django.contrib.auth.views import (
@@ -71,7 +72,7 @@ urlpatterns = [ # pylint: disable=invalid-name
), ),
path("delete/", DeleteAccountView.as_view(), name="delete"), path("delete/", DeleteAccountView.as_view(), name="delete"),
path("profile/", ProfileView.as_view(), name="profile"), path("profile/", ProfileView.as_view(), name="profile"),
re_path( url(
"profile/(?P<profile_username>.+)", "profile/(?P<profile_username>.+)",
ProfileView.as_view(), ProfileView.as_view(),
name="profile_with_profile_username", name="profile_with_profile_username",
@@ -80,77 +81,73 @@ urlpatterns = [ # pylint: disable=invalid-name
path("add_openid/", AddOpenIDView.as_view(), name="add_openid"), path("add_openid/", AddOpenIDView.as_view(), name="add_openid"),
path("upload_photo/", UploadPhotoView.as_view(), name="upload_photo"), path("upload_photo/", UploadPhotoView.as_view(), name="upload_photo"),
path("password_set/", PasswordSetView.as_view(), name="password_set"), path("password_set/", PasswordSetView.as_view(), name="password_set"),
re_path( url(
r"remove_unconfirmed_openid/(?P<openid_id>\d+)", r"remove_unconfirmed_openid/(?P<openid_id>\d+)",
RemoveUnconfirmedOpenIDView.as_view(), RemoveUnconfirmedOpenIDView.as_view(),
name="remove_unconfirmed_openid", name="remove_unconfirmed_openid",
), ),
re_path( url(
r"remove_confirmed_openid/(?P<openid_id>\d+)", r"remove_confirmed_openid/(?P<openid_id>\d+)",
RemoveConfirmedOpenIDView.as_view(), RemoveConfirmedOpenIDView.as_view(),
name="remove_confirmed_openid", name="remove_confirmed_openid",
), ),
re_path( url(
r"openid_redirection/(?P<openid_id>\d+)", r"openid_redirection/(?P<openid_id>\d+)",
RedirectOpenIDView.as_view(), RedirectOpenIDView.as_view(),
name="openid_redirection", name="openid_redirection",
), ),
re_path( url(
r"confirm_openid/(?P<openid_id>\w+)", r"confirm_openid/(?P<openid_id>\w+)",
ConfirmOpenIDView.as_view(), ConfirmOpenIDView.as_view(),
name="confirm_openid", name="confirm_openid",
), ),
re_path( url(
r"confirm_email/(?P<verification_key>\w+)", r"confirm_email/(?P<verification_key>\w+)",
ConfirmEmailView.as_view(), ConfirmEmailView.as_view(),
name="confirm_email", name="confirm_email",
), ),
re_path( url(
r"remove_unconfirmed_email/(?P<email_id>\d+)", r"remove_unconfirmed_email/(?P<email_id>\d+)",
RemoveUnconfirmedEmailView.as_view(), RemoveUnconfirmedEmailView.as_view(),
name="remove_unconfirmed_email", name="remove_unconfirmed_email",
), ),
re_path( url(
r"remove_confirmed_email/(?P<email_id>\d+)", r"remove_confirmed_email/(?P<email_id>\d+)",
RemoveConfirmedEmailView.as_view(), RemoveConfirmedEmailView.as_view(),
name="remove_confirmed_email", name="remove_confirmed_email",
), ),
re_path( url(
r"assign_photo_email/(?P<email_id>\d+)", r"assign_photo_email/(?P<email_id>\d+)",
AssignPhotoEmailView.as_view(), AssignPhotoEmailView.as_view(),
name="assign_photo_email", name="assign_photo_email",
), ),
re_path( url(
r"assign_photo_openid/(?P<openid_id>\d+)", r"assign_photo_openid/(?P<openid_id>\d+)",
AssignPhotoOpenIDView.as_view(), AssignPhotoOpenIDView.as_view(),
name="assign_photo_openid", name="assign_photo_openid",
), ),
re_path(r"import_photo/$", ImportPhotoView.as_view(), name="import_photo"), url(r"import_photo/$", ImportPhotoView.as_view(), name="import_photo"),
re_path( url(
r"import_photo/(?P<email_addr>[\w.+-]+@[\w.]+.[\w.]+)", r"import_photo/(?P<email_addr>[\w.+-]+@[\w.]+.[\w.]+)",
ImportPhotoView.as_view(), ImportPhotoView.as_view(),
name="import_photo", name="import_photo",
), ),
re_path( url(
r"import_photo/(?P<email_id>\d+)", r"import_photo/(?P<email_id>\d+)",
ImportPhotoView.as_view(), ImportPhotoView.as_view(),
name="import_photo", name="import_photo",
), ),
re_path( url(r"delete_photo/(?P<pk>\d+)", DeletePhotoView.as_view(), name="delete_photo"),
r"delete_photo/(?P<pk>\d+)", DeletePhotoView.as_view(), name="delete_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"),
re_path(r"raw_image/(?P<pk>\d+)", RawImageView.as_view(), name="raw_image"), url(r"pref/$", UserPreferenceView.as_view(), name="user_preference"),
re_path(r"crop_photo/(?P<pk>\d+)", CropPhotoView.as_view(), name="crop_photo"), url(r"upload_export/$", UploadLibravatarExportView.as_view(), name="upload_export"),
re_path(r"pref/$", UserPreferenceView.as_view(), name="user_preference"), url(
re_path(
r"upload_export/$", UploadLibravatarExportView.as_view(), name="upload_export"
),
re_path(
r"upload_export/(?P<save>save)$", r"upload_export/(?P<save>save)$",
UploadLibravatarExportView.as_view(), UploadLibravatarExportView.as_view(),
name="upload_export", name="upload_export",
), ),
re_path( url(
r"resend_confirmation_mail/(?P<email_id>\d+)", r"resend_confirmation_mail/(?P<email_id>\d+)",
ResendConfirmationMailView.as_view(), ResendConfirmationMailView.as_view(),
name="resend_confirmation_mail", name="resend_confirmation_mail",

View File

@@ -50,16 +50,11 @@ class Tester(TestCase): # pylint: disable=too-many-public-methods
Test incorrect digest Test incorrect digest
""" """
response = self.client.get("/avatar/%s" % "x" * 65, follow=True) response = self.client.get("/avatar/%s" % "x" * 65, follow=True)
self.assertEqual( self.assertRedirects(
response.redirect_chain[0][0], response=response,
"/static/img/deadbeef.png", expected_url="/static/img/deadbeef.png",
"Doesn't redirect to static?", msg_prefix="Why does an invalid hash not redirect to deadbeef?",
) )
# self.assertRedirects(
# response=response,
# expected_url="/static/img/deadbeef.png",
# msg_prefix="Why does an invalid hash not redirect to deadbeef?",
# )
def test_stats(self): def test_stats(self):
""" """

View File

@@ -3,11 +3,11 @@
ivatar/tools URL configuration ivatar/tools URL configuration
""" """
from django.urls import path, re_path from django.conf.urls import url
from .views import CheckView, CheckDomainView from .views import CheckView, CheckDomainView
urlpatterns = [ # pylint: disable=invalid-name urlpatterns = [ # pylint: disable=invalid-name
path("check/", CheckView.as_view(), name="tools_check"), url("check/", CheckView.as_view(), name="tools_check"),
path("check_domain/", CheckDomainView.as_view(), name="tools_check_domain"), url("check_domain/", CheckDomainView.as_view(), name="tools_check_domain"),
re_path("check_domain$", CheckDomainView.as_view(), name="tools_check_domain"), url("check_domain$", CheckDomainView.as_view(), name="tools_check_domain"),
] ]

View File

@@ -3,7 +3,8 @@
ivatar URL configuration ivatar URL configuration
""" """
from django.contrib import admin from django.contrib import admin
from django.urls import path, include, re_path from django.urls import path, include
from django.conf.urls import url
from django.conf.urls.static import static from django.conf.urls.static import static
from django.views.generic import TemplateView, RedirectView from django.views.generic import TemplateView, RedirectView
from ivatar import settings from ivatar import settings
@@ -12,72 +13,65 @@ from .views import AvatarImageView, GravatarProxyView, StatsView
urlpatterns = [ # pylint: disable=invalid-name urlpatterns = [ # pylint: disable=invalid-name
path("admin/", admin.site.urls), path("admin/", admin.site.urls),
path("i18n/", include("django.conf.urls.i18n")), path("i18n/", include("django.conf.urls.i18n")),
path("openid/", include("django_openid_auth.urls")), url("openid/", include("django_openid_auth.urls")),
path("tools/", include("ivatar.tools.urls")), url("tools/", include("ivatar.tools.urls")),
re_path( url(r"avatar/(?P<digest>\w{64})", AvatarImageView.as_view(), name="avatar_view"),
r"avatar/(?P<digest>\w{64})", AvatarImageView.as_view(), name="avatar_view" url(r"avatar/(?P<digest>\w{32})", AvatarImageView.as_view(), name="avatar_view"),
), url(r"avatar/$", AvatarImageView.as_view(), name="avatar_view"),
re_path( url(
r"avatar/(?P<digest>\w{32})", AvatarImageView.as_view(), name="avatar_view"
),
re_path(r"avatar/$", AvatarImageView.as_view(), name="avatar_view"),
re_path(
r"avatar/(?P<digest>\w*)", r"avatar/(?P<digest>\w*)",
RedirectView.as_view(url="/static/img/deadbeef.png"), RedirectView.as_view(url="/static/img/deadbeef.png"),
name="invalid_hash", name="invalid_hash",
), ),
re_path( url(
r"gravatarproxy/(?P<digest>\w*)", r"gravatarproxy/(?P<digest>\w*)",
GravatarProxyView.as_view(), GravatarProxyView.as_view(),
name="gravatarproxy", name="gravatarproxy",
), ),
path( url(
"description/", "description/",
TemplateView.as_view(template_name="description.html"), TemplateView.as_view(template_name="description.html"),
name="description", name="description",
), ),
# The following two are TODO TODO TODO TODO TODO # The following two are TODO TODO TODO TODO TODO
path( url(
"run_your_own/", "run_your_own/",
TemplateView.as_view(template_name="run_your_own.html"), TemplateView.as_view(template_name="run_your_own.html"),
name="run_your_own", name="run_your_own",
), ),
path( url(
"features/", "features/",
TemplateView.as_view(template_name="features.html"), TemplateView.as_view(template_name="features.html"),
name="features", name="features",
), ),
path( url(
"security/", "security/",
TemplateView.as_view(template_name="security.html"), TemplateView.as_view(template_name="security.html"),
name="security", name="security",
), ),
path( url("privacy/", TemplateView.as_view(template_name="privacy.html"), name="privacy"),
"privacy/", TemplateView.as_view(template_name="privacy.html"), name="privacy" url("contact/", TemplateView.as_view(template_name="contact.html"), name="contact"),
),
path(
"contact/", TemplateView.as_view(template_name="contact.html"), name="contact"
),
path("talk_to_us/", RedirectView.as_view(url="/contact"), name="talk_to_us"), path("talk_to_us/", RedirectView.as_view(url="/contact"), name="talk_to_us"),
path("stats/", StatsView.as_view(), name="stats"), url("stats/", StatsView.as_view(), name="stats"),
] ]
MAINTENANCE = False MAINTENANCE = False
try: try:
if settings.MAINTENANCE: if settings.MAINTENANCE:
MAINTENANCE = True MAINTENANCE = True
except Exception: # pylint: disable=bare-except except: # pylint: disable=bare-except
pass pass
if MAINTENANCE: if MAINTENANCE:
urlpatterns.append( urlpatterns.append(
path("", TemplateView.as_view(template_name="maintenance.html"), name="home") url("", TemplateView.as_view(template_name="maintenance.html"), name="home")
) )
urlpatterns.insert(3, path("accounts/", RedirectView.as_view(url="/"))) urlpatterns.insert(3, url("accounts/", RedirectView.as_view(url="/")))
else: else:
urlpatterns.append( urlpatterns.append(
path("", TemplateView.as_view(template_name="home.html"), name="home") url("", TemplateView.as_view(template_name="home.html"), name="home")
) )
urlpatterns.insert(3, path("accounts/", include("ivatar.ivataraccount.urls"))) urlpatterns.insert(3, url("accounts/", include("ivatar.ivataraccount.urls")))
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

View File

@@ -1,7 +1,7 @@
autopep8 autopep8
bcrypt bcrypt
defusedxml defusedxml
Django Django < 4.0
django-anymail[mailgun] django-anymail[mailgun]
django-auth-ldap django-auth-ldap
django-bootstrap4 django-bootstrap4
@@ -27,10 +27,10 @@ py3dns
pydocstyle pydocstyle
pyLibravatar pyLibravatar
pylint pylint
pymemcache
PyMySQL PyMySQL
python-coveralls python-coveralls
python-language-server python-language-server
python-memcached
python3-openid python3-openid
pytz pytz
rope rope