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 +4 -4
- data/README.md +69 -0
- data/lib/cannie/controller_extensions.rb +35 -0
- data/lib/cannie/version.rb +1 -1
- data/spec/cannie/controller_extensions_spec.rb +53 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9fbbd16e6ac148de444fe153765a6dc094dc24e9
|
4
|
+
data.tar.gz: cb1002198639bb6ae623277915b5cc903147c88d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/cannie/version.rb
CHANGED
@@ -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
|
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-
|
11
|
+
date: 2013-09-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|