consul 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of consul might be problematic. Click here for more details.
- data/.travis.yml +7 -3
- data/README.md +62 -4
- data/lib/consul/power.rb +3 -1
- data/lib/consul/version.rb +1 -1
- data/spec/rails-3.2/Gemfile +0 -1
- data/spec/rails-3.2/spec/spec_helper.rb +5 -6
- data/spec/shared/consul/power_spec.rb +54 -12
- metadata +62 -46
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
Consul - A scope-based authorization solution
|
2
2
|
=============================================
|
3
3
|
|
4
|
+
[![Build Status](https://secure.travis-ci.org/makandra/consul.png?branch=master)](https://travis-ci.org/makandra/consul)
|
5
|
+
|
4
6
|
Consul is a authorization solution for Ruby on Rails that uses scopes to control what a user can see or edit.
|
5
7
|
|
6
8
|
We have used Consul in combination with [assignable_values](https://github.com/makandra/assignable_values) to solve a variety of authorization requirements ranging from boring to bizarre.
|
7
9
|
|
10
|
+
Also see our crash course video: [Solving bizare authorization requirements with Rails](http://bizarre-authorization.talks.makandra.com/).
|
11
|
+
|
8
12
|
|
9
13
|
Describing a power for your application
|
10
14
|
---------------------------------------
|
@@ -59,8 +63,8 @@ You can also write power checks like this:
|
|
59
63
|
|
60
64
|
power.include?(:notes)
|
61
65
|
power.include!(:notes)
|
62
|
-
power.include?(:
|
63
|
-
power.include!(:
|
66
|
+
power.include?(:notes, Note.last)
|
67
|
+
power.include!(:notes, Note.last)
|
64
68
|
|
65
69
|
|
66
70
|
Boolean powers
|
@@ -83,6 +87,60 @@ You can query it like the other powers:
|
|
83
87
|
power.dashboard! # => raises Consul::Powerless unless Power#dashboard? returns true
|
84
88
|
|
85
89
|
|
90
|
+
Powers that give no access at all
|
91
|
+
---------------------------------
|
92
|
+
|
93
|
+
Note that there is a difference between having access to an empty list of records, and having no access at all.
|
94
|
+
If you want to express that a user has no access at all, make the respective power return `nil`.
|
95
|
+
|
96
|
+
Note how the power in the example below returns `nil` unless the user is an admin:
|
97
|
+
|
98
|
+
class Power
|
99
|
+
...
|
100
|
+
|
101
|
+
power :users do
|
102
|
+
User if @user.admin?
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
When a non-admin queries the `:users` power, she will get the following behavior:
|
108
|
+
|
109
|
+
power.notes # => returns nil
|
110
|
+
power.notes? # => returns false
|
111
|
+
power.notes! # => raises Consul::Powerless
|
112
|
+
power.note?(Note.last) # => returns false
|
113
|
+
power.note!(Note.last) # => raises Consul::Powerless
|
114
|
+
|
115
|
+
|
116
|
+
Other types of powers
|
117
|
+
---------------------
|
118
|
+
|
119
|
+
A power can return any type of object. For instance, you often want to return an array:
|
120
|
+
|
121
|
+
class Power
|
122
|
+
...
|
123
|
+
|
124
|
+
power :assignable_note_states do
|
125
|
+
if admin?
|
126
|
+
%w[draft pending published retracted]
|
127
|
+
else
|
128
|
+
%w[draft pending]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
You can query it like any other power. E.g. if a non-admin queries this power she will get the following behavior:
|
135
|
+
|
136
|
+
power.assignable_note_states # => ['draft', 'pending']
|
137
|
+
power.assignable_note_states? # => returns true
|
138
|
+
power.assignable_note_states! # => does nothing (because the power isn't nil)
|
139
|
+
power.assignable_note_state?('draft') # => returns true
|
140
|
+
power.assignable_note_state?('published') # => returns false
|
141
|
+
power.assignable_note_state!('published') # => raises Consul::Powerless
|
142
|
+
|
143
|
+
|
86
144
|
Role-based permissions
|
87
145
|
----------------------
|
88
146
|
|
@@ -329,9 +387,9 @@ Now run `bundle install` to lock the gem into your project.
|
|
329
387
|
Development
|
330
388
|
-----------
|
331
389
|
|
332
|
-
|
390
|
+
Test applications for various Rails versions lives in `spec`. You can run specs from the project root by saying:
|
333
391
|
|
334
|
-
bundle exec rake spec
|
392
|
+
bundle exec rake all:spec
|
335
393
|
|
336
394
|
If you would like to contribute:
|
337
395
|
|
data/lib/consul/power.rb
CHANGED
@@ -13,7 +13,9 @@ module Consul
|
|
13
13
|
if record.nil?
|
14
14
|
!!power_value
|
15
15
|
else
|
16
|
-
if
|
16
|
+
if power_value.nil?
|
17
|
+
false
|
18
|
+
elsif scope?(power_value)
|
17
19
|
power_ids_name = self.class.power_ids_name(name)
|
18
20
|
send(power_ids_name, *args).include?(record.id)
|
19
21
|
elsif collection?(power_value)
|
data/lib/consul/version.rb
CHANGED
data/spec/rails-3.2/Gemfile
CHANGED
@@ -8,9 +8,8 @@ FileUtils.rm(Dir.glob("#{ENV['RAILS_ROOT']}/db/*.db"), :force => true)
|
|
8
8
|
# Load the Rails environment and testing framework
|
9
9
|
require "#{File.dirname(__FILE__)}/../app_root/config/environment"
|
10
10
|
require 'rspec/rails'
|
11
|
-
require 'database_cleaner'
|
12
11
|
|
13
|
-
DatabaseCleaner.strategy = :truncation
|
12
|
+
# DatabaseCleaner.strategy = :truncation
|
14
13
|
|
15
14
|
require 'rspec_candy/helpers'
|
16
15
|
|
@@ -21,9 +20,9 @@ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate")
|
|
21
20
|
print "\033[0m"
|
22
21
|
|
23
22
|
RSpec.configure do |config|
|
24
|
-
config.use_transactional_fixtures =
|
23
|
+
config.use_transactional_fixtures = true
|
25
24
|
config.use_instantiated_fixtures = false
|
26
|
-
config.before(:each) do
|
27
|
-
|
28
|
-
end
|
25
|
+
#config.before(:each) do
|
26
|
+
# DatabaseCleaner.clean
|
27
|
+
#end
|
29
28
|
end
|
@@ -22,6 +22,60 @@ describe Consul::Power do
|
|
22
22
|
|
23
23
|
end
|
24
24
|
|
25
|
+
context 'nil powers' do
|
26
|
+
|
27
|
+
describe '#include?' do
|
28
|
+
|
29
|
+
context 'when no record is given' do
|
30
|
+
|
31
|
+
it 'should return false' do
|
32
|
+
@user.role = 'guest'
|
33
|
+
@user.power.clients.should be_nil
|
34
|
+
@user.power.clients?.should be_false
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'with a given record' do
|
40
|
+
|
41
|
+
it 'should return false' do
|
42
|
+
client = Client.create!
|
43
|
+
@user.role = 'guest'
|
44
|
+
@user.power.clients.should be_nil
|
45
|
+
@user.power.client?(client).should be_false
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#include!' do
|
53
|
+
|
54
|
+
context 'when no record is given' do
|
55
|
+
|
56
|
+
it 'should raise Consul::Powerless when the power returns nil' do
|
57
|
+
@user.role = 'guest'
|
58
|
+
@user.power.clients.should be_nil
|
59
|
+
expect { @user.power.clients! }.to raise_error(Consul::Powerless)
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'with a given record' do
|
65
|
+
|
66
|
+
it 'should raise Consul::Powerless when' do
|
67
|
+
client = Client.create!
|
68
|
+
@user.role = 'guest'
|
69
|
+
@user.power.clients.should be_nil
|
70
|
+
expect { @user.power.client!(client) }.to raise_error(Consul::Powerless)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
25
79
|
context 'scope powers' do
|
26
80
|
|
27
81
|
it 'should return the registered scope' do
|
@@ -40,12 +94,6 @@ describe Consul::Power do
|
|
40
94
|
@user.power.clients?.should be_true
|
41
95
|
end
|
42
96
|
|
43
|
-
it 'should return false if the power returns nil' do
|
44
|
-
@user.role = 'guest'
|
45
|
-
@user.power.clients.should be_nil
|
46
|
-
@user.power.clients?.should be_false
|
47
|
-
end
|
48
|
-
|
49
97
|
end
|
50
98
|
|
51
99
|
context 'with a given record' do
|
@@ -72,12 +120,6 @@ describe Consul::Power do
|
|
72
120
|
|
73
121
|
context 'when no record is given' do
|
74
122
|
|
75
|
-
it 'should raise Consul::Powerless when the power returns nil' do
|
76
|
-
@user.role = 'guest'
|
77
|
-
@user.power.clients.should be_nil
|
78
|
-
expect { @user.power.clients! }.to raise_error(Consul::Powerless)
|
79
|
-
end
|
80
|
-
|
81
123
|
it 'should not raise Consul::Powerless when the power returns a scope (which might or might not match records)' do
|
82
124
|
expect { @user.power.clients! }.to_not raise_error
|
83
125
|
end
|
metadata
CHANGED
@@ -1,54 +1,60 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: consul
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 11
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 4
|
9
|
+
- 2
|
10
|
+
version: 0.4.2
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Henning Koch
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2012-12-14 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
15
22
|
name: memoizer
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
|
-
requirements:
|
19
|
-
- - ! '>='
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: '0'
|
22
|
-
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ! '>='
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '0'
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: rails
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
33
25
|
none: false
|
34
|
-
requirements:
|
35
|
-
- -
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
38
33
|
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rails
|
39
37
|
prerelease: false
|
40
|
-
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
39
|
none: false
|
42
|
-
requirements:
|
43
|
-
- -
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
46
49
|
description: A scope-based authorization solution for Ruby on Rails.
|
47
50
|
email: henning.koch@makandra.de
|
48
51
|
executables: []
|
52
|
+
|
49
53
|
extensions: []
|
54
|
+
|
50
55
|
extra_rdoc_files: []
|
51
|
-
|
56
|
+
|
57
|
+
files:
|
52
58
|
- .gitignore
|
53
59
|
- .travis.yml
|
54
60
|
- README.md
|
@@ -136,29 +142,39 @@ files:
|
|
136
142
|
- spec/shared/consul/controllers/songs_controller_spec.rb
|
137
143
|
- spec/shared/consul/controllers/users_controller_spec.rb
|
138
144
|
- spec/shared/consul/power_spec.rb
|
145
|
+
has_rdoc: true
|
139
146
|
homepage: https://github.com/makandra/consul
|
140
147
|
licenses: []
|
148
|
+
|
141
149
|
post_install_message:
|
142
150
|
rdoc_options: []
|
143
|
-
|
151
|
+
|
152
|
+
require_paths:
|
144
153
|
- lib
|
145
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
154
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
146
155
|
none: false
|
147
|
-
requirements:
|
148
|
-
- -
|
149
|
-
- !ruby/object:Gem::Version
|
150
|
-
|
151
|
-
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
hash: 3
|
160
|
+
segments:
|
161
|
+
- 0
|
162
|
+
version: "0"
|
163
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
164
|
none: false
|
153
|
-
requirements:
|
154
|
-
- -
|
155
|
-
- !ruby/object:Gem::Version
|
156
|
-
|
165
|
+
requirements:
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
hash: 3
|
169
|
+
segments:
|
170
|
+
- 0
|
171
|
+
version: "0"
|
157
172
|
requirements: []
|
173
|
+
|
158
174
|
rubyforge_project:
|
159
|
-
rubygems_version: 1.
|
175
|
+
rubygems_version: 1.3.9.4
|
160
176
|
signing_key:
|
161
177
|
specification_version: 3
|
162
178
|
summary: A scope-based authorization solution for Ruby on Rails.
|
163
179
|
test_files: []
|
164
|
-
|
180
|
+
|