test_password_reset_template_routes.py 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. """Both reset paths send the "Password Reset" template, the reset link added at the end.
  2. The self-service reset (/auth/forgot-password) and the admin one
  3. (/auth/reset-password) built the link email from fixed text, so an admin's
  4. edit of the template never reached anyone.
  5. """
  6. from unittest.mock import patch
  7. import pytest
  8. from httpx import AsyncClient
  9. from backend.app.models.notification_template import NotificationTemplate
  10. from backend.tests.integration.test_advanced_auth_api import _setup_admin, _setup_smtp_and_advanced_auth
  11. pytestmark = [pytest.mark.asyncio, pytest.mark.integration]
  12. async def _prepare(async_client: AsyncClient, db_session) -> tuple[dict, int]:
  13. token = await _setup_admin(async_client, "tpladmin", "AdminPass1!")
  14. headers = {"Authorization": f"Bearer {token}"}
  15. db_session.add(
  16. NotificationTemplate(
  17. event_type="password_reset",
  18. name="Password Reset",
  19. title_template="Custom reset for {username}",
  20. body_template="Our own words.",
  21. is_default=False,
  22. )
  23. )
  24. await db_session.commit()
  25. with patch("backend.app.api.routes.users.send_email"):
  26. await _setup_smtp_and_advanced_auth(async_client, token)
  27. created = await async_client.post(
  28. "/api/v1/users/",
  29. headers=headers,
  30. json={"username": "tpluser", "email": "tpluser@test.com", "role": "user"},
  31. )
  32. assert created.status_code == 201, created.text
  33. return headers, created.json()["id"]
  34. def _assert_template_sent(mock_send) -> None:
  35. mock_send.assert_called_once()
  36. _smtp, to, subject, text_body, html_body = mock_send.call_args[0][:5]
  37. assert to == "tpluser@test.com"
  38. assert subject == "Custom reset for tpluser"
  39. words, link = text_body.split("\n\n")
  40. assert words == "Our own words."
  41. assert "#reset_token=" in link
  42. assert "#reset_token=" in html_body
  43. async def test_the_self_service_reset_sends_the_template(async_client: AsyncClient, db_session):
  44. await _prepare(async_client, db_session)
  45. with patch("backend.app.api.routes.auth.send_email") as mock_send:
  46. response = await async_client.post("/api/v1/auth/forgot-password", json={"email": "tpluser@test.com"})
  47. assert response.status_code == 200
  48. _assert_template_sent(mock_send)
  49. async def test_the_admin_reset_sends_the_template(async_client: AsyncClient, db_session):
  50. headers, user_id = await _prepare(async_client, db_session)
  51. with patch("backend.app.api.routes.auth.send_email") as mock_send:
  52. response = await async_client.post("/api/v1/auth/reset-password", headers=headers, json={"user_id": user_id})
  53. assert response.status_code == 200
  54. _assert_template_sent(mock_send)