role-authz 0.0.2 → 1.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.
- data/Rakefile +2 -2
- data/lib/role-authz/authorization/authorization.rb +6 -2
- data/lib/role-authz/authorization/controller_helper.rb +3 -8
- data/lib/role-authz/authorization/controller_mixin.rb +2 -2
- data/lib/role-authz/authorization/exceptions.rb +5 -0
- data/lib/role-authz/authorization/object_mixin.rb +0 -3
- data/lib/role-authz/authorization/operator_mixin.rb +8 -5
- data/spec/authorization_spec.rb +50 -0
- data/spec/controller_spec.rb +157 -0
- data/spec/operator_spec.rb +71 -0
- data/spec/role-authz_spec.rb +12 -5
- data/spec/spec_helper.rb +11 -1
- metadata +9 -5
data/Rakefile
CHANGED
@@ -13,7 +13,7 @@ require 'merb-core'
|
|
13
13
|
require 'merb-core/tasks/merb'
|
14
14
|
|
15
15
|
GEM_NAME = "role-authz"
|
16
|
-
GEM_VERSION = "0.0
|
16
|
+
GEM_VERSION = "1.0.0"
|
17
17
|
AUTHOR = "Jorge Villatoro"
|
18
18
|
EMAIL = "jorge@tomatocannon.com"
|
19
19
|
HOMEPAGE = "http://www.github.com/thelazyfox/role-authz"
|
@@ -78,5 +78,5 @@ begin
|
|
78
78
|
end
|
79
79
|
end
|
80
80
|
rescue LoadError
|
81
|
-
|
81
|
+
puts "rspec not installed"
|
82
82
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Authorization
|
2
2
|
@roles = {}
|
3
3
|
|
4
|
-
def self.roles_for(operator, target)
|
4
|
+
def self.roles_for(operator, target=nil)
|
5
5
|
list = []
|
6
6
|
@roles.each do |name, proc|
|
7
7
|
if proc.call(operator, target)
|
@@ -12,6 +12,10 @@ module Authorization
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def self.add_role(name, &block)
|
15
|
-
|
15
|
+
if block.parameters.count == 2
|
16
|
+
@roles[name] = block
|
17
|
+
else
|
18
|
+
raise InvalidRole
|
19
|
+
end
|
16
20
|
end
|
17
21
|
end
|
@@ -1,7 +1,4 @@
|
|
1
|
-
module Authorization
|
2
|
-
class OpenForRoleStatement < Exception; end
|
3
|
-
class NoCurrentForRoleStatement < Exception; end
|
4
|
-
|
1
|
+
module Authorization
|
5
2
|
class ControllerHelper
|
6
3
|
def initialize
|
7
4
|
@working_roles = []
|
@@ -10,7 +7,7 @@ module Authorization
|
|
10
7
|
|
11
8
|
def for_roles(*the_roles)
|
12
9
|
raise OpenForRoleStatement unless @working_roles.empty?
|
13
|
-
@working_roles
|
10
|
+
@working_roles = the_roles.clone
|
14
11
|
self
|
15
12
|
end
|
16
13
|
alias_method :for_role, :for_roles
|
@@ -18,9 +15,7 @@ module Authorization
|
|
18
15
|
def allow(*the_actions)
|
19
16
|
raise NoCurrentForRoleStatement unless !@working_roles.empty?
|
20
17
|
@working_roles.each do |current_role|
|
21
|
-
|
22
|
-
@permissions_list[current_role] = []
|
23
|
-
end
|
18
|
+
@permissions_list[current_role] ||= []
|
24
19
|
@permissions_list[current_role] += the_actions
|
25
20
|
end
|
26
21
|
@working_roles.clear
|
@@ -8,6 +8,7 @@ class Merb::Controller
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def self.authorize(klass, &block)
|
11
|
+
klass.class_inheritable_accessor :_authorization_proxy
|
11
12
|
klass._authorization_proxy = self
|
12
13
|
self._authorization_target = klass
|
13
14
|
self._authorization ||= Authorization::ControllerHelper.new
|
@@ -25,8 +26,7 @@ class Merb::Controller
|
|
25
26
|
end
|
26
27
|
|
27
28
|
def ensure_authorized
|
28
|
-
operator =
|
29
|
-
operator = session.user if session.authenticated?
|
29
|
+
operator = (session.user if session.authenticated?)
|
30
30
|
roles = Authorization.roles_for(operator, authorization_target)
|
31
31
|
roles.each do |role|
|
32
32
|
actions = self.class._authorization.actions_for(role)
|
@@ -1,18 +1,21 @@
|
|
1
1
|
module Authorization::OperatorMixin
|
2
|
-
|
3
2
|
def authorized?(args = {})
|
4
3
|
@roles ||= Authorization.roles_for(self, args[:target])
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
|
5
|
+
if args.key?(:role)
|
6
|
+
return @roles.include?(args[:role])
|
7
|
+
elsif args.key?(:target) && args.key?(:action)
|
8
8
|
target = args[:target]._authorization_proxy unless args[:target]._authorization_proxy.nil?
|
9
9
|
|
10
10
|
@roles.each do |role|
|
11
11
|
actions = target._authorization.actions_for(role)
|
12
12
|
return true if actions.include?(args[:action]) || actions.include?(:all)
|
13
13
|
end
|
14
|
-
false
|
15
14
|
end
|
15
|
+
false
|
16
16
|
end
|
17
17
|
|
18
|
+
def roles_for(target)
|
19
|
+
Authorization.roles_for(self, target)
|
20
|
+
end
|
18
21
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "Authorization" do
|
4
|
+
before :each do
|
5
|
+
Authorization.clear!
|
6
|
+
end
|
7
|
+
|
8
|
+
describe ".add_role(name, &block)" do
|
9
|
+
it "accepts valid roles" do
|
10
|
+
Authorization.should respond_to(:add_role)
|
11
|
+
lambda do
|
12
|
+
Authorization.add_role(:foo) do |operator, target|
|
13
|
+
if operator == "jorge"
|
14
|
+
true
|
15
|
+
else
|
16
|
+
false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end.should_not raise_error
|
20
|
+
end
|
21
|
+
|
22
|
+
it "raises InvalidRole exception when the role block is invalid" do
|
23
|
+
lambda do
|
24
|
+
Authorization.add_role(:foo) {|operator| true}
|
25
|
+
end.should raise_error
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe ".roles_for(operator, target)" do
|
30
|
+
it "returns correct roles for operator, target pairs" do
|
31
|
+
Authorization.add_role(:foo) do |operator, target|
|
32
|
+
if operator == "foo"
|
33
|
+
true
|
34
|
+
else
|
35
|
+
false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
Authorization.add_role(:bar) do |operator, target|
|
39
|
+
if operator == "bar"
|
40
|
+
true
|
41
|
+
else
|
42
|
+
false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
Authorization.roles_for("foo",nil).should == [:foo]
|
47
|
+
Authorization.roles_for("bar",nil).should == [:bar]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "ControllerMixin" do
|
4
|
+
before :each do
|
5
|
+
Authorization.clear!
|
6
|
+
@controller = Class.new Merb::Controller
|
7
|
+
end
|
8
|
+
|
9
|
+
describe ".role(name, &block)" do
|
10
|
+
it "defines roles the the specified name and block" do
|
11
|
+
lambda do
|
12
|
+
@controller.role(:admin) { |operator,target| operator=="admin" }
|
13
|
+
@controller.role(:user) { |operator,target| operator=="user" }
|
14
|
+
@controller.role(:owner) { |operator,target| operator==target }
|
15
|
+
end.should_not raise_error
|
16
|
+
|
17
|
+
Authorization.roles_for("user").should == [:user]
|
18
|
+
Authorization.roles_for("admin").should == [:admin]
|
19
|
+
Authorization.roles_for("owner","owner").should == [:owner]
|
20
|
+
Authorization.roles_for("user","user").should include(:user, :owner)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "raises an exception when the block does not accept 2 arguments" do
|
24
|
+
lambda {@controller.role(:foo) {|operator|}}.should raise_error
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe ".authorize(target, &block)" do
|
29
|
+
it "can specify self as the target" do
|
30
|
+
@controller.should respond_to(:authorize)
|
31
|
+
lambda {@controller.authorize(@controller) {}}.should_not raise_error
|
32
|
+
end
|
33
|
+
|
34
|
+
it "can sepcify a resource as a target" do
|
35
|
+
@resource = Class.new
|
36
|
+
|
37
|
+
@controller.should respond_to(:authorize)
|
38
|
+
lambda {@controller.authorize(@resource) {}}.should_not raise_error
|
39
|
+
@resource.should respond_to(:_authorization_proxy)
|
40
|
+
@resource._authorization_proxy.should == @controller
|
41
|
+
end
|
42
|
+
|
43
|
+
it "enforces #ensure_authorized as a before filter" do
|
44
|
+
lambda {@controller.authorize(@controller) {}}.should_not raise_error
|
45
|
+
@controller._before_filters.flatten.should include(:ensure_authorized)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#ensure_authorized" do
|
50
|
+
it "raises the Unauthenticated exception when unauthenticated" do
|
51
|
+
session = mock("session")
|
52
|
+
session.stub!(:authenticated?).and_return(false)
|
53
|
+
|
54
|
+
controller = @controller.new(nil)
|
55
|
+
controller.stub!(:session).and_return(session)
|
56
|
+
controller.stub!(:params).and_return({:action => :foo})
|
57
|
+
controller.should respond_to(:ensure_authorized)
|
58
|
+
lambda do
|
59
|
+
controller.ensure_authorized
|
60
|
+
end.should raise_exception(Merb::Controller::Unauthenticated)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "raises the Unauthorized exception when no permissions match" do
|
64
|
+
session = mock("session");
|
65
|
+
session.stub!(:authenticated?).and_return(true)
|
66
|
+
session.stub!(:user).and_return("user")
|
67
|
+
|
68
|
+
controller = @controller.new(nil)
|
69
|
+
controller.stub!(:session).and_return(session)
|
70
|
+
controller.stub!(:params).and_return({:action => :foo})
|
71
|
+
controller.should respond_to(:ensure_authorized)
|
72
|
+
lambda do
|
73
|
+
controller.ensure_authorized
|
74
|
+
end.should raise_exception(::Merb::Controller::Unauthorized)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "raises no exceptions when a permission matches" do
|
78
|
+
session = mock("session");
|
79
|
+
session.stub!(:authenticated?).and_return(true)
|
80
|
+
session.stub!(:user).and_return("user")
|
81
|
+
|
82
|
+
@controller.role(:user) {|operator,target|operator=="user"}
|
83
|
+
@controller.authorize(@controller) do
|
84
|
+
for_role(:user).allow(:foo)
|
85
|
+
end
|
86
|
+
|
87
|
+
controller = @controller.new(nil)
|
88
|
+
controller.stub!(:session).and_return(session)
|
89
|
+
controller.stub!(:params).and_return({:action => :foo})
|
90
|
+
|
91
|
+
controller.should respond_to(:ensure_authorized)
|
92
|
+
lambda {controller.ensure_authorized}.should_not raise_exception
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "ControllerHelper" do
|
98
|
+
before :each do
|
99
|
+
@authorization = Authorization::ControllerHelper.new
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "#for_roles(*the_roles)" do
|
103
|
+
it "selects roles for which to define permissions" do
|
104
|
+
@authorization.instance_eval do
|
105
|
+
for_roles(:user).allow(:bar)
|
106
|
+
end
|
107
|
+
@authorization.actions_for(:user).should include(:bar)
|
108
|
+
@authorization.actions_for(:foo).should_not include(:bar)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "raises an exception when called directly after #for_roles" do
|
112
|
+
lambda do
|
113
|
+
@authorization.instance_eval do
|
114
|
+
for_roles(:user)
|
115
|
+
for_roles(:admin)
|
116
|
+
end
|
117
|
+
end.should raise_error
|
118
|
+
end
|
119
|
+
|
120
|
+
it "has the alias #for_role" do
|
121
|
+
@authorization.should respond_to(:for_role)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "#allow(*the_actions)" do
|
126
|
+
it "sets permissions to be set for the specified roles" do
|
127
|
+
@authorization.instance_eval do
|
128
|
+
for_roles(:user).allow(:foo)
|
129
|
+
for_roles(:admin).allow(:bar)
|
130
|
+
end
|
131
|
+
|
132
|
+
@authorization.actions_for(:user).should include(:foo)
|
133
|
+
@authorization.actions_for(:user).should_not include(:bar)
|
134
|
+
@authorization.actions_for(:admin).should include(:bar)
|
135
|
+
@authorization.actions_for(:admin).should_not include(:foo)
|
136
|
+
end
|
137
|
+
|
138
|
+
it "raises an exception when not called directly after #for_roles" do
|
139
|
+
lambda do
|
140
|
+
@authorization.instance_eval do
|
141
|
+
allow(:foo)
|
142
|
+
end
|
143
|
+
end.should raise_error
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe "#actions_for(role)" do
|
148
|
+
it "returns the previously set actions for the specified role" do
|
149
|
+
@authorization.instance_eval do
|
150
|
+
for_role(:user).allow(:foo)
|
151
|
+
end
|
152
|
+
|
153
|
+
@authorization.should respond_to(:actions_for)
|
154
|
+
@authorization.actions_for(:user).should include(:foo)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe "OperatorMixin" do
|
4
|
+
describe "#authorized?(args)" do
|
5
|
+
before do
|
6
|
+
Authorization.clear!
|
7
|
+
@user = Class.new
|
8
|
+
@user.instance_eval {authorizable!}
|
9
|
+
@admin = @user.clone
|
10
|
+
@controller = Class.new Merb::Controller
|
11
|
+
@controller.role(:admin) {|operator,target|operator.kind_of?(@admin)}
|
12
|
+
@controller.role(:user) {|operator,target|operator.kind_of?(@user)}
|
13
|
+
@controller.role(:owner) {|operator,target|target.respond_to?(:owner)&&target.owner==operator}
|
14
|
+
@controller.authorize(@controller) do
|
15
|
+
for_role(:admin).allow(:foo)
|
16
|
+
for_role(:user).allow(:bar)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returns true when the requested role matches" do
|
22
|
+
@admin.new.authorized?(:role=>:admin).should be_true
|
23
|
+
@user.new.authorized?(:role=>:user).should be_true
|
24
|
+
end
|
25
|
+
|
26
|
+
it "returns false when the requested role does not match" do
|
27
|
+
@admin.new.authorized?(:role=>:user).should be_false
|
28
|
+
@user.new.authorized?(:role=>:admin).should be_false
|
29
|
+
end
|
30
|
+
|
31
|
+
it "returns false when only an action is specified" do
|
32
|
+
@admin.new.authorized?(:action=>:bar).should be_false
|
33
|
+
@admin.new.authorized?(:action=>:foo).should be_false
|
34
|
+
end
|
35
|
+
|
36
|
+
it "returns true when the requested target+action matches" do
|
37
|
+
user = @user.new
|
38
|
+
resource = Class.new
|
39
|
+
resource.stub!(:owner).and_return(user)
|
40
|
+
@controller.clone.authorize(resource) {for_role(:owner).allow(:foo)}
|
41
|
+
|
42
|
+
user.authorized?(:target=>resource,:action=>:foo).should be_true
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns false when the requested target+action does not match" do
|
46
|
+
user = @user.new
|
47
|
+
resource = Class.new
|
48
|
+
resource.stub!(:owner).and_return(user.clone)
|
49
|
+
@controller.clone.authorize(resource) {for_role(:owner).allow(:foo)}
|
50
|
+
|
51
|
+
user.authorized?(:target=>resource,:action=>:foo).should be_false
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#roles_for" do
|
57
|
+
it "returns the roles for self on the specified target" do
|
58
|
+
@user = Class.new
|
59
|
+
@user.instance_eval {authorizable!}
|
60
|
+
user = @user.new
|
61
|
+
|
62
|
+
resource = Class.new
|
63
|
+
resource.stub!(:owner).and_return(user)
|
64
|
+
Authorization.add_role(:user){|operator,target|operator.kind_of?(@user)}
|
65
|
+
Authorization.add_role(:owner){|operator,target|target.respond_to?(:owner)&&target.owner==operator}
|
66
|
+
|
67
|
+
user.roles_for(resource).should include(:owner)
|
68
|
+
user.clone.roles_for(resource).should_not include(:owner)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/spec/role-authz_spec.rb
CHANGED
@@ -1,7 +1,14 @@
|
|
1
|
-
require File.
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
2
|
|
3
|
-
describe "
|
4
|
-
|
5
|
-
|
3
|
+
describe "ObjectMixin" do
|
4
|
+
describe ".authorizable!" do
|
5
|
+
it "includes OperatorMixin" do
|
6
|
+
class Foo
|
7
|
+
authorizable!
|
8
|
+
end
|
9
|
+
|
10
|
+
Foo.ancestors.should include(::Authorization::OperatorMixin)
|
11
|
+
end
|
6
12
|
end
|
7
|
-
end
|
13
|
+
end
|
14
|
+
|
data/spec/spec_helper.rb
CHANGED
@@ -1 +1,11 @@
|
|
1
|
-
|
1
|
+
# Loads up Merb and the Plugin
|
2
|
+
require 'merb-core'
|
3
|
+
require 'spec'
|
4
|
+
require File.expand_path("../../lib/role-authz", __FILE__)
|
5
|
+
|
6
|
+
# Simple helper to clear out the auth role list
|
7
|
+
module Authorization
|
8
|
+
def self.clear!
|
9
|
+
@roles.clear
|
10
|
+
end
|
11
|
+
end
|
metadata
CHANGED
@@ -3,10 +3,10 @@ name: role-authz
|
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
|
+
- 1
|
6
7
|
- 0
|
7
8
|
- 0
|
8
|
-
|
9
|
-
version: 0.0.2
|
9
|
+
version: 1.0.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Jorge Villatoro
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date:
|
17
|
+
date: 2011-02-11 00:00:00 -06:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -50,9 +50,13 @@ files:
|
|
50
50
|
- lib/role-authz/authorization/authorization.rb
|
51
51
|
- lib/role-authz/authorization/controller_helper.rb
|
52
52
|
- lib/role-authz/authorization/controller_mixin.rb
|
53
|
+
- lib/role-authz/authorization/exceptions.rb
|
53
54
|
- lib/role-authz/authorization/object_mixin.rb
|
54
55
|
- lib/role-authz/authorization/operator_mixin.rb
|
55
56
|
- lib/role-authz.rb
|
57
|
+
- spec/authorization_spec.rb
|
58
|
+
- spec/controller_spec.rb
|
59
|
+
- spec/operator_spec.rb
|
56
60
|
- spec/role-authz_spec.rb
|
57
61
|
- spec/spec_helper.rb
|
58
62
|
has_rdoc: true
|
@@ -69,7 +73,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
69
73
|
requirements:
|
70
74
|
- - ">="
|
71
75
|
- !ruby/object:Gem::Version
|
72
|
-
hash:
|
76
|
+
hash: 1726181753105293631
|
73
77
|
segments:
|
74
78
|
- 0
|
75
79
|
version: "0"
|
@@ -78,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
82
|
requirements:
|
79
83
|
- - ">="
|
80
84
|
- !ruby/object:Gem::Version
|
81
|
-
hash:
|
85
|
+
hash: 1726181753105293631
|
82
86
|
segments:
|
83
87
|
- 0
|
84
88
|
version: "0"
|