cannie 0.0.5 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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