diff --git a/doc/changelog.rst b/doc/changelog.rst index 541356f..f8d9d7e 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -12,6 +12,7 @@ Added Changed ^^^^^^^ - :attr:`SearchRequest.attributes ` and :attr:`SearchRequest.attributes ` are mutually exclusive. #19 +- :class:`~scim2_models.Schema` ids must be valid URIs. #26 [0.2.2] - 2024-09-20 -------------------- diff --git a/scim2_models/rfc7643/schema.py b/scim2_models/rfc7643/schema.py index 9d778c0..c1cae43 100644 --- a/scim2_models/rfc7643/schema.py +++ b/scim2_models/rfc7643/schema.py @@ -14,8 +14,10 @@ from pydantic import Base64Bytes from pydantic import Field from pydantic import create_model +from pydantic import field_validator from pydantic.alias_generators import to_pascal from pydantic.alias_generators import to_snake +from pydantic_core import Url from ..base import CaseExact from ..base import ComplexAttribute @@ -63,7 +65,10 @@ def make_python_model( for attr in (obj.attributes or []) if attr.name } - pydantic_attributes["schemas"] = (Optional[List[str]], Field(default=[obj.id])) + pydantic_attributes["schemas"] = ( + Optional[List[str]], + Field(default=[obj.id]), + ) model_name = to_pascal(to_snake(obj.name)) model = create_model(model_name, __base__=base, **pydantic_attributes) @@ -254,3 +259,10 @@ class Schema(Resource): ] = None """A complex type that defines service provider attributes and their qualities via the following set of sub-attributes.""" + + @field_validator("id") + @classmethod + def urn_id(cls, value: str) -> str: + """Schema ids are URI, as defined in RFC7643 §7.""" + + return str(Url(value)) diff --git a/tests/test_schema.py b/tests/test_schema.py index 76340a5..e7b7f4f 100644 --- a/tests/test_schema.py +++ b/tests/test_schema.py @@ -1,3 +1,6 @@ +import pytest +from pydantic import ValidationError + from scim2_models import Attribute from scim2_models import Mutability from scim2_models import Returned @@ -72,3 +75,14 @@ def test_group_schema(load_sample): ) assert obj.model_dump(exclude_unset=True) == payload + + +def test_uri_ids(): + """Test that schema ids are URI, as defined in RFC7643 §7. + + https://datatracker.ietf.org/doc/html/rfc7643#section-7 + """ + + Schema(id="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User") + with pytest.raises(ValidationError): + Schema(id="invalid\nuri")