Service#
The SCIM protocol, without input or output.
- class scim2_server.service.ScimService(provider: ScimProvider)[source]#
The SCIM protocol, without input or output.
A service validates the requests, applies the PUT and PATCH requests to the resources, evaluates the conditional headers and builds the responses. It neither reads nor writes resources:
ScimHandlercalls the storage between its steps. It knows nothing about the web framework either: the integration reads the request, and turns theScimResponseinto a response of the framework.Every public method can be overridden.
base_urlis the root URL of the SCIM endpoints, as the client sees it, such ashttps://example.com/scim/v2.- get_model(resource_type: ResourceType) type[Resource][source]#
Return the model of a resource type, its extensions included.
- get_resource_type_by_endpoint(endpoint: str) ResourceType | None[source]#
Return the resource type an endpoint serves, if any.
- static match(request: ScimRequest) Target[source]#
Return the operation a request asks for (RFC 7644 §3.2).
The target of a
/Merequest is not resolved yet.- Raises:
NotFoundException – When no endpoint has the path of the request.
MethodNotAllowedException – When the endpoint does not support the method of the request.
- route(request: ScimRequest, operation: Operation) Target[source]#
Return what a request for an operation acts on.
A
/Merequest acts on the resource ofme_target(), or creates a resource of the type ofme_creation_type().- Parameters:
operation – The operation the caller serves. A request for another operation is a routing error of the integration.
- Raises:
NotFoundException – When no endpoint has the path of the request.
MethodNotAllowedException – When the endpoint does not support the method of the request.
- static endpoint_of(resource_type: ResourceType) str[source]#
Return the endpoint of a resource type, without its slashes.
- me_target(request: ScimRequest) tuple[ResourceType, str][source]#
Return the type and the identifier of the resource
/Mestands for (RFC 7644 §3.11).Override this method to serve
/Me. It reads the authenticated subject inScimRequest.subject. The exceptions it raises answer the request.- Raises:
NotImplementedException – By default, so that
/Meanswers 501.UnauthorizedException – When the request has no authenticated subject, for an application that accepts anonymous requests. It answers 401.
ForbiddenException – When the subject may not use
/Me, for a 403.NotFoundException – When the subject has no resource, for a 404.
- me_creation_type(request: ScimRequest) ResourceType[source]#
Return the type of the resource a POST on
/Mecreates (RFC 7644 §3.11).Override this method to let the clients register themselves (RFC 7644 §7.6). Linking the created resource to the subject is left to the application. The exceptions it raises answer the request.
- Raises:
NotImplementedException – By default, so that a POST on
/Meanswers 501.UnauthorizedException – When the request has no authenticated subject, for an application that accepts anonymous requests. It answers 401.
ForbiddenException – When the subject may not register, for a 403.
UniquenessException – When the subject already has a resource, for a 409.
- me_response(request: ScimRequest, target: Target, response: ScimResponse) ScimResponse[source]#
Add the location of the resource
/Mestands for to a response (RFC 7644 §3.11).
- static read_conditions(request: ScimRequest) Conditions[source]#
Return the conditional headers of a request.
- max_body_size(request: ScimRequest) int | None[source]#
Return the largest body the service accepts for a request, in bytes.
An integration reads at most one byte more, and leaves the 413 answer to the service. A bulk request is limited by maxPayloadSize (RFC 7644 §3.7.4). Other requests have no limit.
- resource_type_at(endpoint: str) ResourceType[source]#
Return the resource type an endpoint serves.
- Raises:
NotFoundException – When no resource type is served at this endpoint.
- get_resource_type(name: str) ResourceType[source]#
Return the resource type of a name, such as
User.- Raises:
ValueError – When the provider serves no resource type of this name.
- get_resource_type_of(resource: Resource) ResourceType[source]#
Return the resource type of a stored resource, from its meta.resourceType.
- Raises:
ValueError – When the storage returned a resource of a type the provider does not serve.
- property etag_supported: bool#
Whether the configuration declares the resources versioned with ETags.
- static ensure_supported(capability: Patch | Bulk | Filter | Sort | None, operation: str) None[source]#
Refuse with a 501 an operation the configuration does not declare supported.
RFC 7644 §3.12 answers 501 when the service provider does not support the request operation.
- bulk_max_payload_size() int | None[source]#
Return the largest bulk request body the service accepts, in bytes.
An integration can use it to stop reading a larger body early.
- ensure_bulk_payload_size(size: int) None[source]#
Refuse with a 413 a bulk request body larger than maxPayloadSize (RFC 7644 §3.7.4).
- Parameters:
size – The size of the body, in bytes.
- static payload_too_large(limit: int) PayloadTooLargeException[source]#
Return the 413 error of a bulk request body larger than maxPayloadSize.
- static ensure_json(content_type: str | None) None[source]#
Refuse with a 415 a request body that is not JSON.
- read_body(model: type[ModelT], body: bytes, content_type: str | None, scim_ctx: Context) ModelT[source]#
Validate a request body with a model, in the context of its operation.
- decode_body(body: bytes, content_type: str | None) Any[source]#
Return the JSON value of a request body, unvalidated.
- resource_location(base_url: str, resource_type: ResourceType, resource_id: str) str[source]#
Return the URL of a resource.
Override this method to serve the resources at other URLs.
- publish(base_url: str, resource: Resource) Resource[source]#
Return a copy of a stored resource in the form sent to the client.
Its location is set, and its version is left out when the service does not support ETags.
- static resource_response(resource: Resource, scim_ctx: Context, response_parameters: ResponseParameters[Any] | None = None, status: HTTPStatus = HTTPStatus.OK) ScimResponse[source]#
Return the response carrying a published resource, with its ETag.
- check_preconditions(resource: Resource, method: str, conditions: Conditions) bool[source]#
Evaluate the conditional headers of a request against a resource.
- Returns:
Falsewhen a GET should answer 304 Not Modified.- Raises:
PreconditionFailedException – When the method must not be performed.
- read_creation(resource_type: ResourceType, body: bytes, content_type: str | None) Resource[source]#
Validate the body of a creation request.
- creation_response(base_url: str, created: Resource) ScimResponse[source]#
Return the 201 response to a creation, with the location of the resource.
- read_response_parameters(resource_type: ResourceType, query: Mapping[str, str]) ResponseParameters[Any][source]#
Read the “attributes” and “excludedAttributes” query parameters.
- query_response(base_url: str, resource: Resource, response_parameters: ResponseParameters[Any], conditions: Conditions) ScimResponse[source]#
Return the response to the read of a resource, or a 304.
- read_search_query(resource_types: list[ResourceType], query: Mapping[str, str]) SearchRequest[Any][source]#
Read the query parameters of a search with GET (RFC 7644 §3.4.2).
- read_search_body(resource_types: list[ResourceType], body: bytes, content_type: str | None) SearchRequest[Any][source]#
Read the body of a search with POST on “.search” (RFC 7644 §3.4.3).
- read_search(resource_types: list[ResourceType], payload: Any) SearchRequest[Any][source]#
Validate a search request, and bound its count by maxResults.
- searched_types(endpoint: str | None) list[ResourceType][source]#
Return the resource types a search covers: those of the endpoint, or all of them at the root.
- search_response(base_url: str, total_results: int, resources: list[Resource], search_request: SearchRequest[Any]) ScimResponse[source]#
Return the response listing a page of found resources.
- read_replacement(resource_type: ResourceType, body: bytes, content_type: str | None) Resource[source]#
Validate the body of a replacement request.
- apply_replacement(current: Resource, replacement: Resource, conditions: Conditions) Resource | None[source]#
Apply a replacement to a stored resource.
- Returns:
The new state of the resource, or
Nonewhen the replacement changes nothing. Such a PUT keeps meta.lastModified and the ETag.
- replacement_response(base_url: str, resource: Resource, response_parameters: ResponseParameters[Any]) ScimResponse[source]#
Return the response to a replacement.
- ensure_patch_supported() None[source]#
Refuse with a 501 a PATCH when the configuration does not support it.
- read_patch(resource_type: ResourceType, body: bytes, content_type: str | None) PatchOp[Any][source]#
Validate the body of a PATCH request.
- apply_patch(current: Resource, patch_op: PatchOp[Any], conditions: Conditions) Resource | None[source]#
Apply a PATCH to a stored resource.
- Returns:
The new state of the resource, or
Nonewhen the PATCH changes nothing. Such a PATCH keeps meta.lastModified and the ETag.
- patch_response(base_url: str, resource: Resource, response_parameters: ResponseParameters[Any]) ScimResponse[source]#
Return the response to a PATCH.
RFC 7644 §3.5.2: a PATCH MAY answer 204 when no attributes were requested.
- check_deletion(current: Resource, conditions: Conditions) None[source]#
Evaluate the conditional headers of a deletion.
- static deletion_response() ScimResponse[source]#
Return the 204 response to a deletion.
- read_bulk(body: bytes, content_type: str | None) BulkPlan[source]#
Validate a bulk request against the limits of the service, and plan its operations (RFC 7644 §3.7).
- static bulk_outcome(operation: BulkOperation[Resource]) dict[str, Any][source]#
Start the outcome of a bulk operation, before it runs.
- locate_bulk_operation(base_url: str, operation: BulkOperation[Resource], outcome: dict[str, Any]) ResourceType | None[source]#
Return the resource type a resolved bulk operation targets, and locate its resource.
The location is set before the operation runs, so a failure still knows it. RFC 7644 §3.7.3 requires it for every operation but a failed POST.
- static bulk_validation_failure(operation: BulkOperation[Resource], outcome: dict[str, Any]) dict[str, Any] | None[source]#
Return the outcome of a bulk operation that failed its validation, if it did.
- static check_bulk_target(operation: BulkOperation[Resource]) str | None[source]#
Check that the path of a bulk operation fits its method.
- Returns:
The identifier of the targeted resource, or
Nonefor a POST.- Raises:
InvalidValueException – When a POST targets a resource, or another method a resource type endpoint.
- bulk_failure(outcome: dict[str, Any], exception: Exception) dict[str, Any][source]#
Return the outcome of a bulk operation that raised an exception.
- bulk_success(base_url: str, operation: BulkOperation[Resource], outcome: dict[str, Any], resource: Resource | None) dict[str, Any][source]#
Return the outcome of a bulk operation that succeeded.
- bulk_response(plan: BulkPlan) ScimResponse[source]#
Return the response listing the outcome of each operation that ran.
- static forbid_filter(query: Mapping[str, str]) None[source]#
Refuse a filter on a discovery endpoint.
RFC 7644 §4: “If a “filter” is provided, the service provider SHOULD respond with HTTP status code 403 (Forbidden)”.
- static locate(resource: DiscoveryResourceT, location: str) DiscoveryResourceT[source]#
Return a copy of a discovery resource carrying its meta.
- service_provider_config(location: str, query: Mapping[str, str]) ScimResponse[source]#
Return the ServiceProviderConfig.
- Parameters:
location – The URL of the endpoint.
- resource_types(location: str, query: Mapping[str, str]) ScimResponse[source]#
Return the list of the resource types.
- resource_type(location: str, resource_type_id: str, query: Mapping[str, str]) ScimResponse[source]#
Return a single resource type.
- schemas(location: str, query: Mapping[str, str]) ScimResponse[source]#
Return the list of the schemas.
- schema(location: str, schema_id: str, query: Mapping[str, str]) ScimResponse[source]#
Return a single schema.
- static error_of(exception: Exception) Error[source]#
Return the SCIM error of an exception raised while serving a request.
Any other exception than a
SCIMExceptionis unexpected, and gives a 500, without its message nor its traceback.
- error_response(exception: Exception) ScimResponse[source]#
Return the SCIM error response of an exception raised while serving a request.
A 401 response carries the
WWW-Authenticateheader ofwww_authenticate().
- www_authenticate(exception: SCIMException) str | None[source]#
Return the
WWW-Authenticateheader of a 401 response (RFC 7644 §2).It holds one challenge per authentication scheme of the service provider configuration, for the Bearer and Basic schemes. Override this method to announce other schemes, or to add parameters to the challenges, such as
resource_metadata(RFC 9728 §5.1).