From 7b49a53da51a49caff78b2f596184ad26bafba53 Mon Sep 17 00:00:00 2001 From: leora Date: Sat, 10 Oct 2026 12:36:36 +0800 Subject: [PATCH] human_signup: clear error when the Gitea account's grant was already claimed under another handle --- coffer/product.py | 5 +++++ tests/test_people.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/coffer/product.py b/coffer/product.py index de7dc88..671e929 100644 --- a/coffer/product.py +++ b/coffer/product.py @@ -565,6 +565,11 @@ class CofferProduct: raise ProductError("gitea_id is required") key = f"signup_grant:gitea:{gid}" with self._atomic(): + row = self.db.execute("SELECT order_id FROM idempotency WHERE key=?", (key,)).fetchone() + if row is not None and row["order_id"].split("|", 1)[-1] != aid: + # Same Gitea user, different handle (e.g. a renamed account): the grant already went + # to the earlier wallet and is never given twice. + raise ProductError("signup grant already claimed for this Gitea account under another handle") seen = self._claim(key, aid) if seen is not None: self.db.commit() diff --git a/tests/test_people.py b/tests/test_people.py index a7b699b..d411772 100644 --- a/tests/test_people.py +++ b/tests/test_people.py @@ -33,7 +33,7 @@ class PeopleTests(unittest.TestCase): def test_grant_keyed_on_gitea_id_rename_and_concurrency(self): self.p.human_signup("sam", 101) - with self.assertRaises(ProductError): # rename: the Gitea id already had its grant + with self.assertRaisesRegex(ProductError, "already claimed for this Gitea account under another handle"): # rename self.p.human_signup("sam-renamed", 101) self.assertEqual(self.p.balance("human:sam-renamed")["spendable"], 0.0) import threading