Verified Commit 66b2ed14 authored by Éloi Rivard's avatar Éloi Rivard
Browse files

chore: bump the python-scim libraries

parent a1cee487
Loading
Loading
Loading
Loading
+9 −0
Changes for CHANGES.rst: 9 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -19,6 +19,13 @@ Changed
  outgoing requests, such as the password compromise check and the download of
  ``request_uri`` and ``jwks_uri`` documents. HTTPS certificates are checked against
  the system trust store, instead of the certifi bundle.
- The SCIM server follows RFC 7644 more closely on PATCH requests, as it now relies on
  scim2-models 0.10. For instance, a PATCH that writes the ``display`` of a group
  member is refused with a ``mutability`` error.
- The SCIM ``ResourceType`` endpoints are relative to the SCIM base URL, such as
  ``/Users``, as RFC 7643 §6 defines them.
- The SCIM ``User`` resource type declares the enterprise extension as optional.
  Users without it were already accepted.

Removed
^^^^^^^
@@ -26,6 +33,8 @@ Removed

Fixed
^^^^^
- SCIM PATCH requests that cannot be applied answer a SCIM error instead of an
  HTTP 500 error.
- User impersonation was a ``GET`` request, thus not covered by the CSRF protection. It is now confirmed with a form, and the ``/impersonate/<user>`` endpoint is removed.
- The inline validation of the login and password fields redirected users without
  a password to the password initialization page. As the redirection was answered
+1 −1
Changes for canaille/app/features.py: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -125,7 +125,7 @@ class Features:
        and needs the ``scim`` extra package to be installed.
        """
        try:
            import httpx  # noqa: F401
            import httpx2  # noqa: F401
            import scim2_client  # noqa: F401

            return (
+8 −5
Changes for canaille/scim/client.py: 8 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -2,9 +2,10 @@ import datetime

from blinker import signal
from flask import current_app
from httpx import Client as httpx_client
from scim2_client import SCIMClientError
from scim2_client.engines.httpx import SyncSCIMClient
from httpx2 import Client as httpx_client
from scim2_client import SCIMClientException
from scim2_client.engines.httpx2 import SyncSCIMClient
from scim2_models import SCIMException
from scim2_models import SearchRequest
from werkzeug.security import gen_salt

@@ -89,7 +90,7 @@ def initiate_scim_client(client):
    scim = SyncSCIMClient(client_httpx)
    try:
        scim.discover()
    except SCIMClientError:
    except (SCIMClientException, SCIMException):
        current_app.logger.info(
            f"SCIM protocol not supported by client {client.client_name}"
        )
@@ -117,7 +118,7 @@ def execute_scim_user_action(client_id, user_id, method):
    if method == "delete" and distant_scim_user:
        try:
            scim.delete(User, distant_scim_user.id)
        except SCIMClientError:
        except (SCIMClientException, SCIMException):
            current_app.logger.warning(
                f"SCIM User {user.user_name} delete for client {client.client_name} failed"
            )
@@ -133,6 +134,7 @@ def execute_scim_user_action(client_id, user_id, method):
                )
        else:
            scim_user.id = distant_scim_user.id
            scim_user.meta = distant_scim_user.meta
            try:
                scim.replace(scim_user)
            except Exception:
@@ -173,6 +175,7 @@ def execute_scim_group_action(scim, group, client_name, method):
                )
        else:
            group.id = scim_group.id
            group.meta = scim_group.meta
            try:
                scim.replace(group)
            except Exception:
+13 −12
Changes for canaille/scim/endpoints.py: 13 added lines, 12 removed lines.
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ from scim2_models import PatchOp
from scim2_models import ResourceType
from scim2_models import ResponseParameters
from scim2_models import Schema
from scim2_models import SCIMException
from scim2_models import SearchRequest
from werkzeug.exceptions import HTTPException
from werkzeug.exceptions import PreconditionFailed
@@ -132,6 +133,12 @@ def scim_error_handler(error):
    return obj.model_dump(), obj.status


@bp.errorhandler(SCIMException)
def scim_exception_handler(error):
    obj = error.to_error()
    return obj.model_dump(), obj.status


def parse_search_request(request) -> SearchRequest:
    """Create a SearchRequest object from the request arguments."""
    max_nb_items_per_page = 1000
@@ -164,8 +171,7 @@ def _query_resources(canaille_model, scim_type, to_scim):
    )
    return list_response.model_dump(
        scim_ctx=Context.RESOURCE_QUERY_RESPONSE,
        attributes=req.attributes,
        excluded_attributes=req.excluded_attributes,
        response_parameters=req,
    )


@@ -174,8 +180,7 @@ def _query_resource(resource, to_scim):
    scim_resource = to_scim(resource)
    return scim_resource.model_dump(
        scim_ctx=Context.RESOURCE_QUERY_RESPONSE,
        attributes=req.attributes,
        excluded_attributes=req.excluded_attributes,
        response_parameters=req,
    )


@@ -194,8 +199,7 @@ def _create_resource(scim_type, canaille_model, to_scim, from_scim):
    return (
        response_resource.model_dump(
            scim_ctx=Context.RESOURCE_CREATION_RESPONSE,
            attributes=req.attributes,
            excluded_attributes=req.excluded_attributes,
            response_parameters=req,
        ),
        HTTPStatus.CREATED,
    )
@@ -218,8 +222,7 @@ def _replace_resource(resource, scim_type, to_scim, from_scim):
    response = to_scim(updated)
    return response.model_dump(
        scim_ctx=Context.RESOURCE_REPLACEMENT_RESPONSE,
        attributes=req.attributes,
        excluded_attributes=req.excluded_attributes,
        response_parameters=req,
    )


@@ -242,8 +245,7 @@ def _patch_resource(resource, scim_type, to_scim, from_scim):

    return scim_resource.model_dump(
        scim_ctx=Context.RESOURCE_PATCH_RESPONSE,
        attributes=req.attributes,
        excluded_attributes=req.excluded_attributes,
        response_parameters=req,
    )


@@ -376,8 +378,7 @@ def search():
    )
    payload = list_response.model_dump(
        scim_ctx=Context.RESOURCE_QUERY_RESPONSE,
        attributes=req.attributes,
        excluded_attributes=req.excluded_attributes,
        response_parameters=req,
    )
    return payload

+3 −3
Changes for canaille/scim/models.py: 3 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -258,13 +258,13 @@ def get_resource_types():
        "User": ResourceType(
            id="User",
            name="User",
            endpoint=url_for("scim.query_users", _external=True),
            endpoint="/Users",
            description="User accounts",
            schema_="urn:ietf:params:scim:schemas:core:2.0:User",
            schema_extensions=[
                SchemaExtension(
                    schema_="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",
                    required=True,
                    required=False,
                )
            ],
            meta=Meta(
@@ -279,7 +279,7 @@ def get_resource_types():
        "Group": ResourceType(
            id="Group",
            name="Group",
            endpoint=url_for("scim.query_groups", _external=True),
            endpoint="/Groups",
            description="Group management",
            schema_="urn:ietf:params:scim:schemas:core:2.0:Group",
            meta=Meta(
Loading