You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+15
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,20 @@
1
1
## Changelog
2
2
3
+
## v2.0.0-dev
4
+
Canary 2.0.0 introduces authorization hooks for Phoenix LiveView. The Plug based authorization was refactored a bit to make the API cosistent. Please follow the [Upgrade guide to 2.0.0](docs/upgrade.md#upgrading-from-canary-1-2-0-to-2-0-0) for more details.
5
+
6
+
* Enhancements
7
+
* added support for authorization LiveView with `Canary.Hooks`
8
+
* added `:error_handler` and ErrorHandler behaviour
9
+
* added `:required` option, default to true
10
+
11
+
* Dependency changes
12
+
* Elixir ~> 1.14 is now required
13
+
14
+
* Deprecations
15
+
* The `:non_id_actions` option is deprecated and will be removed in Canary 2.1.0. Use separate `:authorize_resource` plug for `non_id_actions` and `:except` to exclude non_in_actions.
16
+
* The `:persisted` option is deprecated and will be removed in Canary 2.1.0. Use `:required` instead.
An authorization library in Elixir for Plug applications that restricts what resources
7
-
the current user is allowed to access, and automatically loads resources for the current request.
6
+
An authorization library in Elixir for `Plug` and `Phoenix.LiveView` applications that restricts what resources the current user is allowed to access, and automatically load and assigns resources.
8
7
9
8
Inspired by [CanCan](https://github.com/CanCanCommunity/cancancan) for Ruby on Rails.
10
9
11
10
[Read the docs](http://hexdocs.pm/canary)
12
11
13
12
## Installation
14
13
15
-
For the latest master:
14
+
For the latest master (2.0.0-dev):
16
15
17
16
```elixir
18
17
defpdepsdo
@@ -24,59 +23,75 @@ For the latest release:
24
23
25
24
```elixir
26
25
defpdepsdo
27
-
{:canary, "~> 1.2.1"}
26
+
{:canary, "~> 2.0.0-dev"}
28
27
end
29
28
```
30
29
31
30
Then run `mix deps.get` to fetch the dependencies.
32
31
33
-
## Usage
32
+
## Quick start
34
33
35
-
Canary provides three functions to be used as plugs to load and authorize resources:
34
+
Canary provides functions to be used as plugs or LiveView hooks to load and authorize resources:
36
35
37
-
`load_resource/2`, `authorize_resource/2`, and `load_and_authorize_resource/2`.
36
+
`load_resource`, `authorize_resource`, `authorize_controller`*, and `load_and_authorize_resource`.
38
37
39
-
`load_resource/2` and `authorize_resource/2` can be used by themselves, while `load_and_authorize_resource/2` combines them both.
38
+
`load_resource` and `authorize_resource` can be used by themselves, while `load_and_authorize_resource` combines them both.
39
+
40
+
*Available only in plug based authentication*
40
41
41
42
In order to use Canary, you will need, at minimum:
42
43
43
44
- A [Canada.Can protocol](https://github.com/jarednorman/canada) implementation (a good place would be `lib/abilities.ex`)
44
45
45
-
- An Ecto record struct containing the user to authorize in `conn.assigns.current_user` (the key can be customized - see https://github.com/cpjk/canary#overriding-the-default-user).
46
+
- An Ecto record struct containing the user to authorize in `assigns.current_user` (the key can be customized - [see more](#overriding-the-default-user)).
46
47
47
48
- Your Ecto repo specified in your `config/config.exs`: `config :canary, repo: YourApp.Repo`
48
49
49
-
Then, just `import Canary.Plugs` in order to use the plugs. In a Phoenix app the best place would probably be inside `controller/0` in your `web/web.ex`, in order to make the functions available in all of your controllers.
50
+
For the plugs just `import Canary.Plugs`. In a Phoenix app the best place would probably be inside `controller/0` in your `web/web.ex`, in order to make the functions available in all of your controllers.
50
51
51
-
### load_resource/2
52
+
For the liveview hooks just `use Canary.Hooks`. In a Phoenix app the best place would probably be inside `live_view/0` in your `web/web.ex`, in order to make the functions available in all of your controllers.
52
53
53
-
Loads the resource having the id given in `conn.params["id"]` from the database using the given Ecto repo and model, and assigns the resource to `conn.assigns.<resource_name>`, where `resource_name` is inferred from the model name.
54
54
55
-
For example,
55
+
### load_resource
56
56
57
+
Loads the resource having the id given in `params["id"]` from the database using the given Ecto repo and model, and assigns the resource to `assigns.<resource_name>`, where `resource_name` is inferred from the model name.
58
+
59
+
<!-- tabs-open -->
60
+
### Conn Plugs example
57
61
```elixir
58
62
plug :load_resource, model:Project.Post
59
63
```
60
-
Will load the `Project.Post` having the id given in `conn.params["id"]` through `YourApp.Repo`, into
61
-
`conn.assigns.post`
62
64
63
-
### authorize_resource/2
65
+
Will load the `Project.Post` having the id given in `conn.params["id"]` through `YourApp.Repo`, and assign it to `conn.assigns.post`.
66
+
67
+
### LiveView Hooks example
68
+
```elixir
69
+
mount_canary :load_resource, model:Project.Post
70
+
```
71
+
72
+
Will load the `Project.Post` having the id given in `params["id"]` through `YourApp.Repo`, and assign it to `socket.assigns.post`
73
+
<!-- tabs-close -->
64
74
65
-
Checks whether or not the `current_user` for the request can perform the given action on the given resource and assigns the result (true/false) to `conn.assigns.authorized`. It is up to you to decide what to do with the result.
75
+
### authorize_resource
76
+
77
+
Checks whether or not the `current_user` for the request can perform the given action on the given resource and assigns the result (true/false) to `assigns.authorized`. It is up to you to decide what to do with the result.
66
78
67
79
For Phoenix applications, Canary determines the action automatically.
80
+
For non-Phoenix applications, or to override the action provided by Phoenix, simply ensure that `assigns.canary_action` contains an atom specifying the action.
81
+
82
+
For the LiveView on `handle_params` it uses `socket.assigns.live_action` as action, on `handle_event` it uses the event name as action.
83
+
68
84
69
-
For non-Phoenix applications, or to override the action provided by Phoenix, simply ensure that `conn.assigns.canary_action` contains an atom specifying the action.
70
85
71
86
In order to authorize resources, you must specify permissions by implementing the [Canada.Can protocol](https://github.com/jarednorman/canada) for your `User` model (Canada is included as a light weight dependency).
72
87
73
-
### load_and_authorize_resource/2
88
+
### load_and_authorize_resource
74
89
75
-
Authorizes the resource and then loads it if authorization succeeds. Again, the resource is loaded into `conn.assigns.<resource_name>`.
90
+
Authorizes the resource and then loads it if authorization succeeds. Again, the resource is loaded into `assigns.<resource_name>`.
76
91
77
92
In the following example, the `Post` with the same `user_id` as the `current_user` is only loaded if authorization succeeds.
78
93
79
-
###Usage Example
94
+
## Usage Example
80
95
81
96
Let's say you have a Phoenix application with a `Post` model, and you want to authorize the `current_user` for accessing `Post` resources.
82
97
@@ -90,7 +105,10 @@ defimpl Canada.Can, for: User do
90
105
defcan?(%User{ id: user_id }, _, _), do:false
91
106
end
92
107
```
93
-
and in your `web/router.ex:` you have:
108
+
109
+
### Example for Conn Plugs
110
+
111
+
In your `web/router.ex:` you have:
94
112
95
113
```elixir
96
114
get "/posts/:id", PostController, :show
@@ -107,6 +125,46 @@ In this case, on `GET /posts/12` authorization succeeds, and the `Post` specifie
107
125
108
126
However, on `DELETE /posts/12`, authorization fails and the `Post` resource is not loaded.
109
127
128
+
### Example for LiveView Hooks
129
+
130
+
In your `web/router.ex:` you have:
131
+
132
+
```elixir
133
+
live "/posts/:id", PostLive, :show
134
+
```
135
+
136
+
and in your PostLive module `web/live/post_live.ex`:
In this case, once opening `/posts/12` the `load_and_authorize_resource` on `handle_params` stage will be performed. The the `Post` specified by `params["id]` will be loaded into `socket.assigns.post`.
165
+
166
+
However, when the `delete` event will be triggered, authorization fails and the `Post` resource is not loaded. Socket will be halted.
167
+
110
168
### Excluding actions
111
169
112
170
To exclude an action from any of the plugs, pass the `:except` key, with a single action or list of actions.
For the `:index`, `:new`, and `:create` actions, the resource passed to the `Canada.Can` implementation
187
-
should be the *module* name of the model rather than a struct.
258
+
To authorize actions where there is no loaded resource, the resource passed to the `Canada.Can` implementation should be the module name of the model rather than a struct.
188
259
189
-
For example, when authorizing access to the `Post` resource,
260
+
To authorize such actions use `authorize_resource` plug with `required: false` option
to load and authorize the parent `Post` resource using the `post_id` in /posts/:post_id/comments before you
239
-
create the `Comment` resource using its parent.
240
-
241
338
### Specifing database field
242
339
243
340
You can tell Canary to search for a resource using a field other than the default `:id` by using the `:id_field` option. Note that the specified field must be able to uniquely identify any resource in the specified table.
0 commit comments