cannie 0.0.5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fb9f9ff798ce6036fb378e643d66ab7a6cc678e8
4
- data.tar.gz: 4ae746f74792940b996abfd21842078b8fe794a7
3
+ metadata.gz: 9fbbd16e6ac148de444fe153765a6dc094dc24e9
4
+ data.tar.gz: cb1002198639bb6ae623277915b5cc903147c88d
5
5
  SHA512:
6
- metadata.gz: f7ce6ab4dfdfecca9c648bba8b28d19b8438cc15dc956098567853e54bf9d4cf4a8efece057537f6e30838a2db73d4014e2621fafaf55aa92ee12f975fc68a50
7
- data.tar.gz: 65bd5926da7baf5da5f5329ce4a2c466dbf38236d55bfc0b64ba351abd37971604f3603d21a935e2bc3e93a5cbcc7d72e90230087d62bd70c179c4d3d1a8f335
6
+ metadata.gz: 87b47746d61b5604032cc51f2f11720893628a1b6019274d9ab870f41d875d76bd13119105fdfecc154020ecae50d2ada46792853aa4366f147903de97c53445
7
+ data.tar.gz: ae87022d66e48972f60f9fa31adef1a5e00e4e7324ab312fe32162375051f6ab8a6f78441a77251676740d78a2d3629ab47ee44b945fed372a7963beeb88dd2c
data/README.md CHANGED
@@ -55,6 +55,38 @@ To be sure that permissions checking is handled in each action of your controlle
55
55
  #...
56
56
  end
57
57
 
58
+ It's also possible to set a condition by specifying `:if` or `:unless` options for `check_permissions` call:
59
+
60
+ class PostsController < ApplicationController
61
+ check_permissions if: :some_method
62
+
63
+ #...
64
+ end
65
+
66
+ or
67
+
68
+ class PostsController < ApplicationController
69
+ check_permissions if: ->(controller) { controller.some_method }
70
+
71
+ #...
72
+ end
73
+
74
+ or
75
+
76
+ class PostsController < ApplicationController
77
+ check_permissions unless: some_method
78
+
79
+ #...
80
+ end
81
+
82
+ or
83
+
84
+ class PostsController < ApplicationController
85
+ check_permissions unless: ->(controller) { controller.some_method }
86
+
87
+ #...
88
+ end
89
+
58
90
  To skip checking permissions for controller, add `skip_check_permissions` method call:
59
91
 
60
92
  class PagesController < ApplicationController
@@ -74,6 +106,43 @@ Checking of permissions on per-action basis is done by calling `permit!` method
74
106
  end
75
107
  end
76
108
 
109
+ It is possible to check permissions for resource actions. Currently collection and entry name is taken from resource controller name (some_namespace/entries_controller => @entries/@entry instance variables).
110
+ To add this behavior add `permit_resource_actions` instead of `check_permissions` with no need to write custom `permit!` calls in each resource action:
111
+
112
+ class EntriesController < ApplicationController
113
+ permit_resource_actions
114
+
115
+ def index
116
+ @entries = Entry.all
117
+ end
118
+
119
+ def show
120
+ @entry = Entry.find(params[:id])
121
+ end
122
+ end
123
+
124
+ For now only standard resource actions supported: `index`, `show`, `new`, `create`, `edit`, `update`, `destroy`.
125
+ To define `Permissions` properly, use this mapping of action names to permissions:
126
+ - :index => :list
127
+ - :show => :read
128
+ - :new or :create => :create
129
+ - :edit or :update => :update
130
+ - :destroy => :destroy
131
+
132
+ Sample `Permissions` class to deal with all resource actions for `EntriesController`:
133
+
134
+ class Permissions
135
+ include Cannie::Permissions
136
+
137
+ def initialize(user)
138
+ allow :list, on: Entry # index action
139
+ allow :read, on: Entry # show action
140
+ allow :create, on: Entry # new & create actions
141
+ allow :update, on: Entry # edit & update actions
142
+ allow :destroy, on: Entry # destroy action
143
+ end
144
+ end
145
+
77
146
  ### Handling of unpermitted access
78
147
 
79
148
  If user is not permitted for appropriate action, `Cannie::ActionForbidden` exception will be raised.
@@ -7,6 +7,16 @@ module Cannie
7
7
  helper_method :can?, :current_permissions
8
8
  end
9
9
 
10
+ RESOURCE_ACTIONS = {
11
+ index: :list,
12
+ show: :read,
13
+ new: :create,
14
+ create: :create,
15
+ edit: :update,
16
+ update: :update,
17
+ destroy: :destroy
18
+ }
19
+
10
20
  module ClassMethods
11
21
  # Method is used to be sure, that permissions checking is handled for each action inside controller.
12
22
  #
@@ -37,6 +47,23 @@ module Cannie
37
47
  controller.instance_variable_set(:@_permitted, true)
38
48
  end
39
49
  end
50
+
51
+ # Permit resource actions [index, show, new, create, edit, update, destroy] in controller
52
+ #
53
+ #
54
+ def permit_resource_actions(options={})
55
+ after_action(options.slice(:only, :except)) do |controller|
56
+ begin
57
+ next if controller.permitted?
58
+ next if options[:if] && !controller.instance_eval(&options[:if])
59
+ next if options[:unless] && controller.instance_eval(&options[:unless])
60
+ controller.permit! RESOURCE_ACTIONS.with_indifferent_access[action_name], on: controller.subject_for_action
61
+ rescue Cannie::ActionForbidden
62
+ self.response_body = nil
63
+ raise
64
+ end
65
+ end
66
+ end
40
67
  end
41
68
 
42
69
  # Checks whether passed action is permitted for passed subject
@@ -80,6 +107,14 @@ module Cannie
80
107
  @current_permissions ||= ::Permissions.new(current_user)
81
108
  end
82
109
 
110
+ def subject_for_action
111
+ return unless RESOURCE_ACTIONS.with_indifferent_access.keys.include?(action_name)
112
+ entry_name = controller_name.classify.demodulize.downcase
113
+ collection_name = entry_name.pluralize
114
+ variable_name = action_name == 'index' ? collection_name : entry_name
115
+ instance_variable_get(:"@#{variable_name}")
116
+ end
117
+
83
118
  private
84
119
  attr_reader :_permitted
85
120
  end
@@ -1,3 +1,3 @@
1
1
  module Cannie
2
- VERSION = '0.0.5'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -4,6 +4,17 @@ describe Cannie::ControllerExtensions do
4
4
  let(:klass) {
5
5
  Class.new(ActionController::Base) do
6
6
  def action; end
7
+ def index
8
+ @entries = [1,2,3,4,5]
9
+ render text: @entries.to_s
10
+ end
11
+
12
+ %i(show new create edit update destroy).each do |action|
13
+ define_method action do
14
+ @entry = 123
15
+ render text: @entry.to_s
16
+ end
17
+ end
7
18
  end
8
19
  }
9
20
 
@@ -21,6 +32,17 @@ describe Cannie::ControllerExtensions do
21
32
  end
22
33
  end
23
34
 
35
+ let(:resource_permissions) do
36
+ Class.new do
37
+ include Cannie::Permissions
38
+
39
+ def initialize
40
+ allow :list, on: Array
41
+ %i(read create update destroy).each{ |v| allow v, on: Fixnum }
42
+ end
43
+ end
44
+ end
45
+
24
46
  describe '.check_permissions' do
25
47
  describe 'without conditions' do
26
48
  before { klass.check_permissions }
@@ -72,6 +94,37 @@ describe Cannie::ControllerExtensions do
72
94
  end
73
95
  end
74
96
 
97
+ describe 'permit_resource_actions' do
98
+ before do
99
+ klass.permit_resource_actions
100
+ subject.stub(:controller_name).and_return('test/entries')
101
+ subject.stub(:current_permissions).and_return resource_permissions.new
102
+ end
103
+
104
+ it 'calls permit! for index with valid params' do
105
+ expect(subject).to receive(:permit!).with(Cannie::ControllerExtensions::RESOURCE_ACTIONS[:index], on: [1,2,3,4,5])
106
+ subject.dispatch(:index, ActionDispatch::TestRequest.new)
107
+ end
108
+
109
+ it 'calls permit! for show with valid params' do
110
+ expect(subject).to receive(:permit!).with(Cannie::ControllerExtensions::RESOURCE_ACTIONS[:show], on: 123)
111
+ subject.dispatch(:show, ActionDispatch::TestRequest.new)
112
+ end
113
+
114
+ %i(index show).each do |action|
115
+ it "permits #{action} action" do
116
+ subject.dispatch(action, ActionDispatch::TestRequest.new)
117
+ expect(subject.permitted?).to be_true
118
+ end
119
+ end
120
+
121
+ it 'raises Cannie::ActionForbidden error up the stack' do
122
+ expect(subject).to receive(:index).and_raise(Cannie::ActionForbidden)
123
+ expect { subject.dispatch(:index, ActionDispatch::TestRequest.new) }.to raise_error(Cannie::ActionForbidden)
124
+ expect(subject.response_body).to be_nil
125
+ end
126
+ end
127
+
75
128
  describe '#can?' do
76
129
  it 'raises SubjectNotSetError if value of :on param is nil' do
77
130
  expect { subject.can? :action }.to raise_error(Cannie::SubjectNotSetError)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cannie
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - hck
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-14 00:00:00.000000000 Z
11
+ date: 2013-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler