ExScim.Lifecycle.Adapter behaviour (ex_scim v0.6.0)

Copy Markdown View Source

Behaviour for lifecycle hooks around SCIM operations.

Implement this behaviour to run custom logic before or after SCIM operations. All callbacks are optional. Unimplemented callbacks are no-ops.

Configuration

config :ex_scim, lifecycle_adapter: MyApp.ScimLifecycle

Before hooks

Fire after validation/mapping/metadata, immediately before storage. Can modify domain data or reject the operation by returning {:error, term()}.

After hooks

Fire after the write is committed and mapped to a SCIM response. Observe-only (return :ok).

Before-commit hook

before_commit/4 runs inside the storage transaction, right after the write for create, replace, patch, and delete. It receives the record returned by storage, or the ID for delete. Returning {:error, reason} or raising rolls back the write, skips the after hook, and fires on_error. Use it for work that must be committed with the write. Without ExScim.Storage.Adapter.transaction/1, the write is not rolled back.

Error hook

Fires when an operation fails. Observe-only.

Example

defmodule MyApp.ScimLifecycle do
  use ExScim.Lifecycle.Adapter

  @impl true
  def before_create(:user, data, _caller) do
    if some_business_rule_violated?(data) do
      {:error, {:forbidden, "Business rule violated"}}
    else
      {:ok, data}
    end
  end

  @impl true
  def after_create(:user, scim_response, _caller) do
    MyApp.Notifications.send_welcome(scim_response["id"])
    :ok
  end
end

Summary

Types

The authenticated caller scope for the current request.

The SCIM operation type that triggered the hook.

The domain-level resource data (struct or map) being processed.

The unique identifier of the resource.

The type of resource being operated on: :user or :group.

The SCIM JSON response map after mapping from the domain struct.

The SCIM operations that write to storage.

Callbacks

Fires after a resource is successfully created. Observe-only.

Fires after a resource is successfully deleted. Observe-only.

Fires after a resource is successfully retrieved. Observe-only.

Fires after a resource is successfully patched. Observe-only.

Fires after a resource is successfully replaced. Observe-only.

Fires inside the storage transaction after a write. Receives the record returned by storage, or the ID for delete. Return :ok to commit or {:error, reason} to roll back.

Fires before a resource is created. Return {:ok, data} to proceed or {:error, reason} to reject.

Fires before a resource is deleted. Return :ok to proceed or {:error, reason} to reject.

Fires before a resource is retrieved. Return :ok to proceed or {:error, reason} to reject.

Fires before a resource is patched. Return {:ok, data} to proceed or {:error, reason} to reject.

Fires before a resource is replaced (PUT). Return {:ok, data} to proceed or {:error, reason} to reject.

Fires when an operation fails. Observe-only; intended for logging or metrics.

Types

caller()

@type caller() :: ExScim.Scope.t()

The authenticated caller scope for the current request.

operation()

@type operation() :: :create | :replace | :patch | :delete | :get

The SCIM operation type that triggered the hook.

resource_data()

@type resource_data() :: term()

The domain-level resource data (struct or map) being processed.

resource_id()

@type resource_id() :: binary()

The unique identifier of the resource.

resource_type()

@type resource_type() :: :user | :group

The type of resource being operated on: :user or :group.

scim_response()

@type scim_response() :: map()

The SCIM JSON response map after mapping from the domain struct.

write_operation()

@type write_operation() :: :create | :replace | :patch | :delete

The SCIM operations that write to storage.

Callbacks

after_create(resource_type, scim_response, caller)

(optional)
@callback after_create(resource_type(), scim_response(), caller()) :: :ok

Fires after a resource is successfully created. Observe-only.

after_delete(resource_type, resource_id, caller)

(optional)
@callback after_delete(resource_type(), resource_id(), caller()) :: :ok

Fires after a resource is successfully deleted. Observe-only.

after_get(resource_type, scim_response, caller)

(optional)
@callback after_get(resource_type(), scim_response(), caller()) :: :ok

Fires after a resource is successfully retrieved. Observe-only.

after_patch(resource_type, scim_response, caller)

(optional)
@callback after_patch(resource_type(), scim_response(), caller()) :: :ok

Fires after a resource is successfully patched. Observe-only.

after_replace(resource_type, scim_response, caller)

(optional)
@callback after_replace(resource_type(), scim_response(), caller()) :: :ok

Fires after a resource is successfully replaced. Observe-only.

before_commit(write_operation, resource_type, arg3, caller)

(optional)
@callback before_commit(
  write_operation(),
  resource_type(),
  resource_data() | resource_id(),
  caller()
) ::
  :ok | {:error, term()}

Fires inside the storage transaction after a write. Receives the record returned by storage, or the ID for delete. Return :ok to commit or {:error, reason} to roll back.

before_create(resource_type, resource_data, caller)

(optional)
@callback before_create(resource_type(), resource_data(), caller()) ::
  {:ok, resource_data()} | {:error, term()}

Fires before a resource is created. Return {:ok, data} to proceed or {:error, reason} to reject.

before_delete(resource_type, resource_id, caller)

(optional)
@callback before_delete(resource_type(), resource_id(), caller()) ::
  :ok | {:error, term()}

Fires before a resource is deleted. Return :ok to proceed or {:error, reason} to reject.

before_get(resource_type, resource_id, caller)

(optional)
@callback before_get(resource_type(), resource_id(), caller()) :: :ok | {:error, term()}

Fires before a resource is retrieved. Return :ok to proceed or {:error, reason} to reject.

before_patch(resource_type, resource_id, resource_data, caller)

(optional)
@callback before_patch(resource_type(), resource_id(), resource_data(), caller()) ::
  {:ok, resource_data()} | {:error, term()}

Fires before a resource is patched. Return {:ok, data} to proceed or {:error, reason} to reject.

before_replace(resource_type, resource_id, resource_data, caller)

(optional)
@callback before_replace(resource_type(), resource_id(), resource_data(), caller()) ::
  {:ok, resource_data()} | {:error, term()}

Fires before a resource is replaced (PUT). Return {:ok, data} to proceed or {:error, reason} to reject.

on_error(operation, resource_type, term, caller)

(optional)
@callback on_error(operation(), resource_type(), term(), caller()) :: :ok

Fires when an operation fails. Observe-only; intended for logging or metrics.