action_policy 0.4.0 → 0.5.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/CHANGELOG.md +233 -171
- data/LICENSE.txt +1 -1
- data/README.md +7 -11
- data/lib/action_policy.rb +7 -1
- data/lib/action_policy/behaviour.rb +22 -16
- data/lib/action_policy/behaviours/policy_for.rb +10 -3
- data/lib/action_policy/behaviours/scoping.rb +2 -1
- data/lib/action_policy/behaviours/thread_memoized.rb +1 -3
- data/lib/action_policy/ext/module_namespace.rb +1 -6
- data/lib/action_policy/ext/policy_cache_key.rb +15 -33
- data/lib/action_policy/ext/{symbol_classify.rb → symbol_camelize.rb} +6 -6
- data/lib/action_policy/i18n.rb +1 -1
- data/lib/action_policy/lookup_chain.rb +41 -21
- data/lib/action_policy/policy/aliases.rb +7 -12
- data/lib/action_policy/policy/authorization.rb +14 -17
- data/lib/action_policy/policy/cache.rb +34 -18
- data/lib/action_policy/policy/core.rb +25 -12
- data/lib/action_policy/policy/defaults.rb +3 -9
- data/lib/action_policy/policy/execution_result.rb +3 -9
- data/lib/action_policy/policy/pre_check.rb +19 -58
- data/lib/action_policy/policy/reasons.rb +30 -20
- data/lib/action_policy/policy/scoping.rb +5 -6
- data/lib/action_policy/rails/controller.rb +6 -1
- data/lib/action_policy/rails/ext/active_record.rb +7 -0
- data/lib/action_policy/rails/policy/instrumentation.rb +1 -1
- data/lib/action_policy/rspec/be_authorized_to.rb +5 -9
- data/lib/action_policy/rspec/dsl.rb +3 -3
- data/lib/action_policy/rspec/have_authorized_scope.rb +5 -7
- data/lib/action_policy/testing.rb +1 -1
- data/lib/action_policy/utils/pretty_print.rb +21 -24
- data/lib/action_policy/utils/suggest_message.rb +1 -3
- data/lib/action_policy/version.rb +1 -1
- data/lib/generators/action_policy/install/templates/{application_policy.rb → application_policy.rb.tt} +1 -1
- data/lib/generators/action_policy/policy/policy_generator.rb +4 -1
- data/lib/generators/action_policy/policy/templates/{policy.rb → policy.rb.tt} +0 -0
- data/lib/generators/rspec/templates/{policy_spec.rb → policy_spec.rb.tt} +0 -0
- data/lib/generators/test_unit/templates/{policy_test.rb → policy_test.rb.tt} +0 -0
- metadata +30 -119
- data/.gitattributes +0 -2
- data/.github/FUNDING.yml +0 -1
- data/.github/ISSUE_TEMPLATE.md +0 -18
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -29
- data/.gitignore +0 -15
- data/.rubocop.yml +0 -54
- data/.tidelift.yml +0 -6
- data/.travis.yml +0 -31
- data/Gemfile +0 -22
- data/Rakefile +0 -27
- data/action_policy.gemspec +0 -44
- data/benchmarks/namespaced_lookup_cache.rb +0 -71
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/docs/.nojekyll +0 -0
- data/docs/CNAME +0 -1
- data/docs/README.md +0 -77
- data/docs/_sidebar.md +0 -27
- data/docs/aliases.md +0 -122
- data/docs/assets/docsify-search.js +0 -364
- data/docs/assets/docsify.min.js +0 -3
- data/docs/assets/fonts/FiraCode-Medium.woff +0 -0
- data/docs/assets/fonts/FiraCode-Regular.woff +0 -0
- data/docs/assets/images/banner.png +0 -0
- data/docs/assets/images/cache.png +0 -0
- data/docs/assets/images/cache.svg +0 -70
- data/docs/assets/images/layer.png +0 -0
- data/docs/assets/images/layer.svg +0 -35
- data/docs/assets/prism-ruby.min.js +0 -1
- data/docs/assets/styles.css +0 -347
- data/docs/assets/vue.min.css +0 -1
- data/docs/authorization_context.md +0 -92
- data/docs/behaviour.md +0 -113
- data/docs/caching.md +0 -273
- data/docs/controller_action_aliases.md +0 -109
- data/docs/custom_lookup_chain.md +0 -48
- data/docs/custom_policy.md +0 -53
- data/docs/debugging.md +0 -55
- data/docs/decorators.md +0 -27
- data/docs/favicon.ico +0 -0
- data/docs/graphql.md +0 -302
- data/docs/i18n.md +0 -44
- data/docs/index.html +0 -43
- data/docs/instrumentation.md +0 -84
- data/docs/lookup_chain.md +0 -17
- data/docs/namespaces.md +0 -77
- data/docs/non_rails.md +0 -28
- data/docs/pre_checks.md +0 -57
- data/docs/pundit_migration.md +0 -80
- data/docs/quick_start.md +0 -118
- data/docs/rails.md +0 -120
- data/docs/reasons.md +0 -120
- data/docs/scoping.md +0 -255
- data/docs/testing.md +0 -333
- data/docs/writing_policies.md +0 -107
- data/gemfiles/jruby.gemfile +0 -8
- data/gemfiles/rails42.gemfile +0 -8
- data/gemfiles/rails6.gemfile +0 -8
- data/gemfiles/railsmaster.gemfile +0 -6
- data/lib/action_policy/ext/string_match.rb +0 -14
- data/lib/action_policy/ext/yield_self_then.rb +0 -25
data/.gitattributes
DELETED
data/.github/FUNDING.yml
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
tidelift: "rubygems/action_policy"
|
data/.github/ISSUE_TEMPLATE.md
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
<!--
|
2
|
-
This template is for bug reports. If you are reporting a bug, please continue on. If you are here for another reason,
|
3
|
-
feel free to skip the rest of this template.
|
4
|
-
-->
|
5
|
-
|
6
|
-
### Tell us about your environment
|
7
|
-
|
8
|
-
**Ruby Version:**
|
9
|
-
|
10
|
-
**Framework Version (Rails, whatever):**
|
11
|
-
|
12
|
-
**Action Policy Version:**
|
13
|
-
|
14
|
-
### What did you do?
|
15
|
-
|
16
|
-
### What did you expect to happen?
|
17
|
-
|
18
|
-
### What actually happened?
|
@@ -1,29 +0,0 @@
|
|
1
|
-
<!--
|
2
|
-
First of all, thanks for contributing!
|
3
|
-
|
4
|
-
If it's a typo fix or minor documentation update feel free to skip the rest of this template!
|
5
|
-
-->
|
6
|
-
|
7
|
-
<!--
|
8
|
-
If it's a bug fix, then link it to the issue, for example:
|
9
|
-
|
10
|
-
Fixes #xxx
|
11
|
-
-->
|
12
|
-
|
13
|
-
|
14
|
-
<!--
|
15
|
-
Otherwise, describe the changes:
|
16
|
-
|
17
|
-
### What is the purpose of this pull request?
|
18
|
-
|
19
|
-
### What changes did you make? (overview)
|
20
|
-
|
21
|
-
### Is there anything you'd like reviewers to focus on?
|
22
|
-
|
23
|
-
-->
|
24
|
-
|
25
|
-
PR checklist:
|
26
|
-
|
27
|
-
- [ ] Tests included
|
28
|
-
- [ ] Documentation updated
|
29
|
-
- [ ] Changelog entry added
|
data/.gitignore
DELETED
data/.rubocop.yml
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
require:
|
2
|
-
- standard/cop/semantic_blocks
|
3
|
-
- rubocop-md
|
4
|
-
|
5
|
-
inherit_gem:
|
6
|
-
standard: config/base.yml
|
7
|
-
|
8
|
-
AllCops:
|
9
|
-
Exclude:
|
10
|
-
- 'bin/*'
|
11
|
-
- 'tmp/**/*'
|
12
|
-
- 'Gemfile'
|
13
|
-
- 'vendor/**/*'
|
14
|
-
- 'gemfiles/**/*'
|
15
|
-
- 'lib/generators/**/templates/**/*'
|
16
|
-
DisplayCopNames: true
|
17
|
-
TargetRubyVersion: 2.4
|
18
|
-
|
19
|
-
Standard/SemanticBlocks:
|
20
|
-
Enabled: false
|
21
|
-
|
22
|
-
Style/FrozenStringLiteralComment:
|
23
|
-
Enabled: true
|
24
|
-
|
25
|
-
Style/TrailingCommaInArrayLiteral:
|
26
|
-
EnforcedStyleForMultiline: no_comma
|
27
|
-
|
28
|
-
Style/TrailingCommaInHashLiteral:
|
29
|
-
EnforcedStyleForMultiline: no_comma
|
30
|
-
|
31
|
-
Layout/AlignParameters:
|
32
|
-
EnforcedStyle: with_first_parameter
|
33
|
-
|
34
|
-
Lint/Void:
|
35
|
-
Exclude:
|
36
|
-
- '**/*.md'
|
37
|
-
|
38
|
-
# See https://github.com/rubocop-hq/rubocop/issues/4222
|
39
|
-
Lint/AmbiguousBlockAssociation:
|
40
|
-
Exclude:
|
41
|
-
- 'spec/**/*'
|
42
|
-
- '**/*.md'
|
43
|
-
|
44
|
-
Lint/DuplicateMethods:
|
45
|
-
Exclude:
|
46
|
-
- '**/*.md'
|
47
|
-
|
48
|
-
Naming/FileName:
|
49
|
-
Exclude:
|
50
|
-
- '**/*.md'
|
51
|
-
|
52
|
-
Layout/InitialIndentation:
|
53
|
-
Exclude:
|
54
|
-
- 'CHANGELOG.md'
|
data/.tidelift.yml
DELETED
data/.travis.yml
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
sudo: false
|
2
|
-
language: ruby
|
3
|
-
cache: bundler
|
4
|
-
notifications:
|
5
|
-
email: false
|
6
|
-
|
7
|
-
before_install:
|
8
|
-
- gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
|
9
|
-
- gem install bundler -v '< 2'
|
10
|
-
|
11
|
-
script:
|
12
|
-
- bundle exec rake test:ci
|
13
|
-
|
14
|
-
matrix:
|
15
|
-
fast_finish: true
|
16
|
-
include:
|
17
|
-
- rvm: ruby-head
|
18
|
-
gemfile: gemfiles/railsmaster.gemfile
|
19
|
-
- rvm: jruby-9.2.8.0
|
20
|
-
gemfile: gemfiles/jruby.gemfile
|
21
|
-
- rvm: 2.6.0
|
22
|
-
gemfile: gemfiles/rails6.gemfile
|
23
|
-
- rvm: 2.5.3
|
24
|
-
gemfile: Gemfile
|
25
|
-
- rvm: 2.4.3
|
26
|
-
gemfile: gemfiles/rails42.gemfile
|
27
|
-
allow_failures:
|
28
|
-
- rvm: ruby-head
|
29
|
-
gemfile: gemfiles/railsmaster.gemfile
|
30
|
-
- rvm: jruby-9.2.8.0
|
31
|
-
gemfile: gemfiles/jruby.gemfile
|
data/Gemfile
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
source "https://rubygems.org"
|
4
|
-
|
5
|
-
gemspec
|
6
|
-
|
7
|
-
gem "pry-byebug", platform: :mri
|
8
|
-
|
9
|
-
gem "method_source"
|
10
|
-
gem "unparser"
|
11
|
-
|
12
|
-
gem 'sqlite3', "~> 1.3.0", platform: :mri
|
13
|
-
gem 'activerecord-jdbcsqlite3-adapter', '~> 50.0', platform: :jruby
|
14
|
-
gem 'jdbc-sqlite3', platform: :jruby
|
15
|
-
|
16
|
-
local_gemfile = File.join(__dir__, "Gemfile.local")
|
17
|
-
|
18
|
-
if File.exist?(local_gemfile)
|
19
|
-
eval(File.read(local_gemfile)) # rubocop:disable Security/Eval
|
20
|
-
else
|
21
|
-
gem "rails", "~> 5.0"
|
22
|
-
end
|
data/Rakefile
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "rake/testtask"
|
4
|
-
require "rubocop/rake_task"
|
5
|
-
require "rspec/core/rake_task"
|
6
|
-
|
7
|
-
RuboCop::RakeTask.new
|
8
|
-
|
9
|
-
RSpec::Core::RakeTask.new(:spec)
|
10
|
-
|
11
|
-
Rake::TestTask.new(:test) do |t|
|
12
|
-
t.libs << "test"
|
13
|
-
t.libs << "lib"
|
14
|
-
t.test_files = FileList["test/**/*_test.rb"]
|
15
|
-
end
|
16
|
-
|
17
|
-
namespace :test do
|
18
|
-
task :isolated do
|
19
|
-
Dir.glob("test/**/*_test.rb").all? do |file|
|
20
|
-
sh(Gem.ruby, "-w", "-Ilib:test", file)
|
21
|
-
end || raise("Failures")
|
22
|
-
end
|
23
|
-
|
24
|
-
task ci: %w[rubocop test:isolated spec]
|
25
|
-
end
|
26
|
-
|
27
|
-
task default: [:rubocop, :test, :spec]
|
data/action_policy.gemspec
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
lib = File.expand_path("lib", __dir__)
|
4
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
require "action_policy/version"
|
6
|
-
|
7
|
-
Gem::Specification.new do |spec|
|
8
|
-
spec.name = "action_policy"
|
9
|
-
spec.version = ActionPolicy::VERSION
|
10
|
-
spec.authors = ["Vladimir Dementyev"]
|
11
|
-
spec.email = ["dementiev.vm@gmail.com"]
|
12
|
-
|
13
|
-
spec.summary = "Authorization framework for Ruby/Rails application"
|
14
|
-
spec.description = "Authorization framework for Ruby/Rails application"
|
15
|
-
spec.homepage = "https://github.com/palkan/action_policy"
|
16
|
-
spec.license = "MIT"
|
17
|
-
|
18
|
-
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
19
|
-
f.match(%r{^(test|spec|features)/})
|
20
|
-
end
|
21
|
-
|
22
|
-
spec.metadata = {
|
23
|
-
"bug_tracker_uri" => "http://github.com/palkan/action_policy/issues",
|
24
|
-
"changelog_uri" => "https://github.com/palkan/action_policy/blob/master/CHANGELOG.md",
|
25
|
-
"documentation_uri" => "https://actionpolicy.evilmartians.io/",
|
26
|
-
"homepage_uri" => "https://actionpolicy.evilmartians.io/",
|
27
|
-
"source_code_uri" => "http://github.com/palkan/action_policy"
|
28
|
-
}
|
29
|
-
|
30
|
-
spec.require_paths = ["lib"]
|
31
|
-
|
32
|
-
spec.required_ruby_version = ">= 2.4.0"
|
33
|
-
|
34
|
-
spec.add_development_dependency "ammeter", "~> 1.1.3"
|
35
|
-
spec.add_development_dependency "bundler", ">= 1.15"
|
36
|
-
spec.add_development_dependency "minitest", "~> 5.0"
|
37
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
38
|
-
spec.add_development_dependency "rspec", "~> 3.3"
|
39
|
-
spec.add_development_dependency "rubocop", "~> 0.67.0"
|
40
|
-
spec.add_development_dependency "rubocop-md", "~> 0.2"
|
41
|
-
spec.add_development_dependency "standard", "~> 0.0.39"
|
42
|
-
spec.add_development_dependency "benchmark-ips", "~> 2.7.0"
|
43
|
-
spec.add_development_dependency "i18n"
|
44
|
-
end
|
@@ -1,71 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
#
|
4
|
-
# This benchmark measures the efficiency of NamespaceCache.
|
5
|
-
#
|
6
|
-
# Run it multiple times with cache on/off to see the results:
|
7
|
-
#
|
8
|
-
# $ bundle exec ruby namespaced_lookup_cache.rb
|
9
|
-
# $ bundle exec ruby namespaced_lookup_cache.rb
|
10
|
-
# $ NO_CACHE=1 bundle exec ruby namespaced_lookup_cache.rb
|
11
|
-
# $ NO_CACHE=1 bundle exec ruby namespaced_lookup_cache.rb
|
12
|
-
#
|
13
|
-
|
14
|
-
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
|
15
|
-
|
16
|
-
require "action_policy"
|
17
|
-
require "benchmark/ips"
|
18
|
-
|
19
|
-
GC.disable
|
20
|
-
|
21
|
-
class A; end
|
22
|
-
|
23
|
-
class B; end
|
24
|
-
|
25
|
-
module X
|
26
|
-
class BPolicy < ActionPolicy::Base; end
|
27
|
-
|
28
|
-
module Y
|
29
|
-
module Z
|
30
|
-
class APolicy < ActionPolicy::Base; end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
a = A.new
|
36
|
-
b = B.new
|
37
|
-
|
38
|
-
if ENV["NO_CACHE"]
|
39
|
-
ActionPolicy::LookupChain.namespace_cache_enabled = false
|
40
|
-
end
|
41
|
-
|
42
|
-
Benchmark.ips do |x|
|
43
|
-
x.warmup = 0
|
44
|
-
|
45
|
-
x.report("cache A") do
|
46
|
-
ActionPolicy.lookup(a, namespace: X::Y::Z)
|
47
|
-
end
|
48
|
-
|
49
|
-
x.report("cache B") do
|
50
|
-
ActionPolicy.lookup(b, namespace: X::Y::Z)
|
51
|
-
end
|
52
|
-
|
53
|
-
x.report("no cache A") do
|
54
|
-
ActionPolicy.lookup(a, namespace: X::Y::Z)
|
55
|
-
end
|
56
|
-
|
57
|
-
x.report("no cache B") do
|
58
|
-
ActionPolicy.lookup(b, namespace: X::Y::Z)
|
59
|
-
end
|
60
|
-
|
61
|
-
x.hold! "temp_results"
|
62
|
-
|
63
|
-
x.compare!
|
64
|
-
end
|
65
|
-
|
66
|
-
#
|
67
|
-
# Comparison:
|
68
|
-
# cache B: 178577.4 i/s
|
69
|
-
# cache A: 173061.4 i/s - same-ish: difference falls within error
|
70
|
-
# no cache A: 97991.7 i/s - same-ish: difference falls within error
|
71
|
-
# no cache B: 42505.4 i/s - 4.20x slower
|
data/bin/console
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "action_policy"
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start(__FILE__)
|
data/bin/setup
DELETED
data/docs/.nojekyll
DELETED
File without changes
|
data/docs/CNAME
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
actionpolicy.evilmartians.io
|
data/docs/README.md
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
[](https://badge.fury.io/rb/action_policy)
|
2
|
-
[](https://travis-ci.org/palkan/action_policy)
|
3
|
-
|
4
|
-
## Action Policy
|
5
|
-
|
6
|
-
> Authorization framework for Ruby and Rails.
|
7
|
-
<br>Composable. Extensible. Performant.
|
8
|
-
|
9
|
-
**NOTE:** this documentation is for the version "0.3.0+".
|
10
|
-
|
11
|
-
## What is it?
|
12
|
-
|
13
|
-
_Authorization_ is an act of giving **someone** official
|
14
|
-
permission to **do something** (to not be confused with [_authentication_](https://en.wikipedia.org/wiki/Authentication)).
|
15
|
-
|
16
|
-
Action Policy provides flexible tools to build an _authorization layer_ for your application.
|
17
|
-
|
18
|
-
<div class="chart-container">
|
19
|
-
<img src="assets/images/layer.svg" alt="Authorization layer" width="80%">
|
20
|
-
</div>
|
21
|
-
|
22
|
-
**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?**
|
23
|
-
|
24
|
-
## Where to go from here?
|
25
|
-
- [Quick start](./quick_start.md)
|
26
|
-
- [Using with Rails](./rails.md)
|
27
|
-
- [Using with other Ruby frameworks](./non_rails.md)
|
28
|
-
- [Using with GraphQL Ruby](./graphql.md)
|
29
|
-
|
30
|
-
## Project State
|
31
|
-
|
32
|
-
The project is being used in production since mid 2018. Major features have been implemented, API has been stabilized. Check out our [development board](https://github.com/palkan/action_policy/projects/1) to see what's coming next.
|
33
|
-
|
34
|
-
## History
|
35
|
-
|
36
|
-
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.
|
37
|
-
|
38
|
-
We have decided to collect all our authorization techniques and pack them into a standalone gem–and that is how Action Policy was born!
|
39
|
-
|
40
|
-
## What about the existing solutions?
|
41
|
-
|
42
|
-
Why did we decide to build our own authorization gem instead of using the existing solutions, such as [Pundit][] and [CanCanCan][]?
|
43
|
-
|
44
|
-
**TL;DR they didn't solve all of our problems.**
|
45
|
-
|
46
|
-
[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.
|
47
|
-
|
48
|
-
These _hacks_ later became Action Policy (initially, we even called it "Pundit, re-visited").
|
49
|
-
|
50
|
-
We also took a few ideas from [CanCanCan][]—such as [default rules and rule aliases](./aliases.md).
|
51
|
-
|
52
|
-
It is also worth noting that Action Policy (despite having 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.
|
53
|
-
|
54
|
-
So, what are the main reasons to consider Action Policy as your authorization tool?
|
55
|
-
|
56
|
-
- **Performance**: multiple [caching strategies](./caching.md) out-of-the-box make authorization overhead as small as possible–especially useful when your rules involve DB queries; you can also monitor the performance and detect the bottlenecks using the built-in [instrumentation](./instrumentation) features.
|
57
|
-
|
58
|
-
- **Composition & Customization**: use [only the features you need](./custom_policy.md) or easily extend the functionality–it's just Ruby classes and modules, (almost) zero magic! And you can add authorization [anywhere in your code](./non_rails.md), not only in controllers.
|
59
|
-
|
60
|
-
- **Code Organization**: use [namespaces](./namespaces.md) to organize your policies (for example, when you have multiple authorization strategies); add [pre-checks](./pre_checks.md) to make rules more readable and better express your business-logic.
|
61
|
-
|
62
|
-
- **...and more**: [testability](./testing.md), [i18n](./i18n.md) integrations, [actionable errors](./reasons.md).
|
63
|
-
|
64
|
-
Learn more about the motivation behind the Action Policy and its features by watching this [RailsConf talk](https://www.youtube.com/watch?v=NVwx0DARDis).
|
65
|
-
|
66
|
-
## Resources
|
67
|
-
|
68
|
-
- Seattle.rb, 2019 "A Denial!" talk [[slides](https://speakerdeck.com/palkan/seattle-dot-rb-2019-a-denial)]
|
69
|
-
|
70
|
-
- RailsConf, 2018 "Access Denied" talk [[video](https://www.youtube.com/watch?v=NVwx0DARDis), [slides](https://speakerdeck.com/palkan/railsconf-2018-access-denied-the-missing-guide-to-authorization-in-rails)]
|
71
|
-
|
72
|
-
<a href="https://evilmartians.com/?utm_source=action_policy">
|
73
|
-
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
|
74
|
-
|
75
|
-
[CanCanCan]: https://github.com/CanCanCommunity/cancancan
|
76
|
-
[Pundit]: https://github.com/varvet/pundit
|
77
|
-
[Evil Martians]: https://evilmartians.com
|