permission_ex v0.6.0 PermissionEx View Source

Main module and interface to testing permissions.

If you wish to test a single permission for equality, then you would use PermissionEx.test_permission/2.

If you wish to test an entire permission struct for matching allowed permissions then you would use PermissionEx.test_permissions/2.

If you wish to test an entire permission struct for matching allowed permissions on a struct tagged map then you would use PermissionEx.test_tagged_permissions/2.

The examples in this module use these definitions of structs for testing permissions:


defmodule PermissionEx.Test.Structs.User do
  @moduledoc false
  @derive [Poison.Encoder]
  defstruct name: nil
end

defmodule PermissionEx.Test.Structs.Page do
  @moduledoc false
  @derive [Poison.Encoder]
  defstruct action: nil
end

defmodule PermissionEx.Test.Structs.PageReq do
  @moduledoc false
  @derive [Poison.Encoder]
  defstruct action: nil
end

defmodule PermissionEx.Test.Structs.PagePerm do
  @moduledoc false
  @derive [Poison.Encoder]
  defstruct action: nil
end

Link to this section Summary

Types

A Permission matcher is either anything, of which it must then match the required permission precisely, or it is a list starting with :any such as [:any | permissions] where each item in the list will be tested against the requirement as a base permission, if any are true then this matches.

This is a set of permissions such as %{}, [%{}], etc...

This is a map that has a mapping of a %{Struct => %Struct{}}.

Functions

This tests a specific required permission against a specific permission.

This tests a specific requirement against a set of permission.

This takes a map of permissions with the keys being a tag to be looked up on. The required permission struct type is the tag to match on.

Link to this section Types

Link to this type

permission() View Source
permission() :: [:any | permission()] | any()

A Permission matcher is either anything, of which it must then match the required permission precisely, or it is a list starting with :any such as [:any | permissions] where each item in the list will be tested against the requirement as a base permission, if any are true then this matches.

Link to this type

permissions() View Source
permissions() ::
  :_
  | boolean()
  | nil
  | [permissions()]
  | %{required(any()) => permission()}
  | struct()

This is a set of permissions such as %{}, [%{}], etc...

A :_ or true matches any entire requirement set.

A false or nil will always not match.

A list of permissions will each be checked individually against the requirement, if any are a true match then it returns true.

A struct or map will be tested against the requirements directly, a struct is treated like a map except the :__struct__ field will not be tested, useful if you want a requirement and permission to use different structs. Do note that the tagged_permissions keys should match the :__struct__ of the requirement struct, not of the permission struct. I.E. given a PermissionEx.Test.Structs.PageReq and a PermissionEx.Test.Structs.PagePerm, such as if you want the default values for the requirement stuct to be by default tight or lenient, and the opposite for the permission struct, then calling PermissionEx.test_permissions/2 will be like:


iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.PageReq{action: :show}, %{PermissionEx.Test.Structs.PageReq => [%PermissionEx.Test.Structs.PagePerm{action: :_}]})
true

iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.PageReq{action: :show}, %{PermissionEx.Test.Structs.PagePerm => [%PermissionEx.Test.Structs.PagePerm{action: :_}]})
false
Link to this type

tagged_permissions() View Source
tagged_permissions() ::
  struct()
  | %{:admin => tagged_permissions(), required(atom()) => permissions()}
  | %{required(atom()) => permissions()}

This is a map that has a mapping of a %{Struct => %Struct{}}.

The value being an actual struct is optional, it can also be a map on its own, as long as it has matching keys => values of the struct, any missing will have the requirement be false unless the requirement is :_.

If there is an :admin key in the permissions, then this is checked first and can act as an easy override for the main permission set.

Link to this section Functions

Link to this function

test_permission(required, permission) View Source
test_permission(any(), permission()) :: boolean()

This tests a specific required permission against a specific permission.

  • If either are :_ then it is true.
  • If both are identical, then it is true.
  • If the permission is the list starting with :any such as [:any | <permissions>] then each permission in the list is tested against the requirement
  • The permission "" is equivilent to `:`

Examples


  iex> PermissionEx.test_permission(:_, :_)
  true

  iex> PermissionEx.test_permission(:_, "_")
  true

  iex> PermissionEx.test_permission("_", :_)
  true

  iex> PermissionEx.test_permission("_", "_")
  true

  iex> PermissionEx.test_permission(:_, nil)
  true

  iex> PermissionEx.test_permission(nil, :_)
  true

  iex> PermissionEx.test_permission("_", nil)
  true

  iex> PermissionEx.test_permission(nil, "_")
  true

  iex> PermissionEx.test_permission(nil, nil)
  true

  iex> PermissionEx.test_permission(nil, :notnil)
  false

  iex> PermissionEx.test_permission(:notnil, nil)
  false

  iex> PermissionEx.test_permission(1, 1)
  true

  iex> PermissionEx.test_permission(1, 1.0)
  false

  iex> PermissionEx.test_permission('test', 'test')
  true

  iex> PermissionEx.test_permission("test", "test")
  true

  iex> PermissionEx.test_permission('test', "test")
  false

  iex> PermissionEx.test_permission(:show, :show)
  true

  iex> PermissionEx.test_permission(:show, :edit)
  false

  iex> PermissionEx.test_permission(:show, [:any])
  false

  iex> PermissionEx.test_permission(:show, [:any, :show])
  true

  iex> PermissionEx.test_permission(:show, [:any, :show, :edit])
  true

  iex> PermissionEx.test_permission(:show, [:any, :edit, :show])
  true

  iex> PermissionEx.test_permission(:show, [:any, :edit, :otherwise])
  false

  iex> PermissionEx.test_permission(:show, ["any"])
  false

  iex> PermissionEx.test_permission(:show, ["any", :show])
  true

  iex> PermissionEx.test_permission(:show, ["any", :show, :edit])
  true

  iex> PermissionEx.test_permission(:show, ["any", :edit, :show])
  true

  iex> PermissionEx.test_permission(:show, ["any", :edit, :otherwise])
  false

  iex> PermissionEx.test_permission(:show, ["any", "edit", "show"])
  true

  iex> PermissionEx.test_permission(:show, ["any", "edit", "otherwise"])
  false

  iex> PermissionEx.test_permission(:show, [:many])
  false

  iex> PermissionEx.test_permission(:show, [:many, :show, :edit])
  true

  iex> PermissionEx.test_permission([:show, :edit], [:many, :show, :edit])
  true

  iex> PermissionEx.test_permission([:edit, :show], [:many, :show, :edit])
  true

  iex> PermissionEx.test_permission(:show, "show")
  true

  iex> PermissionEx.test_permission(:show, "_")
  true

  iex> PermissionEx.test_permission(nil, "_")
  true

  iex> PermissionEx.test_permission([:show, 123], ["show", 123])
  true

  iex> PermissionEx.test_permission(%{}, %{})
  true

  iex> PermissionEx.test_permission(%{action: :show}, %{action: "show"})
  true

  iex> PermissionEx.test_permission(%{action: "show"}, %{action: "show"})
  true

  iex> PermissionEx.test_permission(%{action: :show}, %{"action" => :show})
  true

  iex> PermissionEx.test_permission(%{"action" => :show}, %{action: :show})
  true

  iex> PermissionEx.test_permission(%{action: :show}, %{action: [:any, :show, :index]})
  true

  iex> PermissionEx.test_permission(%{action: :none}, %{action: [:any, :show, :index]})
  false
Link to this function

test_permissions(required, permissions) View Source
test_permissions(struct(), permissions()) :: boolean()

This tests a specific requirement against a set of permission.

See PermissionEx.test_permission/2 for possible permission formats.

Examples


  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, :_)
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, true)
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, false)
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, nil)
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [])
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %{})
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %{action: :edit})
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %{action: :show})
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %{action: :_})
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %{action: true})
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %{action: [:any, :edit, :show]})
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %PermissionEx.Test.Structs.Page{})
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %PermissionEx.Test.Structs.Page{action: :edit})
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %PermissionEx.Test.Structs.Page{action: :show})
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %PermissionEx.Test.Structs.Page{action: :_})
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %PermissionEx.Test.Structs.Page{action: true})
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %PermissionEx.Test.Structs.Page{action: [:any, :edit, :show]})
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [:_])
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [true])
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [false])
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [nil])
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [[]])
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [%{}])
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [%{action: :edit}])
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [%{action: :show}])
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [%{action: :_}])
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [%{action: true}])
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [%{action: [:any, :edit, :show]}])
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [%PermissionEx.Test.Structs.Page{}])
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [%PermissionEx.Test.Structs.Page{action: :edit}])
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [%PermissionEx.Test.Structs.Page{action: :show}])
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [%PermissionEx.Test.Structs.Page{action: :_}])
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [%PermissionEx.Test.Structs.Page{action: true}])
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [%PermissionEx.Test.Structs.Page{action: [:any, :edit, :show]}])
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [%{"action" => :edit}])
  false

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [%{"action" => :show}])
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [%{"action" => :_}])
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: :show}, [%{"action" => "_"}])
  true

  iex> PermissionEx.test_permissions(%PermissionEx.Test.Structs.Page{action: [:something, 123]}, [%{"action" => ["something", 123]}])
  true
Link to this function

test_tagged_permissions(required, tagged_perm_map) View Source
test_tagged_permissions(struct(), tagged_permissions()) :: boolean()

This takes a map of permissions with the keys being a tag to be looked up on. The required permission struct type is the tag to match on.

In the key of :admin, if true, will always return true no matter what the required matcher wants, it is an override that allows all permissions.

If the key of :admin contains a map, then the tag will be looked up in it and tested against, such as if true then they will get permission for that tag regardless.

If a given tag has the boolean of 'true' then it will always return true, basically giving admin just for that specific tag.

See PermissionEx.test_permissions/2 for how a permission struct/map is matched.

See PermissionEx.test_permission/2 for possible permission formats.

Examples


  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.Page{}, %{admin: true})
  true

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.Page{}, %{admin: %{PermissionEx.Test.Structs.Page => true}})
  true

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.User{}, %{admin: %{PermissionEx.Test.Structs.Page => true}})
  false

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %{admin: %{PermissionEx.Test.Structs.Page => %{action: :show}}})
  true

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.Page{action: :edit}, %{admin: %{PermissionEx.Test.Structs.Page => %{action: :show}}})
  false

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %{PermissionEx.Test.Structs.Page => true})
  true

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %{PermissionEx.Test.Structs.Page => %{}})
  false

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %{PermissionEx.Test.Structs.Page => %{}})
  false

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %{PermissionEx.Test.Structs.Page => %PermissionEx.Test.Structs.Page{action: :show}})
  true

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %{PermissionEx.Test.Structs.Page => %PermissionEx.Test.Structs.Page{action: :_}})
  true

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %{PermissionEx.Test.Structs.Page => %PermissionEx.Test.Structs.Page{action: nil}})
  false

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %{PermissionEx.Test.Structs.Page => [%PermissionEx.Test.Structs.Page{action: :show}]})
  true

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %{PermissionEx.Test.Structs.Page => [%PermissionEx.Test.Structs.Page{action: :_}]})
  true

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.Page{action: :show}, %{PermissionEx.Test.Structs.Page => [%PermissionEx.Test.Structs.Page{action: nil}]})
  false

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.PageReq{action: :show}, %{PermissionEx.Test.Structs.PageReq => [%PermissionEx.Test.Structs.PagePerm{action: :_}]})
  true

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.PageReq{action: :show}, %{PermissionEx.Test.Structs.PagePerm => [%PermissionEx.Test.Structs.PagePerm{action: :_}]})
  false

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.PageReq{action: :show}, %{"Elixir.PermissionEx.Test.Structs.PageReq" => [%PermissionEx.Test.Structs.PagePerm{action: :_}]})
  true

  iex> PermissionEx.test_tagged_permissions(%PermissionEx.Test.Structs.PageReq{action: :show}, %{"Elixir.PermissionEx.Test.Structs.PagePerm" => [%PermissionEx.Test.Structs.PagePerm{action: :_}]})
  false