aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/tests
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/tests')
-rw-r--r--packages/meshbay-hub/tests/test_mail_is_not_a_relay.py50
1 files changed, 43 insertions, 7 deletions
diff --git a/packages/meshbay-hub/tests/test_mail_is_not_a_relay.py b/packages/meshbay-hub/tests/test_mail_is_not_a_relay.py
index a3f9a21..157dbd5 100644
--- a/packages/meshbay-hub/tests/test_mail_is_not_a_relay.py
+++ b/packages/meshbay-hub/tests/test_mail_is_not_a_relay.py
@@ -148,21 +148,57 @@ async def test_one_recipient_has_a_cooldown_and_a_daily_allowance(db_session):
"a second purpose walked around the cooldown")
cap = MailConfig().destination_daily_cap
- key = mail_mod.destination_key(victim)
+ cool = "cool:invitation:" + mail_mod.destination_key(victim)[len("dest:"):]
+
+ async def past_the_cooldown():
+ # Step past it without waiting it out. The daily count is deliberately
+ # left alone.
+ row = await db_session.get(MailQuota, cool)
+ if row:
+ row.last_sent = None
+ await db_session.commit()
+
for _ in range(cap - 1):
- # Step past the cooldown without waiting it out. The daily count is
- # deliberately left alone.
- (await db_session.get(MailQuota, key)).last_sent = None
- await db_session.commit()
+ await past_the_cooldown()
assert await _charge(db_session, "invite", victim)
- (await db_session.get(MailQuota, key)).last_sent = None
- await db_session.commit()
+ await past_the_cooldown()
assert not await _charge(db_session, "invite", victim), (
f"the {cap}-a-day allowance for one recipient was not enforced")
@pytest.mark.asyncio
+async def test_an_invitation_does_not_stop_the_code_its_invitee_asks_for(db_session):
+ """
+ The regression: an invitation link arrives, the invitee registers a minute
+ later, and the verification code was refused — silently — by the cooldown
+ the invitation had just armed. Nobody invited by link could sign up without
+ waiting two minutes and then asking again, with nothing on screen saying so.
+
+ The two are one conversation, so they do not share a cooldown; each family
+ still keeps its own, and the daily cap still counts both.
+ """
+ async def charge(purpose, addr):
+ try:
+ await mail_mod.reserve(db_session, purpose, addr, sender="owner-1")
+ except mail_mod.MailRefused:
+ await db_session.rollback()
+ return False
+ await db_session.commit()
+ return True
+
+ for invitation in ("invite", "invite_link"):
+ addr = f"newcomer-{invitation}@example.test"
+ assert await charge(invitation, addr)
+ assert await charge("registration", addr), (
+ f"a verification code was refused after an {invitation} mail")
+ assert not await charge("password_reset", addr), (
+ "within the account family the cooldown must still hold")
+ assert not await charge("invite", addr), (
+ "a second invitation in the same burst must still wait")
+
+
+@pytest.mark.asyncio
async def test_the_same_recipient_is_one_recipient_however_it_is_written(db_session):
"""Case and surrounding space are not a new person."""
assert await _charge(db_session, "registration", "Victim@Example.Test")