752 lines
30 KiB
Python
752 lines
30 KiB
Python
# note(jon): please see https://datatracker.ietf.org/doc/html/rfc7643 for details on these constants
|
||
from typing import Any
|
||
|
||
def _attribute_characteristics(
|
||
name: str,
|
||
description: str,
|
||
type: str="string",
|
||
sub_attributes: dict[str, Any] | None=None,
|
||
# note(jon): no default for multiValued is defined in the docs and it is marked as optional.
|
||
# from our side, we'll default it to False.
|
||
multi_valued: bool=False,
|
||
required: bool=False,
|
||
canonical_values: list[str] | None=None,
|
||
case_exact: bool=False,
|
||
mutability: str="readWrite",
|
||
returned: str="default",
|
||
uniqueness: str="none",
|
||
reference_types: list[str] | None=None,
|
||
):
|
||
characteristics = {
|
||
"name": name,
|
||
"type": type,
|
||
"subAttributes": sub_attributes,
|
||
"multiValued": multi_valued,
|
||
"description": description,
|
||
"required": required,
|
||
"canonicalValues": canonical_values,
|
||
"caseExact": case_exact,
|
||
"mutability": mutability,
|
||
"returned": returned,
|
||
"uniqueness": uniqueness,
|
||
"referenceTypes": reference_types,
|
||
}
|
||
characteristics_without_none = {
|
||
key: value
|
||
for key, value in characteristics.items()
|
||
if value is not None
|
||
}
|
||
return characteristics_without_none
|
||
|
||
|
||
def _multi_valued_attributes(type_canonical_values: list[str], type_required: bool=False, type_mutability="readWrite"):
|
||
return [
|
||
_attribute_characteristics(
|
||
name="type",
|
||
description="A label indicating the attribute's function.",
|
||
canonical_values=type_canonical_values,
|
||
case_exact=True,
|
||
required=type_required,
|
||
mutability=type_mutability,
|
||
),
|
||
_attribute_characteristics(
|
||
name="primary",
|
||
type="boolean",
|
||
description="A Boolean value indicating the 'primary' or preferred attribute value for this attribute.",
|
||
),
|
||
_attribute_characteristics(
|
||
name="display",
|
||
description="A human-readable name.",
|
||
mutability="immutable",
|
||
),
|
||
_attribute_characteristics(
|
||
name="value",
|
||
description="The attribute's significant value.",
|
||
),
|
||
_attribute_characteristics(
|
||
name="$ref",
|
||
type="reference",
|
||
reference_types=["uri"],
|
||
description="The reference URI of a target resource."
|
||
),
|
||
]
|
||
|
||
|
||
# note(jon): the docs are a little confusing regarding this, but
|
||
# in section 3.1 of RFC7643, it is specified that ResourceType and
|
||
# ServiceProviderConfig are not included in the common attributes. but
|
||
# in other references, they treat them as a resource.
|
||
def _common_resource_attributes(id_required: bool=True, id_uniqueness: str="none"):
|
||
return [
|
||
_attribute_characteristics(
|
||
name="id",
|
||
description="A unique identifier for the SCIM resource.",
|
||
case_exact=True,
|
||
mutability="readOnly",
|
||
returned="always",
|
||
required=id_required,
|
||
uniqueness=id_uniqueness,
|
||
),
|
||
_attribute_characteristics(
|
||
name="externalId",
|
||
description="A String that is an identifier for the resource as defined by the provisioning client.",
|
||
case_exact=True,
|
||
),
|
||
_attribute_characteristics(
|
||
name="schemas",
|
||
type="reference",
|
||
reference_types=["uri"],
|
||
description="An array of Strings containing URI that are used to indicate the namespaces of the SCIM schemas that define the attributes present in the current JSON structure.",
|
||
multi_valued=True,
|
||
canonical_values=[
|
||
"urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig",
|
||
"urn:ietf:params:scim:schemas:core:2.0:ResourceType",
|
||
"urn:ietf:params:scim:schemas:core:2.0:Schema",
|
||
# todo(jon): add the user and group schem when completed
|
||
],
|
||
case_exact=True,
|
||
mutability="readOnly",
|
||
returned="default",
|
||
required=True,
|
||
),
|
||
_attribute_characteristics(
|
||
name="meta",
|
||
type="complex",
|
||
description="A complex attribute containing resource metadata.",
|
||
required=True,
|
||
sub_attributes=[
|
||
_attribute_characteristics(
|
||
name="resourceType",
|
||
description="The name of the resource type of the resource.",
|
||
mutability="readOnly",
|
||
case_exact=True,
|
||
required=True,
|
||
),
|
||
_attribute_characteristics(
|
||
name="created",
|
||
type="dateTime",
|
||
description="The 'DateTime' that the resource was added to the service provider.",
|
||
mutability="readOnly",
|
||
required=True,
|
||
),
|
||
_attribute_characteristics(
|
||
name="lastModified",
|
||
type="dateTime",
|
||
description="The most recent DateTime that the details of this resource were updated at the service provider.",
|
||
mutability="readOnly",
|
||
required=True,
|
||
),
|
||
_attribute_characteristics(
|
||
name="location",
|
||
type="reference",
|
||
reference_types=["uri"],
|
||
description="The URI of the resource being returned.",
|
||
mutability="readOnly",
|
||
required=True,
|
||
),
|
||
# todo(jon): decide if we'll handle versioning. for now, we won't do it.
|
||
],
|
||
),
|
||
]
|
||
|
||
|
||
|
||
SERVICE_PROVIDER_CONFIG_SCHEMA = {
|
||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Schema"],
|
||
"id": "urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig",
|
||
"name": "Service Provider Configuration",
|
||
"description": "Schema for representing the service provider's configuration.",
|
||
"meta": {
|
||
"resourceType": "Schema",
|
||
"created": "2025-04-16T14:48:00Z",
|
||
# note(jon): we might want to think about adding this resource as part of our db
|
||
# and then updating these timestamps from an api and such. for now, if we update
|
||
# the configuration, we should update the timestamp here.
|
||
"lastModified": "2025-04-16T14:48:00Z",
|
||
"location": "Schemas/urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig",
|
||
},
|
||
"attributes": [
|
||
*_common_resource_attributes(id_required=False),
|
||
_attribute_characteristics(
|
||
name="documentationUri",
|
||
type="reference",
|
||
reference_types=["external"],
|
||
description="An HTTP-addressable URL pointing to the service provider's human-consumable help documentation.",
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="patch",
|
||
type="complex",
|
||
description="A complex type that specifies PATCH configuration options.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
sub_attributes=[
|
||
_attribute_characteristics(
|
||
name="supported",
|
||
type="boolean",
|
||
description="A Boolean value specifying whether or not the operation is supported.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
],
|
||
),
|
||
_attribute_characteristics(
|
||
name="bulk",
|
||
type="complex",
|
||
description="A complex type that specifies bulk configuration options.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
sub_attributes=[
|
||
_attribute_characteristics(
|
||
name="supported",
|
||
type="boolean",
|
||
description="A Boolean value specifying whether or not the operation is supported.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="maxOperations",
|
||
type="integer",
|
||
description="An integer value specifying the maximum number of operations.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="maxPayloadSize",
|
||
type="integer",
|
||
description="An integer value specifying the maximum payload size in bytes.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
],
|
||
),
|
||
_attribute_characteristics(
|
||
name="filter",
|
||
type="complex",
|
||
description="A complex type that specifies FILTER options.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
sub_attributes=[
|
||
_attribute_characteristics(
|
||
name="supported",
|
||
type="boolean",
|
||
description="A Boolean value specifying whether or not the operation is supported.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="maxResults",
|
||
type="integer",
|
||
description="The integer value specifying the maximum number of resources returned in a response.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
],
|
||
),
|
||
_attribute_characteristics(
|
||
name="changePassword",
|
||
type="complex",
|
||
description="A complex type that specifies configuration options related to changing a password.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
sub_attributes=[
|
||
_attribute_characteristics(
|
||
name="supported",
|
||
type="boolean",
|
||
description="A Boolean value specifying whether or not the operation is supported.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
],
|
||
),
|
||
_attribute_characteristics(
|
||
name="sort",
|
||
type="complex",
|
||
description="A complex type that specifies sort result options.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
sub_attributes=[
|
||
_attribute_characteristics(
|
||
name="supported",
|
||
type="boolean",
|
||
description="A Boolean value specifying whether or not the operation is supported.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
],
|
||
),
|
||
_attribute_characteristics(
|
||
name="etag",
|
||
type="complex",
|
||
description="A complex type that specifies ETag configuration options.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
sub_attributes=[
|
||
_attribute_characteristics(
|
||
name="supported",
|
||
type="boolean",
|
||
description="A Boolean value specifying whether or not the operation is supported.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
],
|
||
),
|
||
_attribute_characteristics(
|
||
name="authenticationSchemes",
|
||
type="complex",
|
||
multi_valued=True,
|
||
description="A complex type that specifies supported authentication scheme properties.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
sub_attributes=[
|
||
*_multi_valued_attributes(
|
||
type_canonical_values=[
|
||
"oauth",
|
||
"oauth2",
|
||
"oauthbearertoken",
|
||
"httpbasic",
|
||
"httpdigest",
|
||
],
|
||
type_required=True,
|
||
type_mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="name",
|
||
description="The common authentication scheme name, e.g., HTTP Basic.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="description",
|
||
description="A description of the authentication scheme.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="specUri",
|
||
type="reference",
|
||
reference_types=["external"],
|
||
description="An HTTP-addressable URL pointing to the authentication scheme's specification.",
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="documentationUri",
|
||
type="reference",
|
||
reference_types=["external"],
|
||
description="An HTTP-addressable URL pointing to the authentication scheme's usage documentation.",
|
||
mutability="readOnly",
|
||
),
|
||
],
|
||
),
|
||
]
|
||
}
|
||
|
||
|
||
RESOURCE_TYPE_SCHEMA = {
|
||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Schema"],
|
||
"id": "urn:ietf:params:scim:schemas:core:2.0:ResourceType",
|
||
"name": "Resource Type",
|
||
"description": "Specifies the schema that describes a SCIM resource type.",
|
||
"meta": {
|
||
"resourceType": "Schema",
|
||
"created": "2025-04-16T14:48:00Z",
|
||
# note(jon): we might want to think about adding this resource as part of our db
|
||
# and then updating these timestamps from an api and such. for now, if we update
|
||
# the configuration, we should update the timestamp here.
|
||
"lastModified": "2025-04-16T14:48:00Z",
|
||
"location": "Schemas/urn:ietf:params:scim:schemas:core:2.0:ResourceType",
|
||
},
|
||
"attributes": [
|
||
*_common_resource_attributes(id_required=False, id_uniqueness="global"),
|
||
_attribute_characteristics(
|
||
name="name",
|
||
description="The resource type name.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="description",
|
||
description="The resource type's human-readable description.",
|
||
mutability="readOnly",
|
||
),
|
||
# todo(jon): figure out what the correct type/reference_type is here
|
||
_attribute_characteristics(
|
||
name="endpoint",
|
||
type="reference",
|
||
reference_types=["uri"],
|
||
description="The resource type's HTTP-addressable endpoint relative to the Base URL of the service provider.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="schema",
|
||
type="reference",
|
||
reference_types=["uri"],
|
||
description="The resource type's primary/base schema URI.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="schemaExtensions",
|
||
type="complex",
|
||
multi_valued=True,
|
||
description="A list of URIs of the resource type's schema extensions.",
|
||
mutability="readOnly",
|
||
sub_attributes=[
|
||
_attribute_characteristics(
|
||
name="schema",
|
||
type="reference",
|
||
reference_types=["uri"],
|
||
description="The URI of an extended schema.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="required",
|
||
type="boolean",
|
||
description="A Boolean value that specifies whether or not the schema extension is required for the resource type.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
]
|
||
),
|
||
]
|
||
}
|
||
|
||
SCHEMA_SCHEMA = {
|
||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Schema"],
|
||
"id": "urn:ietf:params:scim:schemas:core:2.0:Schema",
|
||
"name": "Schema",
|
||
"description": "Specifies the schema that describes a SCIM schema.",
|
||
"meta": {
|
||
"resourceType": "Schema",
|
||
"created": "2025-04-16T14:48:00Z",
|
||
# note(jon): we might want to think about adding this resource as part of our db
|
||
# and then updating these timestamps from an api and such. for now, if we update
|
||
# the configuration, we should update the timestamp here.
|
||
"lastModified": "2025-04-16T14:48:00Z",
|
||
"location": "Schemas/urn:ietf:params:scim:schemas:core:2.0:Schema",
|
||
},
|
||
"attributes": [
|
||
*_common_resource_attributes(id_uniqueness="global"),
|
||
_attribute_characteristics(
|
||
name="name",
|
||
description="The schema's human‐readable name.",
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="description",
|
||
description="The schema's human-readable name.",
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="attributes",
|
||
type="complex",
|
||
multi_valued=True,
|
||
description="A complex attribute that defines service provider attributes and their qualities.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
sub_attributes=[
|
||
_attribute_characteristics(
|
||
name="name",
|
||
description="The attribute's name.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="type",
|
||
description="The attribute's data type.",
|
||
required=True,
|
||
canonical_values=[
|
||
"string",
|
||
"complex",
|
||
"boolean",
|
||
"decimal",
|
||
"integer",
|
||
"dateTime",
|
||
"reference",
|
||
],
|
||
case_exact=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="multiValued",
|
||
type="boolean",
|
||
description="A Boolean value indicating an attribute's plurality.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="description",
|
||
description="The attribute's human-readable description.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="required",
|
||
type="boolean",
|
||
description="A Boolean value indicating whether or not the attribute is required.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="canonicalValues",
|
||
multi_valued=True,
|
||
description="A collection of canonical values.",
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="caseExact",
|
||
type="boolean",
|
||
description="A Boolean that specifies whether or not a string attribute is case sensitive.",
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="mutability",
|
||
description="A single keyword indicating the circumstances under which the value of the attribute can be (re)defined.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
canonical_values=[
|
||
"readOnly",
|
||
"readWrite",
|
||
"immutable",
|
||
"writeOnly",
|
||
],
|
||
case_exact=True,
|
||
),
|
||
_attribute_characteristics(
|
||
name="returned",
|
||
description="A single keyword that indicates when an attribute and associated values are returned in response to a GET request or in response to a PUT, POST, or PATCH request.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
canonical_values=[
|
||
"always",
|
||
"never",
|
||
"default",
|
||
"request",
|
||
],
|
||
case_exact=True,
|
||
),
|
||
_attribute_characteristics(
|
||
name="uniqueness",
|
||
description="A single keyword value that specifies how the service provider enforces uniqueness of attribute values.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
canonical_values=[
|
||
"none",
|
||
"server",
|
||
"global",
|
||
],
|
||
case_exact=True,
|
||
),
|
||
_attribute_characteristics(
|
||
name="referenceTypes",
|
||
multi_valued=True,
|
||
description="A multi-valued array of JSON strings that indicate the SCIM resource types that may be referenced.",
|
||
mutability="readOnly",
|
||
canonical_values=[
|
||
# todo(jon): add "User" and "Group" once those are done.
|
||
"external",
|
||
"uri"
|
||
],
|
||
case_exact=True,
|
||
),
|
||
_attribute_characteristics(
|
||
name="subAttributes",
|
||
type="complex",
|
||
multi_valued=True,
|
||
description="When an attribute is of type 'complex', this defines a set of sub-attributes.",
|
||
mutability="readOnly",
|
||
sub_attributes=[
|
||
_attribute_characteristics(
|
||
name="name",
|
||
description="The attribute's name.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="type",
|
||
description="The attribute's data type.",
|
||
required=True,
|
||
canonical_values=[
|
||
"string",
|
||
"complex",
|
||
"boolean",
|
||
"decimal",
|
||
"integer",
|
||
"dateTime",
|
||
"reference",
|
||
],
|
||
case_exact=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="multiValued",
|
||
type="boolean",
|
||
description="A Boolean value indicating an attribute's plurality.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="description",
|
||
description="The attribute's human-readable description.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="required",
|
||
type="boolean",
|
||
description="A Boolean value indicating whether or not the attribute is required.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="canonicalValues",
|
||
multi_valued=True,
|
||
description="A collection of canonical values.",
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="caseExact",
|
||
type="boolean",
|
||
description="A Boolean that specifies whether or not a string attribute is case sensitive.",
|
||
mutability="readOnly",
|
||
),
|
||
_attribute_characteristics(
|
||
name="mutability",
|
||
description="A single keyword indicating the circumstances under which the value of the attribute can be (re)defined.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
canonical_values=[
|
||
"readOnly",
|
||
"readWrite",
|
||
"immutable",
|
||
"writeOnly",
|
||
],
|
||
case_exact=True,
|
||
),
|
||
_attribute_characteristics(
|
||
name="returned",
|
||
description="A single keyword that indicates when an attribute and associated values are returned in response to a GET request or in response to a PUT, POST, or PATCH request.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
canonical_values=[
|
||
"always",
|
||
"never",
|
||
"default",
|
||
"request",
|
||
],
|
||
case_exact=True,
|
||
),
|
||
_attribute_characteristics(
|
||
name="uniqueness",
|
||
description="A single keyword value that specifies how the service provider enforces uniqueness of attribute values.",
|
||
required=True,
|
||
mutability="readOnly",
|
||
canonical_values=[
|
||
"none",
|
||
"server",
|
||
"global",
|
||
],
|
||
case_exact=True,
|
||
),
|
||
_attribute_characteristics(
|
||
name="referenceTypes",
|
||
multi_valued=True,
|
||
description="A multi-valued array of JSON strings that indicate the SCIM resource types that may be referenced.",
|
||
mutability="readOnly",
|
||
canonical_values=[
|
||
# todo(jon): add "User" and "Group" once those are done.
|
||
"external",
|
||
"uri"
|
||
],
|
||
case_exact=True,
|
||
),
|
||
],
|
||
),
|
||
]
|
||
)
|
||
]
|
||
}
|
||
|
||
|
||
|
||
SCHEMAS = sorted(
|
||
# todo(jon): add the user schema
|
||
[
|
||
SERVICE_PROVIDER_CONFIG_SCHEMA,
|
||
RESOURCE_TYPE_SCHEMA,
|
||
SCHEMA_SCHEMA,
|
||
],
|
||
key=lambda x: x["id"],
|
||
)
|
||
|
||
SERVICE_PROVIDER_CONFIG = {
|
||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig"],
|
||
"patch": {
|
||
# todo(jon): this needs to be updated to True once we properly implement patching for users and groups
|
||
"supported": False,
|
||
},
|
||
"bulk": {
|
||
"supported": False,
|
||
"maxOperations": 0,
|
||
"maxPayloadSize": 0,
|
||
},
|
||
"filter": {
|
||
# todo(jon): this needs to be updated to True once we properly implement filtering for users and groups
|
||
"supported": False,
|
||
"maxResults": 0,
|
||
},
|
||
"changePassword": {
|
||
"supported": False,
|
||
},
|
||
"sort": {
|
||
"supported": False,
|
||
},
|
||
"etag": {
|
||
"supported": False,
|
||
},
|
||
"authenticationSchemes": [
|
||
{
|
||
"type": "oauthbearertoken",
|
||
"name": "OAuth Bearer Token",
|
||
"description": "Authentication scheme using the OAuth Bearer Token Standard. The access token should be sent in the 'Authorization' header using the Bearer schema.",
|
||
"specUri": "https://tools.ietf.org/html/rfc6750",
|
||
# todo(jon): see if we have our own documentation for this
|
||
# "documentationUri": "", # optional
|
||
"primary": True,
|
||
},
|
||
],
|
||
"meta": {
|
||
"resourceType": "ServiceProviderConfig",
|
||
"created": "2025-04-15T15:45:00Z",
|
||
# note(jon): we might want to think about adding this resource as part of our db
|
||
# and then updating these timestamps from an api and such. for now, if we update
|
||
# the configuration, we should update the timestamp here.
|
||
"lastModified": "2025-04-15T15:45:00Z",
|
||
"location": "", # note(jon): this field will be computed in the /ServiceProviderConfig endpoint
|
||
},
|
||
}
|
||
|
||
RESOURCE_TYPES = sorted(
|
||
[
|
||
{
|
||
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:ResourceType"],
|
||
"id": "User",
|
||
"name": "User",
|
||
"endpoint": "/Users",
|
||
"description": "User account",
|
||
"schema": "urn:ietf:params:scim:schemas:core:2.0:User",
|
||
"meta": {
|
||
"resourceType": "ResourceType",
|
||
"created": "2025-04-16T08:37:00Z",
|
||
# note(jon): we might want to think about adding this resource as part of our db
|
||
# and then updating these timestamps from an api and such. for now, if we update
|
||
# the configuration, we should update the timestamp here.
|
||
"lastModified": "2025-04-16T08:37:00Z",
|
||
"location": "ResourceType/User",
|
||
},
|
||
}
|
||
],
|
||
key=lambda x: x["id"],
|
||
)
|