View Source Membership (ex_membership v1.0.6)

Main Membership module for including macros

Membership has 4 main components:

Relations between models

Membership.Member -> Membership.Feature[1-n] - Any given member have multiple features with this we can have more granular features for each member is adding a specific feature to a member not in his plan

Membership.Member -> Membership.Plan [1-n] - Any given member can have multiple plans

Membership.Member -> Membership.Role [1-n] - Any given member can have multiple roles

Membership.Plan -> Membership.Feature [m-n] - Any given plan can have multiple features

Membership.Role -> Membership.Feature [m-n] - Any given role can have multiple features

Calculating permissions

Calculation of permissions is done by 2 ets tables one holding the logged in members permissions the other holds modules function/permissions, then true = Enum.member?(module_permissions, member_permissions)

Available as_authorized

Summary

Functions

Macro for wrapping protected code

Returns authorization result on collected member and required features/plans

Defines calculated permission to be evaluated in runtime

Looks up Application config or raises if keyspace is not configured.

List membership and related modules.

Requires a feature within permissions block

Perform feature check on passed member and feature

Requires an plan within permissions block

Perform authorization on passed member and plans

Requires an role within permissions block

Perform authorization on passed member and roles

Perform authorization on passed member and roles

The Function list to ignore when building the permissions registry's

Load the plans into ets for the module/functions

Macro for defining required permissions

List version.

Functions

add_function_param_to_block(block)

as_authorized(member, func_name, list)

(macro)

Macro for wrapping protected code

Example

defmodule HelloTest do
  use Membership
  member = HelloTest.Repo.get(Membership.Member, 1)
  {:ok, member }  = load_and_authorize_member(member)

  def test_authorization do
    as_authorized(member, :test_authorization) do
      IO.inspect("This code is executed only for authorized member")
    end
  end
end

authorized?(member, func_name)

Returns authorization result on collected member and required features/plans

Example

defmodule HelloTest do
  use Membership

  def test_authorization do
    case authorized? do
      :ok -> "Member is authorized"
      {:error, message: _message} -> "Member is not authorized"
  end
end
end

calculated(current_member, func_name)

(macro)

Defines calculated permission to be evaluated in runtime

Examples

defmodule HelloTest do
  use Membership
  member = HelloTest.Repo.get(Membership.Member, 1)
  {:ok, member }  = load_and_authorize_member(member)

  def test_authorization do
    permissions do
      calculated(fn member ->
        member.email_confirmed?
      end)
    end

    as_authorized(member) do
      IO.inspect("This code is executed only for authorized member")
    end
  end
end

You can also use DSL form which takes function name as argument

  defmodule HelloTest do
  use Membership

  def test_authorization do
  use Membership
  member = HelloTest.Repo.get(Membership.Member, 1)
 {:ok, member } = load_and_authorize_member(member)

    permissions do
      calculated(member,:email_confirmed, :calculated)
    end

    as_authorized(member) do
      IO.inspect("This code is executed only for authorized member")
    end
  end

  def email_confirmed(member) do
    member.email_confirmed?
  end
end

For more complex calculations you need to pass bindings to the function

  defmodule HelloTest do
  use Membership
  member = HelloTest.Repo.get(Membership.Member, 1)
  {:ok, member} = load_and_authorize_member(member)

  def test_authorization do
    post = %Post{owner_id: 1}

    permissions do
      calculated(member,:is_owner, [post])
      calculated(fn member, [post] ->
        post.owner_id == member.id
      end)
    end

    as_authorized(member) do
      IO.inspect("This code is executed only for authorized member")
    end
  end

  def is_owner(member, [post]) do
    post.owner_id == member.id
  end
end

calculated(current_member, callback, func_name)

(macro)

calculated(current_member, callback, bindings, func_name)

(macro)

config(keyspace)

Looks up Application config or raises if keyspace is not configured.

Examples

config :membership, :files, [
  uploads_dir: Path.expand("../priv/uploads", __DIR__),
  host: [scheme: "http", host: "localhost", port: 4000],
]

iex> Membership.config([:files, :uploads_dir])
iex> Membership.config([:files, :host, :port])

get_loaded_modules()

List membership and related modules.

Examples

iex> Membership.get_loaded_modules()

has_feature(feature, func_name)

@spec has_feature(atom(), atom()) :: {:ok, atom()}

Requires a feature within permissions block

Example

defmodule HelloTest do
  use Membership

  def test_authorization do
    permissions do
      has_feature(:admin)
    end
  end
end

has_feature?(member, feature_name)

Perform feature check on passed member and feature

has_feature?(member, func_name, feature_name)

has_plan(plan, func_name)

@spec has_plan(atom(), atom()) :: {:ok, atom()}

Requires an plan within permissions block

Example

defmodule HelloTest do
  use Membership

  def test_authorization do
    permissions do
      has_plan(:gold, :test_authorization)
    end
  end
end

has_plan?(member, func_name, plan_name)

@spec has_plan?(Membership.Member.t(), atom(), String.t()) :: boolean()

Perform authorization on passed member and plans

has_role(role, func_name)

@spec has_role(atom(), atom()) :: {:ok, atom()}

Requires an role within permissions block

Example

defmodule HelloTest do
  use Membership

  def test_authorization do
    permissions do
      has_role(:gold, :test_authorization)
    end
  end
end

has_role?(member, role_name)

Perform authorization on passed member and roles

has_role?(member, func_name, role_name)

@spec has_role?(Membership.Member.t(), atom(), String.t()) :: boolean()
@spec has_role?(Membership.Member.t(), atom(), String.t()) :: boolean()

Perform authorization on passed member and roles

ignored_functions()

The Function list to ignore when building the permissions registry's

load_ets_data(current_module \\ __MODULE__)

Load the plans into ets for the module/functions

permissions(list)

(macro)

Macro for defining required permissions

Example

defmodule HelloTest do
  use Membership

  def test_authorization do
    permissions do
      has_feature(:admin_feature, :test_authorization)
      has_plan(:gold, :test_authorization)
    end
  end
end

permissions(member, list)

(macro)

version()

List version.

Examples

iex> Membership.version()