permissioner 0.0.2.beta → 0.1.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/permissioner.rb +2 -2
- data/lib/permissioner/{permission_configurer.rb → configurer.rb} +2 -2
- data/lib/permissioner/controller_additions.rb +1 -2
- data/lib/permissioner/matchers.rb +39 -7
- data/lib/permissioner/matchers/exactly_allow_attributes.rb +137 -0
- data/lib/permissioner/matchers/exactly_allow_controllers.rb +48 -0
- data/lib/permissioner/matchers/exactly_allow_resources.rb +44 -0
- data/lib/permissioner/matchers/exactly_expect_actions.rb +100 -0
- data/lib/permissioner/{permission_service_additions.rb → service_additions.rb} +23 -7
- data/lib/permissioner/version.rb +1 -1
- data/permissioner.gemspec +1 -1
- data/spec/permissioner/{permission_configurer_spec.rb → configurer_spec.rb} +8 -2
- data/spec/permissioner/controller_additions_spec.rb +3 -20
- data/spec/permissioner/matchers/exactly_allow_attributes_spec.rb +227 -0
- data/spec/permissioner/matchers/exactly_allow_controllers_spec.rb +86 -0
- data/spec/permissioner/matchers/exactly_allow_resources_spec.rb +78 -0
- data/spec/permissioner/matchers/exactly_expect_actions_spec.rb +188 -0
- data/spec/permissioner/matchers_spec.rb +70 -27
- data/spec/permissioner/{permission_service_additions_spec.rb → service_additions_spec.rb} +117 -28
- data/spec/spec_helper.rb +1 -1
- metadata +22 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ba85c8029c5e0f9a4f4f9e57c546ff2dc87e74e
|
4
|
+
data.tar.gz: e9502b6cb5c9a1dc7a269ce74af1e93b23e4606e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e4802cc89cfb79b4a6d500f72ca4d0e4d31650bf6c183bebd8c7caac7d34342d074fead3c94e9ece2d6e3eb79f4d3b04566a497c52806d2cf8e12be65c993295
|
7
|
+
data.tar.gz: 9d1710c507e6d7a74ed131d8f8899bd3ef6abcd7623ff676c69c3341be585a0d150f7c7536c073152ae4ad8674286157c017cbaf83f983a24485448b90d995c0
|
data/lib/permissioner.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require "permissioner/version"
|
2
|
-
require "permissioner/
|
3
|
-
require "permissioner/
|
2
|
+
require "permissioner/service_additions"
|
3
|
+
require "permissioner/configurer"
|
4
4
|
require "permissioner/controller_additions"
|
5
5
|
require "permissioner/exceptions"
|
6
6
|
require "permissioner/railtie" if defined?(Rails)
|
@@ -24,10 +24,10 @@ module Permissioner
|
|
24
24
|
# end
|
25
25
|
# end
|
26
26
|
#
|
27
|
-
module
|
27
|
+
module Configurer
|
28
28
|
|
29
29
|
attr_reader :current_user, :permission_service
|
30
|
-
delegate :allow_actions, :allow_attributes, :add_filter, to: :permission_service
|
30
|
+
delegate :allow_actions, :allow_attributes, :add_filter, :clear_filters, to: :permission_service
|
31
31
|
|
32
32
|
|
33
33
|
# Expects an instance of a class including module Permissioner::PermissionServiceAdditions acting as
|
@@ -7,8 +7,7 @@ module Permissioner
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def authorize
|
10
|
-
if permission_service.allow_action?(params[:controller], params[:action], current_resource)
|
11
|
-
permission_service.passed_filters?(params[:controller], params[:action], params)
|
10
|
+
if permission_service.allow_action?(params[:controller], params[:action], resource: current_resource, params: params)
|
12
11
|
permission_service.permit_params!(params)
|
13
12
|
else
|
14
13
|
raise Permissioner::NotAuthorized
|
@@ -1,16 +1,48 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
end
|
1
|
+
require 'permissioner/matchers/exactly_expect_actions'
|
2
|
+
require 'permissioner/matchers/exactly_allow_attributes'
|
3
|
+
require 'permissioner/matchers/exactly_allow_controllers'
|
4
|
+
require 'permissioner/matchers/exactly_allow_resources'
|
6
5
|
|
7
6
|
RSpec::Matchers.define :allow_attribute do |*args|
|
8
7
|
match do |permission_service|
|
9
8
|
permission_service.allow_attribute?(*args)
|
10
9
|
end
|
11
10
|
end
|
12
|
-
|
11
|
+
|
12
|
+
RSpec::Matchers.define :pass_filters do |*args|
|
13
13
|
match do |permission_service|
|
14
|
-
permission_service.passed_filters?(
|
14
|
+
permission_service.passed_filters?(*args)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Permissioner
|
19
|
+
module Matchers
|
20
|
+
|
21
|
+
RSpec::Matchers.define :allow_action do |*args|
|
22
|
+
match do |permission_service|
|
23
|
+
permission_service.allow_action?(*args)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def exactly_allow_actions(*expected_actions)
|
28
|
+
ExactlyExpectActions.new(:@allowed_actions, *expected_actions)
|
29
|
+
end
|
30
|
+
|
31
|
+
def exactly_have_filters_for(*expected_actions)
|
32
|
+
ExactlyExpectActions.new(:@filters, *expected_actions)
|
33
|
+
end
|
34
|
+
|
35
|
+
def exactly_allow_attributes(*expected_attributes)
|
36
|
+
ExactlyAllowAttributes.new(*expected_attributes)
|
37
|
+
end
|
38
|
+
|
39
|
+
def exactly_allow_controllers(*expected_controllers)
|
40
|
+
ExactlyAllowControllers.new(*expected_controllers)
|
41
|
+
end
|
42
|
+
|
43
|
+
def exactly_allow_resources(*expected_resources)
|
44
|
+
ExactlyAllowResources.new(*expected_resources)
|
45
|
+
end
|
46
|
+
|
15
47
|
end
|
16
48
|
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
module Permissioner
|
2
|
+
module Matchers
|
3
|
+
class ExactlyAllowAttributes
|
4
|
+
|
5
|
+
def initialize(*all_expected_attributes)
|
6
|
+
@all_expected_attributes = all_expected_attributes.collect do |value|
|
7
|
+
raise 'multiple attributes for a resource must stated as array, e.g. [:user_id, :username]' if value.size > 2
|
8
|
+
[value[0], Array(value[1])]
|
9
|
+
end
|
10
|
+
@failing_attributes = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def matches?(permission_service)
|
14
|
+
@permission_service = permission_service
|
15
|
+
expected_attributes_exactly_match?
|
16
|
+
end
|
17
|
+
|
18
|
+
def failure_message_for_should
|
19
|
+
if @failing_attributes.empty?
|
20
|
+
"expected to find allowed attributes for resources\n" \
|
21
|
+
"#{all_expected_resources}, but found allowed attributes for resources\n"\
|
22
|
+
"#{all_allowed_resources}"
|
23
|
+
else
|
24
|
+
message = "expected attributes did not match for following resources:\n"
|
25
|
+
@failing_attributes.inject(message) do |msg, value|
|
26
|
+
msg +=
|
27
|
+
"#{value[0]}:\n"\
|
28
|
+
"#{value[1]} were expected to be allowed, but attributes\n"\
|
29
|
+
"#{allowed_attrributes_for_resource(value[0])} are allowed\n"
|
30
|
+
msg
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def failure_message_for_should_not
|
36
|
+
'given attributes are exactly allowed although this is not expected'
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def expected_attributes_exactly_match?
|
42
|
+
resources_exactly_match? && attributes_exactly_match?
|
43
|
+
end
|
44
|
+
|
45
|
+
def resources_exactly_match?
|
46
|
+
all_expected_resources == all_allowed_resources
|
47
|
+
end
|
48
|
+
|
49
|
+
def attributes_exactly_match?
|
50
|
+
@all_expected_attributes.each do |resource, expected_attributes_for_resource|
|
51
|
+
|
52
|
+
match = expected_attributes_for_resource.count == allowed_attrributes_for_resource(resource).count
|
53
|
+
|
54
|
+
if match
|
55
|
+
match = expected_attributes_for_resource.all? do |expected_attribute|
|
56
|
+
@permission_service.allow_attribute?(resource, expected_attribute)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
unless match
|
61
|
+
@failing_attributes << [resource, expected_attributes_for_resource]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
@failing_attributes.empty?
|
65
|
+
end
|
66
|
+
|
67
|
+
def all_expected_resources
|
68
|
+
@all_expected_resources ||= begin
|
69
|
+
@all_expected_attributes.collect { |value| value[0] }.sort
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def all_allowed_resources
|
74
|
+
@all_allowed_resources ||= begin
|
75
|
+
if all_allowed_attributes.any?
|
76
|
+
all_allowed_attributes.keys.sort
|
77
|
+
else
|
78
|
+
[]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def allowed_attrributes_for_resource(resource)
|
84
|
+
@all_allowed_attributes ||= {}
|
85
|
+
@all_allowed_attributes[resource] ||= begin
|
86
|
+
if all_allowed_attributes[resource]
|
87
|
+
all_allowed_attributes[resource].sort
|
88
|
+
else
|
89
|
+
[]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def all_allowed_attributes
|
95
|
+
@all_allowed_attributes ||= begin
|
96
|
+
all_allowed_attributes = @permission_service.instance_variable_get(:@allowed_attributes)
|
97
|
+
all_allowed_attributes || {}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
#def matches?(permission_service)
|
102
|
+
# @permission_service = permission_service
|
103
|
+
# expected_attributs_exactly_macht? allowed_attributes_for_resource
|
104
|
+
#end
|
105
|
+
#
|
106
|
+
#def failure_message_for_should
|
107
|
+
# "expected that for resource \"#{@resource}\" attributes\n"\
|
108
|
+
# "#{@expected_attributes} are exactly allowed, but found attributes\n"\
|
109
|
+
# "#{allowed_attributes_for_resource} allowed"
|
110
|
+
#end
|
111
|
+
#
|
112
|
+
#def failure_message_for_should_not
|
113
|
+
# "expected that for resource \"#{@resource}\" attributes\n"\
|
114
|
+
# "#{@expected_attributes} are exactly not allowed,\n"\
|
115
|
+
# "but those attributes are exactly allowed\n"
|
116
|
+
#end
|
117
|
+
#
|
118
|
+
#private
|
119
|
+
#
|
120
|
+
#def expected_attributs_exactly_macht?(allowed_attributes_for_resource)
|
121
|
+
# allowed_attributes_for_resource.count == @expected_attributes.count &&
|
122
|
+
# @expected_attributes.all? { |attribute| allowed_attributes_for_resource.include? attribute }
|
123
|
+
#end
|
124
|
+
#
|
125
|
+
#def allowed_attributes_for_resource
|
126
|
+
# @allowed_attributes_for_resource ||= begin
|
127
|
+
# all_allowed_attributes = @permission_service.instance_variable_get(:@allowed_attributes)
|
128
|
+
# if all_allowed_attributes && all_allowed_attributes[@resource]
|
129
|
+
# all_allowed_attributes[@resource]
|
130
|
+
# else
|
131
|
+
# []
|
132
|
+
# end
|
133
|
+
# end
|
134
|
+
#end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Permissioner
|
2
|
+
module Matchers
|
3
|
+
class ExactlyAllowControllers
|
4
|
+
|
5
|
+
def initialize(*expected_controllers)
|
6
|
+
@expected_controllers = expected_controllers.collect { |controller| controller.to_s }
|
7
|
+
end
|
8
|
+
|
9
|
+
def matches?(permission_service)
|
10
|
+
@permission_service = permission_service
|
11
|
+
controllers_exactly_match?(allowed_controllers)
|
12
|
+
end
|
13
|
+
|
14
|
+
def failure_message_for_should
|
15
|
+
"expected to exactly allow controllers \n" \
|
16
|
+
"#{@expected_controllers.sort}, but found controllers\n"\
|
17
|
+
"#{allowed_controllers.sort} allowed"
|
18
|
+
end
|
19
|
+
|
20
|
+
def failure_message_for_should_not
|
21
|
+
"expected to exactly not allow controllers \n" \
|
22
|
+
"#{@expected_controllers.sort}, but these controllers are exactly allowed\n"\
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def allowed_controllers
|
28
|
+
@allowed_controllers ||= begin
|
29
|
+
all_allowed_actions = @permission_service.instance_variable_get(:@allowed_actions)
|
30
|
+
if all_allowed_actions
|
31
|
+
all_allowed_actions.keys.collect { |e| e.first }.uniq
|
32
|
+
else
|
33
|
+
[]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def all_controllers_allowed?(allowed_controllers)
|
39
|
+
@expected_controllers.all? { |controller| allowed_controllers.include? controller }
|
40
|
+
end
|
41
|
+
|
42
|
+
def controllers_exactly_match?(allowed_controllers)
|
43
|
+
allowed_controllers.count == @expected_controllers.count && all_controllers_allowed?(allowed_controllers)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Permissioner
|
2
|
+
module Matchers
|
3
|
+
class ExactlyAllowResources
|
4
|
+
|
5
|
+
def initialize(*expected_resources)
|
6
|
+
@expected_resources = expected_resources
|
7
|
+
end
|
8
|
+
|
9
|
+
def matches?(permission_service)
|
10
|
+
@permission_service = permission_service
|
11
|
+
resources_exactly_match?
|
12
|
+
end
|
13
|
+
|
14
|
+
def failure_message_for_should
|
15
|
+
"expected to exactly allow resources \n" \
|
16
|
+
"#{@expected_resources.sort}, but found resources\n"\
|
17
|
+
"#{allowed_resources.sort} allowed"
|
18
|
+
end
|
19
|
+
|
20
|
+
def failure_message_for_should_not
|
21
|
+
"expected to exactly not allow resources \n" \
|
22
|
+
"#{@expected_resources.sort}, but these resources are exactly allowed\n"\
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def resources_exactly_match?
|
28
|
+
allowed_resources.count == @expected_resources.count &&
|
29
|
+
@expected_resources.all? { |resource| allowed_resources.include? resource }
|
30
|
+
end
|
31
|
+
|
32
|
+
def allowed_resources
|
33
|
+
@allowed_resources ||= begin
|
34
|
+
allowed_attributes = @permission_service.instance_variable_get(:@allowed_attributes)
|
35
|
+
if allowed_attributes
|
36
|
+
allowed_attributes.keys
|
37
|
+
else
|
38
|
+
[]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Permissioner
|
2
|
+
module Matchers
|
3
|
+
class ExactlyExpectActions
|
4
|
+
|
5
|
+
def initialize(actions_instance_var, *all_expected_actions)
|
6
|
+
@all_expected_actions = all_expected_actions.collect do |value|
|
7
|
+
raise 'multiple actions for a controller must stated as array, e.g. [:new, :create]' if value.size > 2
|
8
|
+
[value[0].to_s, Array(value[1]).collect! { |e| e.to_s }]
|
9
|
+
end
|
10
|
+
@failing_actions = []
|
11
|
+
@actions_instance_var = actions_instance_var
|
12
|
+
end
|
13
|
+
|
14
|
+
def matches?(permission_service)
|
15
|
+
@permission_service = permission_service
|
16
|
+
expected_actions_exactly_match?
|
17
|
+
end
|
18
|
+
|
19
|
+
def failure_message_for_should
|
20
|
+
if @failing_actions.empty?
|
21
|
+
"expected to find actions for controllers \n" \
|
22
|
+
"#{all_expected_controllers}, but found actions for controllers\n"\
|
23
|
+
"#{all_actuel_controllers}"
|
24
|
+
else
|
25
|
+
message = "expected actions did not match for following controllers:\n"
|
26
|
+
@failing_actions.inject(message) do |msg, value|
|
27
|
+
msg +=
|
28
|
+
"#{value[0]}:\n"\
|
29
|
+
"#{value[1]} were expected but found actions\n"\
|
30
|
+
"#{actual_actions_for_controller(value[0])}\n"
|
31
|
+
msg
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def failure_message_for_should_not
|
37
|
+
'given actions are exactly match although this is not expected'
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def expected_actions_exactly_match?
|
43
|
+
controllers_exactly_match? && actions_exactly_match?
|
44
|
+
end
|
45
|
+
|
46
|
+
def controllers_exactly_match?
|
47
|
+
all_actuel_controllers == all_expected_controllers
|
48
|
+
end
|
49
|
+
|
50
|
+
def actions_exactly_match?
|
51
|
+
@all_expected_actions.each do |controller, expected_actions_for_controller|
|
52
|
+
expected_actions_for_controller.sort!
|
53
|
+
match = actions_for_controller_exactly_match?(controller, expected_actions_for_controller)
|
54
|
+
@failing_actions << [controller, expected_actions_for_controller] unless match
|
55
|
+
match
|
56
|
+
end
|
57
|
+
@failing_actions.empty?
|
58
|
+
end
|
59
|
+
|
60
|
+
def actions_for_controller_exactly_match?(controller, expected_actions_for_controller)
|
61
|
+
if expected_actions_for_controller == ['all']
|
62
|
+
actual_actions_for_controller(controller).include?('all')
|
63
|
+
else
|
64
|
+
expected_actions_for_controller == actual_actions_for_controller(controller)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def all_actuel_actions
|
69
|
+
@all_actuel_actions ||= begin
|
70
|
+
@permission_service.instance_variable_get(@actions_instance_var) || {}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def all_actuel_controllers
|
75
|
+
@all_actuel_controllers ||= begin
|
76
|
+
all_actuel_actions.keys.collect { |e| e.first }.uniq.sort
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def all_expected_controllers
|
81
|
+
@all_expected_controllers ||= begin
|
82
|
+
@all_expected_actions.collect { |e| e[0] }
|
83
|
+
end.sort
|
84
|
+
end
|
85
|
+
|
86
|
+
def actual_actions_for_controller(controller)
|
87
|
+
@actual_actions_for_controller ||= {}
|
88
|
+
|
89
|
+
@actual_actions_for_controller[controller] ||= begin
|
90
|
+
all_actuel_actions.keys.inject([]) do |actual_actions_for_controller, value|
|
91
|
+
if value[0] == controller
|
92
|
+
actual_actions_for_controller << value[1]
|
93
|
+
end
|
94
|
+
actual_actions_for_controller
|
95
|
+
end.uniq.sort
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Permissioner
|
2
|
-
module
|
2
|
+
module ServiceAdditions
|
3
3
|
|
4
4
|
attr_accessor :current_user
|
5
5
|
|
@@ -8,19 +8,23 @@ module Permissioner
|
|
8
8
|
configure_permissions
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
def allow_action?(controller, action, subjects={})
|
12
|
+
allowed =
|
13
|
+
@allow_all ||
|
14
|
+
(@allowed_actions &&
|
15
|
+
(@allowed_actions[[controller.to_s, action.to_s]] || @allowed_actions[[controller.to_s, 'all']]))
|
16
|
+
allowed = allowed && (allowed == true || allowed.call(subjects[:resource]))
|
17
|
+
allowed && passed_filters?(controller, action, subjects)
|
15
18
|
end
|
16
19
|
|
17
20
|
def allow_attribute?(resource, attribute)
|
18
21
|
@allow_all || @allowed_attributes && @allowed_attributes[resource].try(:include?, attribute)
|
19
22
|
end
|
20
23
|
|
21
|
-
def passed_filters?(controller, action,
|
24
|
+
def passed_filters?(controller, action, subjects={})
|
25
|
+
resource, params = subjects[:resource], subjects[:params] || {}
|
22
26
|
if @filters && @filters[[controller.to_s, action.to_s]]
|
23
|
-
@filters[[controller.to_s, action.to_s]].all? { |block| block.call(params) }
|
27
|
+
@filters[[controller.to_s, action.to_s]].all? { |block| block.call(resource, params) }
|
24
28
|
else
|
25
29
|
true
|
26
30
|
end
|
@@ -85,6 +89,18 @@ module Permissioner
|
|
85
89
|
end
|
86
90
|
end
|
87
91
|
|
92
|
+
def clear_all_filters
|
93
|
+
@filters = nil
|
94
|
+
end
|
95
|
+
|
96
|
+
def clear_filters controllers, actions
|
97
|
+
Array(controllers).each do |controller|
|
98
|
+
Array(actions).each do |action|
|
99
|
+
@filters.delete([controller.to_s, action.to_s])
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
88
104
|
# Configures permissions by instantiate a new object of the given class which is intended to include
|
89
105
|
# the module Permissioner::PermissionConfigurer.
|
90
106
|
#
|