be9-acl9 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|