be9-acl9 0.9.2 → 0.9.3
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.
- data/CHANGELOG.textile +6 -0
- data/Manifest +17 -13
- data/README.textile +53 -0
- data/Rakefile +1 -1
- data/TODO +42 -0
- data/acl9.gemspec +10 -10
- data/lib/acl9.rb +2 -0
- data/lib/acl9/controller_extensions.rb +18 -15
- data/lib/acl9/controller_extensions/generators.rb +28 -1
- data/lib/acl9/helpers.rb +19 -0
- data/lib/acl9/model_extensions/subject.rb +1 -1
- data/lib/acl9/version.rb +1 -1
- data/spec/access_control_spec.rb +59 -136
- data/spec/controllers.rb +139 -0
- data/spec/helpers_spec.rb +92 -0
- data/spec/roles_spec.rb +3 -0
- data/spec/spec_helper.rb +18 -4
- metadata +27 -21
data/CHANGELOG.textile
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
h2. 0.9.3 (04-Feb-2009)
|
2
|
+
|
3
|
+
* Fix bug in delete_role - didn't work with custom class names
|
4
|
+
* Add @:helper@ option for @access_control@.
|
5
|
+
* Ability to generate helper methods directly (place @include Acl9Helpers@ in your helper module).
|
6
|
+
|
1
7
|
h2. 0.9.2 (11-Jan-2009)
|
2
8
|
|
3
9
|
* @access_control :method do end@ as shorter form for @access_control :as_method => :method do end@.
|
data/Manifest
CHANGED
@@ -1,22 +1,26 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
lib/acl9/model_extensions.rb
|
4
|
-
lib/acl9/version.rb
|
1
|
+
lib/acl9/helpers.rb
|
2
|
+
lib/acl9/config.rb
|
5
3
|
lib/acl9/model_extensions/subject.rb
|
6
4
|
lib/acl9/model_extensions/object.rb
|
5
|
+
lib/acl9/controller_extensions.rb
|
7
6
|
lib/acl9/controller_extensions/generators.rb
|
8
7
|
lib/acl9/controller_extensions/dsl_base.rb
|
9
|
-
lib/acl9/
|
10
|
-
lib/acl9/
|
8
|
+
lib/acl9/version.rb
|
9
|
+
lib/acl9/model_extensions.rb
|
11
10
|
lib/acl9.rb
|
12
|
-
|
13
|
-
acl9.gemspec
|
14
|
-
CHANGELOG.textile
|
15
|
-
MIT-LICENSE
|
16
|
-
Rakefile
|
11
|
+
TODO
|
17
12
|
spec/db/schema.rb
|
18
|
-
spec/
|
13
|
+
spec/helpers_spec.rb
|
19
14
|
spec/spec_helper.rb
|
15
|
+
spec/models.rb
|
16
|
+
spec/dsl_base_spec.rb
|
20
17
|
spec/access_control_spec.rb
|
18
|
+
spec/controllers.rb
|
21
19
|
spec/roles_spec.rb
|
22
|
-
|
20
|
+
acl9.gemspec
|
21
|
+
Manifest
|
22
|
+
MIT-LICENSE
|
23
|
+
Rakefile
|
24
|
+
README.textile
|
25
|
+
init.rb
|
26
|
+
CHANGELOG.textile
|
data/README.textile
CHANGED
@@ -763,6 +763,33 @@ you may not only call @lolcats?@ with no arguments, which will basically return
|
|
763
763
|
but also as @lolcats?(:lol => Lol.find(params[:lol]))@. The hash will be looked into first,
|
764
764
|
even if you have an instance variable @lol@.
|
765
765
|
|
766
|
+
h3. :helper
|
767
|
+
|
768
|
+
Sometimes you want to have a boolean method (like @:filter => false@) accessible
|
769
|
+
in your views. Acl9 can call @helper_method@ for you:
|
770
|
+
|
771
|
+
<pre><code>
|
772
|
+
class LolController < ApplicationController
|
773
|
+
access_control :helper => :lolcats? do
|
774
|
+
allow :cats, :by => :lol
|
775
|
+
# ...
|
776
|
+
end
|
777
|
+
end
|
778
|
+
</code></pre>
|
779
|
+
|
780
|
+
That's equivalent to
|
781
|
+
|
782
|
+
<pre><code>
|
783
|
+
class LolController < ApplicationController
|
784
|
+
access_control :lolcats?, :filter => false do
|
785
|
+
allow :cats, :by => :lol
|
786
|
+
# ...
|
787
|
+
end
|
788
|
+
|
789
|
+
helper_method :lolcats?
|
790
|
+
end
|
791
|
+
</code></pre>
|
792
|
+
|
766
793
|
h3. Other options
|
767
794
|
|
768
795
|
Other options will be passed to @before_filter@. As such, you may use @:only@ and @:except@ to narrow
|
@@ -796,6 +823,32 @@ is basically equivalent to
|
|
796
823
|
end
|
797
824
|
</code></pre>
|
798
825
|
|
826
|
+
h2. access_control in your helpers
|
827
|
+
|
828
|
+
Apart from using @:helper@ option for @access_control@ call inside controller, there's a
|
829
|
+
way to generate helper methods directly, like this:
|
830
|
+
|
831
|
+
<pre><code>
|
832
|
+
module SettingsHelper
|
833
|
+
include Acl9Helpers
|
834
|
+
|
835
|
+
access_control :show_settings? do
|
836
|
+
allow :admin
|
837
|
+
allow :settings_manager
|
838
|
+
end
|
839
|
+
end
|
840
|
+
</code></pre>
|
841
|
+
|
842
|
+
Here we mix in @Acl9Helpers@ module which brings in @access_control@ method and call it,
|
843
|
+
obtaining @show_settings?@ method.
|
844
|
+
|
845
|
+
An imaginary view:
|
846
|
+
|
847
|
+
<pre><code>
|
848
|
+
<% if show_settings? %>
|
849
|
+
<%= link_to 'Settings', settings_path %>
|
850
|
+
<% end %>
|
851
|
+
</code></pre>
|
799
852
|
|
800
853
|
Copyright (c) 2009 Oleg Dashevskii, released under the MIT license.
|
801
854
|
|
data/Rakefile
CHANGED
@@ -17,7 +17,7 @@ begin
|
|
17
17
|
p.summary = "Yet another role-based authorization system for Rails with a nice DSL for access control lists."
|
18
18
|
p.url = "http://github.com/be9/acl9"
|
19
19
|
p.ignore_pattern = ["spec/db/*.sqlite3", "spec/debug.log"]
|
20
|
-
p.development_dependencies = ["rspec >=1.1.
|
20
|
+
p.development_dependencies = ["rspec >=1.1.12", "rspec-rails >=1.1.12"]
|
21
21
|
end
|
22
22
|
rescue LoadError => boom
|
23
23
|
puts "You are missing a dependency required for meta-operations on this gem."
|
data/TODO
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
* Complex roles with ANDing.
|
2
|
+
|
3
|
+
Something like:
|
4
|
+
|
5
|
+
access_control do
|
6
|
+
allow all, :except => :destroy
|
7
|
+
allow complex_role, :to => :destroy do
|
8
|
+
is :strong
|
9
|
+
is :decisive
|
10
|
+
is :owner, :of => :object
|
11
|
+
is_not :banned
|
12
|
+
is_not :fake
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
* Acl9-based menu generator.
|
17
|
+
|
18
|
+
If you get Access Denied on /secrets/index, probably you shouldn't see "Secrets" item
|
19
|
+
in the menu at all.
|
20
|
+
|
21
|
+
It can be very DRY. Say, we introduce :menu => true option to access_control method which
|
22
|
+
will make it register a lambda (can see/cannot see) in some global hash (indexed by controller name).
|
23
|
+
|
24
|
+
Then, given an URL, you'll be able to check it against this hash. /secrets/index is mapped to
|
25
|
+
SecretsController#index, so you run access_control_hash['SecretsController'].call('index') and
|
26
|
+
show the link only if true is returned.
|
27
|
+
|
28
|
+
The problem here is with objects. SecretsController's access_control block can reference instance
|
29
|
+
variables during the permission check, but we have only current instantiated controller which can be any.
|
30
|
+
|
31
|
+
Another option is to distinguish visible part from access control part.
|
32
|
+
|
33
|
+
menu do
|
34
|
+
item 'Home', home_path
|
35
|
+
item 'Secrets', secrets_path do
|
36
|
+
allow :trusted
|
37
|
+
end
|
38
|
+
|
39
|
+
# ...
|
40
|
+
end
|
41
|
+
|
42
|
+
Here only "trusted" users will see "Secrets" item.
|
data/acl9.gemspec
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{acl9}
|
5
|
-
s.version = "0.9.
|
5
|
+
s.version = "0.9.3"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Oleg Dashevskii"]
|
9
|
-
s.date = %q{2009-
|
9
|
+
s.date = %q{2009-02-04}
|
10
10
|
s.description = %q{Yet another role-based authorization system for Rails with a nice DSL for access control lists.}
|
11
11
|
s.email = %q{olegdashevskii@gmail.com}
|
12
|
-
s.extra_rdoc_files = ["lib/acl9/
|
13
|
-
s.files = ["
|
12
|
+
s.extra_rdoc_files = ["lib/acl9/helpers.rb", "lib/acl9/config.rb", "lib/acl9/model_extensions/subject.rb", "lib/acl9/model_extensions/object.rb", "lib/acl9/controller_extensions.rb", "lib/acl9/controller_extensions/generators.rb", "lib/acl9/controller_extensions/dsl_base.rb", "lib/acl9/version.rb", "lib/acl9/model_extensions.rb", "lib/acl9.rb", "TODO", "README.textile", "CHANGELOG.textile"]
|
13
|
+
s.files = ["lib/acl9/helpers.rb", "lib/acl9/config.rb", "lib/acl9/model_extensions/subject.rb", "lib/acl9/model_extensions/object.rb", "lib/acl9/controller_extensions.rb", "lib/acl9/controller_extensions/generators.rb", "lib/acl9/controller_extensions/dsl_base.rb", "lib/acl9/version.rb", "lib/acl9/model_extensions.rb", "lib/acl9.rb", "TODO", "spec/db/schema.rb", "spec/helpers_spec.rb", "spec/spec_helper.rb", "spec/models.rb", "spec/dsl_base_spec.rb", "spec/access_control_spec.rb", "spec/controllers.rb", "spec/roles_spec.rb", "acl9.gemspec", "Manifest", "MIT-LICENSE", "Rakefile", "README.textile", "init.rb", "CHANGELOG.textile"]
|
14
14
|
s.has_rdoc = true
|
15
15
|
s.homepage = %q{http://github.com/be9/acl9}
|
16
16
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Acl9", "--main", "README.textile"]
|
@@ -24,14 +24,14 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.specification_version = 2
|
25
25
|
|
26
26
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
27
|
-
s.add_development_dependency(%q<rspec>, [">= 1.1.
|
28
|
-
s.add_development_dependency(%q<rspec-rails>, [">= 1.1.
|
27
|
+
s.add_development_dependency(%q<rspec>, [">= 1.1.12"])
|
28
|
+
s.add_development_dependency(%q<rspec-rails>, [">= 1.1.12"])
|
29
29
|
else
|
30
|
-
s.add_dependency(%q<rspec>, [">= 1.1.
|
31
|
-
s.add_dependency(%q<rspec-rails>, [">= 1.1.
|
30
|
+
s.add_dependency(%q<rspec>, [">= 1.1.12"])
|
31
|
+
s.add_dependency(%q<rspec-rails>, [">= 1.1.12"])
|
32
32
|
end
|
33
33
|
else
|
34
|
-
s.add_dependency(%q<rspec>, [">= 1.1.
|
35
|
-
s.add_dependency(%q<rspec-rails>, [">= 1.1.
|
34
|
+
s.add_dependency(%q<rspec>, [">= 1.1.12"])
|
35
|
+
s.add_dependency(%q<rspec-rails>, [">= 1.1.12"])
|
36
36
|
end
|
37
37
|
end
|
data/lib/acl9.rb
CHANGED
@@ -9,6 +9,8 @@ end
|
|
9
9
|
|
10
10
|
if defined? ActionController::Base
|
11
11
|
require File.join(File.dirname(__FILE__), 'acl9', 'controller_extensions')
|
12
|
+
require File.join(File.dirname(__FILE__), 'acl9', 'helpers')
|
12
13
|
|
13
14
|
ActionController::Base.send(:include, Acl9::ControllerExtensions)
|
15
|
+
Acl9Helpers = Acl9::Helpers unless defined?(Acl9Helpers)
|
14
16
|
end
|
@@ -8,11 +8,7 @@ module Acl9
|
|
8
8
|
|
9
9
|
module ClassMethods
|
10
10
|
def access_control(*args, &block)
|
11
|
-
opts =
|
12
|
-
args.pop
|
13
|
-
else
|
14
|
-
{}
|
15
|
-
end
|
11
|
+
opts = args.extract_options!
|
16
12
|
|
17
13
|
case args.size
|
18
14
|
when 0 then true
|
@@ -22,20 +18,33 @@ module Acl9
|
|
22
18
|
if meth.is_a? Symbol
|
23
19
|
opts[:as_method] = meth
|
24
20
|
else
|
25
|
-
raise ArgumentError, "
|
21
|
+
raise ArgumentError, "access_control argument must be a :symbol!"
|
26
22
|
end
|
27
23
|
else
|
28
24
|
raise ArgumentError, "Invalid arguments for access_control"
|
29
25
|
end
|
30
26
|
|
31
|
-
subject_method = opts
|
27
|
+
subject_method = opts[:subject_method] || Acl9::config[:default_subject_method]
|
32
28
|
|
33
29
|
raise ArgumentError, "Block must be supplied to access_control" unless block
|
34
30
|
|
35
|
-
filter = opts
|
31
|
+
filter = opts[:filter]
|
36
32
|
filter = true if filter.nil?
|
37
33
|
|
38
|
-
|
34
|
+
case helper = opts[:helper]
|
35
|
+
when true
|
36
|
+
raise ArgumentError, "you should specify :helper => :method_name" if !opts[:as_method]
|
37
|
+
when nil then nil
|
38
|
+
else
|
39
|
+
if opts[:as_method]
|
40
|
+
raise ArgumentError, "you can't specify both method name and helper name"
|
41
|
+
else
|
42
|
+
opts[:as_method] = helper
|
43
|
+
filter = false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
method = opts[:as_method]
|
39
48
|
|
40
49
|
generator = case
|
41
50
|
when method && filter
|
@@ -48,12 +57,6 @@ module Acl9
|
|
48
57
|
|
49
58
|
generator.acl_block!(&block)
|
50
59
|
|
51
|
-
if opts.delete(:debug)
|
52
|
-
Rails::logger.debug "=== Acl9 access_control expression dump (#{self.to_s})"
|
53
|
-
Rails::logger.debug generator.to_s
|
54
|
-
Rails::logger.debug "======"
|
55
|
-
end
|
56
|
-
|
57
60
|
generator.install_on(self, opts)
|
58
61
|
end
|
59
62
|
end
|
@@ -34,6 +34,16 @@ module Acl9
|
|
34
34
|
def _controller_ref
|
35
35
|
@controller ? "#{@controller}." : ''
|
36
36
|
end
|
37
|
+
|
38
|
+
def install_on(controller_class, options)
|
39
|
+
debug_dump(controller_class) if options[:debug]
|
40
|
+
end
|
41
|
+
|
42
|
+
def debug_dump(klass)
|
43
|
+
Rails::logger.debug "=== Acl9 access_control expression dump (#{klass.to_s})"
|
44
|
+
Rails::logger.debug self.to_s
|
45
|
+
Rails::logger.debug "======"
|
46
|
+
end
|
37
47
|
end
|
38
48
|
|
39
49
|
class FilterLambda < BaseGenerator
|
@@ -44,6 +54,8 @@ module Acl9
|
|
44
54
|
end
|
45
55
|
|
46
56
|
def install_on(controller_class, options)
|
57
|
+
super
|
58
|
+
|
47
59
|
controller_class.send(:before_filter, options, &self.to_proc)
|
48
60
|
end
|
49
61
|
|
@@ -71,6 +83,7 @@ module Acl9
|
|
71
83
|
end
|
72
84
|
|
73
85
|
def install_on(controller_class, options)
|
86
|
+
super
|
74
87
|
_add_method(controller_class)
|
75
88
|
controller_class.send(:before_filter, @method_name, options)
|
76
89
|
end
|
@@ -96,8 +109,14 @@ module Acl9
|
|
96
109
|
end
|
97
110
|
|
98
111
|
class BooleanMethod < FilterMethod
|
99
|
-
def install_on(controller_class,
|
112
|
+
def install_on(controller_class, opts)
|
113
|
+
debug_dump(controller_class) if opts[:debug]
|
114
|
+
|
100
115
|
_add_method(controller_class)
|
116
|
+
|
117
|
+
if opts[:helper]
|
118
|
+
controller_class.send(:helper_method, @method_name)
|
119
|
+
end
|
101
120
|
end
|
102
121
|
|
103
122
|
protected
|
@@ -114,6 +133,14 @@ module Acl9
|
|
114
133
|
"(options[:#{object}] || #{super})"
|
115
134
|
end
|
116
135
|
end
|
136
|
+
|
137
|
+
class HelperMethod < BooleanMethod
|
138
|
+
def initialize(subject_method, method)
|
139
|
+
super
|
140
|
+
|
141
|
+
@controller = 'controller'
|
142
|
+
end
|
143
|
+
end
|
117
144
|
end
|
118
145
|
end
|
119
146
|
end
|
data/lib/acl9/helpers.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Acl9
|
2
|
+
module Helpers
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def access_control(method, opts = {}, &block)
|
9
|
+
subject_method = opts.delete(:subject_method) || Acl9::config[:default_subject_method]
|
10
|
+
raise ArgumentError, "Block must be supplied to access_control" unless block
|
11
|
+
|
12
|
+
generator = Acl9::Dsl::Generators::HelperMethod.new(subject_method, method)
|
13
|
+
|
14
|
+
generator.acl_block!(&block)
|
15
|
+
generator.install_on(self, opts)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/acl9/version.rb
CHANGED
data/spec/access_control_spec.rb
CHANGED
@@ -1,93 +1,32 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
2
|
require File.join(File.dirname(__FILE__), '..', 'lib', 'acl9')
|
3
|
+
require File.join(File.dirname(__FILE__), 'controllers')
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
[:index, :show, :new, :edit, :update, :delete, :destroy].each do |act|
|
9
|
-
define_method(act) {}
|
10
|
-
end
|
11
|
-
|
12
|
-
private
|
13
|
-
|
14
|
-
def set_current_user
|
15
|
-
if params[:user]
|
16
|
-
self.current_user = params[:user]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
class Admin
|
22
|
-
def has_role?(role, obj = nil)
|
23
|
-
role == "admin"
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
# all these controllers behave the same way
|
28
|
-
|
29
|
-
class ACLBlock < EmptyController
|
30
|
-
access_control do
|
31
|
-
allow all, :to => [:index, :show]
|
32
|
-
allow :admin
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
class ACLMethod < EmptyController
|
37
|
-
access_control :as_method => :acl do
|
38
|
-
allow all, :to => [:index, :show]
|
39
|
-
allow :admin, :except => [:index, :show]
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
class ACLMethod2 < EmptyController
|
44
|
-
access_control :acl do
|
45
|
-
allow all, :to => [:index, :show]
|
46
|
-
allow :admin, :except => [:index, :show]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
class ACLArguments < EmptyController
|
51
|
-
access_control :except => [:index, :show] do
|
52
|
-
allow :admin
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
class ACLBooleanMethod < EmptyController
|
57
|
-
access_control :acl, :filter => false do
|
58
|
-
allow all, :to => [:index, :show]
|
59
|
-
allow :admin
|
60
|
-
end
|
61
|
-
|
62
|
-
before_filter :check_acl
|
63
|
-
|
64
|
-
def check_acl
|
65
|
-
if self.acl
|
66
|
-
true
|
67
|
-
else
|
68
|
-
raise Acl9::AccessDenied
|
5
|
+
describe "permit anonymous to index and show and admin everywhere else", :shared => true do
|
6
|
+
class Admin
|
7
|
+
def has_role?(role, obj = nil)
|
8
|
+
role == "admin"
|
69
9
|
end
|
70
10
|
end
|
71
|
-
end
|
72
11
|
|
73
|
-
describe "permit anonymous to index and show and admin everywhere else", :shared => true do
|
74
12
|
[:index, :show].each do |act|
|
75
13
|
it "should permit anonymous to #{act}" do
|
76
14
|
get act
|
15
|
+
response.body.should == 'OK'
|
77
16
|
end
|
78
17
|
end
|
79
18
|
|
80
19
|
[:new, :edit, :update, :delete, :destroy].each do |act|
|
81
20
|
it "should forbid anonymous to #{act}" do
|
82
|
-
|
83
|
-
|
84
|
-
end.should raise_error(Acl9::AccessDenied)
|
21
|
+
get act
|
22
|
+
response.body.should == 'AccessDenied'
|
85
23
|
end
|
86
24
|
end
|
87
25
|
|
88
26
|
[:index, :show, :new, :edit, :update, :delete, :destroy].each do |act|
|
89
27
|
it "should permit admin to #{act}" do
|
90
28
|
get act, :user => Admin.new
|
29
|
+
response.body.should == 'OK'
|
91
30
|
end
|
92
31
|
end
|
93
32
|
end
|
@@ -120,29 +59,6 @@ describe ACLBooleanMethod, :type => :controller do
|
|
120
59
|
it_should_behave_like "permit anonymous to index and show and admin everywhere else"
|
121
60
|
end
|
122
61
|
|
123
|
-
class MyDearFoo
|
124
|
-
include Singleton
|
125
|
-
end
|
126
|
-
|
127
|
-
class VenerableBar; end
|
128
|
-
|
129
|
-
class ACLIvars < EmptyController
|
130
|
-
before_filter :set_ivars
|
131
|
-
|
132
|
-
access_control do
|
133
|
-
action :destroy do
|
134
|
-
allow :owner, :of => :foo
|
135
|
-
allow :bartender, :at => VenerableBar
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
private
|
140
|
-
|
141
|
-
def set_ivars
|
142
|
-
@foo = MyDearFoo.instance
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
62
|
describe ACLIvars, :type => :controller do
|
147
63
|
class OwnerOfFoo
|
148
64
|
def has_role?(role, obj)
|
@@ -152,77 +68,68 @@ describe ACLIvars, :type => :controller do
|
|
152
68
|
|
153
69
|
class Bartender
|
154
70
|
def has_role?(role, obj)
|
155
|
-
role == 'bartender' && obj == VenerableBar
|
71
|
+
role == 'bartender' && obj == ACLIvars::VenerableBar
|
156
72
|
end
|
157
73
|
end
|
158
74
|
|
159
75
|
it "should allow owner of foo to destroy" do
|
160
76
|
delete :destroy, :user => OwnerOfFoo.new
|
77
|
+
response.body.should == 'OK'
|
161
78
|
end
|
162
79
|
|
163
80
|
it "should allow bartender to destroy" do
|
164
81
|
delete :destroy, :user => Bartender.new
|
82
|
+
response.body.should == 'OK'
|
165
83
|
end
|
166
84
|
end
|
167
85
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
def has_role?(role, subj)
|
172
|
-
role == "the_only_one"
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
class ACLSubjectMethod < ActionController::Base
|
177
|
-
access_control :subject_method => :the_only_user do
|
178
|
-
allow :the_only_one
|
179
|
-
end
|
180
|
-
|
181
|
-
def index; end
|
182
|
-
|
183
|
-
private
|
86
|
+
describe ACLSubjectMethod, :type => :controller do
|
87
|
+
class TheOnlyUser
|
88
|
+
include Singleton
|
184
89
|
|
185
|
-
|
186
|
-
|
90
|
+
def has_role?(role, subj)
|
91
|
+
role == "the_only_one"
|
92
|
+
end
|
187
93
|
end
|
188
|
-
end
|
189
94
|
|
190
|
-
describe ACLSubjectMethod, :type => :controller do
|
191
95
|
it "should allow the only user to index" do
|
192
96
|
get :index, :user => TheOnlyUser.instance
|
97
|
+
response.body.should == 'OK'
|
193
98
|
end
|
194
99
|
|
195
100
|
it "should deny anonymous to index" do
|
196
|
-
|
197
|
-
|
198
|
-
end.should raise_error(Acl9::AccessDenied)
|
101
|
+
get :index
|
102
|
+
response.body.should == 'AccessDenied'
|
199
103
|
end
|
200
104
|
end
|
201
105
|
|
202
|
-
class
|
203
|
-
|
204
|
-
|
106
|
+
class FooOwner
|
107
|
+
def has_role?(role_name, obj)
|
108
|
+
role_name == 'owner' && obj == MyDearFoo.instance
|
205
109
|
end
|
110
|
+
end
|
206
111
|
|
207
|
-
|
208
|
-
|
209
|
-
|
112
|
+
describe ACLObjectsHash, :type => :controller do
|
113
|
+
it "should consider objects hash and prefer it to @ivar" do
|
114
|
+
get :allow, :user => FooOwner.new
|
115
|
+
response.body.should == 'OK'
|
210
116
|
end
|
211
117
|
|
212
|
-
|
213
|
-
|
118
|
+
it "should return AccessDenied when not logged in" do
|
119
|
+
get :allow
|
120
|
+
response.body.should == 'AccessDenied'
|
214
121
|
end
|
215
122
|
end
|
216
123
|
|
217
|
-
describe
|
218
|
-
|
219
|
-
def has_role?(role_name, obj)
|
220
|
-
role_name == 'owner' && obj == MyDearFoo.instance
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
it "should consider objects hash and prefer it to @ivar" do
|
124
|
+
describe ACLHelperMethod, :type => :controller do
|
125
|
+
it "should return OK checking helper method" do
|
225
126
|
get :allow, :user => FooOwner.new
|
127
|
+
response.body.should == 'OK'
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should return AccessDenied when not logged in" do
|
131
|
+
get :allow
|
132
|
+
response.body.should == 'AccessDenied'
|
226
133
|
end
|
227
134
|
end
|
228
135
|
|
@@ -235,7 +142,7 @@ describe "Argument checking" do
|
|
235
142
|
|
236
143
|
it "should raise ArgumentError without a block" do
|
237
144
|
arg_err do
|
238
|
-
class FailureController <
|
145
|
+
class FailureController < ApplicationController
|
239
146
|
access_control
|
240
147
|
end
|
241
148
|
end
|
@@ -243,7 +150,7 @@ describe "Argument checking" do
|
|
243
150
|
|
244
151
|
it "should raise ArgumentError with 1st argument which is not a symbol" do
|
245
152
|
arg_err do
|
246
|
-
class FailureController <
|
153
|
+
class FailureController < ApplicationController
|
247
154
|
access_control 123 do end
|
248
155
|
end
|
249
156
|
end
|
@@ -251,9 +158,25 @@ describe "Argument checking" do
|
|
251
158
|
|
252
159
|
it "should raise ArgumentError with more than 1 positional argument" do
|
253
160
|
arg_err do
|
254
|
-
class FailureController <
|
161
|
+
class FailureController < ApplicationController
|
255
162
|
access_control :foo, :bar do end
|
256
163
|
end
|
257
164
|
end
|
258
165
|
end
|
166
|
+
|
167
|
+
it "should raise ArgumentError with :helper => true and no method name" do
|
168
|
+
arg_err do
|
169
|
+
class FailureController < ApplicationController
|
170
|
+
access_control :helper => true do end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should raise ArgumentError with :helper => :method and a method name" do
|
176
|
+
arg_err do
|
177
|
+
class FailureController < ApplicationController
|
178
|
+
access_control :meth, :helper => :another_meth do end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
259
182
|
end
|
data/spec/controllers.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
class ApplicationController
|
2
|
+
rescue_from Acl9::AccessDenied do |e|
|
3
|
+
render :text => 'AccessDenied'
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class EmptyController < ApplicationController
|
8
|
+
attr_accessor :current_user
|
9
|
+
before_filter :set_current_user
|
10
|
+
|
11
|
+
[:index, :show, :new, :edit, :update, :delete, :destroy].each do |act|
|
12
|
+
define_method(act) { render :text => 'OK' }
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def set_current_user
|
18
|
+
if params[:user]
|
19
|
+
self.current_user = params[:user]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# all these controllers behave the same way
|
25
|
+
|
26
|
+
class ACLBlock < EmptyController
|
27
|
+
access_control :debug => true do
|
28
|
+
allow all, :to => [:index, :show]
|
29
|
+
allow :admin
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class ACLMethod < EmptyController
|
34
|
+
access_control :as_method => :acl do
|
35
|
+
allow all, :to => [:index, :show]
|
36
|
+
allow :admin, :except => [:index, :show]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class ACLMethod2 < EmptyController
|
41
|
+
access_control :acl do
|
42
|
+
allow all, :to => [:index, :show]
|
43
|
+
allow :admin, :except => [:index, :show]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class ACLArguments < EmptyController
|
48
|
+
access_control :except => [:index, :show] do
|
49
|
+
allow :admin
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class ACLBooleanMethod < EmptyController
|
54
|
+
access_control :acl, :filter => false do
|
55
|
+
allow all, :to => [:index, :show]
|
56
|
+
allow :admin
|
57
|
+
end
|
58
|
+
|
59
|
+
before_filter :check_acl
|
60
|
+
|
61
|
+
def check_acl
|
62
|
+
if self.acl
|
63
|
+
true
|
64
|
+
else
|
65
|
+
raise Acl9::AccessDenied
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
###########################################
|
71
|
+
class MyDearFoo
|
72
|
+
include Singleton
|
73
|
+
end
|
74
|
+
|
75
|
+
class ACLIvars < EmptyController
|
76
|
+
class VenerableBar; end
|
77
|
+
|
78
|
+
before_filter :set_ivars
|
79
|
+
|
80
|
+
access_control do
|
81
|
+
action :destroy do
|
82
|
+
allow :owner, :of => :foo
|
83
|
+
allow :bartender, :at => VenerableBar
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def set_ivars
|
90
|
+
@foo = MyDearFoo.instance
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class ACLSubjectMethod < ApplicationController
|
95
|
+
access_control :subject_method => :the_only_user do
|
96
|
+
allow :the_only_one
|
97
|
+
end
|
98
|
+
|
99
|
+
def index
|
100
|
+
render :text => 'OK'
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def the_only_user
|
106
|
+
params[:user]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class ACLObjectsHash < ApplicationController
|
111
|
+
access_control :allowed?, :filter => false do
|
112
|
+
allow :owner, :of => :foo
|
113
|
+
end
|
114
|
+
|
115
|
+
def allow
|
116
|
+
@foo = nil
|
117
|
+
render :text => (allowed?(:foo => MyDearFoo.instance) ? 'OK' : 'AccessDenied')
|
118
|
+
end
|
119
|
+
|
120
|
+
def current_user
|
121
|
+
params[:user]
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
class ACLHelperMethod < ApplicationController
|
126
|
+
access_control :helper => :foo? do
|
127
|
+
allow :owner, :of => :foo
|
128
|
+
end
|
129
|
+
|
130
|
+
def allow
|
131
|
+
@foo = MyDearFoo.instance
|
132
|
+
|
133
|
+
render :inline => "<%= foo? ? 'OK' : 'AccessDenied' %>"
|
134
|
+
end
|
135
|
+
|
136
|
+
def current_user
|
137
|
+
params[:user]
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'acl9')
|
3
|
+
|
4
|
+
module SomeHelper
|
5
|
+
include Acl9Helpers
|
6
|
+
|
7
|
+
access_control :the_question do
|
8
|
+
allow :hamlet, :to => :be
|
9
|
+
allow :hamlet, :except => :be
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe SomeHelper do
|
14
|
+
module Hamlet
|
15
|
+
def current_user
|
16
|
+
user = Object.new
|
17
|
+
|
18
|
+
class <<user
|
19
|
+
def has_role?(role, obj=nil)
|
20
|
+
role == 'hamlet'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
user
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module NotLoggedIn
|
29
|
+
def current_user; nil end
|
30
|
+
end
|
31
|
+
|
32
|
+
module Noone
|
33
|
+
def current_user
|
34
|
+
user = Object.new
|
35
|
+
|
36
|
+
class <<user
|
37
|
+
def has_role?(*_); false end
|
38
|
+
end
|
39
|
+
|
40
|
+
user
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Base
|
45
|
+
include SomeHelper
|
46
|
+
|
47
|
+
attr_accessor :action_name
|
48
|
+
def controller
|
49
|
+
self
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Klass1 < Base
|
54
|
+
include Hamlet
|
55
|
+
end
|
56
|
+
|
57
|
+
class Klass2 < Base
|
58
|
+
include NotLoggedIn
|
59
|
+
end
|
60
|
+
|
61
|
+
class Klass3 < Base
|
62
|
+
include Noone
|
63
|
+
end
|
64
|
+
|
65
|
+
it "has :the_question method" do
|
66
|
+
Base.new.should respond_to(:the_question)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "role :hamlet is allowed to be" do
|
70
|
+
k = Klass1.new
|
71
|
+
k.action_name = 'be'
|
72
|
+
k.the_question.should be_true
|
73
|
+
end
|
74
|
+
|
75
|
+
it "role :hamlet is allowed to not_be" do
|
76
|
+
k = Klass1.new
|
77
|
+
k.action_name = 'not_be'
|
78
|
+
k.the_question.should be_true
|
79
|
+
end
|
80
|
+
|
81
|
+
it "not logged in is not allowed to be" do
|
82
|
+
k = Klass2.new
|
83
|
+
k.action_name = 'be'
|
84
|
+
k.the_question.should == false
|
85
|
+
end
|
86
|
+
|
87
|
+
it "noone is not allowed to be" do
|
88
|
+
k = Klass3.new
|
89
|
+
k.action_name = 'be'
|
90
|
+
k.the_question.should == false
|
91
|
+
end
|
92
|
+
end
|
data/spec/roles_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
require 'activesupport'
|
2
3
|
require 'spec'
|
3
4
|
require 'activerecord'
|
4
5
|
require 'action_controller'
|
@@ -8,15 +9,22 @@ require 'action_controller/integration'
|
|
8
9
|
|
9
10
|
require 'active_record/fixtures'
|
10
11
|
|
11
|
-
class ApplicationController < ActionController::Base
|
12
|
-
end
|
13
|
-
|
14
12
|
require 'rails/version'
|
15
13
|
|
16
14
|
require 'spec/rails/matchers'
|
17
15
|
require 'spec/rails/mocks'
|
16
|
+
|
17
|
+
class ApplicationController < ActionController::Base
|
18
|
+
end
|
19
|
+
|
18
20
|
require 'spec/rails/example'
|
19
|
-
|
21
|
+
|
22
|
+
begin
|
23
|
+
require 'spec/rails/extensions'
|
24
|
+
rescue MissingSourceFile
|
25
|
+
# it tries to load application.rb
|
26
|
+
end
|
27
|
+
|
20
28
|
#require 'spec/rails/interop/testcase'
|
21
29
|
|
22
30
|
this_dir = File.dirname(__FILE__)
|
@@ -32,3 +40,9 @@ load(File.join(this_dir, "db", "schema.rb"))
|
|
32
40
|
ActionController::Routing::Routes.draw do |map|
|
33
41
|
map.connect ":controller/:action/:id"
|
34
42
|
end
|
43
|
+
|
44
|
+
module Rails
|
45
|
+
mattr_accessor :logger
|
46
|
+
end
|
47
|
+
|
48
|
+
Rails.logger = ActiveRecord::Base.logger
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: be9-acl9
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oleg Dashevskii
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-02-04 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
requirements:
|
20
20
|
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 1.1.
|
22
|
+
version: 1.1.12
|
23
23
|
version:
|
24
24
|
- !ruby/object:Gem::Dependency
|
25
25
|
name: rspec-rails
|
@@ -28,7 +28,7 @@ dependencies:
|
|
28
28
|
requirements:
|
29
29
|
- - ">="
|
30
30
|
- !ruby/object:Gem::Version
|
31
|
-
version: 1.1.
|
31
|
+
version: 1.1.12
|
32
32
|
version:
|
33
33
|
description: Yet another role-based authorization system for Rails with a nice DSL for access control lists.
|
34
34
|
email: olegdashevskii@gmail.com
|
@@ -37,40 +37,46 @@ executables: []
|
|
37
37
|
extensions: []
|
38
38
|
|
39
39
|
extra_rdoc_files:
|
40
|
-
- lib/acl9/
|
41
|
-
- lib/acl9/
|
40
|
+
- lib/acl9/helpers.rb
|
41
|
+
- lib/acl9/config.rb
|
42
42
|
- lib/acl9/model_extensions/subject.rb
|
43
43
|
- lib/acl9/model_extensions/object.rb
|
44
|
+
- lib/acl9/controller_extensions.rb
|
44
45
|
- lib/acl9/controller_extensions/generators.rb
|
45
46
|
- lib/acl9/controller_extensions/dsl_base.rb
|
46
|
-
- lib/acl9/
|
47
|
-
- lib/acl9/
|
47
|
+
- lib/acl9/version.rb
|
48
|
+
- lib/acl9/model_extensions.rb
|
48
49
|
- lib/acl9.rb
|
50
|
+
- TODO
|
49
51
|
- README.textile
|
50
52
|
- CHANGELOG.textile
|
51
53
|
files:
|
52
|
-
-
|
53
|
-
-
|
54
|
-
- lib/acl9/model_extensions.rb
|
55
|
-
- lib/acl9/version.rb
|
54
|
+
- lib/acl9/helpers.rb
|
55
|
+
- lib/acl9/config.rb
|
56
56
|
- lib/acl9/model_extensions/subject.rb
|
57
57
|
- lib/acl9/model_extensions/object.rb
|
58
|
+
- lib/acl9/controller_extensions.rb
|
58
59
|
- lib/acl9/controller_extensions/generators.rb
|
59
60
|
- lib/acl9/controller_extensions/dsl_base.rb
|
60
|
-
- lib/acl9/
|
61
|
-
- lib/acl9/
|
61
|
+
- lib/acl9/version.rb
|
62
|
+
- lib/acl9/model_extensions.rb
|
62
63
|
- lib/acl9.rb
|
63
|
-
-
|
64
|
-
- acl9.gemspec
|
65
|
-
- CHANGELOG.textile
|
66
|
-
- MIT-LICENSE
|
67
|
-
- Rakefile
|
64
|
+
- TODO
|
68
65
|
- spec/db/schema.rb
|
69
|
-
- spec/
|
66
|
+
- spec/helpers_spec.rb
|
70
67
|
- spec/spec_helper.rb
|
68
|
+
- spec/models.rb
|
69
|
+
- spec/dsl_base_spec.rb
|
71
70
|
- spec/access_control_spec.rb
|
71
|
+
- spec/controllers.rb
|
72
72
|
- spec/roles_spec.rb
|
73
|
-
-
|
73
|
+
- acl9.gemspec
|
74
|
+
- Manifest
|
75
|
+
- MIT-LICENSE
|
76
|
+
- Rakefile
|
77
|
+
- README.textile
|
78
|
+
- init.rb
|
79
|
+
- CHANGELOG.textile
|
74
80
|
has_rdoc: true
|
75
81
|
homepage: http://github.com/be9/acl9
|
76
82
|
post_install_message:
|