View Source Authorizir behaviour (Authorizir v1.0.1)
Ecto-backed Authorization Library for Elixir Applications
See README for a description of the mathematical model used as the basis of this system.
usage
Usage
Imagine you are creating an app that handles online ordering.
First, create your app's authorization module, configuring it with your application repository:
defmodule Auth do
use Authorizir, repo: Repo
endUsers of the application might be organized into a hierarchy as follows (note that an employee can also be a customer):
graph TD
*[Users *] --> E[Employees]
* --> C[Customers]
E --> A[Admins]
E --> M[Marketing]
E --> F[Finance]
E --> S[Shipping and Fulfillment]
A --> Bob
M --> Bob
M --> Jane
F --> Amanda
S --> George
S --> Beth
C --> Amanda
C --> George
C --> JohnWe have two types of Subject entities represented here; "Organizational Units"
represent groups of users such as internal departments and customers, while
"Users" represent the individual system accounts. Each of these are
represented with Ecto schemas in our app, and we include the
Authorizir.Subject behavior in the modules, so that they can participate in
the Subject hierarcy.
First we add the necessary migrations by running mix ecto.gen.migraion add_org_units_and_users and editing the resulting migration file:
defmodule AddOrgUnitsAndUsers do
use Ecto.Migration
import Authorizir.Migrations, only: [apply_subject_hierarchy: 2]
create table("org_units") do
add :name, :string, null: false
timestamps()
end
apply_subject_hierarchy("org_units", id_field: :id)
create table("users") do
add :name, :string, null: false
timestamps()
end
apply_subject_hierarchy("users", id_field: :id)
enddefmodule OrgUnit do
use Ecto.Schema
use Authorizir.Subject
schema "org_units" do
field :name, :string
end
end
defmodule User do
use Ecto.Schema
use Authorizir.Subject
schema "users" do
field :name, :string
end
endYou can create the hierarchy as:
{:ok, employees} = %OrgUnit{name: "Employees"} |> Repo.insert()
{:ok, customers} = %OrgUnit{name: "Customers"} |> Repo.insert()
{:ok, admins} = %OrgUnit{name: "Admins"} |> Repo.insert()
:ok = Auth.add_child(employees.id, admins.id, Subject)
{:ok, marketing} = %OrgUnit{name: "Marketing"} |> Repo.insert()
:ok = Auth.add_child(employees.id, marketing.id, Subject)
{:ok, finance} = %OrgUnit{name: "Finance"} |> Repo.insert()
:ok = Auth.add_child(employees.id, finance.id, Subject)
{:ok, shipping} = %OrgUnit{name: "Shipping and Fulfillment"} |> Repo.insert()
:ok = Auth.add_child(employees.id, shipping.id, Subject)
{:ok, bob} = %User{name: "Bob"} |> Repo.insert()
:ok = Auth.add_child(admins.id, bob.id, Subject)
:ok = Auth.add_child(marketing.id, bob.id, Subject)
{:ok, jane} = %User{name: "Jane"} |> Repo.insert()
:ok = Auth.add_child(marketing.id, jane.id, Subject)
{:ok, amanda} = %User{name: "Amanda"} |> Repo.insert()
:ok = Auth.add_child(finance.id, amanda.id, Subject)
:ok = Auth.add_child(customers.id, amanda.id, Subject)
{:ok, george} = %User{name: "George"} |> Repo.insert()
:ok = Auth.add_child(shipping.id, george.id, Subject)
:ok = Auth.add_child(customers.id, george.id, Subject)
{:ok, beth} = %User{name: "Beth"} |> Repo.insert()
:ok = Auth.add_child(shipping.id, beth.id, Subject)
{:ok, john} = %User{name: "John"} |> Repo.insert()
:ok = Auth.add_child(customers.id, john.id, Subject)