Act immediately on flagged signups Mastodon already auto-approved

account.approved never fires for a signup that went through open
registration without ever being queued (no prior block on that
address). process_signup was waiting on that event forever, so the
first flagged signup on any new bad IP/email domain never got welcomed
or watched by the suspicious-sweep. Now checks Admin::Account.approved
from the account.created payload and acts immediately if it's already
true.
This commit is contained in:
2026-07-06 13:27:15 -07:00
parent 0356fe7997
commit 51233868ca
2 changed files with 30 additions and 6 deletions
+19 -6
View File
@@ -547,7 +547,8 @@ def register_email_domain_block(domain: str, acct: str) -> None:
log.error("failed to register email_domain_block for %s (acct=%s): %s", domain, acct, exc)
def process_signup(account_id: str, acct: str, ip: str, email: str = "") -> None:
def process_signup(account_id: str, acct: str, ip: str, email: str = "",
approved: bool = False) -> None:
"""Classify a new signup's IP and email domain, and act on account.created.
Non-flagged (or both signals disabled/unavailable) signups are welcomed
@@ -555,7 +556,10 @@ def process_signup(account_id: str, acct: str, ip: str, email: str = "") -> None
either signal (datacenter IP and/or high-risk email domain) gets a
moderator DM, the matching auto-block(s) (ip_block / email_domain_block),
and — unless dry-run — has its welcome held until account.approved fires
(see _handle_account_created).
(see _handle_account_created). `approved` is the account's *current*
Admin::Account.approved state at signup time: if it's already true (open
registration, never queued), account.approved will never be delivered for
it, so the hold is lifted immediately instead of waiting forever.
"""
reasons: list[str] = []
hold = False
@@ -599,11 +603,15 @@ def process_signup(account_id: str, acct: str, ip: str, email: str = "") -> None
+ (" Welcome DM held pending approval." if hold else "")
)
if not hold:
if not hold or approved:
# Either never held, or held but Mastodon already auto-approved this
# signup (open registration, no moderator queue) — account.approved
# is not coming, so act now instead of waiting for it.
send_welcome(account_id, acct)
maybe_start_suspicious_watch(account_id, acct)
# else: held — sent later if/when account.approved fires (human review),
# which is also where maybe_start_suspicious_watch gets called.
# else: genuinely queued for a moderator's decision — sent later if/when
# account.approved fires (human review), which is also where
# maybe_start_suspicious_watch gets called.
def maybe_start_suspicious_watch(account_id: str, acct: str) -> None:
@@ -1063,7 +1071,12 @@ def _handle_account_created(obj: dict, background: BackgroundTasks, event: str):
# decide whether to welcome now or hold for account.approved.
ip = obj.get("ip") or ""
email = obj.get("email") or ""
background.add_task(process_signup, account_id, acct, ip, email)
# Admin::Account.approved is already true here for any signup that
# Mastodon auto-approved as part of open registration (no moderator
# queue involved) — account.approved never fires for those, so
# process_signup must act now instead of waiting for it.
approved = bool(obj.get("approved"))
background.add_task(process_signup, account_id, acct, ip, email, approved)
else:
# account.approved: a human has cleared the approval-required
# registration gate. Always welcome (dedup makes this safe) — this is
+11
View File
@@ -263,6 +263,17 @@ def ip_scrutiny_tests():
main.send_welcome("102", "dc1") # simulate account.approved's unconditional welcome
assert ("102", "dc1") in sent, sent
# B2. datacenter IP, held, but Mastodon already auto-approved the signup
# (open registration, never queued) -> account.approved will never
# fire, so process_signup must welcome + start the watch immediately
# instead of waiting for an event that isn't coming.
sent.clear(); dms.clear(); ipblocks.clear()
classifications["198.51.100.22"] = ("datacenter", "Example Cloud Hosting Inc", True)
main.process_signup("104", "dc3", "198.51.100.22", "", True)
assert ("104", "dc3") in sent, "already-approved flagged signup must be welcomed immediately"
assert main.get_signup_flag("104") is True
assert main.already_watched_suspicious("104"), "already-approved flagged signup must start its watch immediately"
# C. same datacenter IP, but IP_SCRUTINY_DRY_RUN -> welcomed immediately
# (no hold), no ip-block write, DM carries the dry-run prefix.
sent.clear(); dms.clear(); ipblocks.clear()