diff --git a/auth0/client.py b/auth0/client.py index 202759d1..c4c69cdf 100644 --- a/auth0/client.py +++ b/auth0/client.py @@ -96,7 +96,8 @@ def get_user(self, user_id: str) -> Auth0UserData: def create_user(self, user: BiocommonsRegisterData) -> Auth0UserData: url = f"https://{self.domain}/api/v2/users" - resp = self._client.post(url, json=user.model_dump(mode="json")) + # Exclude None values to avoid validation errors. + resp = self._client.post(url, json=user.model_dump(mode="json", exclude_none=True)) resp.raise_for_status() return Auth0UserData(**resp.json()) diff --git a/tests/datagen.py b/tests/datagen.py index d84cd9e9..39c74981 100644 --- a/tests/datagen.py +++ b/tests/datagen.py @@ -4,7 +4,11 @@ from polyfactory.decorators import post_generated from polyfactory.factories.pydantic_factory import ModelFactory -from schemas.biocommons import Auth0UserData, BiocommonsAppMetadata +from schemas.biocommons import ( + Auth0UserData, + BiocommonsAppMetadata, + BiocommonsRegisterData, +) from schemas.biocommons_register import BiocommonsRegistrationRequest from schemas.bpa import BPARegistrationRequest from schemas.galaxy import GalaxyRegistrationData @@ -28,6 +32,12 @@ def sub(cls) -> str: return random_auth0_id() +class BiocommonsRegisterDataFactory(ModelFactory[BiocommonsRegisterData]): + + @classmethod + def connection(cls) -> str: + return "Username-Password-Authentication" + class SessionUserFactory(ModelFactory[SessionUser]): ... diff --git a/tests/test_auth0_client.py b/tests/test_auth0_client.py index c1d1e20d..e999721c 100644 --- a/tests/test_auth0_client.py +++ b/tests/test_auth0_client.py @@ -1,3 +1,5 @@ +import json + import pytest import respx from httpx import Response @@ -5,6 +7,7 @@ from auth0.client import UsersWithTotals from tests.datagen import ( Auth0UserDataFactory, + BiocommonsRegisterDataFactory, random_auth0_id, random_auth0_role_id, ) @@ -131,3 +134,34 @@ def test_add_roles_to_user(test_auth0_client): call_data = route.calls[0].request.content # Check role_id is passed as a list assert call_data == b'{"roles":["' +role_id.encode() + b'"]}' + + +@respx.mock +def test_create_user(test_auth0_client): + """ + Test that we call the Auth0 API to create a user with the data we expect + """ + register_data = BiocommonsRegisterDataFactory.build() + # Mock the response from the Auth0 API, non-matching data + auth0_data = Auth0UserDataFactory.build() + route = respx.post("https://auth0.example.com/api/v2/users").respond(201, json=auth0_data.model_dump(mode="json")) + test_auth0_client.create_user(register_data) + assert route.called + assert json.loads(route.calls.last.request.content) == register_data.model_dump(mode="json", exclude_none=True) + + +@respx.mock +def test_create_user_omits_none(test_auth0_client): + """ + Test that None/null fields are omitted from the request to Auth0 API + """ + register_data = BiocommonsRegisterDataFactory.build(name=None, user_metadata=None) + # Mock the response from the Auth0 API, non-matching data + auth0_data = Auth0UserDataFactory.build() + route = respx.post("https://auth0.example.com/api/v2/users").respond(201, json=auth0_data.model_dump(mode="json")) + test_auth0_client.create_user(register_data) + assert route.called + call_data = json.loads(route.calls.last.request.content) + assert call_data == register_data.model_dump(mode="json", exclude_none=True) + assert "name" not in call_data + assert "user_metadata" not in call_data