consul 0.4.2 → 0.5.0
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/README.md +15 -0
- data/lib/consul.rb +1 -0
- data/lib/consul/power.rb +31 -30
- data/lib/consul/util.rb +39 -0
- data/lib/consul/version.rb +1 -1
- data/spec/rails-2.3/spec/spec_helper.rb +2 -0
- data/spec/rails-3.0/spec/spec_helper.rb +2 -2
- data/spec/rails-3.2/spec/spec_helper.rb +1 -2
- data/spec/shared/app_root/app/models/power.rb +16 -0
- data/spec/shared/app_root/app/models/song.rb +7 -0
- data/spec/shared/app_root/db/migrate/004_create_songs.rb +14 -0
- data/spec/shared/consul/power_spec.rb +30 -0
- metadata +8 -5
data/README.md
CHANGED
@@ -141,6 +141,21 @@ You can query it like any other power. E.g. if a non-admin queries this power sh
|
|
141
141
|
power.assignable_note_state!('published') # => raises Consul::Powerless
|
142
142
|
|
143
143
|
|
144
|
+
Defining multiple powers at once
|
145
|
+
--------------------------------
|
146
|
+
|
147
|
+
You can define multiple powers at once by giving multiple power names:
|
148
|
+
|
149
|
+
class Power
|
150
|
+
...
|
151
|
+
|
152
|
+
power :destroyable_users, updatable_users do
|
153
|
+
User if admin?
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
|
144
159
|
Role-based permissions
|
145
160
|
----------------------
|
146
161
|
|
data/lib/consul.rb
CHANGED
data/lib/consul/power.rb
CHANGED
@@ -13,12 +13,17 @@ module Consul
|
|
13
13
|
if record.nil?
|
14
14
|
!!power_value
|
15
15
|
else
|
16
|
+
# record is given
|
16
17
|
if power_value.nil?
|
17
18
|
false
|
18
|
-
elsif scope?(power_value)
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
elsif Util.scope?(power_value)
|
20
|
+
if Util.scope_selects_all_records?(power_value)
|
21
|
+
true
|
22
|
+
else
|
23
|
+
power_ids_name = self.class.power_ids_name(name)
|
24
|
+
send(power_ids_name, *args).include?(record.id)
|
25
|
+
end
|
26
|
+
elsif Util.collection?(power_value)
|
22
27
|
power_value.include?(record)
|
23
28
|
else
|
24
29
|
raise Consul::NoCollection, "can only call #include? on a collection, but power was of type #{power_value.class.name}"
|
@@ -36,35 +41,12 @@ module Consul
|
|
36
41
|
[TrueClass, FalseClass, NilClass].include?(value.class)
|
37
42
|
end
|
38
43
|
|
39
|
-
def scope?(value)
|
40
|
-
value.respond_to?(:scoped)
|
41
|
-
end
|
42
|
-
|
43
|
-
def collection?(value)
|
44
|
-
value.is_a?(Array) || value.is_a?(Set)
|
45
|
-
end
|
46
|
-
|
47
44
|
module ClassMethods
|
48
45
|
|
49
|
-
def power(
|
50
|
-
|
51
|
-
|
52
|
-
define_method("#{name.to_s}!") { |*args| include!(name, *args) }
|
53
|
-
define_method("#{name.to_s.singularize}?") { |*args| include?(name, *args) }
|
54
|
-
define_method("#{name.to_s.singularize}!") { |*args| include!(name, *args) }
|
55
|
-
ids_method = power_ids_name(name)
|
56
|
-
define_method(ids_method) do |*args|
|
57
|
-
scope = send(name, *args)
|
58
|
-
scope = scope.scoped(:select => "`#{scope.table_name}`.`id`")
|
59
|
-
query = if scope.respond_to?(:to_sql)
|
60
|
-
scope.to_sql
|
61
|
-
else
|
62
|
-
scope.construct_finder_sql({})
|
63
|
-
end
|
64
|
-
::ActiveRecord::Base.connection.select_values(query).collect(&:to_i)
|
46
|
+
def power(*names, &block)
|
47
|
+
names.each do |name|
|
48
|
+
define_power(name, &block)
|
65
49
|
end
|
66
|
-
memoize ids_method
|
67
|
-
name
|
68
50
|
end
|
69
51
|
|
70
52
|
def power_ids_name(name)
|
@@ -84,6 +66,25 @@ module Consul
|
|
84
66
|
self.current = old_power
|
85
67
|
end
|
86
68
|
|
69
|
+
private
|
70
|
+
|
71
|
+
def define_power(name, &block)
|
72
|
+
define_method(name, &block)
|
73
|
+
define_method("#{name.to_s}?") { |*args| include?(name, *args) }
|
74
|
+
define_method("#{name.to_s}!") { |*args| include!(name, *args) }
|
75
|
+
define_method("#{name.to_s.singularize}?") { |*args| include?(name, *args) }
|
76
|
+
define_method("#{name.to_s.singularize}!") { |*args| include!(name, *args) }
|
77
|
+
ids_method = power_ids_name(name)
|
78
|
+
define_method(ids_method) do |*args|
|
79
|
+
scope = send(name, *args)
|
80
|
+
scope = scope.scoped(:select => "`#{scope.table_name}`.`id`")
|
81
|
+
query = Util.scope_to_sql(scope)
|
82
|
+
::ActiveRecord::Base.connection.select_values(query).collect(&:to_i)
|
83
|
+
end
|
84
|
+
memoize ids_method
|
85
|
+
name
|
86
|
+
end
|
87
|
+
|
87
88
|
end
|
88
89
|
|
89
90
|
end
|
data/lib/consul/util.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module Consul
|
2
|
+
module Util
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def scope_to_sql(scope)
|
6
|
+
if scope.respond_to?(:to_sql)
|
7
|
+
scope.to_sql
|
8
|
+
else
|
9
|
+
scope.send(:construct_finder_sql, {})
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def scope_selects_all_records?(scope)
|
14
|
+
scope = scope.scoped({})
|
15
|
+
scope_sql = scope_to_sql(scope)
|
16
|
+
quoted_table_name = Regexp.quote(scope.connection.quote_table_name(scope.table_name))
|
17
|
+
all_sql_pattern = /\ASELECT (#{quoted_table_name}\.)?\* FROM #{quoted_table_name}\z/
|
18
|
+
scope_sql.squish =~ all_sql_pattern
|
19
|
+
end
|
20
|
+
|
21
|
+
def scope?(value)
|
22
|
+
value.respond_to?(:scoped)
|
23
|
+
end
|
24
|
+
|
25
|
+
def collection?(value)
|
26
|
+
value.is_a?(Array) || value.is_a?(Set)
|
27
|
+
end
|
28
|
+
|
29
|
+
def define_scope(klass, name, options)
|
30
|
+
if Rails.version.to_i < 3
|
31
|
+
klass.send(:named_scope, name, options)
|
32
|
+
else
|
33
|
+
klass.send(:scope, name, options)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
data/lib/consul/version.rb
CHANGED
@@ -3,6 +3,8 @@ $: << File.join(File.dirname(__FILE__), "/../../lib" )
|
|
3
3
|
# Set the default environment to sqlite3's in_memory database
|
4
4
|
ENV['RAILS_ENV'] = 'in_memory'
|
5
5
|
|
6
|
+
FileUtils.rm(Dir.glob("db/*.db"), :force => true)
|
7
|
+
|
6
8
|
# Load the Rails environment and testing framework
|
7
9
|
require "#{File.dirname(__FILE__)}/../app_root/config/environment"
|
8
10
|
require 'spec/rails'
|
@@ -4,14 +4,14 @@ $: << File.join(File.dirname(__FILE__), "/../../lib" )
|
|
4
4
|
ENV['RAILS_ENV'] ||= 'test'
|
5
5
|
ENV['RAILS_ROOT'] = 'app_root'
|
6
6
|
|
7
|
+
FileUtils.rm(Dir.glob("db/*.db"), :force => true)
|
8
|
+
|
7
9
|
# Load the Rails environment and testing framework
|
8
10
|
require "#{File.dirname(__FILE__)}/../app_root/config/environment"
|
9
11
|
require 'rspec/rails'
|
10
12
|
|
11
13
|
require 'rspec_candy/helpers'
|
12
14
|
|
13
|
-
FileUtils.rm(Dir.glob("#{Rails.root}/db/*.db"), :force => true)
|
14
|
-
|
15
15
|
# Run the migrations
|
16
16
|
print "\033[30m" # dark gray text
|
17
17
|
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate")
|
@@ -3,7 +3,7 @@ $: << File.join(File.dirname(__FILE__), "/../../lib" )
|
|
3
3
|
ENV['RAILS_ENV'] ||= 'test'
|
4
4
|
ENV['RAILS_ROOT'] = 'app_root'
|
5
5
|
|
6
|
-
FileUtils.rm(Dir.glob("
|
6
|
+
FileUtils.rm(Dir.glob("db/*.db"), :force => true)
|
7
7
|
|
8
8
|
# Load the Rails environment and testing framework
|
9
9
|
require "#{File.dirname(__FILE__)}/../app_root/config/environment"
|
@@ -13,7 +13,6 @@ require 'rspec/rails'
|
|
13
13
|
|
14
14
|
require 'rspec_candy/helpers'
|
15
15
|
|
16
|
-
|
17
16
|
# Run the migrations
|
18
17
|
print "\033[30m" # dark gray text
|
19
18
|
ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate")
|
@@ -9,6 +9,10 @@ class Power
|
|
9
9
|
Client.active unless guest?
|
10
10
|
end
|
11
11
|
|
12
|
+
power :all_clients do
|
13
|
+
Client
|
14
|
+
end
|
15
|
+
|
12
16
|
power :client_notes do |client|
|
13
17
|
client.notes
|
14
18
|
end
|
@@ -57,6 +61,18 @@ class Power
|
|
57
61
|
'secret-api-key' unless guest?
|
58
62
|
end
|
59
63
|
|
64
|
+
power :shorthand1, :shorthand2, :shorthand3 do
|
65
|
+
'shorthand'
|
66
|
+
end
|
67
|
+
|
68
|
+
power :songs do
|
69
|
+
Song
|
70
|
+
end
|
71
|
+
|
72
|
+
power :recent_songs do
|
73
|
+
Song.recent
|
74
|
+
end
|
75
|
+
|
60
76
|
private
|
61
77
|
|
62
78
|
attr_accessor :user
|
@@ -112,6 +112,26 @@ describe Consul::Power do
|
|
112
112
|
@user.power.client?(@deleted_client)
|
113
113
|
end
|
114
114
|
|
115
|
+
it 'should trigger a query if the scope defines a condition' do
|
116
|
+
ActiveRecord::Base.connection.should_receive(:select_values).and_return([])
|
117
|
+
@user.power.client?(@client1)
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should not trigger a query if the scope defines no conditions' do
|
121
|
+
ActiveRecord::Base.connection.should_not_receive(:select_values)
|
122
|
+
@user.power.all_client?(@client1)
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should always trigger a query if a returned model has a default scope, even if it defines no additional conditions' do
|
126
|
+
ActiveRecord::Base.connection.should_receive(:select_values).and_return([])
|
127
|
+
@user.power.song?(Song.new)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'should trigger query if a returned model has a default scope and defines additional conditions' do
|
131
|
+
ActiveRecord::Base.connection.should_receive(:select_values).and_return([])
|
132
|
+
@user.power.recent_song?(Song.new)
|
133
|
+
end
|
134
|
+
|
115
135
|
end
|
116
136
|
|
117
137
|
end
|
@@ -351,6 +371,16 @@ describe Consul::Power do
|
|
351
371
|
|
352
372
|
end
|
353
373
|
|
374
|
+
describe '.power' do
|
375
|
+
|
376
|
+
it 'should allow to define multiple powers at once' do
|
377
|
+
@user.power.shorthand1.should == 'shorthand'
|
378
|
+
@user.power.shorthand2.should == 'shorthand'
|
379
|
+
@user.power.shorthand3.should == 'shorthand'
|
380
|
+
end
|
381
|
+
|
382
|
+
end
|
383
|
+
|
354
384
|
describe '.current' do
|
355
385
|
|
356
386
|
it 'should provide a class method to set and get the current Power' do
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 5
|
9
|
+
- 0
|
10
|
+
version: 0.5.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Henning Koch
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2013-01-14 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -66,6 +66,7 @@ files:
|
|
66
66
|
- lib/consul/errors.rb
|
67
67
|
- lib/consul/power.rb
|
68
68
|
- lib/consul/spec/matchers.rb
|
69
|
+
- lib/consul/util.rb
|
69
70
|
- lib/consul/version.rb
|
70
71
|
- spec/rails-2.3/Gemfile
|
71
72
|
- spec/rails-2.3/Rakefile
|
@@ -131,10 +132,12 @@ files:
|
|
131
132
|
- spec/shared/app_root/app/models/client.rb
|
132
133
|
- spec/shared/app_root/app/models/note.rb
|
133
134
|
- spec/shared/app_root/app/models/power.rb
|
135
|
+
- spec/shared/app_root/app/models/song.rb
|
134
136
|
- spec/shared/app_root/app/models/user.rb
|
135
137
|
- spec/shared/app_root/db/migrate/001_create_users.rb
|
136
138
|
- spec/shared/app_root/db/migrate/002_create_clients.rb
|
137
139
|
- spec/shared/app_root/db/migrate/003_create_notes.rb
|
140
|
+
- spec/shared/app_root/db/migrate/004_create_songs.rb
|
138
141
|
- spec/shared/consul/active_record_spec.rb
|
139
142
|
- spec/shared/consul/controllers/cakes_controller_spec.rb
|
140
143
|
- spec/shared/consul/controllers/dashboards_controller_spec.rb
|
@@ -172,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
172
175
|
requirements: []
|
173
176
|
|
174
177
|
rubyforge_project:
|
175
|
-
rubygems_version: 1.3.9.
|
178
|
+
rubygems_version: 1.3.9.5
|
176
179
|
signing_key:
|
177
180
|
specification_version: 3
|
178
181
|
summary: A scope-based authorization solution for Ruby on Rails.
|