"""Reset a password by email (milestone 497): a link's states, where it points, and the email that carries it.""" import re from datetime import datetime, timedelta, timezone from zoneinfo import ZoneInfo from steward.core import mail, password_resets from steward.models.password_resets import PasswordReset NOW = datetime(2026, 10, 9, 12, 0, tzinfo=timezone.utc) def _reset(**kw): return PasswordReset(**({"user_id": "u", "key_hash": "x", "created_at": NOW, "expires_at": NOW + password_resets.LIFETIME} | kw)) def test_a_link_works_for_an_hour_and_once(): assert password_resets.LIFETIME == timedelta(hours=1) assert password_resets.state(_reset(), NOW + timedelta(minutes=59)) == "pending" assert password_resets.state(_reset(), NOW + timedelta(hours=1)) == "expired" assert password_resets.state(_reset(used_at=NOW), NOW) == "used" def test_the_link_carries_the_key_under_steward_s_address(): assert password_resets.link("https://steward.example/", "abc") == "https://steward.example/reset/abc" def test_the_reset_email_names_the_account_the_deadline_and_what_to_do_if_unasked(): url = "https://steward.example/reset/KEY123" subject, text, html = mail.reset_email("ann ", NOW + timedelta(hours=1), url, ZoneInfo("Europe/London")) assert subject == "[Steward] Reset your password" for part in (text, html): assert url in part and "Fri 9 Oct 2026 14:00 BST" in part assert "your password is unchanged" in part and "UTC" not in part assert "ann <x>" in html and "" not in html assert all(u.startswith("https://steward.example") for u in re.findall(r"""https?://[^\s"'<>)]+""", html))