yaal-coop / scim2-models

SCIM resources serialization and validation with Pydantic
https://scim2-models.readthedocs.io
Apache License 2.0
5 stars 2 forks source link

Handle resource attributes mutability and returnability #3

Closed azmeuk closed 1 month ago

azmeuk commented 1 month ago

use cases

In several situations described in RFC7644, partial objects payloads can be generated:

There are actually two situations:

documentation elements

RFC7643 §3.1 indicates that the id, externalId and meta parameters must be defined for all the resources (except for ServiceProviderConfig and ResourceType). But be defined is different than mandatory:

   [...] these attributes MUST be defined for all resources,
   including any extended resource types.  When accepted by a service
   provider (e.g., after a SCIM create), the attributes "id" and "meta"
   (and its associated sub-attributes) MUST be assigned values by the
   service provider.  Common attributes are considered to be part of
   every base resource schema and do not use their own "schemas" URI.

RFC7643 §3.1 indicates that the id is mandatory for each representation, but also that it is forbidden on client creation requests.

id
    Each representation of the resource MUST include a
    non-empty "id" value. 
    [...] The value of
    the "id" attribute is always issued by the service provider and
    MUST NOT be specified by the client. [...]

RFC7643 §3.1 indicates that the meta parameter is not relevant for client requests:

   meta
      A complex attribute containing resource metadata.  All "meta"
      sub-attributes are assigned by the service provider (have a
      "mutability" of "readOnly"), and all of these sub-attributes have
      a "returned" characteristic of "default".  This attribute SHALL be
      ignored when provided by clients.  "meta" contains the following
      sub-attributes:

conclusion

For a given resource, it is expected to have different fields wether it is part of a client request or a server response. The behavior for server response is dictated by Schema.returned and the behavior for client requests is dictated by Schema.mutability.

possible solutions

# Client validating a server response
user = User.validate_payload(payload, returned=(Returned.always, Returned.default, Returned.request))

# Server validating a client POST request
user = User.validate_payload(payload, mutability=(Mutability.read_write, Mutability.immutable, Mutability.write_only))

# Server validating a client PUT request
user = User.validate_put_request(payload, mutability=(Mutability.read_write, Mutability.read_only, Mutability.write_only))

# Server generating a response
payload = user.dump_payload(user, returned=(Returned.always, Returned.default, Returned.request))

# Client building a POST payload
payload = user.dump_payload(user, mutability=(Mutability.read_write, Mutability.immutable, Mutability.write_only))

# Client building a PUT payload
payload = user.dump_payload(user, mutability=(Mutability.read_write, Mutability.read_only, Mutability.write_only))