Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ All notable changes to this project will be documented in this file.
* This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)

## [Unreleased]
### Changed
- [Breaking] Require explicitly specified `:actions_module` on `use Permit` rather than fetching it through permissions module to avoid compile-time dependency.

## [v0.3.0]
### Changed
- [Breaking] Change order of args in `Permit.verify_record/3` and add delegation as `do?/3` when doing `use Permit`.

This way, permisisons to perform a dynamically computed action can be checked like this:
This way, permissions to perform a dynamically computed action can be checked like this:
```elixir
action = :read
can(user) |> do?(action, %Item{id: 1})
Expand Down
24 changes: 20 additions & 4 deletions lib/permit.ex
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ defmodule Permit do
end

defmodule MyApp.Permissions do
use Permit.Permissions, actions_module: Permit.Actions.CrudActions
use Permit.Permissions

def can(%{role: :admin} = user) do
permit()
Expand All @@ -85,7 +85,6 @@ defmodule Permit do
def can(user), do: permit()
end
```
Note that in the permission definitions module the `read` function is generated based on configuration provided as the `:actions_module` option - in this case, `CrudActions` generates `create`, `read`, `update` and `delete`. For more on this, see `Permit.Actions` and `Permit.Permissions`.

### Check a user's authorization to perform an action on a resource
```elixir
Expand All @@ -99,7 +98,22 @@ defmodule Permit do
iex(4)> can(%MyApp.User{role: :admin}) |> delete?(%MyApp.Article{author_id: 2})
true
```
Functions such as `MyApp.Authorization.read?/2`, `MyApp.Authorization.update?/2`, etc. are also generated based on the `:actions_module` option. See more in `Permit.Actions`.

### Configure further actions
By default, Permit will generate predicate functions for the 4 common CRUD actions. If you need further actions,
you can define a custom actions module and configure it in both your `Authorization` and your `Permissions` module.
See `Permit.Actions` for more information.
```elixir
defmodule MyApp.Authorization do
use Permit,
actions_module: MyApp.Actions,
permissions_module: MyApp.Permissions
end

defmodule MyApp.Permissions do
use Permit.Permissions, actions_module: MyApp.Actions
# ...
end
"""

alias Permit.Permissions
Expand All @@ -114,7 +128,9 @@ defmodule Permit do
permissions_module = Keyword.fetch!(opts, :permissions_module)

predicates =
Macro.expand(permissions_module, __CALLER__).actions_module()
opts
|> Keyword.get(:actions_module, Permit.Actions.CrudActions)
|> Macro.expand(__CALLER__)
|> Permit.Actions.list_groups()
|> Enum.map(&add_predicate_name/1)
|> Enum.map(fn {predicate, name} ->
Expand Down
12 changes: 10 additions & 2 deletions lib/permit/permissions.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ defmodule Permit.Permissions do
A very simple usage example:
```
defmodule MyApp.Permissions do
use Permit.Permissions, actions_module: Permit.Actions.CrudActions
use Permit.Permissions

@impl true
def can(%MyApp.User{role: :admin}) do
Expand All @@ -31,6 +31,14 @@ defmodule Permit.Permissions do

## Named action functions

By default, Permit will generate actions functions for the 4 common CRUD actions. If you need further actions, you can define a custom actions module .and configure it in both your `Authorization` and your `Permissions` module. See `Permit.Actions` for more information.

```elixir
defmodule MyApp.Permissions do
# actions_module defaults to Permit.Actions.CrudActions.
use Permit.Permissions, actions_module: MyApp.Actions
```

Each action defined in the `:actions_module` results in a 2-, 3-, and 4-arity function being generated.

For instance, if a `:read` action is defined, there are the following calls available to grant the `:read` permission on a given resource type:
Expand Down Expand Up @@ -97,7 +105,7 @@ defmodule Permit.Permissions do
condition_parser = opts[:condition_parser] || (&ConditionParser.build/2)
condition_types_module = opts[:condition_types_module] || Permit.Types.ConditionTypes

actions_module = opts |> Keyword.get(:actions_module, Permit.Actions.CrudActions)
actions_module = Keyword.get(opts, :actions_module, Permit.Actions.CrudActions)

# Unnamed action macro
permission_to = PermissionTo.mixin(condition_parser, condition_types_module)
Expand Down
1 change: 1 addition & 0 deletions test/permit/permit_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ defmodule Permit.PermitTest do
defmodule TestAuthorization do
@moduledoc false
use Permit,
actions_module: TestActions,
permissions_module: Permit.PermitTest.TestPermissions
end

Expand Down