permissive 0.0.1 → 0.2.0.alpha
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemspec +19 -1
- data/.gitignore +3 -1
- data/CHANGELOG +0 -0
- data/README.markdown +37 -29
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/generators/permissive_migration/templates/permissive_migration.rb +0 -2
- data/lib/permissive.rb +14 -12
- data/lib/permissive/errors.rb +4 -0
- data/lib/permissive/has_permissions.rb +153 -0
- data/lib/permissive/permission.rb +12 -30
- data/lib/permissive/permission_definition.rb +94 -0
- data/spec/has_permissions_spec.rb +326 -0
- data/spec/rcov.opts +2 -1
- data/spec/spec_helper.rb +2 -22
- metadata +23 -16
- data/README.markdown.html +0 -191
- data/lib/permissive/acts_as_permissive.rb +0 -134
- data/lib/permissive/permissions.rb +0 -29
- data/spec/acts_as_permissive_spec.rb +0 -192
- data/spec/permissions_spec.rb +0 -44
data/README.markdown.html
DELETED
@@ -1,191 +0,0 @@
|
|
1
|
-
<h1>Permissive gives your ActiveRecord models granular permission support</h1>
|
2
|
-
|
3
|
-
<p>Permissive combines a model-based permissions system with bitmasking to
|
4
|
-
create a flexible approach to maintaining permissions on your ActiveRecord
|
5
|
-
models. It supports an easy-to-use set of methods for accessing and
|
6
|
-
determining permissions, including some fun metaprogramming.</p>
|
7
|
-
|
8
|
-
<h2>Installation</h2>
|
9
|
-
|
10
|
-
<ol>
|
11
|
-
<li><p>Get yourself some code. You can install as a gem:</p>
|
12
|
-
|
13
|
-
<p><code>gem install permissive</code></p>
|
14
|
-
|
15
|
-
<p>or as a plugin:</p>
|
16
|
-
|
17
|
-
<p><code>script/plugin install git://github.com/flipsasser/permissive.git</code></p></li>
|
18
|
-
<li><p>Generate a migration so you can get some sweet table action:</p>
|
19
|
-
|
20
|
-
<p><code>script/generate permissive_migration</code></p>
|
21
|
-
|
22
|
-
<p><code>rake db:migrate</code></p></li>
|
23
|
-
</ol>
|
24
|
-
|
25
|
-
|
26
|
-
<h2>Usage</h2>
|
27
|
-
|
28
|
-
<p>First, define a few permissions constants. We'll define them in <code>Rails.root/config/initializers/permissive.rb</code>. The best practice is to name them in a verb format that follows this pattern: "Object can <code>DO_PERMISSION_NAME</code>".</p>
|
29
|
-
|
30
|
-
<p>Permission constants need to be int values counting up from zero. We use ints because Permissive uses bit masking to keep permissions data compact and performant.</p>
|
31
|
-
|
32
|
-
<pre><code>module Permissive::Permissions
|
33
|
-
MANAGE_GAMES = 0
|
34
|
-
CONTROL_RIDES = 1
|
35
|
-
PUNCH = 2
|
36
|
-
end
|
37
|
-
</code></pre>
|
38
|
-
|
39
|
-
<p>And that's all it takes to configure permissions! Now that we have them, let's grant them to a model or two:</p>
|
40
|
-
|
41
|
-
<pre><code>class Employee < ActiveRecord::Base
|
42
|
-
acts_as_permissive
|
43
|
-
validates_presence_of :first_name, :last_name
|
44
|
-
end
|
45
|
-
|
46
|
-
class Company < ActiveRecord::Base
|
47
|
-
validates_presence_of :name
|
48
|
-
end
|
49
|
-
</code></pre>
|
50
|
-
|
51
|
-
<p>Easy-peasy, right? Let's try granting a few permissions:</p>
|
52
|
-
|
53
|
-
<pre><code>@james = Employee.create(:first_name => 'James', :last_name => 'Brennan')
|
54
|
-
@frigo = Employee.create(:first_name => 'Tommy', :last_name => 'Frigo')
|
55
|
-
@adventureland = Company.create(:name => 'Adventureland')
|
56
|
-
|
57
|
-
# Okay, let's do some granting. We'll start by scoping to a specific company.
|
58
|
-
@james.can!(:manage_games, :on => @adventureland)
|
59
|
-
|
60
|
-
# Now let's do some permission checking.
|
61
|
-
@james.can?(:manage_games, :on => @adventureland) #=> true
|
62
|
-
|
63
|
-
# We can also use the metaprogramming syntax:
|
64
|
-
@james.can_manage_games_on?(@adventureland) #=> true
|
65
|
-
@james.can_control_rides_on?(@adventureland) #=> false
|
66
|
-
|
67
|
-
# We can check for multiple permissions, too:
|
68
|
-
@james.can?(:manage_games, :control_rides) #=> false
|
69
|
-
# OR:
|
70
|
-
@james.can_manage_games_and_control_rides?
|
71
|
-
|
72
|
-
# Scoping can be done through any object
|
73
|
-
@frigo.can!(:punch, :on => @james)
|
74
|
-
@frigo.can_punch_on?(@james) #=> true
|
75
|
-
|
76
|
-
# And the permissions aren't reciprocal
|
77
|
-
@james.can_punch_on?(@frigo) #=> false
|
78
|
-
|
79
|
-
# Of course, we can grant global (non-scoped) permissions, too:
|
80
|
-
@frigo.can!(:control_rides)
|
81
|
-
@frigo.can_control_rides? #=> true
|
82
|
-
|
83
|
-
# BUT! Global permissions don't override scoped permissions.
|
84
|
-
@frigo.can_control_rides_on?(@adventureland) #=> false
|
85
|
-
|
86
|
-
# Likewise, scoped permissions don't bubble up globally:
|
87
|
-
@james.can_manage_games? #=> false
|
88
|
-
|
89
|
-
# And, last but not least, let's take all of those great permissions away:
|
90
|
-
@james.revoke(:manage_games, :on => @adventureland)
|
91
|
-
|
92
|
-
# We can revoke all permissions, in any scope, too:
|
93
|
-
@frigo.revoke(:all)
|
94
|
-
</code></pre>
|
95
|
-
|
96
|
-
<p>And that's it!</p>
|
97
|
-
|
98
|
-
<h2>Scoping</h2>
|
99
|
-
|
100
|
-
<p>Permissive supports scoping at the class-configuration level, which adds relationships to permitted objects:</p>
|
101
|
-
|
102
|
-
<pre><code>class Employee < ActiveRecord::Base
|
103
|
-
acts_as_permissive :scope => :company
|
104
|
-
end
|
105
|
-
|
106
|
-
@frigo.permissive_companies #=> [Company 1, Company 2]
|
107
|
-
</code></pre>
|
108
|
-
|
109
|
-
<h2>Replacing Permissions</h2>
|
110
|
-
|
111
|
-
<p>Sometimes you want to overwrite all previous permissions in a can! method. That's pretty easy: just add :reset => true to the options.</p>
|
112
|
-
|
113
|
-
<pre><code>@frigo.can!(:control_rides, :on => @adventureland, :reset => true)
|
114
|
-
</code></pre>
|
115
|
-
|
116
|
-
<h2>Next Steps</h2>
|
117
|
-
|
118
|
-
<p>There's a number of things I want to add to the permissive settings. At the moment, Permissive currently support scoping at the class level, BUT all it really does is add a <code>has_many</code> relationship. <code>@employee.can!(:do_anything)</code> will still work, as will <code>@employee.can!(:do_something, :on => @something_that_isnt_a_company)</code>. That's pretty confusing to me. Adding more granular permissions might be cooler:</p>
|
119
|
-
|
120
|
-
<pre><code>class Employee < ActiveRecord::Base
|
121
|
-
has_permissions do
|
122
|
-
on :companies
|
123
|
-
on :employees
|
124
|
-
end
|
125
|
-
end
|
126
|
-
</code></pre>
|
127
|
-
|
128
|
-
<p>which might yield something like</p>
|
129
|
-
|
130
|
-
<pre><code>@employee.permissive_companies
|
131
|
-
# and
|
132
|
-
@employee.can_control_rides_in_company @adventureland
|
133
|
-
</code></pre>
|
134
|
-
|
135
|
-
<p>I'd also like to support a more intelligent grammar:</p>
|
136
|
-
|
137
|
-
<pre><code>@james.can_punch? @frigo
|
138
|
-
@frigo.can!(:control_rides, :in => @adventureland)
|
139
|
-
</code></pre>
|
140
|
-
|
141
|
-
<p>Meta-programmed methods for granting and revoking would be cool, too:</p>
|
142
|
-
|
143
|
-
<pre><code>@james.can_punch! @frigo
|
144
|
-
@frigo.cannot_control_rides_in! @adventureland
|
145
|
-
</code></pre>
|
146
|
-
|
147
|
-
<p>And while we're on the subject of metaprogramming, let's add some OR-ing to the whole thing:</p>
|
148
|
-
|
149
|
-
<pre><code>@james.can_control_rides_or_manage_games_in? @adventureland
|
150
|
-
</code></pre>
|
151
|
-
|
152
|
-
<p>I'd also like to enable Permissive::Templates (pre-set permission groups, like roles):</p>
|
153
|
-
|
154
|
-
<pre><code>administrator = Permissive::Template.named('Administrator')
|
155
|
-
@james.acts_like administrator
|
156
|
-
</code></pre>
|
157
|
-
|
158
|
-
<p>Next up! I currently use a manual reset to grant permissions through a controller. It would by great to DRY this stuff up and provide some decent path for moving permissions into HTML forms. Right now, it looks something like this:</p>
|
159
|
-
|
160
|
-
<pre><code><%= check_box_tag("employee[permissions][]", Permissive::Permissions::CONTROL_RIDES, @employee.can_control_rides?) %> Control rides
|
161
|
-
</code></pre>
|
162
|
-
|
163
|
-
<p>.. and in the controller:</p>
|
164
|
-
|
165
|
-
<pre><code>def update
|
166
|
-
@employee.can!(params[:employees].delete(:permissions), :revert => true)
|
167
|
-
respond_to do |format|
|
168
|
-
...
|
169
|
-
end
|
170
|
-
end
|
171
|
-
</code></pre>
|
172
|
-
|
173
|
-
<p>Finally, I'd like to use the <code>grant_mask</code> support that exists on the Permissive::Permission model to control what people can or cannot allow others to do. This would necessitate one of two things - first, a quick way of iterating over a person's granting permissions, e.g.:</p>
|
174
|
-
|
175
|
-
<pre><code><% current_user.grant_permissions.each do |permission| %>
|
176
|
-
<!-- Do something! -->
|
177
|
-
<% end %>
|
178
|
-
</code></pre>
|
179
|
-
|
180
|
-
<p>and second, write-time checking of grantor permissions. Something like this, maybe:</p>
|
181
|
-
|
182
|
-
<pre><code>def update
|
183
|
-
current_user.grant(params[:employees][:permissions], :to => @employee)
|
184
|
-
end
|
185
|
-
</code></pre>
|
186
|
-
|
187
|
-
<p>which would allow the Permissive::Permission model to make sure whatever <code>current_user</code> is granting to @employee, they're <strong>allowed</strong> to grant to @employee.</p>
|
188
|
-
|
189
|
-
<p>And that's it! Like all of my projects, I extracted it from some live development - which means it, too, is still in development. So please feel free to contribute!</p>
|
190
|
-
|
191
|
-
<p>Copyright (c) 2009 Flip Sasser, released under the MIT license</p>
|
@@ -1,134 +0,0 @@
|
|
1
|
-
module Permissive
|
2
|
-
module ActsAsPermissive
|
3
|
-
def self.included(base)
|
4
|
-
base.class_eval do
|
5
|
-
# This is the core of the Permissive module. It allows you to define a
|
6
|
-
# permissive model structure complete with :scope. This will dynamically
|
7
|
-
# generate scoped, polymorphic relationships across one or more models.
|
8
|
-
def self.acts_as_permissive(options = {})
|
9
|
-
options.assert_valid_keys(:scope)
|
10
|
-
has_many :permissions, :class_name => 'Permissive::Permission', :as => :permitted_object do
|
11
|
-
def can!(*args)
|
12
|
-
options = args.last.is_a?(Hash) ? args.pop : {}
|
13
|
-
options.assert_valid_keys(:on, :reset)
|
14
|
-
if options[:on]
|
15
|
-
permission = proxy_owner.permissions.find_or_initialize_by_scoped_object_id_and_scoped_object_type(options[:on].id, options[:on].class.to_s)
|
16
|
-
else
|
17
|
-
permission = Permissive::Permission.find_or_initialize_by_permitted_object_id_and_permitted_object_type(proxy_owner.id, proxy_owner.class.to_s)
|
18
|
-
end
|
19
|
-
if options[:reset]
|
20
|
-
permission.mask = 0
|
21
|
-
permission.grant_mask = 0
|
22
|
-
end
|
23
|
-
args.flatten.each do |name|
|
24
|
-
bit = bit_for(name)
|
25
|
-
unless permission.mask & bit != 0
|
26
|
-
permission.mask = permission.mask | bit
|
27
|
-
end
|
28
|
-
end
|
29
|
-
permission.save!
|
30
|
-
end
|
31
|
-
|
32
|
-
def can?(*args)
|
33
|
-
options = args.last.is_a?(Hash) ? args.pop : {}
|
34
|
-
bits = args.map{|name| bit_for(name) }
|
35
|
-
# scope = nil
|
36
|
-
# if options[:on]
|
37
|
-
# scope = scoped(:conditions => ['scoped_object_id = ? AND scoped_object_type = ?', options[:on].id, options[:on].class.to_s])
|
38
|
-
# else
|
39
|
-
# scope = scoped(:conditions => ['scoped_object_id IS NULL AND scoped_object_type IS NULL'])
|
40
|
-
# end
|
41
|
-
# Skip the trip to the database if the proxy has been loaded up already...
|
42
|
-
# TODO: Fix this per-scope ... somehow ... probably beyond the scope of this project.
|
43
|
-
# if @loaded
|
44
|
-
# bits.all?{|bit| self.select{|permission| permission.mask & bit != 0} }
|
45
|
-
# else
|
46
|
-
on(options[:on]).count(:conditions => [bits.map { 'permissive_permissions.mask & ?' }.join(' AND '), *bits]) > 0
|
47
|
-
# end
|
48
|
-
end
|
49
|
-
|
50
|
-
def revoke(*args)
|
51
|
-
options = args.last.is_a?(Hash) ? args.pop : {}
|
52
|
-
if args.length == 1 && args.first == :all
|
53
|
-
on(options[:on]).destroy_all
|
54
|
-
else
|
55
|
-
bits = args.map{|name| bit_for(name) }
|
56
|
-
on(options[:on]).each do |permission|
|
57
|
-
bits.each do |bit|
|
58
|
-
if permission.mask & bit
|
59
|
-
permission.mask = permission.mask ^ bit
|
60
|
-
end
|
61
|
-
end
|
62
|
-
permission.save!
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
if options[:scope]
|
69
|
-
scope_name = "permissive_#{options[:scope].to_s}"
|
70
|
-
unless reflection = reflect_on_association(scope_name)
|
71
|
-
# TODO: There's just no way this should be working. It's WAY too
|
72
|
-
# fragile. We need support for something more intelligent here,
|
73
|
-
# like an options hash that includes :scope_type.
|
74
|
-
namespace = self.to_s.split('::')
|
75
|
-
if namespace.length > 1
|
76
|
-
namespace.pop
|
77
|
-
class_name = namespace.join('::')
|
78
|
-
else
|
79
|
-
class_name = ''
|
80
|
-
end
|
81
|
-
class_name << "::#{options[:scope].to_s.classify}"
|
82
|
-
has_many scope_name, :through => :permissions, :source => :scoped_object, :source_type => class_name
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
class_eval do
|
87
|
-
# Pass calls to the instance down to its permissions collection
|
88
|
-
# e.g. current_user.can(:view_comments) will bubble to
|
89
|
-
# current_user.permissions.can(:view_comments)
|
90
|
-
def can!(*args)
|
91
|
-
permissions.can!(*args)
|
92
|
-
end
|
93
|
-
|
94
|
-
# Pass calls to the instance down to its permissions collection
|
95
|
-
# e.g. current_user.can(:view_comments) will bubble to
|
96
|
-
# current_user.permissions.can(:view_comments)
|
97
|
-
def can?(*args)
|
98
|
-
permissions.can?(*args)
|
99
|
-
end
|
100
|
-
|
101
|
-
def revoke(*args)
|
102
|
-
permissions.revoke(*args)
|
103
|
-
end
|
104
|
-
|
105
|
-
def method_missing(method, *args)
|
106
|
-
if method.to_s =~ /^can_([^\?]+)\?$/
|
107
|
-
permissions = $1
|
108
|
-
options = {}
|
109
|
-
if permissions =~ /_on$/
|
110
|
-
permissions.chomp!('_on')
|
111
|
-
options[:on] = args.shift
|
112
|
-
end
|
113
|
-
permissions = permissions.split('_and_')
|
114
|
-
if permissions.all? {|permission| Permissive::Permissions.hash.has_key?(permission.downcase.to_sym) }
|
115
|
-
class_eval <<-end_eval
|
116
|
-
def #{method}#{"(scope)" if options[:on]}
|
117
|
-
can?(#{[permissions, args].flatten.join(', ').inspect}#{", :on => scope" if options[:on]})
|
118
|
-
end
|
119
|
-
end_eval
|
120
|
-
return can?(*[permissions, options].flatten)
|
121
|
-
end
|
122
|
-
end
|
123
|
-
super
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
if defined?(ActiveRecord::Base)
|
133
|
-
ActiveRecord::Base.send :include, Permissive::ActsAsPermissive
|
134
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# TODO: Abstract this module more later
|
2
|
-
module Permissive
|
3
|
-
class PermissionError < StandardError; end;
|
4
|
-
|
5
|
-
module Permissions
|
6
|
-
class << self
|
7
|
-
def const_set(*args)
|
8
|
-
@@hash = nil
|
9
|
-
super
|
10
|
-
end
|
11
|
-
|
12
|
-
def hash
|
13
|
-
@@hash ||= begin
|
14
|
-
bitwise_hash = constants.inject({}) do |hash, constant_name|
|
15
|
-
hash[constant_name.downcase] = 2 ** Permissive::Permissions.const_get(constant_name.to_sym)
|
16
|
-
hash
|
17
|
-
end
|
18
|
-
inverted_hash = bitwise_hash.invert
|
19
|
-
bitwise_hash.values.sort.inject(ActiveSupport::OrderedHash.new) do |hash, value|
|
20
|
-
hash[inverted_hash[value].to_sym] = value
|
21
|
-
hash
|
22
|
-
end
|
23
|
-
rescue ArgumentError
|
24
|
-
raise Permissive::PermissionError.new("Permissions must be integers or longs. Strings, symbols, and floats are not currently supported.")
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,192 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
-
|
3
|
-
# Setup some basic models to test with. We'll set permissions on both,
|
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
|
14
|
-
before :each do
|
15
|
-
PermissiveSpecHelper.db_up
|
16
|
-
end
|
17
|
-
|
18
|
-
after :each do
|
19
|
-
PermissiveSpecHelper.db_down
|
20
|
-
end
|
21
|
-
|
22
|
-
describe "`acts_as_permissive' default class method" do
|
23
|
-
[Permissive::User, Permissive::Organization].each do |model|
|
24
|
-
before :each do
|
25
|
-
model.acts_as_permissive
|
26
|
-
end
|
27
|
-
|
28
|
-
describe model do
|
29
|
-
it "should create a permissions reflection" do
|
30
|
-
model.new.should respond_to(:permissions)
|
31
|
-
end
|
32
|
-
|
33
|
-
it "should create a `can?' method" do
|
34
|
-
model.new.should respond_to(:can?)
|
35
|
-
end
|
36
|
-
|
37
|
-
it "should create a `revoke' method" do
|
38
|
-
model.new.should respond_to(:revoke)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
describe "permissions checking" do
|
45
|
-
before :each do
|
46
|
-
Permissive::User.acts_as_permissive
|
47
|
-
@user = Permissive::User.create
|
48
|
-
end
|
49
|
-
|
50
|
-
it "should allow permissions checks through the `can?' method" do
|
51
|
-
@user.can?(:edit_organizations).should be_false
|
52
|
-
end
|
53
|
-
|
54
|
-
it "should respond to the `can!' method" do
|
55
|
-
@user.should respond_to(:can!)
|
56
|
-
end
|
57
|
-
|
58
|
-
it "should allow permissions setting through the `can!' method" do
|
59
|
-
count = @user.permissions.count
|
60
|
-
@user.can!(:view_users)
|
61
|
-
@user.permissions.count.should == count.next
|
62
|
-
end
|
63
|
-
|
64
|
-
it "should return correct permissions through the `can?' method" do
|
65
|
-
@user.can!(:view_users)
|
66
|
-
@user.can?(:view_users).should be_true
|
67
|
-
['FINALIZE_LAB_SELECTION_LIST', 'SEARCH_APPLICANTS', 'CREATE_BASIC_USER', 'VIEW_BUDGET_REPORT'].each do |permission|
|
68
|
-
@user.can?(permission).should be_false
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
it "should return correct permissions on multiple requests" do
|
73
|
-
@user.can!(:view_users)
|
74
|
-
@user.can!(:view_budget_report)
|
75
|
-
@user.can?(:view_users, :view_budget_report).should be_true
|
76
|
-
['FINALIZE_LAB_SELECTION_LIST', 'SEARCH_APPLICANTS', 'CREATE_BASIC_USER'].each do |permission|
|
77
|
-
@user.can?(:view_users, permission).should be_false
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
it "should revoke the correct permissions through the `revoke' method" do
|
82
|
-
@user.can!(:view_users, :view_budget_report)
|
83
|
-
@user.can?(:view_users).should be_true
|
84
|
-
@user.can?(:view_budget_report).should be_true
|
85
|
-
@user.revoke(:view_users)
|
86
|
-
@user.can?(:view_users).should be_false
|
87
|
-
@user.can?(:view_budget_report).should be_true
|
88
|
-
end
|
89
|
-
|
90
|
-
it "should revoke the full permissions through the `revoke' method w/an :all argument" do
|
91
|
-
@user.can!(:view_users, :view_budget_report)
|
92
|
-
@user.can?(:view_users).should be_true
|
93
|
-
@user.can?(:view_budget_report).should be_true
|
94
|
-
@user.revoke(:all)
|
95
|
-
@user.can?(:view_users).should be_false
|
96
|
-
@user.can?(:view_budget_report).should be_false
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
describe "scoped permissions" do
|
101
|
-
before :each do
|
102
|
-
Permissive::User.acts_as_permissive(:scope => :organizations)
|
103
|
-
@user = Permissive::User.create
|
104
|
-
@organization = Permissive::Organization.create
|
105
|
-
end
|
106
|
-
|
107
|
-
it "should allow scoped permissions checks through the `can?' method" do
|
108
|
-
@user.can?(:view_users, :on => @organization).should be_false
|
109
|
-
end
|
110
|
-
|
111
|
-
it "should return correct permissions through a scoped `can?' method" do
|
112
|
-
@user.can!(:view_users, :on => @organization)
|
113
|
-
@user.can?(:view_users, :on => @organization).should be_true
|
114
|
-
end
|
115
|
-
|
116
|
-
it "should not respond to generic permissions on scoped permissions" do
|
117
|
-
@user.can!(:view_users, :on => @organization)
|
118
|
-
@user.can?(:view_users).should be_false
|
119
|
-
@user.can?(:view_users, :on => @organization).should be_true
|
120
|
-
end
|
121
|
-
|
122
|
-
it "should revoke the correct permissions through the `revoke' method" do
|
123
|
-
@user.can!(:view_users, :view_budget_report, :on => @organization)
|
124
|
-
@user.can?(:view_users, :on => @organization).should be_true
|
125
|
-
@user.can?(:view_budget_report, :on => @organization).should be_true
|
126
|
-
@user.revoke(:view_users, :on => @organization)
|
127
|
-
@user.can?(:view_users, :on => @organization).should be_false
|
128
|
-
@user.can?(:view_budget_report, :on => @organization).should be_true
|
129
|
-
end
|
130
|
-
|
131
|
-
it "should revoke the full permissions through the `revoke' method w/an :all argument" do
|
132
|
-
@user.can!(:create_basic_user)
|
133
|
-
@user.can!(:view_users, :view_budget_report, :on => @organization)
|
134
|
-
@user.can?(:view_users, :on => @organization).should be_true
|
135
|
-
@user.can?(:view_budget_report, :on => @organization).should be_true
|
136
|
-
@user.can?(:create_basic_user).should be_true
|
137
|
-
@user.revoke(:all, :on => @organization)
|
138
|
-
!@user.can?(:view_users, :on => @organization).should be_false
|
139
|
-
!@user.can?(:view_budget_report, :on => @organization).should be_false
|
140
|
-
@user.can?(:create_basic_user).should be_true
|
141
|
-
end
|
142
|
-
|
143
|
-
end
|
144
|
-
|
145
|
-
describe "automatic method creation" do
|
146
|
-
before :each do
|
147
|
-
Permissive::User.acts_as_permissive(:scope => :organizations)
|
148
|
-
@user = Permissive::User.create
|
149
|
-
@organization = Permissive::Organization.create
|
150
|
-
@user.can!(:finalize_lab_selection_list)
|
151
|
-
@user.can!(:create_basic_user)
|
152
|
-
@user.can!(:view_users, :on => @organization)
|
153
|
-
end
|
154
|
-
|
155
|
-
it "should not respond to invalid permission methods" do
|
156
|
-
lambda {
|
157
|
-
@user.can_finalize_lab_selection_list_fu?
|
158
|
-
}.should raise_error(NoMethodError)
|
159
|
-
end
|
160
|
-
|
161
|
-
it "should cache chained methods" do
|
162
|
-
@user.respond_to?(:can_finalize_lab_selection_list_and_view_users?).should be_false
|
163
|
-
@user.can_finalize_lab_selection_list_and_view_users?.should be_false
|
164
|
-
@user.should respond_to(:can_finalize_lab_selection_list_and_view_users?)
|
165
|
-
end
|
166
|
-
|
167
|
-
it "should respond to valid permission methods" do
|
168
|
-
@user.can_finalize_lab_selection_list?.should be_true
|
169
|
-
@user.can_create_basic_user?.should be_true
|
170
|
-
['SEARCH_APPLICANTS', 'VIEW_USERS', 'VIEW_BUDGET_REPORT'].each do |permission|
|
171
|
-
@user.send("can_#{permission.downcase}?").should be_false
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
it "should respond to chained permission methods" do
|
176
|
-
@user.can_finalize_lab_selection_list_and_create_basic_user?.should be_true
|
177
|
-
['SEARCH_APPLICANTS', 'VIEW_USERS', 'VIEW_BUDGET_REPORT'].each do |permission|
|
178
|
-
@user.send("can_finalize_lab_selection_list_and_#{permission.downcase}?").should be_false
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
it "should respond to scoped permission methods" do
|
183
|
-
@user.can_view_users_on?(@organization).should be_true
|
184
|
-
['FINALIZE_LAB_SELECTION_LIST', 'SEARCH_APPLICANTS', 'CREATE_BASIC_USER', 'VIEW_BUDGET_REPORT'].each do |permission|
|
185
|
-
@user.send("can_#{permission.downcase}_on?", @organization).should be_false
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
PermissiveSpecHelper.clear_log
|