permissive 0.2.2.alpha → 0.2.4.alpha
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/VERSION +1 -1
- data/lib/permissive/has_permissions.rb +16 -18
- data/lib/permissive/permission.rb +0 -1
- data/lib/permissive/permission_definition.rb +63 -7
- data/spec/checking_permissions_spec.rb +71 -0
- data/spec/defining_permissions_spec.rb +37 -0
- data/spec/has_permissions_spec.rb +12 -328
- data/spec/metaprogramming_spec.rb +75 -0
- data/spec/roles_spec.rb +64 -0
- data/spec/scoping_permissions_spec.rb +117 -0
- data/spec/spec_helper.rb +7 -2
- data/spec/spec_models.rb +13 -0
- metadata +9 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.4.alpha
|
@@ -22,6 +22,7 @@ module Permissive
|
|
22
22
|
def can!(*args)
|
23
23
|
options = args.extract_options!
|
24
24
|
options.assert_valid_keys(:on, :reset)
|
25
|
+
options.delete(:on) if options[:on] == :global
|
25
26
|
permission_matcher = case options[:on]
|
26
27
|
when ActiveRecord::Base
|
27
28
|
permission = proxy_owner.permissions.find_or_initialize_by_scoped_object_id_and_scoped_object_type(options[:on].id, options[:on].class.name)
|
@@ -41,8 +42,14 @@ module Permissive
|
|
41
42
|
permission.mask = permission.mask | bit
|
42
43
|
end
|
43
44
|
end
|
44
|
-
|
45
|
+
if proxy_owner.new_record?
|
46
|
+
permission.permitted_object = proxy_owner
|
47
|
+
proxy_owner.permissions.push(permission)
|
48
|
+
else
|
49
|
+
permission.save!
|
50
|
+
end
|
45
51
|
permission
|
52
|
+
# raise 'set'
|
46
53
|
end
|
47
54
|
|
48
55
|
def can?(*args)
|
@@ -54,8 +61,12 @@ module Permissive
|
|
54
61
|
|
55
62
|
def revoke(*args)
|
56
63
|
options = args.extract_options!
|
57
|
-
if args.
|
58
|
-
|
64
|
+
if args.first == :all
|
65
|
+
if options[:on]
|
66
|
+
on(options[:on]).destroy_all
|
67
|
+
else
|
68
|
+
reload.destroy_all
|
69
|
+
end
|
59
70
|
else
|
60
71
|
bits = bits_for(options[:on], args)
|
61
72
|
on(options[:on]).each do |permission|
|
@@ -71,7 +82,7 @@ module Permissive
|
|
71
82
|
|
72
83
|
def bits_for(scope, permissions)
|
73
84
|
on = PermissionDefinition.normalize_scope(proxy_owner.class, scope)
|
74
|
-
permissions.map do |permission|
|
85
|
+
permissions.flatten.map do |permission|
|
75
86
|
proxy_owner.class.permissions[on].try(:permissions).try(:[], permission.to_s.underscore.gsub('/', '_').to_sym) || raise(Permissive::InvalidPermissionError.new("#{proxy_owner.class.name} does not have a#{'n' if permission.to_s[0, 1].downcase =~ /[aeiou]/} #{permission} permission#{" on #{on}" if on}"))
|
76
87
|
end
|
77
88
|
end
|
@@ -81,20 +92,7 @@ module Permissive
|
|
81
92
|
delegate :can!, :can?, :revoke, :to => :permissions
|
82
93
|
|
83
94
|
permission_definition = Permissive::PermissionDefinition.define(self, options, &block)
|
84
|
-
|
85
|
-
permission_setter = options[:on].nil? || options[:on] == :global ? 'permissions=' : "#{options[:on].to_s.singularize}_permissions="
|
86
|
-
class_eval <<-eoc
|
87
|
-
def #{permission_setter}(values)
|
88
|
-
values ||= []
|
89
|
-
if values.all? {|value| value.is_a?(String) || value.is_a?(Symbol)}
|
90
|
-
can!(values, :reset => true, :on => #{options[:on].inspect})
|
91
|
-
else
|
92
|
-
super(values)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
eoc
|
96
|
-
|
97
|
-
|
95
|
+
permission_definition.define_methods
|
98
96
|
# Oh that's right, it'll return an object.
|
99
97
|
permission_definition
|
100
98
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# This is the core permission class that Permissive uses.
|
2
2
|
module Permissive
|
3
3
|
class Permission < ActiveRecord::Base
|
4
|
-
attr_writer :grant_template, :template
|
5
4
|
belongs_to :permitted_object, :polymorphic => true
|
6
5
|
belongs_to :scoped_object, :polymorphic => true
|
7
6
|
named_scope :granted, lambda {|permissions|
|
@@ -17,6 +17,7 @@ module Permissive
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def interpolate_scope(model, scope)
|
20
|
+
return :global if scope.to_s == 'global'
|
20
21
|
attempted_scope = scope.to_s.singularize.classify
|
21
22
|
model_module = model.name.to_s.split('::')
|
22
23
|
model_module.pop
|
@@ -29,6 +30,7 @@ module Permissive
|
|
29
30
|
end
|
30
31
|
|
31
32
|
def normalize_scope(model, scope)
|
33
|
+
return :global if scope.to_s == 'global'
|
32
34
|
scope = case scope
|
33
35
|
when Class
|
34
36
|
scope.name.tableize
|
@@ -51,6 +53,59 @@ module Permissive
|
|
51
53
|
end
|
52
54
|
end
|
53
55
|
|
56
|
+
def define_methods
|
57
|
+
permission_setter = @options[:on] == :global ? 'permissions' : "#{@options[:on].to_s.singularize}_permissions"
|
58
|
+
if model.instance_methods.include?("#{permission_setter}=")
|
59
|
+
if !model.instance_methods.include?("#{permission_setter}_with_permissive=")
|
60
|
+
model.class_eval <<-eoc
|
61
|
+
def #{permission_setter}_with_permissive=(values)
|
62
|
+
values ||= []
|
63
|
+
if values.all? {|value| value.is_a?(String) || value.is_a?(Symbol)}
|
64
|
+
can!(values, :reset => true, :on => #{@options[:on].inspect})
|
65
|
+
else
|
66
|
+
self.#{permission_setter}_without_permissive = values
|
67
|
+
end
|
68
|
+
end
|
69
|
+
# alias_method_chain "#{permission_setter}=", :permissive
|
70
|
+
eoc
|
71
|
+
end
|
72
|
+
model.alias_method_chain "#{permission_setter}=", :permissive
|
73
|
+
else
|
74
|
+
model.class_eval <<-eoc
|
75
|
+
def #{permission_setter}=(values)
|
76
|
+
values ||= []
|
77
|
+
if values.all? {|value| value.is_a?(String) || value.is_a?(Symbol)}
|
78
|
+
can!(values, :reset => true, :on => #{@options[:on].inspect})
|
79
|
+
end
|
80
|
+
end
|
81
|
+
eoc
|
82
|
+
end
|
83
|
+
|
84
|
+
if model.instance_methods.include?('role=') && !model.respond_to?(:permissive_role_defined?)
|
85
|
+
puts "role= defined but role_defined? is false"
|
86
|
+
model.class_eval do
|
87
|
+
def role_with_permissive=(role_name)
|
88
|
+
self.permissions = self.class.permissions[:global].roles[role_name.to_s.downcase.to_sym]
|
89
|
+
self.role_without_permissive = role_name.to_s.downcase
|
90
|
+
end
|
91
|
+
end
|
92
|
+
model.alias_method_chain :role=, :permissive
|
93
|
+
else
|
94
|
+
model.class_eval do
|
95
|
+
def role=(role_name)
|
96
|
+
self.permissions = self.class.permissions[:global].roles[role_name.to_s.downcase.to_sym]
|
97
|
+
end
|
98
|
+
|
99
|
+
class << self
|
100
|
+
def permissive_role_defined?
|
101
|
+
true
|
102
|
+
end
|
103
|
+
protected :permissive_role_defined?
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
54
109
|
def initialize(model, options = {})
|
55
110
|
options.assert_valid_keys(:on)
|
56
111
|
@options = options
|
@@ -62,7 +117,8 @@ module Permissive
|
|
62
117
|
end
|
63
118
|
|
64
119
|
def on(class_name, &block)
|
65
|
-
Permissive::PermissionDefinition.define(model, @options.merge(:on => class_name), &block)
|
120
|
+
permission_definition = Permissive::PermissionDefinition.define(model, @options.merge(:on => class_name), &block)
|
121
|
+
permission_definition.define_methods
|
66
122
|
end
|
67
123
|
|
68
124
|
def permission(name, value)
|
@@ -82,12 +138,12 @@ module Permissive
|
|
82
138
|
@role = name.to_s.to_sym
|
83
139
|
roles[@role] ||= []
|
84
140
|
instance_eval(&block) if block_given?
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
141
|
+
if model.instance_methods.include?('role') && !model.instance_methods.include?("is_#{name}?")
|
142
|
+
model.class_eval <<-eoc
|
143
|
+
def is_#{name}?
|
144
|
+
role == #{name.to_s.downcase.inspect}
|
145
|
+
end
|
146
|
+
eoc
|
91
147
|
end
|
92
148
|
end
|
93
149
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
load File.join File.dirname(__FILE__), 'spec_models.rb'
|
3
|
+
|
4
|
+
describe Permissive, "checking" do
|
5
|
+
before :each do
|
6
|
+
PermissiveSpecHelper.db_up
|
7
|
+
|
8
|
+
Permissive::User.has_permissions do
|
9
|
+
to :manage_games, 0
|
10
|
+
to :control_rides, 1
|
11
|
+
to :punch, 2
|
12
|
+
end
|
13
|
+
@user = Permissive::User.create
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should allow permissions checks through the `can?' method" do
|
17
|
+
@user.can?(:manage_games).should be_false
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should respond to the `can!' method" do
|
21
|
+
@user.should respond_to(:can!)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should allow permissions setting through the `can!' method" do
|
25
|
+
count = @user.permissions.count
|
26
|
+
@user.can!(:manage_games)
|
27
|
+
@user.permissions.count.should == count.next
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return correct permissions through the `can?' method" do
|
31
|
+
@user.can!(:manage_games)
|
32
|
+
@user.can?(:manage_games).should be_true
|
33
|
+
@user.can?(:control_rides).should be_false
|
34
|
+
@user.can?(:punch).should be_false
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should return correct permissions on multiple requests" do
|
38
|
+
@user.can!(:manage_games)
|
39
|
+
@user.can!(:control_rides)
|
40
|
+
@user.can?(:manage_games, :control_rides).should be_true
|
41
|
+
@user.can?(:manage_games, :punch).should be_false
|
42
|
+
@user.can?(:control_rides, :punch).should be_false
|
43
|
+
@user.can?(:manage_games, :control_rides, :punch).should be_false
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should revoke the correct permissions through the `revoke' method" do
|
47
|
+
@user.can!(:manage_games, :control_rides)
|
48
|
+
@user.can?(:manage_games).should be_true
|
49
|
+
@user.can?(:control_rides).should be_true
|
50
|
+
@user.revoke(:control_rides)
|
51
|
+
@user.can?(:control_rides).should be_false
|
52
|
+
@user.can?(:manage_games).should be_true
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should revoke the full permissions through the `revoke' method w/an :all argument" do
|
56
|
+
@user.can!(:manage_games, :control_rides)
|
57
|
+
@user.can?(:manage_games).should be_true
|
58
|
+
@user.can?(:control_rides).should be_true
|
59
|
+
@user.revoke(:all)
|
60
|
+
@user.can?(:manage_games).should be_false
|
61
|
+
@user.can?(:control_rides).should be_false
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should support a :reset option" do
|
65
|
+
@user.can!(:manage_games, :control_rides)
|
66
|
+
@user.can?(:manage_games).should be_true
|
67
|
+
@user.can!(:punch, :reset => true)
|
68
|
+
@user.can?(:manage_games).should_not be_true
|
69
|
+
@user.can?(:punch).should be_true
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
load File.join File.dirname(__FILE__), 'spec_models.rb'
|
3
|
+
|
4
|
+
describe Permissive, "defining permissions" do
|
5
|
+
before :each do
|
6
|
+
PermissiveSpecHelper.db_up
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should require Numeric permissions" do
|
10
|
+
lambda {
|
11
|
+
Permissive::User.has_permissions { to :dance_on_the_rooftops, "Dance, bitches!" }
|
12
|
+
}.should raise_error(Permissive::PermissionError)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should allow me to scope permissions inside the block" do
|
16
|
+
Permissive::Organization.has_permissions do
|
17
|
+
to :hire_employees, 0
|
18
|
+
to :fire_employees, 1
|
19
|
+
|
20
|
+
on :users do
|
21
|
+
to :hire, 0
|
22
|
+
to :fire, 1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Ew, lots of assertions here...
|
27
|
+
Permissive::Organization.permissions[:global].permissions.should have_key(:hire_employees)
|
28
|
+
Permissive::Organization.permissions[:global].permissions.should have_key(:fire_employees)
|
29
|
+
Permissive::Organization.permissions[:global].permissions.should_not have_key(:hire)
|
30
|
+
Permissive::Organization.permissions[:global].permissions.should_not have_key(:fire)
|
31
|
+
|
32
|
+
Permissive::Organization.permissions[:permissive_users].permissions.should have_key(:hire)
|
33
|
+
Permissive::Organization.permissions[:permissive_users].permissions.should have_key(:fire)
|
34
|
+
Permissive::Organization.permissions[:permissive_users].permissions.should_not have_key(:hire_employees)
|
35
|
+
Permissive::Organization.permissions[:permissive_users].permissions.should_not have_key(:fire_employees)
|
36
|
+
end
|
37
|
+
end
|
@@ -1,347 +1,31 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
load File.join File.dirname(__FILE__), 'spec_models.rb'
|
2
3
|
|
3
|
-
|
4
|
-
# and then test :scope'd permissions through both.
|
5
|
-
class Permissive::Organization < ActiveRecord::Base
|
6
|
-
set_table_name :permissive_organizations
|
7
|
-
end
|
8
|
-
|
9
|
-
class Permissive::User < ActiveRecord::Base
|
10
|
-
set_table_name :permissive_users
|
11
|
-
end
|
12
|
-
|
13
|
-
describe Permissive::Permission do
|
4
|
+
describe Permissive, "`has_permissions' default class method" do
|
14
5
|
before :each do
|
15
6
|
PermissiveSpecHelper.db_up
|
16
7
|
end
|
17
8
|
|
18
|
-
|
19
|
-
[Permissive::User, Permissive::Organization].each do |model|
|
20
|
-
before :each do
|
21
|
-
model.has_permissions do
|
22
|
-
on :organizations
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
describe model do
|
27
|
-
it "should create a permissions reflection" do
|
28
|
-
model.new.should respond_to(:permissions)
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should create a `can?' method" do
|
32
|
-
model.new.should respond_to(:can?)
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should create a `revoke' method" do
|
36
|
-
model.new.should respond_to(:revoke)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
describe "permissions definitions" do
|
43
|
-
it "should require Numeric permissions" do
|
44
|
-
lambda {
|
45
|
-
Permissive::User.has_permissions { to :dance_on_the_rooftops, "Dance, bitches!" }
|
46
|
-
}.should raise_error(Permissive::PermissionError)
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should allow me to scope permissions inside the block" do
|
50
|
-
Permissive::Organization.has_permissions do
|
51
|
-
to :hire_employees, 0
|
52
|
-
to :fire_employees, 1
|
53
|
-
|
54
|
-
on :users do
|
55
|
-
to :hire, 0
|
56
|
-
to :fire, 1
|
57
|
-
end
|
58
|
-
end
|
59
|
-
# Ew, lots of assertions here...
|
60
|
-
Permissive::Organization.permissions[:global].permissions.should have_key(:hire_employees)
|
61
|
-
Permissive::Organization.permissions[:global].permissions.should have_key(:fire_employees)
|
62
|
-
Permissive::Organization.permissions[:global].permissions.should_not have_key(:hire)
|
63
|
-
Permissive::Organization.permissions[:global].permissions.should_not have_key(:fire)
|
64
|
-
|
65
|
-
Permissive::Organization.permissions[:permissive_users].permissions.should have_key(:hire)
|
66
|
-
Permissive::Organization.permissions[:permissive_users].permissions.should have_key(:fire)
|
67
|
-
Permissive::Organization.permissions[:permissive_users].permissions.should_not have_key(:hire_employees)
|
68
|
-
Permissive::Organization.permissions[:permissive_users].permissions.should_not have_key(:fire_employees)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
describe "permissions checking" do
|
9
|
+
[Permissive::User, Permissive::Organization].each do |model|
|
73
10
|
before :each do
|
74
|
-
|
75
|
-
|
76
|
-
to :control_rides, 1
|
77
|
-
to :punch, 2
|
11
|
+
model.has_permissions do
|
12
|
+
on :organizations
|
78
13
|
end
|
79
|
-
@user = Permissive::User.create
|
80
|
-
end
|
81
|
-
|
82
|
-
it "should allow permissions checks through the `can?' method" do
|
83
|
-
@user.can?(:manage_games).should be_false
|
84
|
-
end
|
85
|
-
|
86
|
-
it "should respond to the `can!' method" do
|
87
|
-
@user.should respond_to(:can!)
|
88
|
-
end
|
89
|
-
|
90
|
-
it "should allow permissions setting through the `can!' method" do
|
91
|
-
count = @user.permissions.count
|
92
|
-
@user.can!(:manage_games)
|
93
|
-
@user.permissions.count.should == count.next
|
94
14
|
end
|
95
15
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
@user.can?(:control_rides).should be_false
|
100
|
-
@user.can?(:punch).should be_false
|
101
|
-
end
|
102
|
-
|
103
|
-
it "should return correct permissions on multiple requests" do
|
104
|
-
@user.can!(:manage_games)
|
105
|
-
@user.can!(:control_rides)
|
106
|
-
@user.can?(:manage_games, :control_rides).should be_true
|
107
|
-
@user.can?(:manage_games, :punch).should be_false
|
108
|
-
@user.can?(:control_rides, :punch).should be_false
|
109
|
-
@user.can?(:manage_games, :control_rides, :punch).should be_false
|
110
|
-
end
|
111
|
-
|
112
|
-
it "should revoke the correct permissions through the `revoke' method" do
|
113
|
-
@user.can!(:manage_games, :control_rides)
|
114
|
-
@user.can?(:manage_games).should be_true
|
115
|
-
@user.can?(:control_rides).should be_true
|
116
|
-
@user.revoke(:control_rides)
|
117
|
-
@user.can?(:control_rides).should be_false
|
118
|
-
@user.can?(:manage_games).should be_true
|
119
|
-
end
|
120
|
-
|
121
|
-
it "should revoke the full permissions through the `revoke' method w/an :all argument" do
|
122
|
-
@user.can!(:manage_games, :control_rides)
|
123
|
-
@user.can?(:manage_games).should be_true
|
124
|
-
@user.can?(:control_rides).should be_true
|
125
|
-
@user.revoke(:all)
|
126
|
-
@user.can?(:manage_games).should be_false
|
127
|
-
@user.can?(:control_rides).should be_false
|
128
|
-
end
|
129
|
-
|
130
|
-
it "should support a :reset option" do
|
131
|
-
@user.can!(:manage_games, :control_rides)
|
132
|
-
@user.can?(:manage_games).should be_true
|
133
|
-
@user.can!(:punch, :reset => true)
|
134
|
-
@user.can?(:manage_games).should_not be_true
|
135
|
-
@user.can?(:punch).should be_true
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
describe "scoped permissions" do
|
140
|
-
before :each do
|
141
|
-
Permissive::User.has_permissions(:on => :organizations) do
|
142
|
-
to :manage_games, 0
|
143
|
-
to :control_rides, 1
|
144
|
-
|
145
|
-
on :users do
|
146
|
-
to :punch, 2
|
147
|
-
end
|
148
|
-
end
|
149
|
-
@user = Permissive::User.create
|
150
|
-
@organization = Permissive::Organization.create
|
151
|
-
end
|
152
|
-
|
153
|
-
it "should allow scoped permissions checks through the `can?' method" do
|
154
|
-
@user.can?(:manage_games, :on => @organization).should be_false
|
155
|
-
end
|
156
|
-
|
157
|
-
describe "on instances" do
|
158
|
-
it "should return correct permissions through a scoped `can?' method" do
|
159
|
-
@user.can!(:manage_games, :on => @organization)
|
160
|
-
@user.can?(:manage_games, :on => @organization).should be_true
|
16
|
+
describe model do
|
17
|
+
it "should create a permissions reflection" do
|
18
|
+
model.new.should respond_to(:permissions)
|
161
19
|
end
|
162
20
|
|
163
|
-
it "should
|
164
|
-
|
165
|
-
@user.can?(:manage_games).should be_false
|
166
|
-
@user.can?(:manage_games, :on => @organization).should be_true
|
21
|
+
it "should create a `can?' method" do
|
22
|
+
model.new.should respond_to(:can?)
|
167
23
|
end
|
168
24
|
|
169
|
-
it "should
|
170
|
-
|
171
|
-
@user.can?(:manage_games, :on => @organization).should be_true
|
172
|
-
@user.can?(:control_rides, :on => @organization).should be_true
|
173
|
-
@user.revoke(:manage_games, :on => @organization)
|
174
|
-
@user.can?(:manage_games, :on => @organization).should be_false
|
175
|
-
@user.can?(:control_rides, :on => @organization).should be_true
|
176
|
-
end
|
177
|
-
|
178
|
-
it "should revoke the full permissions through the `revoke' method w/an :all argument" do
|
179
|
-
@user.can!(:punch)
|
180
|
-
@user.can!(:manage_games, :control_rides, :on => @organization)
|
181
|
-
@user.can?(:manage_games, :on => @organization).should be_true
|
182
|
-
@user.can?(:control_rides, :on => @organization).should be_true
|
183
|
-
@user.can?(:punch).should be_true
|
184
|
-
@user.revoke(:all, :on => @organization)
|
185
|
-
!@user.can?(:manage_games, :on => @organization).should be_false
|
186
|
-
!@user.can?(:control_rides, :on => @organization).should be_false
|
187
|
-
@user.can?(:punch).should be_true
|
25
|
+
it "should create a `revoke' method" do
|
26
|
+
model.new.should respond_to(:revoke)
|
188
27
|
end
|
189
28
|
end
|
190
|
-
|
191
|
-
describe "on classes" do
|
192
|
-
it "should ignore instance-specific permissions" do
|
193
|
-
@user.can!(:punch, :on => Permissive::User)
|
194
|
-
@user.can?(:punch, :on => Permissive::User).should be_true
|
195
|
-
@user.can?(:punch, :on => Permissive::User.create).should be_false
|
196
|
-
end
|
197
|
-
|
198
|
-
it "should interpolate symbols" do
|
199
|
-
@user.can!(:punch, :on => :users)
|
200
|
-
@user.can?(:punch, :on => Permissive::User).should be_true
|
201
|
-
end
|
202
|
-
|
203
|
-
it "should interpolate strings" do
|
204
|
-
@user.can!(:punch, :on => 'users')
|
205
|
-
@user.can?(:punch, :on => Permissive::User).should be_true
|
206
|
-
end
|
207
|
-
|
208
|
-
it "should forget strings if a corresponding class doesn't exist" do
|
209
|
-
Permissive::User.has_permissions(:on => :foobar) { to :punch, 0 }
|
210
|
-
@user.can!(:punch, :on => :foobar)
|
211
|
-
@user.can?(:punch, :on => :foobar).should be_true
|
212
|
-
end
|
213
|
-
|
214
|
-
it "should probably work with non-namespaced models, since those are standard these days" do
|
215
|
-
class PermissiveUser < ActiveRecord::Base
|
216
|
-
has_permissions do
|
217
|
-
to :do_stuff, 0
|
218
|
-
to :be_lazy, 1
|
219
|
-
|
220
|
-
on Permissive::Organization do
|
221
|
-
to :dance, 0
|
222
|
-
to :sing, 1
|
223
|
-
end
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
user = PermissiveUser.create
|
228
|
-
user.can!(:do_stuff)
|
229
|
-
user.can?(:do_stuff).should be_true
|
230
|
-
|
231
|
-
user.can!(:dance, :on => Permissive::Organization)
|
232
|
-
user.can?(:dance, :on => Permissive::Organization).should be_true
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
describe "automatic method creation" do
|
238
|
-
before :each do
|
239
|
-
Permissive::User.has_permissions(:on => :organizations)
|
240
|
-
@user = Permissive::User.create
|
241
|
-
@organization = Permissive::Organization.create
|
242
|
-
@user.can!(:control_rides)
|
243
|
-
@user.can!(:punch)
|
244
|
-
@user.can!(:manage_games, :on => @organization)
|
245
|
-
end
|
246
|
-
|
247
|
-
it "should not respond to invalid permission methods" do
|
248
|
-
lambda {
|
249
|
-
@user.can_control_rides_fu?
|
250
|
-
}.should raise_error(NoMethodError)
|
251
|
-
end
|
252
|
-
|
253
|
-
it "should cache chained methods" do
|
254
|
-
@user.respond_to?(:can_control_rides_and_manage_games?).should be_false
|
255
|
-
@user.can_control_rides_and_manage_games?.should be_false
|
256
|
-
@user.should respond_to(:can_control_rides_and_manage_games?)
|
257
|
-
end
|
258
|
-
|
259
|
-
it "should respond to valid permission methods" do
|
260
|
-
@user.can_control_rides?.should be_true
|
261
|
-
@user.can_punch?.should be_true
|
262
|
-
@user.can_manage_games?.should be_false
|
263
|
-
end
|
264
|
-
|
265
|
-
it "should respond to chained permission methods" do
|
266
|
-
@user.can_control_rides_and_punch?.should be_true
|
267
|
-
@user.can_control_rides_and_manage_games?.should be_false
|
268
|
-
end
|
269
|
-
|
270
|
-
it "should respond to scoped permission methods" do
|
271
|
-
@user.can_manage_games_on?(@organization).should be_true
|
272
|
-
@user.can_punch?(@organization).should be_false
|
273
|
-
['control_rides', 'punch'].each do |permission|
|
274
|
-
@user.send("can_#{permission}_on?", @organization).should be_false
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
describe "for setting permissions" do
|
279
|
-
it "should return the permission" do
|
280
|
-
@user.can_manage_games!.should be_instance_of Permissive::Permission
|
281
|
-
@user.can_manage_games?.should be_true
|
282
|
-
end
|
283
|
-
|
284
|
-
it "should support scoping" do
|
285
|
-
@user.can_manage_games_in!(@organization).should be_instance_of Permissive::Permission
|
286
|
-
@user.can_manage_games?.should be_false
|
287
|
-
@user.can_manage_games_in?(@organization).should be_true
|
288
|
-
end
|
289
|
-
end
|
290
|
-
|
291
|
-
it "should support revoking, too" do
|
292
|
-
@user.can_manage_games!
|
293
|
-
@user.can_manage_games?.should be_true
|
294
|
-
@user.cannot_manage_games!
|
295
|
-
@user.can_manage_games?.should be_false
|
296
|
-
end
|
297
|
-
end
|
298
|
-
|
299
|
-
describe "roles" do
|
300
|
-
|
301
|
-
before :each do
|
302
|
-
Permissive::User.has_permissions do
|
303
|
-
to :hire_employees, 0
|
304
|
-
to :manage_games, 1
|
305
|
-
to :control_rides, 2
|
306
|
-
|
307
|
-
role :games do
|
308
|
-
can :manage_games
|
309
|
-
end
|
310
|
-
|
311
|
-
role :rides do
|
312
|
-
can :control_rides
|
313
|
-
end
|
314
|
-
end
|
315
|
-
end
|
316
|
-
|
317
|
-
it "should provide a `roles` hash" do
|
318
|
-
Permissive::User.permissions[:global].roles[:games].should == [:manage_games]
|
319
|
-
Permissive::User.permissions[:global].roles[:rides].should == [:control_rides]
|
320
|
-
end
|
321
|
-
|
322
|
-
it "should accept multiple roles" do
|
323
|
-
Permissive::User.has_permissions do
|
324
|
-
to :fight, 0
|
325
|
-
to :flee, 1
|
326
|
-
to :urinate, 2
|
327
|
-
|
328
|
-
role(:normie, :hero) { can :fight }
|
329
|
-
role(:coward, :normie) { can :flee, :urinate }
|
330
|
-
end
|
331
|
-
|
332
|
-
Permissive::User.permissions[:global].roles[:normie].should == [:fight, :flee, :urinate]
|
333
|
-
Permissive::User.permissions[:global].roles[:hero].should == [:fight]
|
334
|
-
Permissive::User.permissions[:global].roles[:coward].should == [:flee, :urinate]
|
335
|
-
end
|
336
|
-
|
337
|
-
it "should allow me to assign a role" do
|
338
|
-
@james = Permissive::User.create!
|
339
|
-
@james.should respond_to(:role=)
|
340
|
-
@james.role = 'rides'
|
341
|
-
@james.can_control_rides?.should be_true
|
342
|
-
@james.can_manage_games?.should be_false
|
343
|
-
end
|
344
|
-
|
345
29
|
end
|
346
30
|
end
|
347
31
|
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
load File.join File.dirname(__FILE__), 'spec_models.rb'
|
3
|
+
|
4
|
+
describe Permissive, "automatic method creation" do
|
5
|
+
before :each do
|
6
|
+
PermissiveSpecHelper.db_up
|
7
|
+
|
8
|
+
Permissive::User.has_permissions do
|
9
|
+
to :manage_games, 0
|
10
|
+
to :control_rides, 1
|
11
|
+
to :punch, 2
|
12
|
+
end
|
13
|
+
|
14
|
+
Permissive::User.has_permissions(:on => :organizations) do
|
15
|
+
to :punch, 0
|
16
|
+
end
|
17
|
+
|
18
|
+
@user = Permissive::User.create
|
19
|
+
@organization = Permissive::Organization.create
|
20
|
+
@user.can!(:control_rides)
|
21
|
+
@user.can!(:punch)
|
22
|
+
@user.can!(:manage_games, :on => @organization)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should not respond to invalid permission methods" do
|
26
|
+
lambda {
|
27
|
+
@user.can_control_rides_fu?
|
28
|
+
}.should raise_error(NoMethodError)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should cache chained methods" do
|
32
|
+
@user.respond_to?(:can_control_rides_and_manage_games?).should be_false
|
33
|
+
@user.can_control_rides_and_manage_games?.should be_false
|
34
|
+
@user.should respond_to(:can_control_rides_and_manage_games?)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should respond to valid permission methods" do
|
38
|
+
@user.can_control_rides?.should be_true
|
39
|
+
@user.can_punch?.should be_true
|
40
|
+
@user.can_manage_games?.should be_false
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should respond to chained permission methods" do
|
44
|
+
@user.can_control_rides_and_punch?.should be_true
|
45
|
+
@user.can_control_rides_and_manage_games?.should be_false
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should respond to scoped permission methods" do
|
49
|
+
@user.can_manage_games_on?(@organization).should be_true
|
50
|
+
@user.can_punch?(@organization).should be_false
|
51
|
+
['control_rides', 'punch'].each do |permission|
|
52
|
+
@user.send("can_#{permission}_on?", @organization).should be_false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "for setting permissions" do
|
57
|
+
it "should return the permission" do
|
58
|
+
@user.can_manage_games!.should be_instance_of Permissive::Permission
|
59
|
+
@user.can_manage_games?.should be_true
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should support scoping" do
|
63
|
+
@user.can_manage_games_in!(@organization).should be_instance_of Permissive::Permission
|
64
|
+
@user.can_manage_games?.should be_false
|
65
|
+
@user.can_manage_games_in?(@organization).should be_true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should support revoking, too" do
|
70
|
+
@user.can_manage_games!
|
71
|
+
@user.can_manage_games?.should be_true
|
72
|
+
@user.cannot_manage_games!
|
73
|
+
@user.can_manage_games?.should be_false
|
74
|
+
end
|
75
|
+
end
|
data/spec/roles_spec.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
load File.join File.dirname(__FILE__), 'spec_models.rb'
|
3
|
+
|
4
|
+
describe Permissive, "roles" do
|
5
|
+
before :each do
|
6
|
+
PermissiveSpecHelper.db_up
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "basics" do
|
10
|
+
before :each do
|
11
|
+
Permissive::User.has_permissions do
|
12
|
+
to :hire_employees, 0
|
13
|
+
to :manage_games, 1
|
14
|
+
to :control_rides, 2
|
15
|
+
|
16
|
+
role :games do
|
17
|
+
can :manage_games
|
18
|
+
end
|
19
|
+
|
20
|
+
role :rides do
|
21
|
+
can :control_rides
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should provide a `roles` hash" do
|
27
|
+
Permissive::User.permissions[:global].roles[:games].should == [:manage_games]
|
28
|
+
Permissive::User.permissions[:global].roles[:rides].should == [:control_rides]
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should allow me to assign a role" do
|
32
|
+
@james = Permissive::User.create!
|
33
|
+
@james.should respond_to(:role=)
|
34
|
+
@james.role = 'rides'
|
35
|
+
@james.can_control_rides?.should be_true
|
36
|
+
@james.can_manage_games?.should be_false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "multiple role definitions" do
|
41
|
+
before :each do
|
42
|
+
Permissive::User.has_permissions do
|
43
|
+
to :fight, 0
|
44
|
+
to :flee, 1
|
45
|
+
to :urinate, 2
|
46
|
+
|
47
|
+
role(:normie, :hero) { can :fight }
|
48
|
+
role(:coward, :normie) { can :flee, :urinate }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should contain the various permissions" do
|
53
|
+
Permissive::User.permissions[:global].roles[:normie].should == [:fight, :flee, :urinate]
|
54
|
+
Permissive::User.permissions[:global].roles[:hero].should == [:fight]
|
55
|
+
Permissive::User.permissions[:global].roles[:coward].should == [:flee, :urinate]
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should assign the correct permissions" do
|
59
|
+
user = Permissive::User.create!(:role => 'hero')
|
60
|
+
user.can?(:fight).should be_true
|
61
|
+
user.can?(:flee).should be_false
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require File.join File.dirname(__FILE__), 'spec_helper'
|
2
|
+
load File.join File.dirname(__FILE__), 'spec_models.rb'
|
3
|
+
|
4
|
+
describe Permissive, "scoped permissions" do
|
5
|
+
before :each do
|
6
|
+
PermissiveSpecHelper.db_up
|
7
|
+
|
8
|
+
Permissive::User.has_permissions(:on => :organizations) do
|
9
|
+
to :manage_games, 0
|
10
|
+
to :control_rides, 1
|
11
|
+
|
12
|
+
on :users do
|
13
|
+
to :punch, 2
|
14
|
+
end
|
15
|
+
end
|
16
|
+
@user = Permissive::User.create
|
17
|
+
@organization = Permissive::Organization.create
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should allow scoped permissions checks through the `can?' method" do
|
21
|
+
@user.can?(:manage_games, :on => @organization).should be_false
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "on instances" do
|
25
|
+
it "should return correct permissions through a scoped `can?' method" do
|
26
|
+
@user.can!(:manage_games, :on => @organization)
|
27
|
+
@user.can?(:manage_games, :on => @organization).should be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should not respond to generic permissions on scoped permissions" do
|
31
|
+
@user.can!(:manage_games, :on => @organization)
|
32
|
+
@user.can?(:manage_games).should be_false
|
33
|
+
@user.can?(:manage_games, :on => @organization).should be_true
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should revoke the correct permissions through the `revoke' method" do
|
37
|
+
@user.can!(:manage_games, :control_rides, :on => @organization)
|
38
|
+
@user.can?(:manage_games, :on => @organization).should be_true
|
39
|
+
@user.can?(:control_rides, :on => @organization).should be_true
|
40
|
+
@user.revoke(:manage_games, :on => @organization)
|
41
|
+
@user.can?(:manage_games, :on => @organization).should be_false
|
42
|
+
@user.can?(:control_rides, :on => @organization).should be_true
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should revoke the full permissions through the `revoke' method w/an :all argument" do
|
46
|
+
user = Permissive::User.create
|
47
|
+
@user.can!(:punch, :on => user)
|
48
|
+
@user.can!(:manage_games, :control_rides, :on => @organization)
|
49
|
+
@user.can?(:manage_games, :on => @organization).should be_true
|
50
|
+
@user.can?(:control_rides, :on => @organization).should be_true
|
51
|
+
@user.can?(:punch, :on => user).should be_true
|
52
|
+
@user.revoke(:all)
|
53
|
+
@user.can?(:manage_games, :on => @organization).should be_false
|
54
|
+
@user.can?(:control_rides, :on => @organization).should be_false
|
55
|
+
@user.can?(:punch, :on => user).should be_false
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should revoke scoped permissions through the `revoke' method w/:on and :all arguments" do
|
59
|
+
user = Permissive::User.create
|
60
|
+
@user.can!(:punch, :on => user)
|
61
|
+
@user.can!(:manage_games, :control_rides, :on => @organization)
|
62
|
+
@user.can?(:manage_games, :on => @organization).should be_true
|
63
|
+
@user.can?(:control_rides, :on => @organization).should be_true
|
64
|
+
@user.can?(:punch, :on => user).should be_true
|
65
|
+
@user.revoke(:all, :on => @organization)
|
66
|
+
@user.can?(:manage_games, :on => @organization).should be_false
|
67
|
+
@user.can?(:control_rides, :on => @organization).should be_false
|
68
|
+
@user.can?(:punch, :on => user).should be_true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "on classes" do
|
73
|
+
it "should ignore instance-specific permissions" do
|
74
|
+
@user.can!(:punch, :on => Permissive::User)
|
75
|
+
@user.can?(:punch, :on => Permissive::User).should be_true
|
76
|
+
@user.can?(:punch, :on => Permissive::User.create).should be_false
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should interpolate symbols" do
|
80
|
+
@user.can!(:punch, :on => :users)
|
81
|
+
@user.can?(:punch, :on => Permissive::User).should be_true
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should interpolate strings" do
|
85
|
+
@user.can!(:punch, :on => 'users')
|
86
|
+
@user.can?(:punch, :on => Permissive::User).should be_true
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should forget strings if a corresponding class doesn't exist" do
|
90
|
+
Permissive::User.has_permissions(:on => :foobar) { to :punch, 0 }
|
91
|
+
@user.can!(:punch, :on => :foobar)
|
92
|
+
@user.can?(:punch, :on => :foobar).should be_true
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should probably work with non-namespaced models, since those are standard these days" do
|
96
|
+
class PermissiveUser < ActiveRecord::Base
|
97
|
+
has_permissions do
|
98
|
+
to :do_stuff, 0
|
99
|
+
to :be_lazy, 1
|
100
|
+
|
101
|
+
on Permissive::Organization do
|
102
|
+
to :dance, 0
|
103
|
+
to :sing, 1
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
user = PermissiveUser.create
|
109
|
+
user.can!(:do_stuff)
|
110
|
+
user.can?(:do_stuff).should be_true
|
111
|
+
|
112
|
+
user.can!(:dance, :on => Permissive::Organization)
|
113
|
+
user.can?(:dance, :on => Permissive::Organization).should be_true
|
114
|
+
user.can?(:sing, :in => Permissive::Organization).should be_false
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'active_record'
|
3
|
-
require 'permissive'
|
3
|
+
require File.join File.dirname(__FILE__), '..', 'lib', 'permissive'
|
4
4
|
|
5
5
|
module PermissiveSpecHelper
|
6
6
|
def self.clear_log
|
@@ -16,6 +16,10 @@ module PermissiveSpecHelper
|
|
16
16
|
create_table :permissive_users, :force => true do |t|
|
17
17
|
t.timestamps
|
18
18
|
end
|
19
|
+
create_table :permissive_users_with_roles, :force => true do |t|
|
20
|
+
t.string :role
|
21
|
+
t.timestamps
|
22
|
+
end
|
19
23
|
create_table :permissive_organizations, :force => true do |t|
|
20
24
|
t.timestamps
|
21
25
|
end
|
@@ -31,9 +35,10 @@ module PermissiveSpecHelper
|
|
31
35
|
end
|
32
36
|
|
33
37
|
def self.log_path
|
34
|
-
File.join(File.dirname(__FILE__), 'spec.log')
|
38
|
+
@log_path ||= File.join(File.dirname(__FILE__), 'spec.log')
|
35
39
|
end
|
36
40
|
end
|
37
41
|
|
38
42
|
# Setup the logging
|
43
|
+
PermissiveSpecHelper.clear_log
|
39
44
|
ActiveRecord::Base.logger = Logger.new(PermissiveSpecHelper.log_path)
|
data/spec/spec_models.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Setup some basic models to test with. We'll set permissions on both,
|
2
|
+
# and then test :scope'd permissions through both.
|
3
|
+
class Permissive::Organization < ActiveRecord::Base
|
4
|
+
set_table_name :permissive_organizations
|
5
|
+
end
|
6
|
+
|
7
|
+
class Permissive::User < ActiveRecord::Base
|
8
|
+
set_table_name :permissive_users
|
9
|
+
end
|
10
|
+
|
11
|
+
class UserWithRole < ActiveRecord::Base
|
12
|
+
set_table_name :permissive_users_with_roles
|
13
|
+
end
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
8
|
+
- 4
|
9
9
|
- alpha
|
10
|
-
version: 0.2.
|
10
|
+
version: 0.2.4.alpha
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Flip Sasser
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-04-
|
18
|
+
date: 2010-04-20 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -85,5 +85,11 @@ signing_key:
|
|
85
85
|
specification_version: 3
|
86
86
|
summary: Permissive gives your ActiveRecord models granular permission support
|
87
87
|
test_files:
|
88
|
+
- spec/checking_permissions_spec.rb
|
89
|
+
- spec/defining_permissions_spec.rb
|
88
90
|
- spec/has_permissions_spec.rb
|
91
|
+
- spec/metaprogramming_spec.rb
|
92
|
+
- spec/roles_spec.rb
|
93
|
+
- spec/scoping_permissions_spec.rb
|
89
94
|
- spec/spec_helper.rb
|
95
|
+
- spec/spec_models.rb
|