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 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
 
@@ -1,4 +1,5 @@
1
1
  require 'memoizer'
2
+ require 'consul/util'
2
3
  require 'consul/power'
3
4
  require 'consul/errors'
4
5
  require 'consul/controller'
@@ -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
- power_ids_name = self.class.power_ids_name(name)
20
- send(power_ids_name, *args).include?(record.id)
21
- elsif collection?(power_value)
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(name, &block)
50
- define_method(name, &block)
51
- define_method("#{name.to_s}?") { |*args| include?(name, *args) }
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
@@ -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
+
@@ -1,3 +1,3 @@
1
1
  module Consul
2
- VERSION = '0.4.2'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -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("#{ENV['RAILS_ROOT']}/db/*.db"), :force => true)
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
@@ -0,0 +1,7 @@
1
+ class Song < ActiveRecord::Base
2
+
3
+ default_scope :conditions => { :trashed => true }
4
+
5
+ Consul::Util.define_scope(self, :recent, :conditions => ['created_at > ?', 1.week.ago])
6
+
7
+ end
@@ -0,0 +1,14 @@
1
+ class CreateSongs < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ create_table :songs do |t|
5
+ t.boolean :trashed
6
+ t.timestamps
7
+ end
8
+ end
9
+
10
+ def self.down
11
+ drop_table :songs
12
+ end
13
+
14
+ end
@@ -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
- - 4
9
- - 2
10
- version: 0.4.2
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: 2012-12-14 00:00:00 +01:00
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.4
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.