permission_ex v0.1.0 PermissionEx
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
Summary
Types
A Permission matcher is either anything, of which it must then match the
required permission precisely, or it is a tuple of {:any, [permission]}
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
Types
permission :: {:any, [permission]} | any
A Permission matcher is either anything, of which it must then match the
required permission precisely, or it is a tuple of {:any, [permission]}
where
each item in the list will be tested against the requirement as a base
permission, if any are true then this matches.
permissions ::
:_ |
boolean |
nil |
[permissions] |
%{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
tagged_permissions ::
struct |
%{:admin => tagged_permissions, atom => permissions} |
%{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.
Functions
Specs
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 tuple
{:any, [<permissions>]}
then each permission in the list is tested against the requirement
Examples
iex> PermissionEx.test_permission(:_, :_)
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
Specs
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
Specs
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