consul 0.9.1 → 0.10.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.

@@ -4,5 +4,6 @@ require 'consul/util'
4
4
  require 'consul/power/dynamic_access'
5
5
  require 'consul/power'
6
6
  require 'consul/errors'
7
+ require 'consul/guard'
7
8
  require 'consul/controller'
8
9
  require 'consul/active_record'
@@ -31,6 +31,7 @@ module Consul
31
31
  before_filter :unchecked_power, options
32
32
  end
33
33
 
34
+ # This is badly named, since it doesn't actually skip the :check_power filter
34
35
  def skip_power_check(options = {})
35
36
  skip_before_filter :unchecked_power, options
36
37
  end
@@ -41,62 +42,26 @@ module Consul
41
42
  helper_method :current_power
42
43
  end
43
44
 
44
- def power(*args)
45
-
46
- args_copy = args.dup
47
- options = args_copy.extract_options!
48
- default_power = args_copy.shift # might be nil
49
-
50
- filter_options = options.slice(:except, :only)
51
- skip_power_check filter_options
52
-
53
- power_method = options[:power] || :current_power
54
-
55
- actions_map = (options[:map] || {})
45
+ def consul_guards
46
+ @consul_guards ||= []
47
+ end
56
48
 
57
- if crud_resource = options[:crud]
58
- default_power ||= crud_resource
59
- actions_map[[:show, :index]] = crud_resource.to_sym
60
- actions_map[[:new, :create]] = "creatable_#{crud_resource}".to_sym
61
- actions_map[[:edit, :update]] = "updatable_#{crud_resource}".to_sym
62
- actions_map[:destroy] = "destroyable_#{crud_resource}".to_sym
63
- end
49
+ def power(*args)
64
50
 
65
- direct_access_method = options[:as]
51
+ guard = Consul::Guard.new(*args)
52
+ consul_guards << guard
53
+ skip_power_check guard.filter_options
66
54
 
67
55
  # Store arguments for testing
68
- @consul_power_args = args
69
-
70
- before_filter :check_power, filter_options
71
-
72
- singleton_class.send(:define_method, :power_name_for_action) do |action_name|
73
- action_name = action_name.to_s
74
- key = actions_map.keys.detect do |actions|
75
- Array(actions).collect(&:to_s).include?(action_name)
76
- end
77
- if key
78
- actions_map[key]
79
- elsif default_power
80
- default_power
81
- else
82
- raise Consul::UnmappedAction, "Could not map the action ##{action_name} to a power"
83
- end
84
- end
56
+ (@consul_power_args ||= []) << args
85
57
 
86
- private
87
-
88
- define_method :check_power do
89
- send(power_method).include_power!(power_name_for_current_action)
90
- end
58
+ before_filter :check_power, guard.filter_options
91
59
 
92
- if direct_access_method
93
- define_method direct_access_method do
94
- send(power_method).send(power_name_for_current_action)
60
+ if guard.direct_access_method
61
+ define_method guard.direct_access_method do
62
+ guard.power_value(self, action_name)
95
63
  end
96
- end
97
-
98
- define_method :power_name_for_current_action do
99
- self.class.power_name_for_action(action_name)
64
+ private guard.direct_access_method
100
65
  end
101
66
 
102
67
  end
@@ -107,6 +72,12 @@ module Consul
107
72
 
108
73
  private
109
74
 
75
+ define_method :check_power do
76
+ self.class.send(:consul_guards).each do |guard|
77
+ guard.ensure!(self, action_name)
78
+ end
79
+ end
80
+
110
81
  def unchecked_power
111
82
  raise Consul::UncheckedPower, "This controller does not check against a power"
112
83
  end
@@ -5,5 +5,5 @@ module Consul
5
5
  class UnmappedAction < Error; end
6
6
  class UnreachablePower < Error; end
7
7
  class NoCollection < Error; end
8
- class InsufficientContext < Error; end
8
+ class MissingContext < Error; end
9
9
  end
@@ -0,0 +1,113 @@
1
+ module Consul
2
+ class Guard
3
+
4
+ class ActionMap
5
+
6
+ def initialize(default_power, custom_mappings)
7
+ @default_power = default_power
8
+ @map = {}
9
+ if custom_mappings.present?
10
+ custom_mappings.each do |action_or_actions, power|
11
+ Array.wrap(action_or_actions).each do |action|
12
+ action = action.to_s
13
+ @map[action] = power
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ def self.crud(resource, custom_map)
20
+ map = {}
21
+ map[[:show, :index]] = resource.to_sym
22
+ map[[:new, :create]] = "creatable_#{resource}".to_sym
23
+ map[[:edit, :update]] = "updatable_#{resource}".to_sym
24
+ map[:destroy] = "destroyable_#{resource}".to_sym
25
+ map = normalize_map(map).merge(normalize_map(custom_map)) # allow people to override the defaults
26
+ new(resource, map)
27
+ end
28
+
29
+ def self.normalize_map(map)
30
+ normalized_map = {}
31
+ if map.present?
32
+ map.each do |action_or_actions, power|
33
+ Array.wrap(action_or_actions).each do |action|
34
+ action = action.to_s
35
+ normalized_map[action] = power
36
+ end
37
+ end
38
+ end
39
+ normalized_map
40
+ end
41
+
42
+ def power_name(action_name)
43
+ action_name = action_name.to_s
44
+ @map[action_name] || @default_power or raise Consul::UnmappedAction, "Could not map the action ##{action_name} to a power"
45
+ end
46
+
47
+ end
48
+
49
+ def initialize(*args)
50
+
51
+ args_copy = args.dup
52
+ @options = args_copy.extract_options!
53
+
54
+ default_power = args_copy.shift # might be nil
55
+
56
+ custom_action_mappings = @options[:map]
57
+
58
+ if @options[:crud]
59
+ @map = ActionMap.crud(@options[:crud], custom_action_mappings)
60
+ else
61
+ @map = ActionMap.new(default_power, custom_action_mappings)
62
+ end
63
+
64
+ end
65
+
66
+ def power_value(controller, action_name)
67
+ repository(controller).send(*power_name_with_context(controller, action_name))
68
+ end
69
+
70
+ def ensure!(controller, action_name)
71
+ repository(controller).include_power!(*power_name_with_context(controller, action_name))
72
+ end
73
+
74
+ def filter_options
75
+ @options.slice(:except, :only)
76
+ end
77
+
78
+ def direct_access_method
79
+ @options[:as]
80
+ end
81
+
82
+ private
83
+
84
+ def power_name(action_name)
85
+ @map.power_name(action_name)
86
+ end
87
+
88
+ def power_name_with_context(controller, action_name)
89
+ [power_name(action_name), *context(controller)]
90
+ end
91
+
92
+ def repository(controller)
93
+ controller.send(repository_method)
94
+ end
95
+
96
+ def repository_method
97
+ @options[:power] || :current_power
98
+ end
99
+
100
+ def context(controller)
101
+ context = []
102
+ Array.wrap(@options[:context]).each do |context_method|
103
+ arg = controller.send(context_method)
104
+ if arg.nil?
105
+ raise Consul::MissingContext
106
+ end
107
+ context << arg
108
+ end
109
+ context
110
+ end
111
+
112
+ end
113
+ end
@@ -11,7 +11,7 @@ module Consul
11
11
  def matches?(controller)
12
12
  @controller_class = controller.class
13
13
  @actual_args = @controller_class.instance_variable_get('@consul_power_args')
14
- @actual_args == @expected_args
14
+ @actual_args.present? && @actual_args.include?(@expected_args)
15
15
  end
16
16
 
17
17
  def failure_message
@@ -1,3 +1,3 @@
1
1
  module Consul
2
- VERSION = '0.9.1'
2
+ VERSION = '0.10.0'
3
3
  end
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- consul (0.8.0)
4
+ consul (0.9.1)
5
5
  edge_rider
6
6
  memoizer
7
7
  rails
@@ -10,4 +10,12 @@ ActionController::Routing::Routes.draw do |map|
10
10
 
11
11
  map.resources :cakes, :member => { :custom_action => :get }
12
12
 
13
+ map.resources :colors
14
+
15
+ map.resources :notes
16
+
17
+ map.resources :clients do
18
+ map.resources :notes
19
+ end
20
+
13
21
  end
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- consul (0.8.0)
4
+ consul (0.9.1)
5
5
  edge_rider
6
6
  memoizer
7
7
  rails
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- consul (0.8.0)
4
+ consul (0.9.1)
5
5
  edge_rider
6
6
  memoizer
7
7
  rails
@@ -7,7 +7,6 @@ class ApplicationController < ActionController::Base
7
7
  Power.new(User.new)
8
8
  end
9
9
 
10
-
11
10
  private
12
11
 
13
12
  def render_nothing
@@ -0,0 +1,13 @@
1
+ class ClientNotesController < ApplicationController
2
+
3
+ power :clients, :as => :client_scope
4
+
5
+ power :client_notes, :context => :client, :as => :note_scope
6
+
7
+ private
8
+
9
+ def client
10
+ @client ||= client_scope.find(params[:client_id])
11
+ end
12
+
13
+ end
@@ -0,0 +1,10 @@
1
+ class ColorsController < ApplicationController
2
+
3
+ power :red, :as => :red_scope
4
+ power :blue, :as => :blue_scope
5
+
6
+ def show
7
+ render_nothing
8
+ end
9
+
10
+ end
@@ -1,8 +1,9 @@
1
1
  class Power
2
2
  include Consul::Power
3
3
 
4
- def initialize(user = nil)
5
- @user = user
4
+ def initialize(*args)
5
+ @options = args.extract_options!
6
+ @user = args.first
6
7
  end
7
8
 
8
9
  power :clients do
@@ -105,6 +106,14 @@ class Power
105
106
  'deal_items power'
106
107
  end
107
108
 
109
+ power :red do
110
+ 'red' if @options[:red]
111
+ end
112
+
113
+ power :blue do
114
+ 'blue' if @options[:blue]
115
+ end
116
+
108
117
  private
109
118
 
110
119
  attr_accessor :user
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe ClientNotesController, :type => :controller do
4
+
5
+ it 'should map powers with context' do
6
+ @client1 = Client.create!
7
+ @client1_note1 = @client1.notes.create!
8
+ @client2 = Client.create!
9
+ @client2_note1 = @client2.notes.create!
10
+ controller.stub(
11
+ :current_power => Power.new,
12
+ :client => @client1
13
+ )
14
+ controller.send(:note_scope).to_a.should == [@client1_note1]
15
+ end
16
+
17
+ it 'should fail if a context is missing' do
18
+ controller.stub(
19
+ :current_power => Power.new,
20
+ :client => nil
21
+ )
22
+ expect { controller.send(:note_scope) }.to raise_error(Consul::MissingContext)
23
+ end
24
+
25
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe ColorsController, :type => :controller do
4
+
5
+ it "should allow multiple .power directives" do
6
+ controller.stub :current_power => Power.new(:red => true, :blue => false)
7
+ expect { get :show, :id => '1' }.to raise_error(Consul::Powerless)
8
+ controller.stub :current_power => Power.new(:red => false, :blue => true)
9
+ expect { get :show, :id => '1' }.to raise_error(Consul::Powerless)
10
+ controller.stub :current_power => Power.new(:red => true, :blue => true)
11
+ expect { get :show, :id => '1' }.to_not raise_error
12
+ end
13
+
14
+ it 'should be able to map multiple powers to methods' do
15
+ controller.stub :current_power => Power.new(:red => true, :blue => false)
16
+ controller.send(:red_scope).should == 'red'
17
+ controller.send(:blue_scope).should be_nil
18
+ controller.stub :current_power => Power.new(:red => false, :blue => true)
19
+ controller.send(:red_scope).should be_nil
20
+ controller.send(:blue_scope).should == 'blue'
21
+ end
22
+
23
+ it 'should make a mapped power method private' do
24
+ controller.stub :current_power => Power.new
25
+ expect { controller.red_scope }.to raise_error(NoMethodError)
26
+ expect { controller.send(:red_scope) }.to_not raise_error
27
+ end
28
+
29
+ end
@@ -11,15 +11,15 @@ describe UsersController, :type => :controller do
11
11
  end
12
12
 
13
13
 
14
- describe '.power_name_for_action' do
15
-
16
- it 'should return the name of the power for the given action (feature request from devolute)' do
17
- UsersController.power_name_for_action(:show).should == :always_true
18
- UsersController.power_name_for_action('show').should == :always_true
19
- UsersController.power_name_for_action(:update).should == :always_false
20
- UsersController.power_name_for_action('update').should == :always_false
21
- end
22
-
23
- end
14
+ #describe '.power_name_for_action' do
15
+ #
16
+ # it 'should return the name of the power for the given action (feature request from devolute)' do
17
+ # UsersController.power_name_for_action(:show).should == :always_true
18
+ # UsersController.power_name_for_action('show').should == :always_true
19
+ # UsersController.power_name_for_action(:update).should == :always_false
20
+ # UsersController.power_name_for_action('update').should == :always_false
21
+ # end
22
+ #
23
+ #end
24
24
 
25
25
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: consul
3
3
  version: !ruby/object:Gem::Version
4
- hash: 57
4
+ hash: 55
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 9
9
- - 1
10
- version: 0.9.1
8
+ - 10
9
+ - 0
10
+ version: 0.10.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: 2013-07-26 00:00:00 +02:00
18
+ date: 2013-08-21 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -79,6 +79,7 @@ files:
79
79
  - lib/consul/active_record.rb
80
80
  - lib/consul/controller.rb
81
81
  - lib/consul/errors.rb
82
+ - lib/consul/guard.rb
82
83
  - lib/consul/power.rb
83
84
  - lib/consul/power/dynamic_access.rb
84
85
  - lib/consul/spec/matchers.rb
@@ -144,6 +145,8 @@ files:
144
145
  - spec/rails-3.2/spec/spec_helper.rb
145
146
  - spec/shared/app_root/app/controllers/application_controller.rb
146
147
  - spec/shared/app_root/app/controllers/cakes_controller.rb
148
+ - spec/shared/app_root/app/controllers/client_notes_controller.rb
149
+ - spec/shared/app_root/app/controllers/colors_controller.rb
147
150
  - spec/shared/app_root/app/controllers/dashboards_controller.rb
148
151
  - spec/shared/app_root/app/controllers/risks_controller.rb
149
152
  - spec/shared/app_root/app/controllers/songs_controller.rb
@@ -161,12 +164,14 @@ files:
161
164
  - spec/shared/app_root/db/migrate/004_create_songs.rb
162
165
  - spec/shared/consul/active_record_spec.rb
163
166
  - spec/shared/consul/controllers/cakes_controller_spec.rb
167
+ - spec/shared/consul/controllers/client_notes_controller_spec.rb
168
+ - spec/shared/consul/controllers/colors_controller_spec.rb
164
169
  - spec/shared/consul/controllers/dashboards_controller_spec.rb
165
170
  - spec/shared/consul/controllers/risks_controller_spec.rb
166
171
  - spec/shared/consul/controllers/songs_controller_spec.rb
167
172
  - spec/shared/consul/controllers/users_controller_spec.rb
168
- - spec/shared/consul/controllers/util_spec.rb
169
173
  - spec/shared/consul/power_spec.rb
174
+ - spec/shared/consul/util_spec.rb
170
175
  has_rdoc: true
171
176
  homepage: https://github.com/makandra/consul
172
177
  licenses: