calcinator v1.5.0 Calcinator

Converts actions from a controller or RPC server using JSONAPI formatted params to calls on a Calcinator.Resources module.

Summary

Types

Nested params format used by Ecto.Changeset.t

The name of the parameter that was used for the query and was not found

The raw request params that need to be validated as a JSONAPI document and converted to an Alembic.Document.t

A rendered JSONAPI document as a map

t()
  • authorization_module - The module that implements the Calcinator.Authorization behaviour
  • subject - the subject that is trying to do the action and needs to be authorized by authorization_module
  • target - the target of subject’s action

Types

association()
association() :: atom | list | map
insertable_params()
insertable_params() :: %{optional(String.t) => term}

Nested params format used by Ecto.Changeset.t.

parameter()
parameter() :: String.t

The name of the parameter that was used for the query and was not found.

params()
params() :: %{optional(String.t) => term}

The raw request params that need to be validated as a JSONAPI document and converted to an Alembic.Document.t

rendered()
rendered() :: map

A rendered JSONAPI document as a map

t()
t() :: %Calcinator{associations_by_include: term, authorization_module: module, ecto_schema_module: module, params: term, resources_module: term, subject: Calcinator.Authorization.subject, view_module: module}
  • authorization_module - The module that implements the Calcinator.Authorization behaviour
  • subject - the subject that is trying to do the action and needs to be authorized by authorization_module
  • target - the target of subject’s action

Functions

allow_sandbox_access(calcinator, params)
authorized(calcinator, resource_or_related)
authorized(t, related :: nil) :: nil
authorized(t, resource :: struct) :: struct
can(calcinator, action, target)
can(t, Calcinator.Authorization.action, Authorizaton.target) ::
  :ok |
  {:error, :unauthorized}
changeset(calcinator, updatable, updatable_params)
create(calcinator, params)
create(t, params) ::
  {:error, :ownership} |
  {:error, :unauthorized} |
  {:error, Alembic.Document.t} |
  {:error, Ecto.Changeset.t} |
  {:ok, rendered}

Creates resource from params.

Steps

  1. state authorization_module can?(subject, :create, ecto_schema_module)
  2. Check params are a valid JSONAPI document
  3. state authorization_module can?(subject, :create, Ecto.Changeset.t)
  4. allow_sandbox_access/2
  5. state authorization_module filter_associations_can(created, subject, :show)
  6. state view_module show(authorized, ...)

Returns

  • {:error, :ownership} - connection to backing store was not owned by the calling process
  • {:error, :unauthorized} - if state authorization_module can?(subject, :create, ecto_schema_module) or can?(subject, :create, %Ecto.Changeset{}) returns false
  • {:error, Alembic.Document.t} - if params is not a valid JSONAPI document
  • {:error, Ecto.Changeset.t} - if validations errors inserting Ecto.Changeset.t
  • {:ok, rendereded} - rendered view of created resource
delete(calcinator, params)
delete(t, params) ::
  :ok |
  {:error, {:not_found, parameter}} |
  {:error, :ownership} |
  {:error, :unauthorized} |
  {:error, Ecto.Changeset.t}

Deletes resource with "id" in params.

Steps

  1. allow_sandbox_access/2
  2. state resources_module get(id, ...)
  3. state authorization_module can?(subject, :delete, struct)
  4. state resources_module delete(struct)

Returns

  • {:error, {:not_found, "id"}} - The “id” did not correspond to resource in the backing store
  • {:error, :ownership} - connection to backing store was not owned by the calling process
  • {:error, :unauthorized} - The state subject is not authorized to delete the resource
  • {:error, Ecto.Changeset.t} - the deletion failed with the errors in Ecto.Changeset.t
  • :ok - resource was successfully deleted
get(resources_module, params, id_key, query_options)
get(module, params, id_key :: String.t, Resources.query_options) ::
  {:error, {:not_found, parameter} | :timeout | term} |
  {:ok, Ecto.Schema.t}
index(calcinator, params, map)
index(t, params, %{base_uri: URI.t}) ::
  {:error, :timeout} |
  {:error, :unauthorized} |
  {:error, Alembic.Document.t} |
  {:ok, rendered}

Gets index of a resource with (optional) pagination depending on whether the state resources_module supports pagination.

Steps

  1. state authorization_module can?(subject, :index, ecto_schema_module)
  2. allow_sandbox_access/2
  3. state resources_module list/1
  4. state authorization_module filter_can(listed, subject, :show)
  5. state authorization_module filter_associations_can(filtered_listed, subject, :show)
  6. state view_module index(association_filtered, ...)

Returns

  • {:error, :ownership} - connection to backing store was not owned by the calling process
  • {:error, :timeout} - if the backing store for state resources_module times out when calling list/1.
  • {:error, :unauthorized} - if state authorization_module can?(subject, :index, ecto_schema_module) returns false
  • {:error, Alembic.Document.t} - if params are not valid JSONAPI.
  • {:ok, rendered} - the rendered resources with (optional) pagination in the "meta".
show(calcinator, map)
show(t, params) ::
  {:error, {:not_found, parameter}} |
  {:error, :ownership} |
  {:error, :unauthorized} |
  {:error, Alembic.Document.t} |
  {:ok, rendered}

Shows resource with the "id" in params.

Steps

  1. allow_sandbox_acces/2
  2. state resources_module get(id, ...)
  3. state authorization_module can?(subject, :show, got)
  4. state authorization_module filter_associations_can(got, subject, :show)
  5. state view_module show(authorized, ...)

Returns

  • {:error, {:not_found, "id"}} - The “id” did not correspond to resource in the backing store
  • {:error, :ownership} - connection to backing store was not owned by the calling process
  • {:error, :unauthorized} - state authorization_module can?(subject, :show, got) returns false
  • {:error, Alembic.Document.t} - params is not valid JSONAPI
  • {:ok, rendered} - rendered resource
show_relationship(calcinator, params, map)
show_relationship(t, params, map) ::
  {:error, {:not_found, parameter}} |
  {:error, :ownership} |
  {:error, :unauthorized} |
  {:ok, rendered}

Shows a relationship.

Steps

  1. Gets source
  2. state authorization_module can?(subject, :show, source)
  3. Get related
  4. state authorization_module can?(subject, :show, [related, source])
  5. state authorization_module filter_associations_can(related, subject, :show)
  6. state view_module show_relationship(authorized, ...)

Returns

  • {:error, {:not_found, id_key}} - The value of the id_key key in params did not correspond to a resource in the backing store.
  • {:error, :ownership} - connection to backing store was not owned by the calling process
  • {:error, :unauthorized} - if the either the source or related resource cannot be shown
  • {:ok, rendered} - rendered view of relationship
update(calcinator, params)
update(t, params) ::
  {:error, :bad_gateway} |
  {:error, {:not_found, parameter}} |
  {:error, :ownership} |
  {:error, :unauthorized} |
  {:error, Alembic.Document.t} |
  {:error, Ecto.Changeset.t} |
  {:ok, rendered}

Updates a resource with the "id" in params

Steps

  1. allow_sandbox_access/2
  2. state resources_module get(id, ...)
  3. Check params are a valid JSONAPI document
  4. state authorization_module can?(subject, :update, Ecto.Changeset.t)
  5. state resources_module update(Ecto.Changeset.t, ...)
  6. state authorization_module filter_associations_can(updated, subject, :show)
  7. state view_module show(authorized, ...)

Returns

  • {:error, :bad_gateway} - backing store as internal error that can’t be represented in any other format. Try again later or call support.
  • {:error, {:not_found, "id"}} - get failed or update failed because the resource was deleted between the get and update.
  • {:error, :ownership} - connection to backing store was not owned by the calling process
  • {:error, :unauthorized} - the resource either can’t be shown or can’t be updated
  • {:error, Alembic.Document.t} - the params are not valid JSONAPI
  • {:error, Ecto.Changeset.t} - validations error when updating
  • {:ok, rendered} - the rendered updated resource
update_changeset(calcinator, changeset, params)
update_changeset(t, Ecto.Changeset.t, params) ::
  {:ok, Ecto.Schema.t} |
  {:error, Alembic.Document.t} |
  {:error, Ecto.Changeset.t} |
  {:error, :bad_gateway} |
  {:error, :not_found}