AshScim.Patch (ash_scim v0.1.0)

Copy Markdown View Source

Translates a SCIM 2.0 PATCH request body (RFC 7644 §3.5.2) into a structured input describing both attribute updates and relationship-level operations:

%{
  attrs: %{first_name: "Alicia"},
  relationships: [
    {:append, :memberships, [%{user_id: "u1"}]},
    {:remove_where, :memberships, %{user_id: %{eq: "u2"}}}
  ]
}

The router applies attrs via the resource's update action and each relationship op as either a manage_relationship/4 call or a custom load+destroy/update step.

Supported operations

  • add / replace with no path — value is treated as a partial SCIM resource and decoded via AshScim.Decoder. Only attribute changes are applied (relationship arrays in path-less ops are ignored, since the semantics of "add a partial resource that includes a member list" aren't well-defined).
  • add / replace / remove with a simple path (e.g. active, name.givenName) — maps to the corresponding Ash attribute.
  • add path: "emails" value: [...] — append-style relationship op.
  • replace path: "emails" value: [...] — full-replace relationship op.
  • remove path: "emails[value eq "x"]" — load-and-destroy op against the related resource matching the bracket filter.

When the multivalued declares mirror_primary_to:, the patch result also carries a :mirror_sync post-op (or a synchronously-computed attr write for replace) that keeps the parent's mirrored scalar in sync with the primary entry's value.

Summary

Functions

Public schema URN for the PatchOp message.

Build the structured patch input from a PATCH body. Returns {:ok, %{attrs: …, relationships: …}} or {:error, reason}.

Types

op()

@type op() :: :add | :remove | :replace

rel_op()

@type rel_op() ::
  {:append, atom(), [%{required(atom()) => term()}]}
  | {:replace_all, atom(), [%{required(atom()) => term()}]}
  | {:remove_where, atom(), %{required(atom()) => term()}}
  | {:mirror_sync, atom(), atom(), atom()}

result()

@type result() :: %{attrs: %{required(atom()) => term()}, relationships: [rel_op()]}

Functions

schema()

Public schema URN for the PatchOp message.

to_params(arg1, resource)

@spec to_params(%{required(String.t()) => term()}, module()) ::
  {:ok, result()} | {:error, term()}

Build the structured patch input from a PATCH body. Returns {:ok, %{attrs: …, relationships: …}} or {:error, reason}.