import pytest from passlib.hash import sha512_crypt from dpdapi.models import Domain, User FIELDS = {"id", "created", "updated", "email", "domain"} @pytest.fixture def user(domain): return User.objects.create(email="Jane@Example.com", password="x", domain=domain) def test_list(api, user): res = api.get("/api/users/") assert res.status_code == 200 assert res.json() == [res.json()[0]] assert set(res.json()[0]) == FIELDS assert res.json()[0]["email"] == "jane@example.com" assert res.json()[0]["domain"] == user.domain_id def test_retrieve(api, user): res = api.get(f"/api/users/{user.pk}/") assert res.status_code == 200 assert set(res.json()) == FIELDS assert str(user) == "jane@example.com" def test_retrieve_missing(api, db): assert api.get("/api/users/999/").status_code == 404 def test_create_hashes_password(api, domain): data = {"email": "New@Example.com", "password": "hunter2", "domain": domain.pk} res = api.post("/api/users/", data, content_type="application/json") assert res.status_code == 201 assert set(res.json()) == FIELDS assert res.json()["email"] == "new@example.com" stored = User.objects.get().password assert stored.startswith("$6$") assert sha512_crypt.verify("hunter2", stored) @pytest.mark.parametrize( "data", [ {"password": "p"}, {"email": "nope", "password": "p"}, {"email": "jane@example.com", "password": "p"}, {"email": "a@example.com"}, {"email": "a@example.com", "password": "p", "domain": 999}, ], ) def test_create_invalid(api, user, data): data.setdefault("domain", user.domain_id) res = api.post("/api/users/", data, content_type="application/json") assert res.status_code == 400 assert User.objects.count() == 1 def test_update_hashes_password(api, user): other = Domain.objects.create(name="other.org") data = {"email": "jane@other.org", "password": "new-secret", "domain": other.pk} res = api.put(f"/api/users/{user.pk}/", data, content_type="application/json") assert res.status_code == 200 assert res.json()["email"] == "jane@other.org" assert res.json()["domain"] == other.pk user.refresh_from_db() assert sha512_crypt.verify("new-secret", user.password) def test_update_invalid(api, user): res = api.put(f"/api/users/{user.pk}/", {"email": "x@example.com"}, content_type="application/json") assert res.status_code == 400 def test_partial_update_keeps_password(api, user): res = api.patch(f"/api/users/{user.pk}/", {"email": "J@example.com"}, content_type="application/json") assert res.status_code == 200 assert res.json()["email"] == "j@example.com" user.refresh_from_db() assert user.password == "x" def test_partial_update_hashes_password(api, user): res = api.patch(f"/api/users/{user.pk}/", {"password": "p2"}, content_type="application/json") assert res.status_code == 200 user.refresh_from_db() assert sha512_crypt.verify("p2", user.password) @pytest.mark.parametrize("field", ["email", "password", "domain"]) def test_partial_update_null(api, user, field): res = api.patch(f"/api/users/{user.pk}/", {field: None}, content_type="application/json") assert res.status_code == 400 assert field in str(res.json()) def test_delete(api, user): assert api.delete(f"/api/users/{user.pk}/").status_code == 204 assert not User.objects.exists() def test_deleting_domain_cascades(api, user): assert api.delete(f"/api/domains/{user.domain_id}/").status_code == 204 assert not User.objects.exists()