abilities 0.1.2 → 4.0.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/MIT-LICENSE +1 -1
- data/README.md +31 -44
- data/Rakefile +1 -14
- data/lib/abilities.rb +9 -18
- data/lib/abilities/definitions.rb +38 -29
- data/lib/abilities/extensions/action_controller/base.rb +28 -0
- data/lib/abilities/proxy.rb +6 -7
- data/lib/abilities/railtie.rb +4 -3
- data/lib/abilities/version.rb +1 -1
- data/lib/generators/abilities/install/install_generator.rb +15 -0
- data/lib/generators/abilities/{templates/abilities.rb → install/templates/configuration.rb} +0 -0
- data/test/dummy/Rakefile +0 -1
- data/test/dummy/app/assets/javascripts/application.js +2 -2
- data/test/dummy/app/assets/stylesheets/application.css +1 -1
- data/test/dummy/app/controllers/products_controller.rb +10 -0
- data/test/dummy/app/models/product.rb +2 -0
- data/test/dummy/app/models/user.rb +0 -1
- data/test/dummy/app/views/layouts/application.html.erb +9 -11
- data/test/dummy/app/views/products/show.html.erb +6 -0
- data/test/dummy/bin/bundle +1 -0
- data/test/dummy/bin/rails +2 -1
- data/test/dummy/bin/rake +1 -0
- data/test/dummy/bin/setup +30 -0
- data/test/dummy/config.ru +1 -1
- data/test/dummy/config/abilities.rb +6 -7
- data/test/dummy/config/application.rb +3 -0
- data/test/dummy/config/database.yml +4 -22
- data/test/dummy/config/database.yml.travis +3 -0
- data/test/dummy/config/environments/development.rb +6 -2
- data/test/dummy/config/environments/production.rb +16 -24
- data/test/dummy/config/environments/test.rb +7 -12
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/mime_types.rb +1 -1
- data/test/dummy/config/routes.rb +1 -54
- data/test/dummy/config/secrets.yml +3 -3
- data/test/dummy/db/migrate/20140629203344_create_users.rb +1 -3
- data/test/dummy/db/migrate/20140629203412_create_products.rb +7 -0
- data/test/dummy/db/schema.rb +9 -9
- data/test/dummy/log/development.log +78 -0
- data/test/dummy/log/test.log +1465 -246
- data/test/dummy/public/404.html +57 -63
- data/test/dummy/public/422.html +57 -63
- data/test/dummy/public/500.html +56 -62
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/2b/2bzOr5XdBQAg_ZBDeXY157jGXLRL6qjEoFZBTPyLFwM.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/48/48oV_bpl6OaHjWm9j-I1uNUp5m7SbkTgYjW6NaNnTfU.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/5L/5Lly_CA8DZvPhQV2jDQx-Y6P_y3Ygra9t5jfSlGhHDA.cache +2 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/OI/OI6uxGcnsKavdWTtwDAasU3wPx8QXhzBgV0X2n1KjMQ.cache +2 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/SG/SGNGr7AZfBE1q7ev2-YM1G-o0XAZ0pKqbsS3NvHtRcA.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/fG/fG_uaNK13wisQiji91xNsGecGxX9QhMCF2eSX_aR0G0.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/gb/gbunrAFVOHPwl2npUgKv_C3f_qiJnZDd9zG5-h3jrpo.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/hZ/hZi1k6tpxxCGYxRe7zY74ItcOI8gZrREOpGuA8JSpGg.cache +2 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/j0/j06P5zp022n2VUoAPi5fqCp_UbS7OaCD8XtVtEbHy58.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/mv/mvqN6PphkrOOC8zbUEhpC_9E_4ybdO25MRy_gG6dq3Y.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/nm/nmcUZlKAIwyJ_35Nm9P8pukLeRX5aApP6NFj5MpNPgc.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/pE/pEhaat2KBd5SrT7szC_8R1_6hK17FTpvoRFkmCRSD3M.cache +2 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/sB/sB6xWxBmgzVC0Co9__ANYrE58lr4WPwiwFa9mswooWM.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/va/vaNrIny9hchHD9eIJxAicyYLC7qeV4PTh4Nh40_Y6Vg.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/x6/x6W7JXRDHOmqATQMRSTLu17o8EcA-ietA1qm_PMPjbo.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v3.0/xd/xdBKQyhEAlDIstGvXw945PWJoEWi23rKuY7elOcWqHc.cache +1 -0
- data/test/generator_test.rb +4 -4
- data/test/policy_test.rb +62 -0
- data/test/test_helper.rb +5 -16
- data/test/view_test.rb +6 -17
- metadata +63 -32
- data/lib/abilities/action_controller/base.rb +0 -20
- data/lib/abilities/action_view/base.rb +0 -14
- data/lib/abilities/concern.rb +0 -12
- data/lib/abilities/configuration.rb +0 -13
- data/lib/generators/abilities/install_generator.rb +0 -13
- data/test/changes_test.rb +0 -12
- data/test/checking_test.rb +0 -64
- data/test/controller_test.rb +0 -38
- data/test/dummy/README.rdoc +0 -28
- data/test/dummy/app/models/post.rb +0 -3
- data/test/dummy/config/initializers/abilities.rb +0 -7
- data/test/dummy/config/initializers/secret_token.rb +0 -1
- data/test/dummy/db/migrate/20140629203412_create_posts.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d2bc9ac0cfbd40fc108a5cd619f54e7844096292
|
4
|
+
data.tar.gz: 1e8aa0c9839cad844c4b540e663124e070cbfe63
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b83c49c8ce1332ca10d8b9dcee7d1415572ed39cc849a2801b5970176fc3b8f5095d822d4fa8560f53b8133f568bd403e98b763df67456c075e3a79910a5e32
|
7
|
+
data.tar.gz: 32d1b4733cf942cf5247110c5790b9c093eb7212febdf11ca1d0ec8f17f44b7ec32710f4e9907dabe3ce1753f9706c1b4c171ad3f6fb7d88fc54c2b4935fc3e5
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -5,7 +5,14 @@
|
|
5
5
|
|
6
6
|
# Abilities
|
7
7
|
|
8
|
-
|
8
|
+
Authorization dsl to manage permissions in rails.
|
9
|
+
|
10
|
+
## Why
|
11
|
+
|
12
|
+
I did this gem to:
|
13
|
+
|
14
|
+
- Use a dsl instead of a plain class to simplify the syntax.
|
15
|
+
- Limit authorizations to only controllers and their views.
|
9
16
|
|
10
17
|
## Install
|
11
18
|
|
@@ -21,65 +28,45 @@ $ bundle
|
|
21
28
|
|
22
29
|
## Configuration
|
23
30
|
|
24
|
-
Generate the
|
31
|
+
Generate the definitions file:
|
25
32
|
```
|
26
33
|
bundle exec rails g abilities:install
|
27
34
|
```
|
28
35
|
|
29
|
-
|
36
|
+
Ensure there is a current_user method in your controllers:
|
30
37
|
```ruby
|
31
|
-
|
32
|
-
|
33
|
-
current_user
|
38
|
+
class ApplicationController < ActionController::Base
|
39
|
+
def current_user
|
40
|
+
@current_user ||= User.find(session[:user_id])
|
34
41
|
end
|
35
42
|
end
|
36
43
|
```
|
37
44
|
|
38
|
-
Add the abilities concern to the model if you want to call can? and cannot? in the user instance:
|
39
|
-
```ruby
|
40
|
-
class User < ActiveRecord::Base
|
41
|
-
include Abilities::Concern
|
42
|
-
end
|
43
|
-
```
|
44
|
-
|
45
45
|
## Usage
|
46
46
|
|
47
|
-
###
|
47
|
+
### Definitions
|
48
48
|
|
49
|
-
|
49
|
+
Use can and cannot methods to define the policies:
|
50
50
|
```ruby
|
51
51
|
Abilities.define do
|
52
|
-
can :
|
53
|
-
|
54
|
-
|
55
|
-
subject.user == self
|
52
|
+
can :view, :any
|
53
|
+
can :manage, User do |user|
|
54
|
+
user == self
|
56
55
|
end
|
57
|
-
can :
|
58
|
-
can :touch, :all
|
56
|
+
can :detroy, Product if admin?
|
59
57
|
end
|
60
58
|
```
|
61
59
|
|
62
|
-
|
63
|
-
```ruby
|
64
|
-
Abilities.define do
|
65
|
-
permissions.each do |permission|
|
66
|
-
can premissions.action, permissions.subject
|
67
|
-
end
|
68
|
-
end
|
69
|
-
```
|
60
|
+
NOTE: Methods besides can and cannot are sent to the current_user.
|
70
61
|
|
71
|
-
|
72
|
-
|
73
|
-
### Checking
|
74
|
-
|
75
|
-
#### Controllers
|
62
|
+
### Controllers
|
76
63
|
|
77
64
|
With the authorize! method Abilities::AccessDenied is raised if authorization fails:
|
78
65
|
```ruby
|
79
|
-
class
|
66
|
+
class UsersController < ApplicationController
|
80
67
|
def edit
|
81
|
-
@
|
82
|
-
authorize! :edit, @
|
68
|
+
@user = User.find(params[:id])
|
69
|
+
authorize! :edit, @user
|
83
70
|
end
|
84
71
|
end
|
85
72
|
```
|
@@ -88,9 +75,9 @@ If you don't want an exception to be raised use can? and cannot? helpers:
|
|
88
75
|
```ruby
|
89
76
|
class UsersController < ApplicationController
|
90
77
|
def edit
|
91
|
-
@
|
92
|
-
if can?
|
93
|
-
@
|
78
|
+
@user = User.find(params[:id])
|
79
|
+
if can?(:edit, @user)
|
80
|
+
@user.update post_params
|
94
81
|
else
|
95
82
|
# handle access denied
|
96
83
|
end
|
@@ -98,12 +85,12 @@ class UsersController < ApplicationController
|
|
98
85
|
end
|
99
86
|
```
|
100
87
|
|
101
|
-
|
88
|
+
### Views
|
102
89
|
|
103
|
-
The helpers can? and cannot? are available
|
90
|
+
The helpers can? and cannot? are available in the controller views too:
|
104
91
|
```erb
|
105
|
-
<% if can?
|
106
|
-
<%= link_to
|
92
|
+
<% if can?(:detroy, @product) %>
|
93
|
+
<%= link_to product_path(@product), method: 'delete' %>
|
107
94
|
<% end %>
|
108
95
|
```
|
109
96
|
|
data/Rakefile
CHANGED
@@ -4,19 +4,6 @@ rescue LoadError
|
|
4
4
|
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
5
|
end
|
6
6
|
|
7
|
-
require 'rdoc/task'
|
8
|
-
|
9
|
-
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
-
rdoc.rdoc_dir = 'rdoc'
|
11
|
-
rdoc.title = 'Abilities'
|
12
|
-
rdoc.options << '--line-numbers'
|
13
|
-
rdoc.rdoc_files.include('README.rdoc')
|
14
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
-
end
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
7
|
Bundler::GemHelper.install_tasks
|
21
8
|
|
22
9
|
require 'rake/testtask'
|
@@ -26,7 +13,7 @@ Rake::TestTask.new(:test) do |t|
|
|
26
13
|
t.libs << 'test'
|
27
14
|
t.pattern = 'test/**/*_test.rb'
|
28
15
|
t.verbose = false
|
16
|
+
t.warning = false
|
29
17
|
end
|
30
18
|
|
31
|
-
|
32
19
|
task default: :test
|
data/lib/abilities.rb
CHANGED
@@ -1,33 +1,24 @@
|
|
1
|
-
require 'abilities/action_controller/base'
|
2
|
-
require 'abilities/action_view/base'
|
3
|
-
require 'abilities/proxy'
|
4
|
-
require 'abilities/configuration'
|
1
|
+
require 'abilities/extensions/action_controller/base'
|
5
2
|
require 'abilities/definitions'
|
6
3
|
require 'abilities/exceptions'
|
7
|
-
require 'abilities/
|
4
|
+
require 'abilities/proxy'
|
8
5
|
require 'abilities/railtie'
|
6
|
+
require 'abilities/version'
|
9
7
|
|
10
8
|
module Abilities
|
11
9
|
class << self
|
12
10
|
|
13
|
-
|
14
|
-
yield configuration
|
15
|
-
end
|
16
|
-
|
17
|
-
def configuration
|
18
|
-
@configuration ||= Configuration.new
|
19
|
-
end
|
11
|
+
attr_reader :block
|
20
12
|
|
21
13
|
def define(&block)
|
22
14
|
@block = block
|
23
15
|
end
|
24
16
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
!can?(*args)
|
17
|
+
%i(can? cannot?).each do |name|
|
18
|
+
define_method name do |user, action, resource|
|
19
|
+
definitions = Definitions.new(user, &block)
|
20
|
+
definitions.send name, action, resource
|
21
|
+
end
|
31
22
|
end
|
32
23
|
|
33
24
|
end
|
@@ -1,31 +1,23 @@
|
|
1
1
|
module Abilities
|
2
2
|
class Definitions
|
3
3
|
|
4
|
-
|
5
|
-
@actor = actor
|
6
|
-
Proxy.new(actor, self, &block)
|
7
|
-
end
|
4
|
+
attr_reader :user
|
8
5
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
subjects.each do |subject|
|
13
|
-
actions.each do |action|
|
14
|
-
(all[find_subject_id(subject)] ||= {})[action.to_s] = block_given? ? block : behavior
|
15
|
-
end
|
16
|
-
end
|
6
|
+
def initialize(user, &block)
|
7
|
+
@user = user
|
8
|
+
Proxy.new self, &block
|
17
9
|
end
|
18
10
|
|
19
|
-
def can?(action,
|
20
|
-
|
21
|
-
if
|
11
|
+
def can?(action, resource)
|
12
|
+
id = resource_id(resource)
|
13
|
+
if id != :any && can?(action, :any)
|
22
14
|
true
|
23
|
-
elsif actions =
|
24
|
-
if
|
25
|
-
if
|
26
|
-
|
15
|
+
elsif actions = registry[id]
|
16
|
+
if policy = (actions[action] || actions[:manage])
|
17
|
+
if policy.is_a?(Proc)
|
18
|
+
user.instance_exec resource, &policy
|
27
19
|
else
|
28
|
-
|
20
|
+
policy
|
29
21
|
end
|
30
22
|
else
|
31
23
|
false
|
@@ -39,19 +31,36 @@ module Abilities
|
|
39
31
|
!can?(*args)
|
40
32
|
end
|
41
33
|
|
42
|
-
|
34
|
+
def add(actions, resources, policy)
|
35
|
+
unless actions.is_a?(Array)
|
36
|
+
actions = [actions]
|
37
|
+
end
|
38
|
+
unless resources.is_a?(Array)
|
39
|
+
resources = [resources]
|
40
|
+
end
|
41
|
+
resources.each do |resource|
|
42
|
+
actions.each do |action|
|
43
|
+
id = resource_id(resource)
|
44
|
+
registry[id] ||= {}
|
45
|
+
registry[id][action] = policy
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
43
51
|
|
44
|
-
def
|
45
|
-
@
|
52
|
+
def registry
|
53
|
+
@registry ||= {}
|
46
54
|
end
|
47
55
|
|
48
|
-
def
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
56
|
+
def resource_id(resource)
|
57
|
+
case resource
|
58
|
+
when :any
|
59
|
+
resource
|
60
|
+
when Class
|
61
|
+
resource.name.underscore.to_sym
|
53
62
|
else
|
54
|
-
|
63
|
+
resource.class.name.underscore.to_sym
|
55
64
|
end
|
56
65
|
end
|
57
66
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Abilities
|
2
|
+
module Extensions
|
3
|
+
module ActionController
|
4
|
+
module Base
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
helper_method :can?, :cannot?
|
9
|
+
end
|
10
|
+
|
11
|
+
%w(can? cannot?).each do |name|
|
12
|
+
define_method name do |action, resource|
|
13
|
+
Abilities.send name, current_user, action, resource
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def authorize!(action, subject)
|
20
|
+
if cannot?(action, subject)
|
21
|
+
raise Abilities::AccessDenied
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/abilities/proxy.rb
CHANGED
@@ -1,22 +1,21 @@
|
|
1
1
|
module Abilities
|
2
2
|
class Proxy
|
3
3
|
|
4
|
-
def initialize(
|
5
|
-
@actor = actor
|
4
|
+
def initialize(definitions, &block)
|
6
5
|
@definitions = definitions
|
7
6
|
instance_eval &block
|
8
7
|
end
|
9
8
|
|
10
|
-
def can(actions,
|
11
|
-
@definitions.add actions,
|
9
|
+
def can(actions, resources, &block)
|
10
|
+
@definitions.add actions, resources, (block_given? ? block : true)
|
12
11
|
end
|
13
12
|
|
14
|
-
def cannot(actions,
|
15
|
-
@definitions.add actions,
|
13
|
+
def cannot(actions, resources, &block)
|
14
|
+
@definitions.add actions, resources, (block_given? ? block : false)
|
16
15
|
end
|
17
16
|
|
18
17
|
def method_missing(name, *args, &block)
|
19
|
-
@
|
18
|
+
@definitions.user.send name, *args, &block
|
20
19
|
end
|
21
20
|
|
22
21
|
end
|
data/lib/abilities/railtie.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
module Abilities
|
2
2
|
class Railtie < Rails::Railtie
|
3
3
|
|
4
|
-
initializer 'abilites' do
|
5
|
-
::
|
6
|
-
|
4
|
+
initializer 'abilites.extensions' do
|
5
|
+
::ActionController::Base.include(
|
6
|
+
Abilities::Extensions::ActionController::Base
|
7
|
+
)
|
7
8
|
end
|
8
9
|
|
9
10
|
config.after_initialize do
|
data/lib/abilities/version.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
module Abilities
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < ::Rails::Generators::Base
|
6
|
+
|
7
|
+
source_root File.expand_path('../templates', __FILE__)
|
8
|
+
|
9
|
+
def create_configuration_file
|
10
|
+
copy_file 'configuration.rb', 'config/abilities.rb'
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
File without changes
|
data/test/dummy/Rakefile
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
// listed below.
|
3
3
|
//
|
4
4
|
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
-
// or vendor/assets/javascripts
|
5
|
+
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
6
|
//
|
7
7
|
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
8
|
// compiled file.
|
9
9
|
//
|
10
|
-
// Read Sprockets README (https://github.com/
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
11
|
// about supported directives.
|
12
12
|
//
|
13
13
|
//= require_tree .
|
@@ -3,7 +3,7 @@
|
|
3
3
|
* listed below.
|
4
4
|
*
|
5
5
|
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
-
* or vendor/assets/stylesheets
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
7
|
*
|
8
8
|
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
9
|
* compiled file so the styles you add here take precedence over styles defined in any styles
|