From 88b7c8d9e2cf72d0c8ad9877b561f1e7ceafaa86 Mon Sep 17 00:00:00 2001
From: Changaco
Date: Wed, 27 Mar 2024 11:24:26 +0100
Subject: [PATCH 1/5] fix size of large icons
---
style/base/icons.scss | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/style/base/icons.scss b/style/base/icons.scss
index b2ad68837..dcc9e64ec 100644
--- a/style/base/icons.scss
+++ b/style/base/icons.scss
@@ -12,6 +12,6 @@
width: 17px;
}
.icon-32 {
- height: 32px;
- width: 32px;
+ height: 34px;
+ width: 34px;
}
From 65e36bcd7448e5e304ee3edc00fe80d11a53c7ef Mon Sep 17 00:00:00 2001
From: Changaco
Date: Thu, 28 Mar 2024 23:21:10 +0100
Subject: [PATCH 2/5] fix tooltips on icons
---
templates/macros/icons.html | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/templates/macros/icons.html b/templates/macros/icons.html
index aac072f32..9a1501651 100644
--- a/templates/macros/icons.html
+++ b/templates/macros/icons.html
@@ -48,8 +48,9 @@
% macro icon(name, sr='', size=16)
% set name = icon_aliases.get(name, name)
% if soft_assert(name in website.icon_names, "unknown icon name %r" % name)
-
+
% else
% endif
From 0bf4db74d096f90922eba12d5e1846f8f04ea6ac Mon Sep 17 00:00:00 2001
From: Changaco
Date: Thu, 4 Apr 2024 12:29:10 +0200
Subject: [PATCH 3/5] show payment instrument counts in `/admin/users`
---
README.md | 2 +-
www/admin/users.spt | 26 ++++++++++++++++++++++++++
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 867904bd3..fbba66092 100644
--- a/README.md
+++ b/README.md
@@ -75,7 +75,7 @@ Make sure you have the following dependencies installed first:
- python ≥ 3.11
- including the C headers of python and libffi, which are packaged separately in many Linux distributions
-- postgresql 13 (see [the official download & install docs](https://www.postgresql.org/download/))
+- postgresql 16 (see [the official download & install docs](https://www.postgresql.org/download/))
- make
Then run:
diff --git a/www/admin/users.spt b/www/admin/users.spt
index 34c3fb432..e366430e7 100644
--- a/www/admin/users.spt
+++ b/www/admin/users.spt
@@ -9,6 +9,11 @@ PT_STATUS_MAP = {
}
ACCOUNT_MARKS = set(website.db.one("SELECT array_to_json(enum_range(NULL::account_mark))"))
ACCOUNT_MARKS.add('')
+PAYMENT_INSTRUMENT_TYPES = {
+ 'paypal': "PayPal",
+ 'stripe-card': "card",
+ 'stripe-sdd': "SEPA mandate",
+}
[---]
@@ -101,6 +106,14 @@ if mode == 'all':
WHERE tip.tipper = p.id
) tip
) AS outgoing_donations
+ , ( SELECT json_objectagg(r.network:r.count)
+ FROM ( SELECT r.network, count(*) AS count
+ FROM exchange_routes r
+ WHERE r.participant = p.id
+ GROUP BY r.network
+ ORDER BY r.network
+ ) r
+ ) AS payment_instruments
, ( SELECT json_agg(json_build_object(
'provider', a.provider,
'id', a.id,
@@ -346,6 +359,19 @@ title = "Users Admin"
none.
% endif
+
+ % if row.payment_instruments is defined
+ Payment instruments:
+ % if row.payment_instruments
+ % for network, count in row.payment_instruments.items()
+ {{ count }} {{ PAYMENT_INSTRUMENT_TYPES.get(network, network) }}
+ {{- '' if count == 1 else 's' }}
+ {{- '.' if loop.last else ',' }}
+ % endfor
+ % else
+ none.
+ % endif
+ % endif
% endif
Payment accounts:
From 4edcdfe881f769b586e0f0f5e1c1a165bdffd40a Mon Sep 17 00:00:00 2001
From: Changaco
Date: Thu, 4 Apr 2024 12:29:21 +0200
Subject: [PATCH 4/5] disallow claiming a purely numerical username
---
liberapay/exceptions.py | 5 +++++
liberapay/models/participant.py | 7 ++++++-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/liberapay/exceptions.py b/liberapay/exceptions.py
index c78e2ede5..6b09ab965 100644
--- a/liberapay/exceptions.py
+++ b/liberapay/exceptions.py
@@ -126,6 +126,11 @@ def msg(self, _):
return _("The username '{0}' contains invalid characters.", self.username)
+class UsernameIsPurelyNumerical(UsernameError):
+ def msg(self, _):
+ return _("The username '{0}' is purely numerical. This isn't allowed.")
+
+
class UsernameIsRestricted(UsernameError):
def msg(self, _):
return _("The username '{0}' is restricted.", self.username)
diff --git a/liberapay/models/participant.py b/liberapay/models/participant.py
index fc645de72..0812ec803 100644
--- a/liberapay/models/participant.py
+++ b/liberapay/models/participant.py
@@ -65,6 +65,7 @@
UsernameContainsInvalidCharacters,
UsernameEndsWithForbiddenSuffix,
UsernameIsEmpty,
+ UsernameIsPurelyNumerical,
UsernameIsRestricted,
UsernameTooLong,
ValueTooLong,
@@ -2048,6 +2049,9 @@ def check_username(suggested):
if set(suggested) - ASCII_ALLOWED_IN_USERNAME:
raise UsernameContainsInvalidCharacters(suggested)
+ if suggested.isdigit():
+ raise UsernameIsPurelyNumerical(suggested)
+
if suggested[0] == '.':
raise UsernameBeginsWithRestrictedCharacter(suggested)
@@ -2059,7 +2063,8 @@ def check_username(suggested):
raise UsernameIsRestricted(suggested)
def change_username(self, suggested, cursor=None, recorder=None):
- self.check_username(suggested)
+ if suggested != f'~{self.id}':
+ self.check_username(suggested)
recorder_id = getattr(recorder, 'id', None)
if suggested != self.username:
From e46f711a3246cd549d99ddb97b745b31e2b92c83 Mon Sep 17 00:00:00 2001
From: Changaco
Date: Tue, 9 Apr 2024 16:49:21 +0200
Subject: [PATCH 5/5] protect cron jobs from database outages/migrations
fixes LIBERAPAYCOM-24T
---
liberapay/cron.py | 49 ++++++++++++++++++++++++++++++-----------------
1 file changed, 31 insertions(+), 18 deletions(-)
diff --git a/liberapay/cron.py b/liberapay/cron.py
index f14171e85..b6ab3b048 100644
--- a/liberapay/cron.py
+++ b/liberapay/cron.py
@@ -172,30 +172,43 @@ def f():
self.running = False
self.cron.website.tell_sentry(e)
if self.exclusive:
- try:
- self.cron.website.db.run("""
- INSERT INTO cron_jobs
- (name, last_error_time, last_error)
- VALUES (%s, current_timestamp, %s)
- ON CONFLICT (name) DO UPDATE
- SET last_error_time = excluded.last_error_time
- , last_error = excluded.last_error
- """, (func_name, traceback.format_exc()))
- except psycopg2.OperationalError:
- pass
+ while True:
+ try:
+ self.cron.website.db.run("""
+ INSERT INTO cron_jobs
+ (name, last_error_time, last_error)
+ VALUES (%s, current_timestamp, %s)
+ ON CONFLICT (name) DO UPDATE
+ SET last_error_time = excluded.last_error_time
+ , last_error = excluded.last_error
+ """, (func_name, traceback.format_exc()))
+ except psycopg2.OperationalError as e:
+ self.cron.website.tell_sentry(e)
+ # retry in a minute
+ sleep(60)
+ else:
+ break
# retry in a minute
sleep(60)
continue
else:
self.running = False
if self.exclusive:
- self.cron.website.db.run("""
- INSERT INTO cron_jobs
- (name, last_success_time)
- VALUES (%s, current_timestamp)
- ON CONFLICT (name) DO UPDATE
- SET last_success_time = excluded.last_success_time
- """, (func_name,))
+ while True:
+ try:
+ self.cron.website.db.run("""
+ INSERT INTO cron_jobs
+ (name, last_success_time)
+ VALUES (%s, current_timestamp)
+ ON CONFLICT (name) DO UPDATE
+ SET last_success_time = excluded.last_success_time
+ """, (func_name,))
+ except psycopg2.OperationalError:
+ self.cron.website.tell_sentry(e)
+ # retry in a minute
+ sleep(60)
+ else:
+ break
if period == 'irregular':
if r is None:
return