active_entry 1.2.4 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Maintainability](https://api.codeclimate.com/v1/badges/3db0f653be6bdfe0fdac/maintainability)](https://codeclimate.com/github/TFM-Agency/active_entry/maintainability)
|
12
12
|
[![Documentation](https://img.shields.io/badge/docs-rdoc.info-blue.svg)](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
|
|