# Permit.Ecto

Integrates [`Permit`]( with Ecto, providing means to convert permissions to Ecto queries,
automatically constructing `Ecto.Query` scopes to preload records that meet authorization criteria.

## Dependencies and related libraries

`Permit.Ecto` depends on `Permit`. It can be used to build custom integrations or in conjunction with `Permit.Phoenix`, which uses
the generated `accessible_by/4` functions to automatically preload, authorize and inject records loaded via Ecto into
controller assigns (see more in [`Permit.Phoenix documentation`](

## Configuration

defmodule MyApp.Authorization do
  use Permit.Ecto,
    permissions_module: MyApp.Permissions,
    repo: MyApp.Repo

defmodule MyApp.Permissions do
  use Permit.Ecto.Permissions, actions_module: Permit.Actions.CrudActions

  def can(%{role: :admin} = user) do
    |> all(MyApp.Blog.Article)

  def can(%{id: user_id} = user) do
    # Checks can be performed directly for record columns as well as associated
    # record values in has_one, has_many and belongs_to associations.
    # For has_one and belongs_to relationships, given condition must be satisfied
    # for the associated record. For has_many relationships, at least one associated
    # record must satisfy the condition - as seen in example below.

    |> all(MyApp.Blog.Article, author_id: user_id)
    |> read(MyApp.Blog.Article, reviews: [approved: true])

  def can(user), do: permit()

iex> MyApp.Repo.all(MyApp.Blog.Article)
  %MyApp.Blog.Article{id: 1, author_id: 1},
  %MyApp.Blog.Article{id: 2, author_id: 1},
  %MyApp.Blog.Article{id: 3, author_id: 2}

# The `accessible_by!/3` function also has a `accessible_by/3` variant which returns `{:ok, ...}` tuples.

iex> MyApp.Permissions.accessible_by!(%MyApp.Users.User{id: 1}, :update, MyApp.Blog.Article)
[%MyApp.Blog.Article{id: 1, ...}, %MyApp.Blog.Article{id: 2, ...}]

iex> MyApp.Permissions.accessible_by!(%MyApp.Users.User{id: 1}, :read, MyApp.Blog.Article)
[%MyApp.Blog.Article{id: 1, ...}, %MyApp.Blog.Article{id: 2, ...}, %MyApp.Blog.Article{id: 3, ...}]

iex> MyApp.Permissions.accessible_by!(%MyApp.Users.User{id: 3, role: :admin}, :update, MyApp.Blog.Article)
[%MyApp.Blog.Article{id: 1, ...}, %MyApp.Blog.Article{id: 2, ...}, %MyApp.Blog.Article{id: 3, ...}]

## Installation

The package can be installed by adding `permit_ecto` to your list of dependencies in `mix.exs`:

def deps do
    {:permit_ecto, "~> 0.1.0"}

The docs can be found at <>.