action_policy 0.0.1 → 0.1.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 +5 -5
- data/.rubocop.yml +85 -0
- data/.travis.yml +25 -2
- data/CHANGELOG.md +7 -0
- data/Gemfile +12 -3
- data/README.md +71 -12
- data/Rakefile +9 -1
- data/action_policy.gemspec +11 -5
- data/docs/.nojekyll +0 -0
- data/docs/CNAME +1 -0
- data/docs/README.md +46 -0
- data/docs/_sidebar.md +19 -0
- data/docs/aliases.md +54 -0
- data/docs/assets/docsify.min.js +1 -0
- data/docs/assets/fonts/FiraCode-Medium.woff +0 -0
- data/docs/assets/fonts/FiraCode-Regular.woff +0 -0
- data/docs/assets/images/cache.png +0 -0
- data/docs/assets/images/cache.svg +70 -0
- data/docs/assets/images/layer.png +0 -0
- data/docs/assets/images/layer.svg +92 -0
- data/docs/assets/prism-ruby.min.js +1 -0
- data/docs/assets/styles.css +317 -0
- data/docs/assets/vue.min.css +1 -0
- data/docs/authorization_context.md +33 -0
- data/docs/caching.md +262 -0
- data/docs/custom_lookup_chain.md +48 -0
- data/docs/custom_policy.md +51 -0
- data/docs/favicon.ico +0 -0
- data/docs/i18n.md +3 -0
- data/docs/index.html +25 -0
- data/docs/instrumentation.md +3 -0
- data/docs/lookup_chain.md +16 -0
- data/docs/namespaces.md +69 -0
- data/docs/non_rails.md +29 -0
- data/docs/pre_checks.md +57 -0
- data/docs/quick_start.md +102 -0
- data/docs/rails.md +110 -0
- data/docs/reasons.md +67 -0
- data/docs/testing.md +116 -0
- data/docs/writing_policies.md +55 -0
- data/gemfiles/jruby.gemfile +5 -0
- data/gemfiles/rails42.gemfile +5 -0
- data/gemfiles/railsmaster.gemfile +6 -0
- data/lib/action_policy.rb +34 -2
- data/lib/action_policy/authorizer.rb +28 -0
- data/lib/action_policy/base.rb +24 -0
- data/lib/action_policy/behaviour.rb +94 -0
- data/lib/action_policy/behaviours/memoized.rb +56 -0
- data/lib/action_policy/behaviours/namespaced.rb +80 -0
- data/lib/action_policy/behaviours/policy_for.rb +23 -0
- data/lib/action_policy/behaviours/thread_memoized.rb +54 -0
- data/lib/action_policy/ext/module_namespace.rb +21 -0
- data/lib/action_policy/ext/policy_cache_key.rb +67 -0
- data/lib/action_policy/ext/string_constantize.rb +23 -0
- data/lib/action_policy/lookup_chain.rb +84 -0
- data/lib/action_policy/policy/aliases.rb +69 -0
- data/lib/action_policy/policy/authorization.rb +91 -0
- data/lib/action_policy/policy/cache.rb +74 -0
- data/lib/action_policy/policy/cached_apply.rb +28 -0
- data/lib/action_policy/policy/core.rb +64 -0
- data/lib/action_policy/policy/defaults.rb +37 -0
- data/lib/action_policy/policy/pre_check.rb +210 -0
- data/lib/action_policy/policy/reasons.rb +109 -0
- data/lib/action_policy/rails/channel.rb +15 -0
- data/lib/action_policy/rails/controller.rb +90 -0
- data/lib/action_policy/railtie.rb +74 -0
- data/lib/action_policy/rspec.rb +3 -0
- data/lib/action_policy/rspec/be_authorized_to.rb +93 -0
- data/lib/action_policy/rspec/pundit_syntax.rb +48 -0
- data/lib/action_policy/test_helper.rb +46 -0
- data/lib/action_policy/testing.rb +64 -0
- data/lib/action_policy/version.rb +3 -1
- metadata +115 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a039b5a6e9cdfa9821dfc8ac42d0e78f52239379d532e75e64e9a136123971f1
|
4
|
+
data.tar.gz: b756862f053a8ab07cc957813231988a8447dce8d2655a8d1f0171dda47ab957
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6855bd1057d2153300d0cc2d92fc7091bab8a49c6ac4d67fd805372e0fdb0caabb6dd38fc30f28f4bcc74d83b8e37d3dfc96e0410e7616f8e7ada2949c69d6e
|
7
|
+
data.tar.gz: b5ee9d56785412b634f405954b7bd456536d1564d31d8c0927926d045068ef67125e42b0674cdda574f6fefc366f30c94fb798e4f641235e95a31aa2c4f9a65c
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require:
|
2
|
+
- rubocop-md
|
3
|
+
|
4
|
+
AllCops:
|
5
|
+
Include:
|
6
|
+
- 'lib/**/*.rb'
|
7
|
+
- 'lib/**/*.rake'
|
8
|
+
- 'test/**/*.rb'
|
9
|
+
Exclude:
|
10
|
+
- 'bin/**/*'
|
11
|
+
- 'gemfiles/**/*'
|
12
|
+
- 'test/dummy/**/*'
|
13
|
+
- 'vendor/**/*'
|
14
|
+
- 'tmp/**/*'
|
15
|
+
DisplayCopNames: true
|
16
|
+
StyleGuideCopsOnly: false
|
17
|
+
TargetRubyVersion: 2.3
|
18
|
+
|
19
|
+
Rails:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Bundler/OrderedGems:
|
23
|
+
Enabled: false
|
24
|
+
|
25
|
+
Lint/Void:
|
26
|
+
Exclude:
|
27
|
+
- '**/*.md'
|
28
|
+
|
29
|
+
Lint/DuplicateMethods:
|
30
|
+
Exclude:
|
31
|
+
- '**/*.md'
|
32
|
+
|
33
|
+
Naming/FileName:
|
34
|
+
Exclude:
|
35
|
+
- 'Rakefile'
|
36
|
+
- 'Gemfile'
|
37
|
+
- '**/*.md'
|
38
|
+
|
39
|
+
Naming/UncommunicativeMethodParamName:
|
40
|
+
Enabled: false
|
41
|
+
|
42
|
+
Naming/VariableNumber:
|
43
|
+
Exclude:
|
44
|
+
- 'test/**/*.rb'
|
45
|
+
|
46
|
+
Style/SymbolArray:
|
47
|
+
Enabled: false
|
48
|
+
|
49
|
+
Style/Documentation:
|
50
|
+
Exclude:
|
51
|
+
- 'test/**/*.rb'
|
52
|
+
- '**/*.md'
|
53
|
+
|
54
|
+
Style/StringLiterals:
|
55
|
+
EnforcedStyle: double_quotes
|
56
|
+
|
57
|
+
Style/RegexpLiteral:
|
58
|
+
Enabled: false
|
59
|
+
|
60
|
+
Style/NumericPredicate:
|
61
|
+
Enabled: false
|
62
|
+
|
63
|
+
Style/Lambda:
|
64
|
+
Enabled: false
|
65
|
+
|
66
|
+
Layout/SpaceInsideStringInterpolation:
|
67
|
+
EnforcedStyle: no_space
|
68
|
+
|
69
|
+
Lint/AmbiguousRegexpLiteral:
|
70
|
+
Enabled: false
|
71
|
+
|
72
|
+
Metrics/LineLength:
|
73
|
+
Max: 100
|
74
|
+
|
75
|
+
Metrics/AbcSize:
|
76
|
+
Exclude:
|
77
|
+
- 'test/**/*.rb'
|
78
|
+
|
79
|
+
Metrics/BlockLength:
|
80
|
+
Exclude:
|
81
|
+
- 'spec/**/*.rb'
|
82
|
+
|
83
|
+
Metrics/MethodLength:
|
84
|
+
Exclude:
|
85
|
+
- 'test/**/*.rb'
|
data/.travis.yml
CHANGED
@@ -1,5 +1,28 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
3
|
rvm:
|
4
|
-
- 2.
|
5
|
-
|
4
|
+
- 2.5.0
|
5
|
+
|
6
|
+
notifications:
|
7
|
+
email: false
|
8
|
+
|
9
|
+
matrix:
|
10
|
+
fast_finish: true
|
11
|
+
include:
|
12
|
+
- rvm: ruby-head
|
13
|
+
gemfile: gemfiles/railsmaster.gemfile
|
14
|
+
- rvm: jruby-9.1.0.0
|
15
|
+
gemfile: gemfiles/jruby.gemfile
|
16
|
+
- rvm: 2.5.0
|
17
|
+
gemfile: Gemfile
|
18
|
+
- rvm: 2.4.3
|
19
|
+
gemfile: Gemfile
|
20
|
+
- rvm: 2.3.1
|
21
|
+
gemfile: gemfiles/rails42.gemfile
|
22
|
+
allow_failures:
|
23
|
+
- rvm: 2.3.1
|
24
|
+
gemfile: gemfiles/rails42.gemfile
|
25
|
+
- rvm: ruby-head
|
26
|
+
gemfile: gemfiles/railsmaster.gemfile
|
27
|
+
- rvm: jruby-9.1.0.0
|
28
|
+
gemfile: gemfiles/jruby.gemfile
|
data/CHANGELOG.md
ADDED
data/Gemfile
CHANGED
@@ -1,6 +1,15 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
source "https://rubygems.org"
|
4
4
|
|
5
|
-
# Specify your gem's dependencies in action_policy.gemspec
|
6
5
|
gemspec
|
6
|
+
|
7
|
+
gem "pry-byebug", platform: :mri
|
8
|
+
|
9
|
+
local_gemfile = File.join(__dir__, "Gemfile.local")
|
10
|
+
|
11
|
+
if File.exist?(local_gemfile)
|
12
|
+
eval(File.read(local_gemfile)) # rubocop:disable Security/Eval
|
13
|
+
else
|
14
|
+
gem "rails", "~> 5.0"
|
15
|
+
end
|
data/README.md
CHANGED
@@ -1,39 +1,98 @@
|
|
1
|
+
[](https://badge.fury.io/rb/action_policy)
|
2
|
+
[](https://travis-ci.org/palkan/action_policy)
|
3
|
+
[](http://actionpolicy.evilmartians.io)
|
4
|
+
|
1
5
|
# ActionPolicy
|
2
6
|
|
3
|
-
|
7
|
+
Action Policy is an authorization framework for Ruby and Rails applications.
|
8
|
+
|
9
|
+
📑 [Documentation][]
|
4
10
|
|
5
|
-
|
11
|
+
<a href="https://evilmartians.com/?utm_source=action_policy">
|
12
|
+
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
|
6
13
|
|
7
14
|
## Installation
|
8
15
|
|
9
|
-
Add this line to your application's Gemfile
|
16
|
+
Add this line to your application's `Gemfile`:
|
10
17
|
|
11
18
|
```ruby
|
12
|
-
gem
|
19
|
+
gem "action_policy"
|
13
20
|
```
|
14
21
|
|
15
22
|
And then execute:
|
16
23
|
|
17
24
|
$ bundle
|
18
25
|
|
19
|
-
|
26
|
+
## Usage
|
20
27
|
|
21
|
-
|
28
|
+
Action Policy relies on resource-specific policy classes (just like [Pundit](https://github.com/varvet/pundit)).
|
22
29
|
|
23
|
-
|
30
|
+
First, add an application-specific `ApplicationPolicy` with some global configuration to inherit from:
|
24
31
|
|
25
|
-
|
32
|
+
```ruby
|
33
|
+
class ApplicationPolicy < ActionPolicy::Base
|
34
|
+
end
|
35
|
+
```
|
26
36
|
|
27
|
-
|
37
|
+
Then write a policy for a resource. For example:
|
28
38
|
|
29
|
-
|
39
|
+
```ruby
|
40
|
+
class PostPolicy < ApplicationPolicy
|
41
|
+
# everyone can see any post
|
42
|
+
def show?
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def update?
|
47
|
+
# `user` is a performing subject,
|
48
|
+
# `record` is a target object (post we want to update)
|
49
|
+
user.admin? || (user.id == record.user_id)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
```
|
30
53
|
|
31
|
-
|
54
|
+
Now you can easily add authorization to your Rails\* controller:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
class PostsController < ApplicationController
|
58
|
+
def update
|
59
|
+
@post = Post.find(params[:id])
|
60
|
+
authorize! @post
|
61
|
+
|
62
|
+
if @post.update(post_params)
|
63
|
+
redirect_to @post
|
64
|
+
else
|
65
|
+
render :edit
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
\* See [Non-Rails Usage](docs/non_rails.md) on how to add `authorize!` to any Ruby project.
|
72
|
+
|
73
|
+
|
74
|
+
When authorization is successful (i.e., the corresponding rule returns `true`), nothing happens, but in case of authorization failure `ActionPolicy::Unauthorized` error is raised.
|
75
|
+
|
76
|
+
There is also an `allowed_to?` method which returns `true` or `false`, and could be used, in views, for example:
|
77
|
+
|
78
|
+
```erb
|
79
|
+
<% @posts.each do |post| %>
|
80
|
+
<li><%= post.title %>
|
81
|
+
<% if allowed_to?(:edit?, post) %>
|
82
|
+
= link_to post, "Edit"
|
83
|
+
<% end %>
|
84
|
+
</li>
|
85
|
+
<% end %>
|
86
|
+
```
|
87
|
+
|
88
|
+
Read more in our [Documentation][].
|
32
89
|
|
33
90
|
## Contributing
|
34
91
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
92
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/palkan/action_policy.
|
36
93
|
|
37
94
|
## License
|
38
95
|
|
39
96
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
97
|
+
|
98
|
+
[Documentation]: http://actionpolicy.evilmartians.io
|
data/Rakefile
CHANGED
@@ -1,5 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "bundler/gem_tasks"
|
2
4
|
require "rake/testtask"
|
5
|
+
require "rubocop/rake_task"
|
6
|
+
require "rspec/core/rake_task"
|
7
|
+
|
8
|
+
RuboCop::RakeTask.new
|
9
|
+
|
10
|
+
RSpec::Core::RakeTask.new(:spec)
|
3
11
|
|
4
12
|
Rake::TestTask.new(:test) do |t|
|
5
13
|
t.libs << "test"
|
@@ -7,4 +15,4 @@ Rake::TestTask.new(:test) do |t|
|
|
7
15
|
t.test_files = FileList["test/**/*_test.rb"]
|
8
16
|
end
|
9
17
|
|
10
|
-
task :
|
18
|
+
task default: [:rubocop, :test, :spec]
|
data/action_policy.gemspec
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require "action_policy/version"
|
5
6
|
|
@@ -9,8 +10,8 @@ Gem::Specification.new do |spec|
|
|
9
10
|
spec.authors = ["Vladimir Dementyev"]
|
10
11
|
spec.email = ["dementiev.vm@gmail.com"]
|
11
12
|
|
12
|
-
spec.summary = "
|
13
|
-
spec.description = "
|
13
|
+
spec.summary = "Authorization framework for Ruby/Rails application"
|
14
|
+
spec.description = "Authorization framework for Ruby/Rails application"
|
14
15
|
spec.homepage = "https://github.com/palkan/action-policy"
|
15
16
|
spec.license = "MIT"
|
16
17
|
|
@@ -20,7 +21,12 @@ Gem::Specification.new do |spec|
|
|
20
21
|
|
21
22
|
spec.require_paths = ["lib"]
|
22
23
|
|
24
|
+
spec.required_ruby_version = ">= 2.3.0"
|
25
|
+
|
23
26
|
spec.add_development_dependency "bundler", "~> 1.15"
|
24
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
25
27
|
spec.add_development_dependency "minitest", "~> 5.0"
|
28
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
29
|
+
spec.add_development_dependency "rspec", "~> 3.3"
|
30
|
+
spec.add_development_dependency "rubocop", "~> 0.51"
|
31
|
+
spec.add_development_dependency "rubocop-md", "~> 0.2"
|
26
32
|
end
|
data/docs/.nojekyll
ADDED
File without changes
|
data/docs/CNAME
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
actionpolicy.evilmartians.io
|
data/docs/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
[](https://badge.fury.io/rb/action_policy)
|
2
|
+
[](https://travis-ci.org/palkan/action_policy)
|
3
|
+
|
4
|
+
## Action Policy
|
5
|
+
|
6
|
+
> Action Policy is an authorization framework for Ruby and Rails applications.
|
7
|
+
|
8
|
+
## What is it?
|
9
|
+
|
10
|
+
_Authorization_ is an act of giving **someone** official
|
11
|
+
permission to **do something** (to not be confused with [_authentication_](https://en.wikipedia.org/wiki/Authentication)).
|
12
|
+
|
13
|
+
Action Policy provides flexible tools to build an _authorization layer_ for your application.
|
14
|
+
|
15
|
+
<div class="chart-container">
|
16
|
+
<img src="assets/images/layer.svg" alt="Authorization layer" width="80%">
|
17
|
+
</div>
|
18
|
+
|
19
|
+
**NOTE:** Action Policy does not force you to use a specific authorization model (i.e., roles, permissions, etc.) and does not provide one. It only answers a single question: **How to verify access?**
|
20
|
+
|
21
|
+
## History
|
22
|
+
|
23
|
+
Action Policy gem is an _extraction_-kind of a library. Most of the code has been used in production for several years in different [Evil Martians][] projects.
|
24
|
+
|
25
|
+
We have decided to collect all our authorization techniques and pack them into a standalone gem–and that is how Action Policy was born!
|
26
|
+
|
27
|
+
## What about the existing solutions?
|
28
|
+
|
29
|
+
Why did we decide to build our own authorization gem instead of using the existing solutions, such as [Pundit][] and [CanCanCan][]?
|
30
|
+
|
31
|
+
**TL;DR they didn't solve all of our problems.**
|
32
|
+
|
33
|
+
[Pundit][] has been our framework of choice for a long time. Being too _dead-simple_, it required a lot of hacking to fulfill business logic requirements.
|
34
|
+
|
35
|
+
These _hacks_ later become into Action Policy (initially, we even called it "Pundit, re-visited").
|
36
|
+
|
37
|
+
We also took a few ideas from [CanCanCan][]—such as default rules and rule aliases.
|
38
|
+
|
39
|
+
It is also worth noting that Action Policy (despite from a _Railsy_ name) is designed to be **Rails-free**. On the other hand, it contains some Rails-specific extensions and seamlessly integrates into the framework.
|
40
|
+
|
41
|
+
<a href="https://evilmartians.com/?utm_source=action_policy">
|
42
|
+
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
|
43
|
+
|
44
|
+
[CanCanCan]: https://github.com/CanCanCommunity/cancancan
|
45
|
+
[Pundit]: https://github.com/varvet/pundit
|
46
|
+
[Evil Martians]: https://evilmartians.com
|
data/docs/_sidebar.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
* Getting Started
|
2
|
+
* [Quick Start](quick_start.md)
|
3
|
+
* [Writing Policies](writing_policies.md)
|
4
|
+
* [Rails Integration](rails.md)
|
5
|
+
* [Non-Rails Usage](non_rails.md)
|
6
|
+
* [Testing](testing.md)
|
7
|
+
* Features
|
8
|
+
* [Policy Lookup](lookup_chain.md)
|
9
|
+
* [Authorization Context](authorization_context.md)
|
10
|
+
* [Aliases](aliases.md)
|
11
|
+
* [Pre-Checks](pre_checks.md)
|
12
|
+
* [Caching](caching.md)
|
13
|
+
* [Namespaces](namespaces.md)
|
14
|
+
* [Failure Reasons](reasons.md)
|
15
|
+
* [Instrumentation](instrumentation.md)
|
16
|
+
* [I18n Support](i18n.md)
|
17
|
+
* Customize
|
18
|
+
* [Base Policy](custom_policy.md)
|
19
|
+
* [Lookup Chain](custom_lookup_chain.md)
|
data/docs/aliases.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Rule Aliases
|
2
|
+
|
3
|
+
Action Policy allows you to add rule aliases. It is useful when you rely on _implicit_ rules in controllers. For example:
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
class PostsController < ApplicationController
|
7
|
+
before_action :load_post, only: [:edit, :update, :destroy]
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def load_post
|
12
|
+
@post = Post.find(params[:id])
|
13
|
+
# depending on action, an `edit?`, `update?` or `destroy?`
|
14
|
+
# rule would be applied
|
15
|
+
authorize! @post
|
16
|
+
end
|
17
|
+
end
|
18
|
+
```
|
19
|
+
|
20
|
+
In your policy, you can create aliases to avoid duplication:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
class PostPolicy < ApplicationPolicy
|
24
|
+
alias_rule :edit?, :destroy?, to: :update?
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
**NOTE**: `alias_rule` is available only if you inherit from `ActionPolicy::Base` or include `ActionPolicy::Policy::Aliases` into your `ApplicationPolicy`.
|
29
|
+
|
30
|
+
**Why not just use Ruby's `alias`?**
|
31
|
+
|
32
|
+
An alias created with `alias_rule` is resolved at _authorization time_ (during an `authorize!` or `allowed_to?` call), and it does not add an alias method to the class.
|
33
|
+
|
34
|
+
That allows us to write tests easier, as we should only test the rule, not the alias–and to leverage [caching](caching.md) better.
|
35
|
+
|
36
|
+
By default, `ActionPolicy::Base` adds one alias: `alias_rule :new?, to: :create?`.
|
37
|
+
|
38
|
+
## Default rule
|
39
|
+
|
40
|
+
You can add a _default_ rule–the rule that would be applied if the rule specified during authorization is missing (like a "wildcard" alias):
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
class PostPolicy < ApplicationPolicy
|
44
|
+
default_rule :manage?
|
45
|
+
|
46
|
+
def manage?
|
47
|
+
# ...
|
48
|
+
end
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
Now when you call `authorize! post` with any rule not explicitly defined in policy class, the `manage?` rule is applied.
|
53
|
+
|
54
|
+
By default, `ActionPolicy::Base` sets `manage?` as a default rule.
|