From 5f440b9e06b278ea7c59d61b3a0137702795680e Mon Sep 17 00:00:00 2001 From: Changaco Date: Tue, 10 Sep 2024 09:33:32 +0200 Subject: [PATCH 1/9] handle all exceptions in `Cron._wait_for_lock()` fixes LIBERAPAYCOM-279 --- liberapay/cron.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/liberapay/cron.py b/liberapay/cron.py index 4b9526cfb..d455186d1 100644 --- a/liberapay/cron.py +++ b/liberapay/cron.py @@ -38,20 +38,23 @@ def __call__(self, period, func, exclusive=False): job.start() def _wait_for_lock(self): - if self.conn: + if self._lock_thread: return # Already waiting - self.conn = self.website.db.get_connection().__enter__() def f(): while True: try: g() - except psycopg2.errors.IdleInTransactionSessionTimeout: + except Exception as e: + if not isinstance(e, psycopg2.errors.IdleInTransactionSessionTimeout): + self.website.tell_sentry(e) if self.has_lock: self.has_lock = False + self.conn = None sleep(10) - self.conn = self.website.db.get_connection().__enter__() def g(): + if not self.conn: + self.conn = self.website.db.get_connection().__enter__() cursor = self.conn.cursor() while True: if cursor.one("SELECT pg_try_advisory_lock(0)"): From 0cfdb9bca2a15df606217946f0e11d65af804e22 Mon Sep 17 00:00:00 2001 From: Changaco Date: Fri, 20 Sep 2024 23:26:19 +0200 Subject: [PATCH 2/9] prevent visual overflow in `/admin/email-domains` --- www/admin/email-domains.spt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/admin/email-domains.spt b/www/admin/email-domains.spt index e92f6bab6..459b953f8 100644 --- a/www/admin/email-domains.spt +++ b/www/admin/email-domains.spt @@ -357,7 +357,7 @@ title = "Email Domains" % for d in email_domains - {{ d.domain }} + {{ d.domain }} {{ d.n_addresses }} % set percent_verified = d.n_verified / d.n_addresses if d.n_addresses else 1 {{ d.n_verified }} From 8cb33746efefe46c8de09af8bddc6028be411c26 Mon Sep 17 00:00:00 2001 From: Changaco Date: Sun, 22 Sep 2024 17:21:26 +0200 Subject: [PATCH 3/9] improve the detection of invalid email addresses --- liberapay/utils/emails.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/liberapay/utils/emails.py b/liberapay/utils/emails.py index c524f5502..a4ddb723b 100644 --- a/liberapay/utils/emails.py +++ b/liberapay/utils/emails.py @@ -372,20 +372,26 @@ def test_email_server(ip_address: str, email=None, timeout=None) -> None: enhanced_code, msg = parse_SMTP_reply(msg) if enhanced_code: cls, subject, detail = enhanced_code.split('.') - recipient_rejected = cls in '45' and ( + else: + cls = subject = detail = None + recipient_rejected = ( + cls and cls in '45' and ( # Address errors subject == '1' and detail in '12346' or # Mailbox errors - subject == '2' and detail in '124' or - # gamil.com SMTP server - msg.startswith("sorry, no mailbox here by that name") or - # Microsoft's SMTP server - msg.startswith("Requested action not taken: mailbox unavailable") or - # Tutanota's SMTP server - msg.endswith("Recipient address rejected: Recipient not found") - ) - if recipient_rejected: - raise EmailAddressRejected(email, msg, ip_address) + subject == '2' and detail in '124' + ) or + # gamil.com SMTP server + msg.startswith("sorry, no mailbox here by that name") or + # Microsoft's SMTP server + msg.startswith("Requested action not taken: mailbox unavailable") or + # OpenSMTPD + msg.startswith("Invalid recipient: ") or + # Tutanota's SMTP server + msg.endswith("Recipient address rejected: Recipient not found") + ) + if recipient_rejected: + raise EmailAddressRejected(email, msg, ip_address) finally: try: smtp.close() From 751271bad7612f6ac582a5710faa8d484e34aee7 Mon Sep 17 00:00:00 2001 From: Changaco Date: Mon, 23 Sep 2024 09:18:29 +0200 Subject: [PATCH 4/9] fix some information shown in `/admin/emails` --- www/admin/emails.spt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/www/admin/emails.spt b/www/admin/emails.spt index 3371af7cf..d30fc3fda 100644 --- a/www/admin/emails.spt +++ b/www/admin/emails.spt @@ -127,15 +127,15 @@ title = "Email Addresses" % if request.method != 'POST' -

Bounces and complaints

+

Blocked addresses

% if blacklist_entries
% for e in blacklist_entries

: - {{ "a complaint was received" if e.reason == 'complaint' else "a message bounced" }} - at {{ locale.format_time(e.ts.time()) }} on {{ locale.format_date(e.ts.date(), format='long') }}. + blocked since {{ locale.format_time(e.ts.time()) }} on {{ locale.format_date(e.ts.date(), format='long') }}, + reason = {{ repr(e.reason) }}

% endfor
From 8e0da5e528ab7b36cd86864cd2f1c73140b834f6 Mon Sep 17 00:00:00 2001 From: Changaco Date: Tue, 24 Sep 2024 15:26:02 +0200 Subject: [PATCH 5/9] handle another Stripe error in `exchange_route.py` fixes LIBERAPAYCOM-27D --- liberapay/models/exchange_route.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/liberapay/models/exchange_route.py b/liberapay/models/exchange_route.py index e06d71a5c..cd32a938d 100644 --- a/liberapay/models/exchange_route.py +++ b/liberapay/models/exchange_route.py @@ -220,7 +220,13 @@ def attach_stripe_source(cls, participant, source, one_off): def invalidate(self, obj=None): if self.network.startswith('stripe-'): if self.address.startswith('pm_'): - stripe.PaymentMethod.detach(self.address) + try: + stripe.PaymentMethod.detach(self.address) + except stripe.error.InvalidRequestError as e: + if "The payment method you provided is not attached " in str(e): + pass + else: + raise else: try: source = stripe.Source.retrieve(self.address).detach() From 99cf30e029472961a8c853b2cd8e51600a3f9807 Mon Sep 17 00:00:00 2001 From: Changaco Date: Tue, 24 Sep 2024 15:40:03 +0200 Subject: [PATCH 6/9] add a `marked_as` filter to `/admin/users` --- www/admin/users.spt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/www/admin/users.spt b/www/admin/users.spt index 1159b2231..7f35e71c6 100644 --- a/www/admin/users.spt +++ b/www/admin/users.spt @@ -53,6 +53,7 @@ if request.method == 'POST': last_showed = request.qs.get_int('last_showed', default=None) mode = request.qs.get('mode', 'all') if mode == 'all': + marked_as = request.qs.get('marked_as') participants = website.db.all(""" SELECT p , c.name AS c_name @@ -159,10 +160,11 @@ if mode == 'all': LEFT JOIN communities c ON c.participant = p.id LEFT JOIN feedback f ON f.participant = p.id WHERE coalesce(p.id < %s, true) + AND coalesce(p.marked_as = %s, true) AND (p.status <> 'stub' OR p.receiving > 0) ORDER BY p.id DESC LIMIT 25 - """, (last_showed,)) + """, (last_showed, marked_as)) page_end = participants[-1][0].id if participants else None elif mode == 'new_recipients': participants = website.db.all(""" From fe08cbfe3fda846542ff35c2632d1e724be4adc8 Mon Sep 17 00:00:00 2001 From: Changaco Date: Wed, 25 Sep 2024 11:16:26 +0200 Subject: [PATCH 7/9] fix `test_email_address()` fixes 12419b627996f587c2f253ee5bc7588efb44d21e, closes #2459 --- liberapay/utils/emails.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/liberapay/utils/emails.py b/liberapay/utils/emails.py index a4ddb723b..8df0e05ec 100644 --- a/liberapay/utils/emails.py +++ b/liberapay/utils/emails.py @@ -222,11 +222,11 @@ def test_email_address(email: NormalizedEmailAddress, timeout: float = 30.0): website.tell_sentry(e) exceptions.append(e) n_attempts += 1 - if n_attempts >= 3: + if n_attempts >= 10: break time_elapsed = time.monotonic() - start_time - timeout = website.app_conf.socket_timeout - time_elapsed - if timeout <= 3: + timeout -= time_elapsed + if timeout < 2: break if not success: if n_ip_addresses == 0: From c4d811eeae53d128908d78a0d71a365c70223188 Mon Sep 17 00:00:00 2001 From: Changaco Date: Thu, 26 Sep 2024 17:43:17 +0200 Subject: [PATCH 8/9] don't download fonts when `Save-Data` is `on` --- liberapay/utils/state_chain.py | 1 + style/{base/10-fonts.scss => fonts.scss} | 0 templates/layouts/base.html | 3 +++ www/assets/fonts.css.spt | 3 +++ 4 files changed, 7 insertions(+) rename style/{base/10-fonts.scss => fonts.scss} (100%) create mode 100644 www/assets/fonts.css.spt diff --git a/liberapay/utils/state_chain.py b/liberapay/utils/state_chain.py index 7af6cf510..f7dc4b2e9 100644 --- a/liberapay/utils/state_chain.py +++ b/liberapay/utils/state_chain.py @@ -22,6 +22,7 @@ def attach_environ_to_request(environ, request): except UnicodeDecodeError: request.hostname = '' request.subdomain = None + request.save_data = request.headers.get(b'Save-Data') == b'on' def create_response_object(request, website): diff --git a/style/base/10-fonts.scss b/style/fonts.scss similarity index 100% rename from style/base/10-fonts.scss rename to style/fonts.scss diff --git a/templates/layouts/base.html b/templates/layouts/base.html index 7859e5ae9..1bb6a3cee 100644 --- a/templates/layouts/base.html +++ b/templates/layouts/base.html @@ -13,6 +13,9 @@ + % if not request.save_data + + % endif % block head_alternates % if request.method in constants.SAFE_METHODS and response.code == 200 diff --git a/www/assets/fonts.css.spt b/www/assets/fonts.css.spt new file mode 100644 index 000000000..1e4b8140d --- /dev/null +++ b/www/assets/fonts.css.spt @@ -0,0 +1,3 @@ +[---] +[---] text/css via scss +@import "style/fonts"; From 03e105f8d2ad0847c3d413d1e9551dbaa0365013 Mon Sep 17 00:00:00 2001 From: Changaco Date: Sat, 28 Sep 2024 10:10:59 +0200 Subject: [PATCH 9/9] fix `/admin/users` for merged accounts --- www/admin/users.spt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/www/admin/users.spt b/www/admin/users.spt index 7f35e71c6..6e6286953 100644 --- a/www/admin/users.spt +++ b/www/admin/users.spt @@ -145,6 +145,8 @@ if mode == 'all': FROM events e WHERE e.participant = p.id AND e.type = 'sign_up_request' + ORDER BY e.ts + LIMIT 1 ) AS sign_up_request , ( SELECT row_to_json(e) FROM ( SELECT e.*, p2.username AS recorder_name