Source code for scim2_tester.checkers.resource_put

from typing import Any

from scim2_models import Mutability
from scim2_models import Resource

from ..filling import fill_with_random_values
from ..utils import CheckContext
from ..utils import CheckResult
from ..utils import Status
from ..utils import check_result
from ..utils import checker


[docs] @checker("crud:update") def object_replacement( context: CheckContext, model: type[Resource[Any]] ) -> list[CheckResult]: """Validate SCIM resource replacement via PUT requests. Tests that resources can be successfully replaced using PUT method, modifying mutable fields and validating the complete resource replacement operation. **Status:** - :attr:`~scim2_tester.Status.SUCCESS`: Resource replaced successfully with valid response - :attr:`~scim2_tester.Status.ERROR`: Replacement failed due to client/server error .. pull-quote:: :rfc:`RFC 7644 Section 3.5.1 - Replacing Resources <7644#section-3.5.1>` "To replace a resource's attributes, clients issue an HTTP PUT request to the resource endpoint (e.g., ``/Users/{id}`` or ``/Groups/{id}``)." "If successful, the server responds with HTTP status code 200 (OK) and includes the updated resource within the response body." """ test_obj = context.resource_manager.create_and_register(model) # Dirty hotfix, waiting to path management in scim2-models # to have a more generic way to do things # https://github.com/python-scim/scim2-models/issues/111 # Store original immutable values to preserve them original_immutable_values = {} for field_name, field_info in model.model_fields.items(): # pragma: no cover # Check if field is immutable is_immutable = any( isinstance(metadata, Mutability) and metadata == Mutability.immutable for metadata in field_info.metadata ) if is_immutable: original_value = getattr(test_obj, field_name, None) if original_value is not None: original_immutable_values[field_name] = original_value modified_obj = fill_with_random_values( context, test_obj, mutability=[Mutability.read_write, Mutability.write_only, Mutability.immutable], ) # Dirty hotfix, waiting to path management in scim2-models # to have a more generic way to do things # https://github.com/python-scim/scim2-models/issues/111 # Restore original immutable values for non-complex fields if modified_obj is not None: for ( field_name, original_value, ) in original_immutable_values.items(): # pragma: no cover # Only restore if it's not a complex list (like members) if not ( isinstance(original_value, list) and original_value and hasattr(original_value[0], "__class__") and hasattr(original_value[0].__class__, "model_fields") ): setattr(modified_obj, field_name, original_value) if modified_obj is None: raise ValueError( f"Could not modify {model.__name__} object with mutable fields" ) response = context.client.replace( modified_obj, expected_status_codes=context.conf.expected_status_codes or [200] ) return [ check_result( context, status=Status.SUCCESS, reason=f"Successfully replaced {model.__name__} object with id {test_obj.id}", data=response, ) ]