permissive 0.0.1 → 0.2.0.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/.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
|