fix(contacts): tolerate non-string body in /api/contacts/import (#3638)

import_vcf built `text = data.get("vcf") or data.get("text") or ""`, so a
non-string JSON value (a number, list, etc.) stayed in place and the following
`text.strip()` raised AttributeError, returning HTTP 500. Coerce vcf/text/csv
with str() so non-string input degrades to the existing structured "no data"
response, matching the file's convention elsewhere.

Adds tests/test_contacts_import_nonstring.py covering non-string vcf, non-string
csv, and an empty body.
This commit is contained in:
Mazen Tamer Salah
2026-06-10 18:50:22 +03:00
committed by GitHub
parent 4e210d3337
commit 96975f8dd9
2 changed files with 44 additions and 2 deletions
+39
View File
@@ -0,0 +1,39 @@
"""POST /api/contacts/import must not 500 on a non-string vcf/text/csv value.
`text = data.get("vcf") or ... or ""` left a non-string value (e.g. a number)
in place, so the next `text.strip()` raised AttributeError -> HTTP 500. The
handler now coerces with str() and degrades to a structured "no data" response.
"""
import asyncio
from routes.contacts_routes import setup_contacts_routes
def _import_handler():
router = setup_contacts_routes()
for route in router.routes:
if getattr(route, "path", "").endswith("/import") and "POST" in getattr(route, "methods", set()):
return route.endpoint
raise AssertionError("import route not found")
def _call(data):
handler = _import_handler()
return asyncio.run(handler(data=data, _admin="admin"))
def test_non_string_vcf_degrades_cleanly():
resp = _call({"vcf": 123})
assert resp["success"] is False
assert "error" in resp
def test_non_string_csv_degrades_cleanly():
resp = _call({"csv": ["a", "b"]})
assert resp["success"] is False
def test_empty_body_reports_no_data():
resp = _call({})
assert resp["success"] is False
assert resp["error"] == "No contact data found"