scim2-server 0.6.1__tar.gz → 0.6.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {scim2_server-0.6.1 → scim2_server-0.6.2}/PKG-INFO +2 -2
- {scim2_server-0.6.1 → scim2_server-0.6.2}/pyproject.toml +2 -2
- {scim2_server-0.6.1 → scim2_server-0.6.2}/pyproject.toml.orig +2 -2
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/service.py +57 -5
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/storage.py +3 -1
- {scim2_server-0.6.1 → scim2_server-0.6.2}/LICENSE +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/README.md +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/__init__.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/applications/__init__.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/applications/asgi.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/applications/base.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/applications/wsgi.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/bulk.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/conditions.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/errors.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/handler.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/memory.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/py.typed +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/requests.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/resources/default-resource-types.json +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/resources/default-schemas.json +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/resources/default-service-provider-config.json +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/responses.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/routing.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/testing.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/testserver/__init__.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/testserver/application.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/testserver/cli.py +0 -0
- {scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: scim2-server
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.2
|
|
4
4
|
Summary: SCIM server core for any storage and web framework
|
|
5
5
|
Keywords: scim,scim2,provisioning,rfc7643,rfc7644
|
|
6
6
|
Author: Yaal Coop, Christian Friedrich Coors
|
|
@@ -217,7 +217,7 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
217
217
|
Classifier: Environment :: Web Environment
|
|
218
218
|
Classifier: Programming Language :: Python
|
|
219
219
|
Classifier: Operating System :: OS Independent
|
|
220
|
-
Requires-Dist: scim2-models>=0.10.
|
|
220
|
+
Requires-Dist: scim2-models>=0.10.6
|
|
221
221
|
Requires-Dist: pytest>=9.1.1 ; extra == 'testing'
|
|
222
222
|
Requires-Python: >=3.11
|
|
223
223
|
Project-URL: repository, https://github.com/python-scim/scim2-server
|
|
@@ -4,7 +4,7 @@ build-backend = "uv_build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "scim2-server"
|
|
7
|
-
version = "0.6.
|
|
7
|
+
version = "0.6.2"
|
|
8
8
|
description = "SCIM server core for any storage and web framework"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
keywords = [
|
|
@@ -28,7 +28,7 @@ classifiers = [
|
|
|
28
28
|
"Operating System :: OS Independent",
|
|
29
29
|
]
|
|
30
30
|
requires-python = ">= 3.11"
|
|
31
|
-
dependencies = ["scim2-models>=0.10.
|
|
31
|
+
dependencies = ["scim2-models>=0.10.6"]
|
|
32
32
|
|
|
33
33
|
[[project.authors]]
|
|
34
34
|
name = "Yaal Coop"
|
|
@@ -4,7 +4,7 @@ build-backend = "uv_build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "scim2-server"
|
|
7
|
-
version = "0.6.
|
|
7
|
+
version = "0.6.2"
|
|
8
8
|
description = "SCIM server core for any storage and web framework"
|
|
9
9
|
authors = [
|
|
10
10
|
{name="Yaal Coop", email="contact@yaal.coop"},
|
|
@@ -29,7 +29,7 @@ classifiers = [
|
|
|
29
29
|
|
|
30
30
|
requires-python = ">= 3.11"
|
|
31
31
|
dependencies = [
|
|
32
|
-
"scim2-models>=0.10.
|
|
32
|
+
"scim2-models>=0.10.6",
|
|
33
33
|
]
|
|
34
34
|
|
|
35
35
|
[project.optional-dependencies]
|
|
@@ -5,6 +5,7 @@ from typing import Any
|
|
|
5
5
|
from typing import TypeVar
|
|
6
6
|
from typing import Union
|
|
7
7
|
from typing import cast
|
|
8
|
+
from urllib.parse import urlsplit
|
|
8
9
|
|
|
9
10
|
from pydantic import ValidationError
|
|
10
11
|
from pydantic_core import from_json
|
|
@@ -28,7 +29,9 @@ from scim2_models import NotFoundException
|
|
|
28
29
|
from scim2_models import NotImplementedException
|
|
29
30
|
from scim2_models import Patch
|
|
30
31
|
from scim2_models import PatchOp
|
|
32
|
+
from scim2_models import Path
|
|
31
33
|
from scim2_models import PayloadTooLargeException
|
|
34
|
+
from scim2_models import Reference
|
|
32
35
|
from scim2_models import Resource
|
|
33
36
|
from scim2_models import ResourceType
|
|
34
37
|
from scim2_models import ResponseParameters
|
|
@@ -512,11 +515,28 @@ class ScimService:
|
|
|
512
515
|
f"{base_url.rstrip('/')}/{resource_type.endpoint.strip('/')}/{resource_id}"
|
|
513
516
|
)
|
|
514
517
|
|
|
518
|
+
def reference_location(self, base_url: str, reference: str) -> str:
|
|
519
|
+
"""Return the URL of a reference to a resource.
|
|
520
|
+
|
|
521
|
+
A reference relative to the SCIM root, such as ``Users/2819c223``,
|
|
522
|
+
becomes the location of the resource
|
|
523
|
+
(:rfc:`RFC 7643 §2.3.7 <7643#section-2.3.7>`). Absolute references
|
|
524
|
+
are kept.
|
|
525
|
+
"""
|
|
526
|
+
if urlsplit(reference).scheme or reference.startswith("/"):
|
|
527
|
+
return reference
|
|
528
|
+
endpoint, _, resource_id = reference.rpartition("/")
|
|
529
|
+
resource_type = self.get_resource_type_by_endpoint(endpoint)
|
|
530
|
+
if resource_type is None or not resource_id:
|
|
531
|
+
return f"{base_url.rstrip('/')}/{reference}"
|
|
532
|
+
return self.resource_location(base_url, resource_type, resource_id)
|
|
533
|
+
|
|
515
534
|
def publish(self, base_url: str, resource: Resource[Any]) -> Resource[Any]:
|
|
516
535
|
"""Return a copy of a stored resource in the form sent to the client.
|
|
517
536
|
|
|
518
|
-
Its location is set,
|
|
519
|
-
|
|
537
|
+
Its location is set, its references to other resources become URLs
|
|
538
|
+
with :meth:`reference_location`, and its version is left out when the
|
|
539
|
+
service does not support ETags.
|
|
520
540
|
"""
|
|
521
541
|
assert resource.meta is not None
|
|
522
542
|
assert resource.id is not None
|
|
@@ -527,9 +547,41 @@ class ScimService:
|
|
|
527
547
|
}
|
|
528
548
|
if not self.etag_supported:
|
|
529
549
|
update["version"] = None
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
)
|
|
550
|
+
published = resource.model_copy(deep=True)
|
|
551
|
+
published.meta = resource.meta.model_copy(update=update)
|
|
552
|
+
self._publish_references(base_url, published)
|
|
553
|
+
return published
|
|
554
|
+
|
|
555
|
+
def _publish_references(self, base_url: str, resource: Resource[Any]) -> None:
|
|
556
|
+
"""Replace in place the references of a resource to other resources by their URLs."""
|
|
557
|
+
|
|
558
|
+
def locate(reference: Any) -> Any:
|
|
559
|
+
if isinstance(reference, list):
|
|
560
|
+
return [locate(item) for item in reference]
|
|
561
|
+
if reference is None:
|
|
562
|
+
return None
|
|
563
|
+
return self.reference_location(base_url, reference)
|
|
564
|
+
|
|
565
|
+
for path in parametrize(Path, type(resource)).iter_paths(
|
|
566
|
+
target_type=[Reference]
|
|
567
|
+
):
|
|
568
|
+
binding = path.resolve()
|
|
569
|
+
assert binding is not None
|
|
570
|
+
target_type = cast(type[Reference[Any]], binding.target_type)
|
|
571
|
+
reference_types = set(target_type.__reference_types__)
|
|
572
|
+
if not reference_types or reference_types & {"external", "uri"}:
|
|
573
|
+
continue
|
|
574
|
+
|
|
575
|
+
if binding.sub_field_name is None:
|
|
576
|
+
path.set(resource, locate(path.get(resource)), strict=False)
|
|
577
|
+
continue
|
|
578
|
+
|
|
579
|
+
head = f"{path.schema}:{path.parts[0]}" if path.schema else path.parts[0]
|
|
580
|
+
entries = Path(head).get(resource)
|
|
581
|
+
for entry in entries if isinstance(entries, list) else [entries]:
|
|
582
|
+
if entry is not None:
|
|
583
|
+
reference = getattr(entry, binding.sub_field_name)
|
|
584
|
+
setattr(entry, binding.sub_field_name, locate(reference))
|
|
533
585
|
|
|
534
586
|
@staticmethod
|
|
535
587
|
def resource_response(
|
|
@@ -26,7 +26,9 @@ class ScimStorage(ABC):
|
|
|
26
26
|
stored resource, and the resources it receives are not changed either.
|
|
27
27
|
- It fills ``id``, ``meta.resourceType``, ``meta.created``,
|
|
28
28
|
``meta.lastModified`` and ``meta.version``. It leaves ``meta.location``
|
|
29
|
-
to the server, which knows the URLs.
|
|
29
|
+
to the server, which knows the URLs. For the same reason, a reference
|
|
30
|
+
to another resource, such as ``members.$ref``, can be relative to the
|
|
31
|
+
SCIM root, such as ``Users/2819c223``. The server returns its URL.
|
|
30
32
|
- The version changes whenever the resource changes. An update that
|
|
31
33
|
changes nothing may keep it.
|
|
32
34
|
- A resource that does not exist raises
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{scim2_server-0.6.1 → scim2_server-0.6.2}/scim2_server/resources/default-resource-types.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|