active_entry 1.2.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +275 -141
- data/app/controllers/concerns/active_entry/concern.rb +57 -0
- data/app/helpers/active_entry/view_helper.rb +20 -0
- data/lib/active_entry.rb +7 -88
- data/lib/active_entry/base.rb +66 -0
- data/lib/active_entry/errors.rb +44 -61
- data/lib/active_entry/generators.rb +4 -0
- data/lib/active_entry/policy_finder.rb +25 -0
- data/lib/active_entry/railtie.rb +6 -6
- data/lib/active_entry/rspec.rb +56 -0
- data/lib/active_entry/version.rb +1 -1
- data/lib/generators/active_entry/install/USAGE +8 -0
- data/lib/generators/active_entry/install/install_generator.rb +9 -0
- data/lib/generators/active_entry/install/templates/application_policy.rb +7 -0
- data/lib/generators/policy/USAGE +8 -0
- data/lib/generators/policy/policy_generator.rb +7 -0
- data/lib/generators/policy/templates/policy.rb +53 -0
- data/lib/generators/rspec/USAGE +8 -0
- data/lib/generators/rspec/policy_generator.rb +11 -0
- data/lib/generators/rspec/templates/policy_spec.rb +5 -0
- metadata +19 -5
- data/lib/active_entry/controller_methods.rb +0 -99
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f0d907b6dc39fa89d8c98128341eb2bd0804328b623ab473e5f6e8b3c9b6db0b
|
4
|
+
data.tar.gz: 4c105a1fedb63bc5ed4415e58184bb3b879744bd6656e477952c07ad898f15c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85ce65d93de8ec106d94c4e00b38d68ee80cfe3c51cb9700284d8ae1f25247ee8b7c4c0ccdb43e595a1e49176525c79117b2ffa5f54f3a144f7586ebc081f9f9
|
7
|
+
data.tar.gz: ff50acbb6a52138618186aa2ec9d17a28807fff5bd66237c426f26db700e969c81b1113abb3dea695ee6479f46a537459d0c8b337f75abb7bd483514b7500ddc
|
data/README.md
CHANGED
@@ -11,7 +11,64 @@
|
|
11
11
|
[](https://codeclimate.com/github/TFM-Agency/active_entry/maintainability)
|
12
12
|
[](https://rubydoc.info/github/TFM-Agency/active_entry/main)
|
13
13
|
|
14
|
-
Active Entry is a
|
14
|
+
Active Entry is a secure way to check for authentication and authorization before an action is performed. It's currently only compatible with Rails. But in later versions will ActiveEntry be Framework independent.
|
15
|
+
|
16
|
+
Active Entry works like many other Authorization Systems like [Pundit](https://github.com/varvet/pundit) or [Action Policy](https://github.com/palkan/action_policy) with **Policies**. However in Active Entry it's all about the method calling the auth mechanism. For every method that needs authentication or authorization, a decision maker method counterpart has to be created in the policy of the class.
|
17
|
+
|
18
|
+
## Example
|
19
|
+
|
20
|
+
Let's say we have an Users controller in our application:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
# app/controllers/users_controller.rb
|
24
|
+
class UsersController < ApplicationController
|
25
|
+
include ActiveEntry::ControllerConcern # Glue for the controller and Active Entry
|
26
|
+
|
27
|
+
def index
|
28
|
+
pass! # The auth happens here
|
29
|
+
load_users
|
30
|
+
end
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
We have to create the UsersPolicy in order for Active Entry to know who is authenticated and authorized and who not.
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
# app/policies/users_policy.rb
|
38
|
+
module UsersPolicy
|
39
|
+
class Authentication < ActiveEntry::Base::Authentication
|
40
|
+
def index?
|
41
|
+
Current.user_signed_in? # Only signed in users are considered to be authenticated.
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Authorization < ActiveEntry::Base::Authorization
|
46
|
+
def index?
|
47
|
+
Current.user.admin? # Only admins are authorized to perform this action
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
Now every time somebody calls the `users#index` endpoint, he or she has to be signed in and an admin. Otherwise `ActiveEntry::NotAuthenticatedError` or `ActiveEntry::NotAuthorizedError` are raised.
|
54
|
+
You can catch them easily in your controller by using Rails' `rescue_from`.
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
class ApplicationController < ActionController::Base
|
58
|
+
rescue_from ActiveEntry::NotAuthenticatedError, with: :not_authenticated
|
59
|
+
rescue_from ActiveEntry::NotAuthorizedError, with: :not_authorized
|
60
|
+
|
61
|
+
def not_authenticated
|
62
|
+
flash[:danger] = "Not authenticated. Please sign in."
|
63
|
+
redirect_to sign_in_path
|
64
|
+
end
|
65
|
+
|
66
|
+
def not_authorized
|
67
|
+
flash[:danger] = "Not authorized."
|
68
|
+
redirect_to root_path
|
69
|
+
end
|
70
|
+
end
|
71
|
+
```
|
15
72
|
|
16
73
|
## Installation
|
17
74
|
Add this line to your application's Gemfile:
|
@@ -20,72 +77,119 @@ Add this line to your application's Gemfile:
|
|
20
77
|
gem 'active_entry'
|
21
78
|
```
|
22
79
|
|
23
|
-
|
80
|
+
Or install it without bundler:
|
24
81
|
```bash
|
82
|
+
$ gem install active_entry
|
83
|
+
```
|
84
|
+
|
85
|
+
Run Bundle:
|
86
|
+
```shell
|
25
87
|
$ bundle
|
26
88
|
```
|
27
89
|
|
28
|
-
|
29
|
-
```
|
30
|
-
$
|
90
|
+
And then install Active Entry:
|
91
|
+
```shell
|
92
|
+
$ rails g active_entry:install
|
31
93
|
```
|
32
94
|
|
95
|
+
This will generate `app/policies/application_policy.rb`.
|
96
|
+
|
33
97
|
## Usage
|
34
|
-
|
98
|
+
Active Entry works with Policies. You can generate policies the following way:
|
99
|
+
|
100
|
+
Let's consider the example from above.
|
101
|
+
We have an UsersController and we want a policy for that:
|
102
|
+
|
103
|
+
```shell
|
104
|
+
$ rails g policy Users
|
105
|
+
```
|
106
|
+
|
107
|
+
This generates a policy called `UsersPolicy` and is located in `app/policies/users_policy.rb`.
|
108
|
+
|
109
|
+
The above generator call would generate something like this, but with a few comments to help you get started:
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
module UsersPolicy
|
113
|
+
class Authentication < ActiveEntry::Base::Authentication
|
114
|
+
end
|
115
|
+
|
116
|
+
class Authorization < ActiveEntry::Base::Authorization
|
117
|
+
end
|
118
|
+
end
|
119
|
+
```
|
35
120
|
|
36
121
|
### Verify authentication and authorization
|
37
|
-
You probably want to control authentication and authorization for every controller action you have in your app. As a safeguard to ensure, that auth is performed in every
|
122
|
+
You probably want to control authentication and authorization for every controller action you have in your app. As a safeguard to ensure, that auth is performed in every request and the auth call is not forgotten in development, add the `verify_authentication!` and `verify_authorization!` to your `ApplicationController`:
|
38
123
|
|
39
124
|
```ruby
|
40
125
|
class ApplicationController < ActionController::Base
|
41
|
-
|
126
|
+
verify_authentication!
|
127
|
+
verify_authorization!
|
42
128
|
# ...
|
43
129
|
end
|
44
130
|
```
|
45
|
-
This ensures, that you
|
131
|
+
This ensures, that you perform auth in all your controllers and raises errors if not.
|
46
132
|
|
47
133
|
### Perform authentication and authorization
|
48
|
-
in order to do the actual authentication and authorization, you have to
|
134
|
+
in order to do the actual authentication and authorization, you have to use `authenticate!` and `authorize!` or `pass!` as in your actions.
|
49
135
|
|
50
136
|
```ruby
|
51
|
-
class
|
52
|
-
|
53
|
-
|
137
|
+
class UsersController < ApplicationController
|
138
|
+
def authentication_only_action
|
139
|
+
authenticate!
|
140
|
+
end
|
141
|
+
|
142
|
+
def authorization_only_action
|
143
|
+
authorize!
|
144
|
+
end
|
145
|
+
|
146
|
+
def both_authentication_and_authorization_action
|
147
|
+
pass!
|
148
|
+
end
|
54
149
|
end
|
55
150
|
```
|
56
151
|
|
57
|
-
If you try to open a page,
|
58
|
-
You can do this by defining the methods `authenticated?` and `authorized?` in your controller.
|
152
|
+
If you try to open a page, Active Entry will raise `ActiveEntry::DecisionMakerMethodNotDefinedError`. This means we have to define the decision makers in our policy.
|
59
153
|
|
60
154
|
```ruby
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
155
|
+
module UsersPolicy
|
156
|
+
class Authentication < ApplicationPolicy::Authentication
|
157
|
+
def authentication_only_action?
|
158
|
+
success # == true | Everybody is allowed
|
159
|
+
end
|
65
160
|
|
66
|
-
|
67
|
-
|
161
|
+
def both_authentication_and_authorization_action?
|
162
|
+
success
|
163
|
+
end
|
68
164
|
end
|
69
165
|
|
70
|
-
|
71
|
-
|
72
|
-
|
166
|
+
class Authorization < ApplicationPolicy::Authorization
|
167
|
+
def authorization_only_action?
|
168
|
+
success
|
169
|
+
end
|
170
|
+
|
171
|
+
def both_authentication_and_authorization_action?
|
172
|
+
success
|
173
|
+
end
|
174
|
+
end
|
73
175
|
end
|
74
176
|
```
|
75
177
|
|
76
|
-
|
178
|
+
Every decision maker ends with an `?`. The name has to be the same as the name of the controller action. So `index` is going to be `index?`.
|
77
179
|
|
78
|
-
|
180
|
+
In order for Active Entry to not raise an auth error, the decision makers have to return `true`. In our above example we used `success`, which simply returns `true`.
|
79
181
|
|
80
|
-
|
81
|
-
|
182
|
+
**Note:** It has to be an explicit `true` and not just a truthy value. A string or object return value would raise an auth error.
|
183
|
+
|
184
|
+
### Rescuing from errors
|
185
|
+
Catch the errors in your controllers to redirect the user or show them a message.
|
82
186
|
|
83
187
|
```ruby
|
84
188
|
class ApplicationController < ActionController::Base
|
85
189
|
# ...
|
86
190
|
|
87
|
-
rescue_from ActiveEntry::NotAuthenticatedError, with: :not_authenticated
|
88
|
-
rescue_from ActiveEntry::NotAuthorizedError, with: :not_authorized
|
191
|
+
rescue_from ActiveEntry::NotAuthenticatedError, with: :not_authenticated
|
192
|
+
rescue_from ActiveEntry::NotAuthorizedError, with: :not_authorized
|
89
193
|
|
90
194
|
private
|
91
195
|
|
@@ -103,86 +207,70 @@ end
|
|
103
207
|
|
104
208
|
In this example above, the user will be redirected with a flash message. But you can do whatever you want. For example logging.
|
105
209
|
|
106
|
-
###
|
107
|
-
|
108
|
-
Instead of putting all authentication/authorization logic into `authenticated?` and `authorized?` you can create scoped decision makers:
|
210
|
+
### Authenticate/authorize outside the action
|
211
|
+
You can authenticate and authorize outside the action:
|
109
212
|
|
110
213
|
```ruby
|
111
|
-
class
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
# Do your authentication for the index action only
|
116
|
-
end
|
117
|
-
def index_authorized?
|
118
|
-
# Do your authorization for the index action only
|
119
|
-
end
|
120
|
-
def index
|
121
|
-
# Actual action
|
122
|
-
end
|
214
|
+
class UsersController < ApplicationController
|
215
|
+
authenticate_now!
|
216
|
+
authorize_now!
|
217
|
+
# pass_now! # Does both, authentication and authorization
|
123
218
|
end
|
124
219
|
```
|
125
220
|
|
126
|
-
|
127
|
-
|
128
|
-
**Note:** The scoped authentication/authorization decision maker methods take precendence over the general ones. That means if you have an `index_authenticated?` for your index action defined, the general `authenticated?` gets ignored.
|
129
|
-
|
130
|
-
### Controller helper methods
|
131
|
-
|
132
|
-
Active Entry also has a few helper methods which help you to distinguish between controller actions. You can check if a specific action got called, by adding `_action?` to the action name in your `authenticated?` or `authorized?`.
|
133
|
-
For an action `show` this would be `show_action?`.
|
134
|
-
|
135
|
-
**Note:** A `NoMethodError` gets raised if you try to call `_action?` if the actual action hasn't been implemented. For example `missing_implementation_action?` raises an error as long as `#missing_implementation` hasn't been implemented as action.
|
136
|
-
|
137
|
-
The are some more helpers that check for more than one RESTful action:
|
221
|
+
Access control on class level will ensure that every action performs it.
|
138
222
|
|
139
|
-
|
140
|
-
* `write_action?` - If the called action writes something. Actions: `new`, `create`, `edit`, `update`, `destroy`
|
141
|
-
* `change_action?` - If something will be updated or destroyed. Actions: `edit`, `update`, `destroy`
|
142
|
-
* `create_action?` - If something will be created. Actions: `new`, `create`
|
143
|
-
* `update_action?` - If something will be updated. Actions: `edit`, `update`
|
144
|
-
* `destroy_action?` - If something will be destroyed. Action: `destroy`
|
145
|
-
* `delete_action?` - Alias for `destroy_action?`. Action: `destroy`
|
146
|
-
* `collection_action?` - If the called action is a collection action. Actions: `index`, `new`, `create`
|
147
|
-
* `member_action?` - Everything that is not a collection action. Including non-RESTful actions.
|
223
|
+
**Note:** Don't use the class methods if the controller is inherited in other controllers. Best, don't use them at all and use the methods in the actions conciously.
|
148
224
|
|
149
|
-
|
225
|
+
## Variables
|
226
|
+
You can pass variables to the decision maker.
|
150
227
|
|
151
228
|
```ruby
|
152
|
-
class
|
153
|
-
# ...
|
154
|
-
|
229
|
+
class UsersController < ApplicationController
|
155
230
|
def show
|
231
|
+
@user = User.find params[:id]
|
232
|
+
pass! user: @user
|
156
233
|
end
|
234
|
+
end
|
235
|
+
```
|
157
236
|
|
158
|
-
|
159
|
-
end
|
160
|
-
|
161
|
-
private
|
162
|
-
|
163
|
-
def authorized?
|
164
|
-
return true if read_action? # Everybody is authorized to call read actions
|
237
|
+
You can now access the user object as instance variable in your decision maker.
|
165
238
|
|
166
|
-
|
167
|
-
|
239
|
+
```ruby
|
240
|
+
module Users
|
241
|
+
class Authentication < ApplicationPolicy::Authentication
|
242
|
+
def show?
|
243
|
+
@user # == <User:Instance>
|
168
244
|
end
|
245
|
+
end
|
169
246
|
|
170
|
-
|
171
|
-
|
247
|
+
class Authorization < ApplicationPolicy::Authorization
|
248
|
+
def show?
|
249
|
+
@user # == <User:Instance>
|
172
250
|
end
|
173
251
|
end
|
174
252
|
end
|
175
253
|
```
|
176
254
|
|
177
|
-
|
178
|
-
|
179
|
-
## Pass a custom error hash
|
180
|
-
You can pass an error hash to the exception and use this in your rescue method:
|
255
|
+
## Custom error data
|
256
|
+
If you write something into `@error` in our decision maker, you can access it in your rescue methods in the controller:
|
181
257
|
|
182
258
|
```ruby
|
259
|
+
module UsersPolicy
|
260
|
+
class Authentication < ApplicationPolicy::Authentication
|
261
|
+
def show?
|
262
|
+
@error = { code: 100 }
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
class Authorization < ApplicationPolicy::Authorization
|
267
|
+
def show?
|
268
|
+
@error = { code: 100 }
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
183
273
|
class ApplicationController < ActionController::Base
|
184
|
-
before_action :authenticate!, :authorize!
|
185
|
-
|
186
274
|
# ...
|
187
275
|
|
188
276
|
rescue_from ActiveEntry::NotAuthenticatedError, with: :not_authenticated
|
@@ -190,88 +278,134 @@ class ApplicationController < ActionController::Base
|
|
190
278
|
|
191
279
|
private
|
192
280
|
|
193
|
-
def not_authenticated
|
281
|
+
def not_authenticated exception
|
194
282
|
flash[:danger] = "You are not authenticated! Code: #{exception.error[:code]}"
|
195
283
|
redirect_to root_path
|
196
284
|
end
|
197
285
|
|
198
|
-
def not_authorized
|
286
|
+
def not_authorized exception
|
199
287
|
flash[:danger] = "You are not authorized to call this action! Code: #{exception.error[:code]}"
|
200
288
|
redirect_to root_path
|
201
289
|
end
|
290
|
+
end
|
291
|
+
```
|
202
292
|
|
203
|
-
|
204
|
-
error[:code] = "ERROR"
|
205
|
-
|
206
|
-
return true if user_signed_in?
|
207
|
-
end
|
208
|
-
|
209
|
-
def authorized?(error)
|
210
|
-
error[:code] = "ERROR"
|
293
|
+
But you can pass in whatever you want into your error hash.
|
211
294
|
|
212
|
-
|
295
|
+
## Testing
|
296
|
+
You can easily test your policies in RSpec. Let's start with the generator:
|
213
297
|
|
214
|
-
|
215
|
-
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
298
|
+
```shell
|
299
|
+
$ rails g rspec:policy Users
|
219
300
|
```
|
220
|
-
|
221
|
-
|
301
|
+
|
302
|
+
This will generate a spec for the `UsersPolicy` located in `spec/policies/users_policy_spec.rb`
|
222
303
|
|
223
304
|
```ruby
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
# ...
|
305
|
+
require "rails_helper"
|
306
|
+
|
307
|
+
RSpec.describe UsersPolicy, type: :policy do
|
308
|
+
pending "add some examples to (or delete) #{__FILE__}"
|
229
309
|
end
|
230
310
|
```
|
231
311
|
|
232
|
-
Now you can
|
312
|
+
Now you can easily test every decision maker with the `be_authenticated_for` and `be_authorized_for` matchers.
|
233
313
|
|
234
314
|
```ruby
|
235
315
|
require "rails_helper"
|
236
316
|
|
237
|
-
RSpec.describe
|
238
|
-
describe
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
317
|
+
RSpec.describe UsersPolicy, type: :policy do
|
318
|
+
describe UsersPolicy::Authentication do
|
319
|
+
subject { UsersPolicy::Authentication }
|
320
|
+
|
321
|
+
context "anonymous" do
|
322
|
+
it { is_expected.to_not be_authenticated_for :index }
|
323
|
+
it { is_expected.to be_authenticated_for :new }
|
324
|
+
it { is_expected.to be_authenticated_for :create }
|
325
|
+
it { is_expected.to_not be_authenticated_for :edit }
|
326
|
+
it { is_expected.to_not be_authenticated_for :update }
|
327
|
+
it { is_expected.to_not be_authenticated_for :destroy }
|
328
|
+
it { is_expected.to_not be_authenticated_for :restore }
|
329
|
+
end
|
330
|
+
|
331
|
+
context "signed in" do
|
332
|
+
before { Current.user = build :user }
|
333
|
+
|
334
|
+
it { is_expected.to be_authenticated_for :index }
|
335
|
+
it { is_expected.to be_authenticated_for :new }
|
336
|
+
it { is_expected.to be_authenticated_for :create }
|
337
|
+
it { is_expected.to be_authenticated_for :edit }
|
338
|
+
it { is_expected.to be_authenticated_for :update }
|
339
|
+
it { is_expected.to be_authenticated_for :destroy }
|
340
|
+
it { is_expected.to be_authenticated_for :restore }
|
252
341
|
end
|
253
342
|
end
|
254
343
|
|
255
|
-
describe
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
344
|
+
describe UsersPolicy::Authorization do
|
345
|
+
subject { UsersPolicy::Authorization }
|
346
|
+
|
347
|
+
let(:user) { build :user }
|
348
|
+
|
349
|
+
context "anonymous" do
|
350
|
+
it { is_expected.to be_authorized_for :index }
|
351
|
+
it { is_expected.to be_authorized_for :new }
|
352
|
+
it { is_expected.to be_authorized_for :create }
|
353
|
+
it { is_expected.to be_authorized_for :show, user: user }
|
354
|
+
it { is_expected.to_not be_authorized_for :edit, user: user }
|
355
|
+
it { is_expected.to_not be_authorized_for :update, user: user }
|
356
|
+
it { is_expected.to_not be_authorized_for :destroy, user: user }
|
357
|
+
it { is_expected.to_not be_authorized_for :restore, user: user }
|
358
|
+
end
|
359
|
+
|
360
|
+
context "if @user is Current.user" do
|
361
|
+
before { Current.user = user }
|
362
|
+
|
363
|
+
it { is_expected.to be_authorized_for :show, user: user }
|
364
|
+
it { is_expected.to be_authorized_for :edit, user: user }
|
365
|
+
it { is_expected.to be_authorized_for :update, user: user }
|
366
|
+
it { is_expected.to be_authorized_for :destroy, user: user }
|
367
|
+
it { is_expected.to be_authorized_for :restore, user: user }
|
368
|
+
end
|
369
|
+
|
370
|
+
context "if @user is not Current.user" do
|
371
|
+
before { Current.user = build :user }
|
372
|
+
|
373
|
+
it { is_expected.to be_authorized_for :show, user: user }
|
374
|
+
it { is_expected.to_not be_authorized_for :edit, user: user }
|
375
|
+
it { is_expected.to_not be_authorized_for :update, user: user }
|
376
|
+
it { is_expected.to_not be_authorized_for :destroy, user: user }
|
377
|
+
it { is_expected.to_not be_authorized_for :restore, user: user }
|
270
378
|
end
|
271
379
|
end
|
272
380
|
end
|
273
381
|
```
|
274
382
|
|
383
|
+
## Differences to Action Policy
|
384
|
+
[Action Policy](https://github.com/palkan/action_policy) is an awesome gem which works pretty similar to Active Entry. But there are some differences:
|
385
|
+
|
386
|
+
### Action Policy expects a performing subject and a target object
|
387
|
+
```ruby
|
388
|
+
class PostPolicy < ApplicationPolicy
|
389
|
+
def update?
|
390
|
+
# `user` is a performing subject,
|
391
|
+
# `record` is a target object (post we want to update)
|
392
|
+
user.admin? || (user.id == record.user_id)
|
393
|
+
end
|
394
|
+
end
|
395
|
+
```
|
396
|
+
|
397
|
+
In Active Entry you can pass in anything you want into the decision maker, which is accessible as instance variables. See Variables.
|
398
|
+
|
399
|
+
One strategy is not better than the other. It's just our preference.
|
400
|
+
|
401
|
+
### Policies in Action Policy are for Resources/Models
|
402
|
+
If you have a `Post` model, you have a `PostPolicy` in Action Policy. In Active Entry you create policies for controllers. So if you have a `PostsController`, you have a `PostsPolicy`.
|
403
|
+
We like to build access control logic around controller endpoints.
|
404
|
+
|
405
|
+
### Action Policy performs only authorization
|
406
|
+
Active Entry does technically also not provide authentication mechanisms. It's just that you place your authentication logic in an authentication decision maker.
|
407
|
+
We like both authentication and authorization logic in the same place but seperated hence `UsersPolicy::Authentication` and `UsersPolicy::Authorization`.
|
408
|
+
|
275
409
|
## Contributing
|
276
410
|
Create pull requests on Github and help us to improve this Gem. There are some guidelines to follow:
|
277
411
|
|