test_printer_camera_url_redaction.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. """Printer readers see the camera URLs without the login secret, whatever shape
  2. the login takes; editors see them as stored."""
  3. import pytest
  4. from backend.app.schemas.printer import PrinterResponse, PrinterResponseWithSecret
  5. BASE = {
  6. "id": 1,
  7. "name": "P",
  8. "serial_number": "00M09A000000001",
  9. "ip_address": "192.168.1.10",
  10. "model": "X1C",
  11. "is_active": True,
  12. "created_at": "2026-10-13T00:00:00",
  13. "updated_at": "2026-10-13T00:00:00",
  14. }
  15. @pytest.mark.parametrize(
  16. ("stored", "shown"),
  17. [
  18. ("rtsp://admin:pw@10.0.0.5:554/s", "rtsp://admin:[REDACTED]@10.0.0.5:554/s"),
  19. ("http://:pw@10.0.0.5/snap.jpg", "http://:[REDACTED]@10.0.0.5/snap.jpg"),
  20. ("rtsp://me@example.com:pw@10.0.0.5/s", "rtsp://me@example.com:[REDACTED]@10.0.0.5/s"),
  21. ("http://secrettoken@10.0.0.5/snap.jpg", "http://[REDACTED]@10.0.0.5/snap.jpg"),
  22. ("rtsp://admin:p@ss@10.0.0.5/s", "rtsp://admin:[REDACTED]@10.0.0.5/s"),
  23. ("rtsp://admin:pa:ss@10.0.0.5/s", "rtsp://admin:[REDACTED]@10.0.0.5/s"),
  24. ("http://admin:pw@10.0.0.5", "http://admin:[REDACTED]@10.0.0.5"),
  25. ("http://admin:pw@10.0.0.5/s?x=1#y", "http://admin:[REDACTED]@10.0.0.5/s?x=1#y"),
  26. ("http://10.0.0.5/snap.jpg?a=b@c", "http://10.0.0.5/snap.jpg?a=b@c"),
  27. ("http://10.0.0.5/path@thing", "http://10.0.0.5/path@thing"),
  28. # Without a path, an @ in the query or fragment cannot be told from
  29. # a password containing ? or #: masked rather than risk the password.
  30. ("http://10.0.0.5?a=b@c", "http://[REDACTED]@c"),
  31. ("http://10.0.0.5#a@b", "http://[REDACTED]@b"),
  32. ("rtsp://admin:pa#ss@10.0.0.5:554/s", "rtsp://admin:[REDACTED]@10.0.0.5:554/s"),
  33. ("rtsp://admin:pa?ss@10.0.0.5/s", "rtsp://admin:[REDACTED]@10.0.0.5/s"),
  34. ("rtsp://admin:my pw@10.0.0.5/s", "rtsp://admin:[REDACTED]@10.0.0.5/s"),
  35. ("rtsp://admin:my\tpw@10.0.0.5/s", "rtsp://admin:[REDACTED]@10.0.0.5/s"),
  36. ("/dev/video0", "/dev/video0"),
  37. ("", ""),
  38. (None, None),
  39. ],
  40. )
  41. def test_readers_never_see_the_login_secret(stored, shown):
  42. reader = PrinterResponse(**BASE, external_camera_url=stored, external_camera_snapshot_url=stored)
  43. editor = PrinterResponseWithSecret(
  44. **BASE, access_code="12345678", external_camera_url=stored, external_camera_snapshot_url=stored
  45. )
  46. assert reader.external_camera_url == shown
  47. assert reader.external_camera_snapshot_url == shown
  48. assert editor.external_camera_url == stored