33 Commits

Author SHA1 Message Date
Oliver Falk
aa6d9945af Merge branch 'devel' into redesign 2022-02-18 14:02:52 +01:00
Oliver Falk
3e43deff9d Merge branch 'devel' into redesign 2021-09-16 13:36:14 +02:00
Oliver Falk
c13de44e0f Merge branch 'devel' into redesign 2021-09-10 13:02:27 +02:00
Oliver Falk
1e32c5ee84 Merge branch 'devel' into redesign 2021-09-10 11:27:36 +02:00
Oliver Falk
3484122ce1 Merge branch 'devel' into redesign 2020-11-13 13:56:05 +01:00
Lukas Schönsgibl
00e3c67a6e change view if just one confirmed openid or confirmed emailaccount 2020-10-21 06:58:57 +02:00
Lukas Schönsgibl
414d1125a2 fix hover on mobile profile page 2020-10-21 06:35:15 +02:00
Lukas Schönsgibl
25b0d59e51 Merge branch 'redesign' of https://git.linux-kernel.at/oliver/ivatar into redesign 2020-10-21 06:25:32 +02:00
Oliver Falk
aaf5fd6a01 Merge branch 'redesign' of git.linux-kernel.at:oliver/ivatar into redesign 2020-10-19 11:21:14 +02:00
Oliver Falk
73dcf70287 Add some space between buttons and ID 2020-10-19 11:21:01 +02:00
Lukas Schönsgibl
c00979c0ae js typo 2020-10-17 08:42:05 +02:00
Lukas Schönsgibl
22b4e5224f mobile polish profile page 2020-10-17 08:33:09 +02:00
Lukas Schönsgibl
8fcd64d20c grid width profile page 2020-10-13 16:01:55 +02:00
Lukas Schönsgibl
f7476ca700 dimension libravatar nobody pic 2020-10-13 15:24:23 +02:00
Oliver Falk
d861fc315a No longer shorten the OpenID URL 2020-10-13 15:14:07 +02:00
Lukas Schönsgibl
bfdbb8393e css style alert message 2020-10-12 20:52:59 +02:00
Lukas Schönsgibl
71a3fc0f81 active top line 2020-10-12 20:35:47 +02:00
Lukas Schönsgibl
e1882a9515 hover active profile 2020-10-12 20:32:51 +02:00
Lukas Schönsgibl
37382700ec mobile optimization 2020-10-11 05:12:37 +02:00
Lukas Schönsgibl
0519da3262 optimize profile view fordisabled javascript 2020-10-11 05:00:26 +02:00
Lukas Schönsgibl
34a6d26b3e more opacity background active container 2020-10-10 20:58:35 +02:00
Lukas Schönsgibl
5aac1a42aa active class on profile 2020-10-10 20:56:17 +02:00
Lukas Schönsgibl
849a5f28f8 max 80px img 2020-10-10 08:36:30 +02:00
Lukas Schönsgibl
2b5c01847b styling for openID 2020-10-10 08:25:02 +02:00
Lukas Schönsgibl
84557711e5 change setup profile on email 2020-10-10 08:23:03 +02:00
Lukas Schönsgibl
7d9ded3644 hover pure css style 2020-10-07 17:37:56 +02:00
Lukas Schönsgibl
d5294cd8c7 font weight 2020-10-07 08:17:20 +02:00
Lukas Schönsgibl
aace95962c grey/black coloring profile page 2020-10-07 07:59:20 +02:00
Lukas Schönsgibl
539f3a98ac alert text debug 2020-10-07 07:01:56 +02:00
Lukas Schönsgibl
eddeb9028f base setup grid profile page 2020-10-07 06:58:54 +02:00
Lukas Schönsgibl
95776f120b grid style first profile page site 2020-10-06 21:48:12 +02:00
Lukas Schönsgibl
a6b8245ec3 profile page grid style 2020-10-06 20:16:52 +02:00
Lukas Schönsgibl
669f0bf71e add .DSStore into gitignore 2020-10-06 11:10:30 +02:00
10 changed files with 26 additions and 323 deletions

View File

@@ -14,7 +14,6 @@ before_script:
test_and_coverage:
stage: test
coverage: '/^TOTAL.*\s+(\d+\%)$/'
script:
- echo 'from ivatar.settings import TEMPLATES' > config_local.py
- echo 'TEMPLATES[0]["OPTIONS"]["debug"] = True' >> config_local.py

View File

@@ -4,16 +4,16 @@ repos:
hooks:
- id: check-useless-excludes
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.6.2
rev: v2.4.0
hooks:
- id: prettier
files: \.(css|js|md|markdown|json)
- repo: https://github.com/python/black
rev: 22.3.0
rev: 21.9b0
hooks:
- id: black
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.2.0
rev: v4.0.1
hooks:
- id: check-added-large-files
- id: check-ast
@@ -57,11 +57,11 @@ repos:
types:
- shell
- repo: https://github.com/asottile/blacken-docs
rev: v1.12.1
rev: v1.11.0
hooks:
- id: blacken-docs
- repo: https://github.com/hcodes/yaspeller.git
rev: v8.0.1
rev: v7.0.0
hooks:
- id: yaspeller

View File

@@ -1,6 +1,6 @@
# Installation
## Prerequisites
## Prequisits
Python 3.x + virtualenv
@@ -10,13 +10,6 @@ Python 3.x + virtualenv
yum install python34-virtualenv.noarch
```
### Debian 11
```
sudo apt-get update
sudo apt-get install git python3-virtualenv libmariadb-dev libldap2-dev libsasl2-dev
```
## Checkout
~~~~bash
@@ -29,8 +22,8 @@ cd ivatar
~~~~bash
virtualenv -p python3 .virtualenv
source .virtualenv/bin/activate
pip install pillow
pip install -r requirements.txt
pip install pillow
~~~~
## (SQL) Migrations

View File

@@ -211,72 +211,19 @@ CACHE_RESPONSE = True
# Trusted URLs for default redirection
TRUSTED_DEFAULT_URLS = [
{
"schemes": [
"https"
],
"host_equals": "ui-avatars.com",
"path_prefix": "/api/"
},
{
"schemes": [
"http",
"https"
],
"host_equals": "gravatar.com",
"path_prefix": "/avatar/"
},
{
"schemes": [
"http",
"https"
],
"host_suffix": ".gravatar.com",
"path_prefix": "/avatar/"
},
{
"schemes": [
"http",
"https"
],
"host_equals": "www.gravatar.org",
"path_prefix": "/avatar/"
},
{
"schemes": [
"https"
],
"host_equals": "avatars.dicebear.com",
"path_prefix": "/api/"
},
{
"schemes": [
"https"
],
"host_equals": "badges.fedoraproject.org",
"path_prefix": "/static/img/"
},
{
"schemes": [
"http",
],
"host_equals": "www.planet-libre.org",
"path_prefix": "/themes/planetlibre/images/"
},
{
"schemes": [
"https"
],
"host_equals": "www.azuracast.com",
"path_prefix": "/img/"
},
{
"schemes": [
"https"
],
"host_equals": "reps.mozilla.org",
"path_prefix": "/static/base/img/remo/"
}
"https://ui-avatars.com/api/",
"http://gravatar.com/avatar/",
"https://gravatar.com/avatar/",
"http://www.gravatar.org/avatar/",
"https://www.gravatar.org/avatar/",
"https://secure.gravatar.com/avatar/",
"http://0.gravatar.com/avatar/",
"https://0.gravatar.com/avatar/",
"https://avatars.dicebear.com/api/",
"https://badges.fedoraproject.org/static/img/",
"http://www.planet-libre.org/themes/planetlibre/images/",
"https://www.azuracast.com/img/",
"https://reps.mozilla.org/static/base/img/remo/",
]
# This MUST BE THE LAST!

View File

@@ -1,78 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Import a CSV - Format as follows:
<mailaddr>,<path_to_image>
Example:
myuser@mydomain.tld,myphoto.jpeg
This will create or update an existing user and assign the image
to the given address.
"""
import os
from os.path import isfile
import sys
from io import BytesIO
import csv
import django
os.environ.setdefault(
"DJANGO_SETTINGS_MODULE", "ivatar.settings"
) # pylint: disable=wrong-import-position
django.setup() # pylint: disable=wrong-import-position
from django.contrib.auth.models import User
from PIL import Image
from ivatar.settings import JPEG_QUALITY
from ivatar.ivataraccount.models import ConfirmedEmail
from ivatar.ivataraccount.models import Photo
from ivatar.ivataraccount.models import file_format
if len(sys.argv) < 2:
print("First argument to '%s' must be the path to the CSV" % sys.argv[0])
exit(-255)
if not isfile(sys.argv[1]):
print("First argument to '%s' must be a path to the CSV" % sys.argv[0])
exit(-255)
PATH = sys.argv[1]
with open(PATH, newline="") as csvfile:
contactreader = csv.reader(csvfile, delimiter=",")
for row in contactreader:
mailaddr = row[0]
image = row[1]
if not isfile(image):
print("File '%s' doesn't exist - cannot add" % image)
continue
print("Adding: %s" % mailaddr)
(user, created) = User.objects.get_or_create(username=mailaddr)
if not user.confirmedemail_set.count() < 1:
ConfirmedEmail.objects.get_or_create(
email=mailaddr,
user=user,
)
user.save()
with open(image, "rb") as avatar:
pilobj = Image.open(avatar)
out = BytesIO()
pilobj.save(out, pilobj.format, quality=JPEG_QUALITY)
out.seek(0)
photo = None
if user.photo_set.count() < 1:
photo = Photo()
photo.user = user
else:
photo = user.photo_set.first()
photo.ip_address = "0.0.0.0"
photo.format = file_format(pilobj.format)
photo.data = out.read()
photo.save()
print("xxx: %s" % user.confirmedemail_set.first())
confirmed_email = user.confirmedemail_set.first()
confirmed_email.photo_id = photo.id
confirmed_email.save()

View File

@@ -113,7 +113,7 @@
</li>
<li class="email-delete">
<button type="submit" class="nobutton" onclick="return confirm('{% trans 'Are you sure that you want to delete this email address?' %}')">
Delete Email Address
Delete Email Adress
</button>
</li>
</ul>
@@ -135,7 +135,7 @@
</li>
<li class="email-delete">
<button type="submit" class="nobutton" onclick="return confirm('{% trans 'Are you sure that you want to delete this email address?' %}')">
Delete Email Address
Delete Email Adress
</button>
</li>
</ul>

View File

@@ -1830,63 +1830,4 @@ class Tester(TestCase): # pylint: disable=too-many-public-methods
Test if uploading export works
"""
# Ensure we have data in place
self.test_export()
self.login()
self.client.get(reverse("export"))
response = self.client.post(
reverse("export"),
{},
follow=False,
)
self.assertIsInstance(response.content, bytes)
fh_gzip = gzip.open(BytesIO(response.content), "rb")
fh = BytesIO(response.content)
response = self.client.post(
reverse("upload_export"),
data={"not_porn": "on", "can_distribute": "on", "export_file": fh_gzip},
follow=True,
)
fh_gzip.close()
self.assertEqual(response.status_code, 200, "Upload worked")
self.assertContains(
response,
"Unable to parse file: Not a gzipped file",
1,
200,
"Upload didn't work?",
)
# Second test - correctly gzipped content
response = self.client.post(
reverse("upload_export"),
data={"not_porn": "on", "can_distribute": "on", "export_file": fh},
follow=True,
)
fh.close()
self.assertEqual(response.status_code, 200, "Upload worked")
self.assertContains(
response,
"Choose items to be imported",
1,
200,
"Upload didn't work?",
)
self.assertContains(
response,
"asdf@asdf.local",
2,
200,
"Upload didn't work?",
)
def test_prefs_page(self):
"""
Test if preferences page works
"""
self.client.get(reverse("user_preference"))
self.client.get(reverse("upload_export"))

View File

@@ -5,7 +5,7 @@ Test our utils from ivatar.utils
from django.test import TestCase
from ivatar.utils import is_trusted_url, openid_variations
from ivatar.utils import openid_variations
class Tester(TestCase):
@@ -45,60 +45,3 @@ class Tester(TestCase):
self.assertEqual(openid_variations(openid3)[1], openid1)
self.assertEqual(openid_variations(openid3)[2], openid2)
self.assertEqual(openid_variations(openid3)[3], openid3)
def test_is_trusted_url(self):
test1 = is_trusted_url("https://gravatar.com/avatar/63a75a80e6b1f4adfdb04c1ca02e596c", [
{
"schemes": [
"http",
"https"
],
"host_equals": "gravatar.com",
"path_prefix": "/avatar/"
}
])
self.assertTrue(test1)
test2 = is_trusted_url("https://gravatar.com.example.org/avatar/63a75a80e6b1f4adfdb04c1ca02e596c", [
{
"schemes": [
"http",
"https"
],
"host_suffix": ".gravatar.com",
"path_prefix": "/avatar/"
}
])
self.assertFalse(test2)
# Test against open redirect with valid URL in query params
test3 = is_trusted_url("https://github.com/SethFalco/?boop=https://secure.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50", [
{
"schemes": [
"http",
"https"
],
"host_suffix": ".gravatar.com",
"path_prefix": "/avatar/"
}
])
self.assertFalse(test3)
test4 = is_trusted_url("https://ui-avatars.com/api/blah", [
{
"schemes": [
"https"
],
"host_equals": "ui-avatars.com",
"path_prefix": "/api/"
},
{
"schemes": [
"http",
"https"
],
"host_suffix": ".gravatar.com",
"path_prefix": "/avatar/"
}
])
self.assertTrue(test4)

View File

@@ -5,7 +5,6 @@ Simple module providing reusable random_string function
import random
import string
from PIL import Image, ImageDraw
from urllib.parse import urlparse
def random_string(length=10):
@@ -113,42 +112,3 @@ def mm_ng(
)
return image
def is_trusted_url(url, url_filters):
"""
Check if a URL is valid and considered a trusted URL.
If the URL is malformed, returns False.
Based on: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/events/UrlFilter
"""
(scheme, netloc, path, params, query, fragment) = urlparse(url)
for filter in url_filters:
if "schemes" in filter:
schemes = filter["schemes"]
if scheme not in schemes:
continue
if "host_equals" in filter:
host_equals = filter["host_equals"]
if netloc != host_equals:
continue
if "host_suffix" in filter:
host_suffix = filter["host_suffix"]
if not netloc.endswith(host_suffix):
continue
if "path_prefix" in filter:
path_prefix = filter["path_prefix"]
if not path.startswith(path_prefix):
continue
return True
return False

View File

@@ -34,7 +34,7 @@ from .ivataraccount.models import ConfirmedEmail, ConfirmedOpenId
from .ivataraccount.models import UnconfirmedEmail, UnconfirmedOpenId
from .ivataraccount.models import Photo
from .ivataraccount.models import pil_format, file_format
from .utils import is_trusted_url, mm_ng
from .utils import mm_ng
URL_TIMEOUT = 5 # in seconds
@@ -146,9 +146,7 @@ class AvatarImageView(TemplateView):
# Check for :// (schema)
if default is not None and default.find("://") > 0:
# Check if it's trusted, if not, reset to None
trusted_url = is_trusted_url(default, TRUSTED_DEFAULT_URLS)
if not trusted_url:
if not any(x in default for x in TRUSTED_DEFAULT_URLS):
print(
"Default URL is not in trusted URLs: '%s' ; Kicking it!" % default
)