Ecto integration for Permit - Convert permissions to Ecto queries with automatic authorization scoping.
Permit.Ecto integrates Permit with Ecto, providing means to convert permissions to Ecto queries and automatically constructing Ecto.Query scopes to preload records that meet authorization criteria.
Key features:
- Automatic query generation - Convert Permit permissions into Ecto queries
- Authorization scoping - Automatically scope database queries based on user permissions
- Association support - Handle has_one, has_many, and belongs_to relationships in permission rules
- Seamless integration - Works with Permit.Phoenix for automatic controller and LiveView authorization
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).
defmodule MyApp.Authorization do
use Permit.Ecto,
permissions_module: MyApp.Permissions,
repo: MyApp.Repo
end
defmodule MyApp.Permissions do
use Permit.Ecto.Permissions, actions_module: Permit.Actions.CrudActions
def can(%{role: :admin} = user) do
permit()
|> all(MyApp.Blog.Article)
end
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.
permit()
|> all(MyApp.Blog.Article, author_id: user_id)
|> read(MyApp.Blog.Article, reviews: [approved: true])
end
def can(user), do: permit()
end
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.Repo.all()
[%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.Repo.all()
[%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.Repo.all()
[%MyApp.Blog.Article{id: 1, ...}, %MyApp.Blog.Article{id: 2, ...}, %MyApp.Blog.Article{id: 3, ...}]Generate Ecto queries based on permissions for direct database querying:
# Generate query scoped to user permissions
query = MyApp.Authorization.accessible_by!(current_user, :read, Article)
articles = MyApp.Repo.all(query)
# Use with pagination and other Ecto features
query
|> where([a], a.published == true)
|> order_by([a], desc: a.inserted_at)
|> limit(10)
|> MyApp.Repo.all()Permit.Ecto is part of the modular Permit ecosystem:
| Package | Version | Description |
|---|---|---|
| permit | Core authorization library | |
| permit_ecto | Ecto integration for database queries | |
| permit_phoenix | Phoenix Controllers & LiveView integration | |
| permit_absinthe | GraphQL API authorization via Absinthe |
The package can be installed by adding permit_ecto to your list of dependencies in mix.exs:
def deps do
[
{:permit, "~> 0.3.0"}, # Core authorization library
{:permit_ecto, "~> 0.2.4"} # Ecto integration
]
endFor a complete setup with Phoenix or Absinthe integration, add :permit_phoenix or :permit_absinthe.
- Permit.Ecto docs: hexdocs.pm/permit_ecto
- Core library: hexdocs.pm/permit
We welcome contributions! Please see our Contributing Guide for details.
Just clone the repository, install dependencies normally, develop and run tests. When running Credo and Dialyzer, please use MIX_ENV=test to ensure tests and support files are validated, too.
- Slack channel: Elixir Slack / #permit
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Blog: Curiosum Blog
- Library maintainer: Michał Buszkiewicz
- Curiosum - Elixir development team behind Permit
This project is licensed under the MIT License - see the LICENSE file for details.