# Annacl

[![Actions Status](](

Associate models with permissions and roles.

This package allows you to manage user permissions and roles in a database.

## Installation

Annacl is published on [Hex]( The package can be installed by adding `annacl` to your list of dependencies in `mix.exs`:

def deps do
    {:annacl, "~> 0.5.0"}

After the packages are installed you must create a database migration to add the annacl tables to your database:

defmodule MyApp.Repo.Migrations.AddAnnaclTables do
  use Ecto.Migration

  def up do

  def down do

This will run all of Annacl's versioned migrations for your database. Migrations between versions are idempotent and will never change after a release. As new versions are released you may need to run additional migrations.

Now, run the migration to create the table:

mix ecto.migrate

## Usage

# config/config.exs
  config :annacl,
    repo: MyApp.Repo
    superadmin_role_name: "superadmin" # The name of the role that bypass all roles and permissions.

# lib/my_app/account/user.ex
defmodule MyApp.Account.User do
  use Ecto.Schema

  alias Annacl.Performers.Performer

  schema "users" do
    belongs_to(:performer, Performer)

# lib/my_app/account.ex
defmodule MyApp.Accounts
  use Annacl


{:ok, _superadmin_role} = Annacl.create_role("superadmin")

{:ok, _user_role} = Annacl.create_role("user")

{:ok, posts_list} = Annacl.create_permission("posts.list")
{:ok, posts_create} = Annacl.create_permission("posts.create")
{:ok, posts_read} = Annacl.create_permission("")
{:ok, posts_update} = Annacl.create_permission("post.udpate")

Annacl.grant_permission_to_role(user_role, posts_list)
Annacl.grant_permission_to_role(user_role, posts_read)

# Create a performer for each user
performer = Annacl.create_performer()

|> Ecto.Changeset.change(%{performer_id:})
|> Repo.update!()

# How to assign role to users
superadmin = MyApp.Accounts.assign_role!(%MyApp.Accounts.User{performer_id: "00000000-0000-0000-0000-000000000000"}, "superadmin")

user = MyApp.Accounts.assign_role!(%MyApp.Accounts.User{performer_id: "00000000-0000-0000-0000-000000000001"}, "user")

true = MyApp.Accounts.can?(user, "posts.list")
true = MyApp.Accounts.can?(user, "")
false = MyApp.Accounts.can?(user, "posts.create")
false = MyApp.Accounts.can?(user, "posts.update")

true = MyApp.Accounts.can?(superadmin, "posts.list")
true = MyApp.Accounts.can?(superadmin, "posts.create")
true = MyApp.Accounts.can?(superadmin, "")
true = MyApp.Accounts.can?(superadmin, "posts.update")

Read the entire documentation [here](

## Test

Duplicate env/example.env to env/test.env and source it.

MIX_ENV=test mix do ecto.drop, ecto.create, ecto.migrate
mix test