consent 1.0.0 → 1.0.1
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/consent.gemspec +3 -0
- data/lib/consent.rb +12 -19
- data/lib/consent/ability.rb +15 -6
- data/lib/consent/action.rb +8 -5
- data/lib/consent/dsl.rb +2 -1
- data/lib/consent/rspec.rb +12 -72
- data/lib/consent/rspec/consent_action.rb +65 -0
- data/lib/consent/rspec/consent_view.rb +79 -0
- data/lib/consent/version.rb +1 -1
- metadata +46 -3
- data/lib/consent/permission.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 925e2e71db7ce7b4c7104784bbd54cfeb8273b2502f0f73f599e64754d5a010a
|
4
|
+
data.tar.gz: 256326fbd83020d39881b53eadc1b3b7cb9c5169bedee5aac5491661a0e3023b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 84ee14b357d0edd8c7be190cc4f79e67d6a0a7f8e0f869d1bf15b0d1ebe87e6f076939aa9db684c172eec8f489bb83f8794c3ca0946a4edc569c07f04a6a9889
|
7
|
+
data.tar.gz: 490da917b1363a0b5d2f209df9363978764874fbe74d500c548b91a95f16f3ca35fab2a80a1ab7ac4de7364e7892101efc4e4a022d25683d0dc82896c7b39da9
|
data/consent.gemspec
CHANGED
@@ -20,9 +20,12 @@ Gem::Specification.new do |spec|
|
|
20
20
|
end
|
21
21
|
spec.require_paths = ['lib']
|
22
22
|
|
23
|
+
spec.add_development_dependency 'activerecord', '>= 5'
|
23
24
|
spec.add_development_dependency 'bundler', '>= 1.17.3'
|
24
25
|
spec.add_development_dependency 'cancancan', '~> 1.15.0'
|
26
|
+
spec.add_development_dependency 'pry', '~> 0.14.1'
|
25
27
|
spec.add_development_dependency 'rake', '>= 12.3.3'
|
26
28
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
27
29
|
spec.add_development_dependency 'rubocop', '~> 0.65.0'
|
30
|
+
spec.add_development_dependency 'sqlite3', '~> 1.4.2'
|
28
31
|
end
|
data/lib/consent.rb
CHANGED
@@ -5,7 +5,6 @@ require 'consent/subject'
|
|
5
5
|
require 'consent/view'
|
6
6
|
require 'consent/action'
|
7
7
|
require 'consent/dsl'
|
8
|
-
require 'consent/permission'
|
9
8
|
require 'consent/ability' if defined?(CanCan)
|
10
9
|
require 'consent/railtie' if defined?(Rails)
|
11
10
|
|
@@ -13,6 +12,8 @@ require 'consent/railtie' if defined?(Rails)
|
|
13
12
|
# concise DSL for authorization so that all abilities do not have
|
14
13
|
# to be in your `Ability` class.
|
15
14
|
module Consent
|
15
|
+
ViewNotFound = Class.new(StandardError)
|
16
|
+
|
16
17
|
# Default views available to every permission
|
17
18
|
#
|
18
19
|
# i.e.:
|
@@ -35,7 +36,7 @@ module Consent
|
|
35
36
|
#
|
36
37
|
# @return [Array<Consent::Subject>]
|
37
38
|
def self.find_subjects(subject_key)
|
38
|
-
|
39
|
+
subjects.find_all do |subject|
|
39
40
|
subject.key.eql?(subject_key)
|
40
41
|
end
|
41
42
|
end
|
@@ -44,21 +45,20 @@ module Consent
|
|
44
45
|
#
|
45
46
|
# @return [Consent::Action,nil]
|
46
47
|
def self.find_action(subject_key, action_key)
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
find_subjects(subject_key)
|
49
|
+
.flat_map(&:actions)
|
50
|
+
.find do |action|
|
51
|
+
action.key.eql?(action_key)
|
52
|
+
end
|
52
53
|
end
|
53
54
|
|
54
55
|
# Finds a view within a subject context
|
55
56
|
#
|
56
57
|
# @return [Consent::View,nil]
|
57
|
-
def self.find_view(subject_key, view_key)
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
views[view_key]
|
58
|
+
def self.find_view(subject_key, action_key, view_key)
|
59
|
+
find_action(subject_key, action_key)&.yield_self do |action|
|
60
|
+
action.views[view_key] || raise(Consent::ViewNotFound)
|
61
|
+
end
|
62
62
|
end
|
63
63
|
|
64
64
|
# Loads all permission (ruby) files from the given directory
|
@@ -87,11 +87,4 @@ module Consent
|
|
87
87
|
DSL.build(subject, defaults, &block)
|
88
88
|
end
|
89
89
|
end
|
90
|
-
|
91
|
-
# Maps a permissions hash to a Consent::Permissions
|
92
|
-
#
|
93
|
-
# @return [Consent::Permissions]
|
94
|
-
def self.permissions(permissions)
|
95
|
-
Permissions.new(permissions)
|
96
|
-
end
|
97
90
|
end
|
data/lib/consent/ability.rb
CHANGED
@@ -10,17 +10,26 @@ module Consent
|
|
10
10
|
apply_defaults! if apply_defaults
|
11
11
|
end
|
12
12
|
|
13
|
-
def consent(
|
14
|
-
|
15
|
-
|
13
|
+
def consent!(subject: nil, action: nil, view: nil)
|
14
|
+
view = case view
|
15
|
+
when Consent::View
|
16
|
+
view
|
17
|
+
when Symbol
|
18
|
+
Consent.find_view(subject, action, view)
|
19
|
+
end
|
16
20
|
|
17
21
|
can(
|
18
|
-
|
19
|
-
|
20
|
-
&permission.object_conditions(*@context)
|
22
|
+
action, subject,
|
23
|
+
view&.conditions(*@context), &view&.object_conditions(*@context)
|
21
24
|
)
|
22
25
|
end
|
23
26
|
|
27
|
+
def consent(**kwargs)
|
28
|
+
consent!(**kwargs)
|
29
|
+
rescue Consent::ViewNotFound
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
|
24
33
|
private
|
25
34
|
|
26
35
|
def apply_defaults!
|
data/lib/consent/action.rb
CHANGED
@@ -2,20 +2,23 @@
|
|
2
2
|
|
3
3
|
module Consent
|
4
4
|
class Action # :nodoc:
|
5
|
-
attr_reader :key, :label, :options
|
5
|
+
attr_reader :subject, :key, :label, :options
|
6
6
|
|
7
|
-
def initialize(key, label, options = {})
|
7
|
+
def initialize(subject, key, label, options = {})
|
8
|
+
@subject = subject
|
8
9
|
@key = key
|
9
10
|
@label = label
|
10
11
|
@options = options
|
11
12
|
end
|
12
13
|
|
13
|
-
def
|
14
|
-
@options.fetch(:views, [])
|
14
|
+
def views
|
15
|
+
@views ||= @subject.views.slice(*@options.fetch(:views, []))
|
15
16
|
end
|
16
17
|
|
17
18
|
def default_view
|
18
|
-
@options
|
19
|
+
return unless @options.key?(:default_view)
|
20
|
+
|
21
|
+
@default_view ||= @subject.views[@options[:default_view]]
|
19
22
|
end
|
20
23
|
end
|
21
24
|
end
|
data/lib/consent/dsl.rb
CHANGED
@@ -27,7 +27,8 @@ module Consent
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def action(key, label, options = {})
|
30
|
-
@subject.actions << Action.new(key, label,
|
30
|
+
@subject.actions << Action.new(@subject, key, label,
|
31
|
+
@defaults.merge(options))
|
31
32
|
end
|
32
33
|
|
33
34
|
def self.build(subject, defaults = {}, &block)
|
data/lib/consent/rspec.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'consent'
|
4
4
|
|
5
|
+
require_relative 'rspec/consent_action'
|
6
|
+
require_relative 'rspec/consent_view'
|
7
|
+
|
5
8
|
module Consent
|
6
9
|
# RSpec helpers for consent. Given permissions are loaded,
|
7
10
|
# gives you the ability of defining permission specs like
|
@@ -20,7 +23,11 @@ module Consent
|
|
20
23
|
# let(:user) { double(department_id: 15) }
|
21
24
|
#
|
22
25
|
# it do
|
23
|
-
# is_expected.to
|
26
|
+
# is_expected.to(
|
27
|
+
# consent_view(:department)
|
28
|
+
# .with_conditions(department_id: 15)
|
29
|
+
# .to(user)
|
30
|
+
# )
|
24
31
|
# end
|
25
32
|
# it { is_expected.to consent_action(:read) }
|
26
33
|
# it { is_expected.to consent_action(:update).with_views(:department) }
|
@@ -29,79 +36,12 @@ module Consent
|
|
29
36
|
# Find more examples at:
|
30
37
|
# https://github.com/powerhome/consent
|
31
38
|
module Rspec
|
32
|
-
|
33
|
-
|
34
|
-
matcher :consent_action do |action_key|
|
35
|
-
chain :with_views do |*views|
|
36
|
-
@views = views
|
37
|
-
end
|
38
|
-
|
39
|
-
match do |subject_key|
|
40
|
-
action = Consent.find_action(subject_key, action_key)
|
41
|
-
if action && @views
|
42
|
-
values_match?(action.view_keys.sort, @views.sort)
|
43
|
-
else
|
44
|
-
!action.nil?
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
failure_message do |subject_key|
|
49
|
-
action = Consent.find_action(subject_key, action_key)
|
50
|
-
message = format(
|
51
|
-
'expected %<skey>s (%<sclass>s) to provide action %<action>s',
|
52
|
-
skey: subject_key.to_s, sclass: subject.class, action: action_key
|
53
|
-
)
|
54
|
-
|
55
|
-
if action && @views
|
56
|
-
format(
|
57
|
-
'%<message>s with views %<views>s, but actual views are %<keys>p',
|
58
|
-
message: message, views: @views, keys: action.view_keys
|
59
|
-
)
|
60
|
-
else
|
61
|
-
message
|
62
|
-
end
|
63
|
-
end
|
39
|
+
def consent_view(view_key, conditions = nil)
|
40
|
+
ConsentView.new(view_key, conditions)
|
64
41
|
end
|
65
42
|
|
66
|
-
|
67
|
-
|
68
|
-
@context = context
|
69
|
-
end
|
70
|
-
|
71
|
-
match do |subject_key|
|
72
|
-
view = Consent.find_view(subject_key, view_key)
|
73
|
-
if conditions
|
74
|
-
view&.conditions(*@context).eql?(conditions)
|
75
|
-
else
|
76
|
-
!view.nil?
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
failure_message do |subject_key|
|
81
|
-
view = Consent.find_view(subject_key, view_key)
|
82
|
-
message = format(
|
83
|
-
'expected %<skey>s (%<sclass>s) to provide view %<view>s with` \
|
84
|
-
`%<conditions>p, but',
|
85
|
-
skey: subject_key.to_s, sclass: subject.class,
|
86
|
-
view: view_key, conditions: conditions
|
87
|
-
)
|
88
|
-
|
89
|
-
if view && conditions
|
90
|
-
actual_conditions = view.conditions(*@context)
|
91
|
-
format(
|
92
|
-
'%<message>s conditions are %<conditions>p',
|
93
|
-
message: message, conditions: actual_conditions
|
94
|
-
)
|
95
|
-
else
|
96
|
-
actual_views = Consent.find_subjects(subject_key)
|
97
|
-
.map(&:views)
|
98
|
-
.map(&:keys).flatten
|
99
|
-
format(
|
100
|
-
'%<message>s available views are %<views>p',
|
101
|
-
message: message, views: actual_views
|
102
|
-
)
|
103
|
-
end
|
104
|
-
end
|
43
|
+
def consent_action(action_key)
|
44
|
+
ConsentAction.new(action_key)
|
105
45
|
end
|
106
46
|
end
|
107
47
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'consent'
|
4
|
+
RSpec::Support.require_rspec_support 'fuzzy_matcher'
|
5
|
+
|
6
|
+
module Consent
|
7
|
+
module Rspec
|
8
|
+
# @private
|
9
|
+
class ConsentAction
|
10
|
+
def initialize(action_key)
|
11
|
+
@action_key = action_key
|
12
|
+
end
|
13
|
+
|
14
|
+
def with_views(*views)
|
15
|
+
@views = views
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def description
|
20
|
+
message = "consents action #{@action_key}"
|
21
|
+
"#{message} with views #{@views}" if @views
|
22
|
+
end
|
23
|
+
|
24
|
+
def matches?(subject_key)
|
25
|
+
@subject_key = subject_key
|
26
|
+
@action = Consent.find_action(@subject_key, @action_key)
|
27
|
+
if @action && @views
|
28
|
+
RSpec::Support::FuzzyMatcher.values_match?(
|
29
|
+
@action.views.keys.sort,
|
30
|
+
@views.sort
|
31
|
+
)
|
32
|
+
else
|
33
|
+
!@action.nil?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def failure_message
|
38
|
+
failure_message_base 'to'
|
39
|
+
end
|
40
|
+
|
41
|
+
def failure_message_when_negated
|
42
|
+
failure_message_base 'to not'
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def failure_message_base(failure) # rubocop:disable Metrics/MethodLength
|
48
|
+
message = format(
|
49
|
+
'expected %<skey>s (%<sclass>s) %<failure> provide action %<action>s',
|
50
|
+
skey: @subject_key.to_s, sclass: @subject_key.class,
|
51
|
+
action: @action_key, failure: failure
|
52
|
+
)
|
53
|
+
|
54
|
+
if @action && @views
|
55
|
+
format(
|
56
|
+
'%<message>s with views %<views>s, but actual views are %<keys>p',
|
57
|
+
message: message, views: @views, keys: @action.views.keys
|
58
|
+
)
|
59
|
+
else
|
60
|
+
message
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Consent
|
4
|
+
module Rspec
|
5
|
+
# @private
|
6
|
+
class ConsentView
|
7
|
+
def initialize(view_key, conditions)
|
8
|
+
@conditions = comparable_conditions(conditions) if conditions
|
9
|
+
@view_key = view_key
|
10
|
+
end
|
11
|
+
|
12
|
+
def to(*context)
|
13
|
+
@context = context
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def description
|
18
|
+
message = "consents view #{@view_key}"
|
19
|
+
"#{message} with conditions #{@conditions}" if @conditions
|
20
|
+
end
|
21
|
+
|
22
|
+
def with_conditions(conditions)
|
23
|
+
@conditions = comparable_conditions(conditions)
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def matches?(subject_key)
|
28
|
+
@subject_key = subject_key
|
29
|
+
@target = Consent.find_subjects(subject_key)
|
30
|
+
.map do |subject|
|
31
|
+
subject.views[@view_key]&.conditions(*@context)
|
32
|
+
end
|
33
|
+
.compact
|
34
|
+
.map(&method(:comparable_conditions))
|
35
|
+
@target.include?(@conditions)
|
36
|
+
end
|
37
|
+
|
38
|
+
def failure_message
|
39
|
+
failure_message_base 'to'
|
40
|
+
end
|
41
|
+
|
42
|
+
def failure_message_when_negated
|
43
|
+
failure_message_base 'to not'
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def comparable_conditions(conditions)
|
49
|
+
return conditions.to_sql if conditions.respond_to?(:to_sql)
|
50
|
+
|
51
|
+
conditions
|
52
|
+
end
|
53
|
+
|
54
|
+
def failure_message_base(failure) # rubocop:disable Metrics/MethodLength
|
55
|
+
message = format(
|
56
|
+
'expected %<skey>s (%<sclass>s) %<fail>s provide view %<view>s with`\
|
57
|
+
`%<conditions>p, but',
|
58
|
+
skey: @subject_key.to_s, sclass: @subject_key.class,
|
59
|
+
view: @view_key, conditions: @conditions, fail: failure
|
60
|
+
)
|
61
|
+
|
62
|
+
if @target.any?
|
63
|
+
format(
|
64
|
+
'%<message>s conditions are %<conditions>p',
|
65
|
+
message: message, conditions: @target
|
66
|
+
)
|
67
|
+
else
|
68
|
+
actual_views = Consent.find_subjects(subject_key)
|
69
|
+
.map(&:views)
|
70
|
+
.map(&:keys).flatten
|
71
|
+
format(
|
72
|
+
'%<message>s available views are %<views>p',
|
73
|
+
message: message, views: actual_views
|
74
|
+
)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/consent/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: consent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carlos Palhares
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +52,20 @@ dependencies:
|
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: 1.15.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.14.1
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.14.1
|
41
69
|
- !ruby/object:Gem::Dependency
|
42
70
|
name: rake
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +108,20 @@ dependencies:
|
|
80
108
|
- - "~>"
|
81
109
|
- !ruby/object:Gem::Version
|
82
110
|
version: 0.65.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: sqlite3
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.4.2
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 1.4.2
|
83
125
|
description: Consent
|
84
126
|
email:
|
85
127
|
- chjunior@gmail.com
|
@@ -105,10 +147,11 @@ files:
|
|
105
147
|
- lib/consent/ability.rb
|
106
148
|
- lib/consent/action.rb
|
107
149
|
- lib/consent/dsl.rb
|
108
|
-
- lib/consent/permission.rb
|
109
150
|
- lib/consent/railtie.rb
|
110
151
|
- lib/consent/reloader.rb
|
111
152
|
- lib/consent/rspec.rb
|
153
|
+
- lib/consent/rspec/consent_action.rb
|
154
|
+
- lib/consent/rspec/consent_view.rb
|
112
155
|
- lib/consent/subject.rb
|
113
156
|
- lib/consent/version.rb
|
114
157
|
- lib/consent/view.rb
|
data/lib/consent/permission.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Consent
|
4
|
-
class Permission # :nodoc:
|
5
|
-
attr_reader :subject_key, :action_key, :view_key, :view
|
6
|
-
|
7
|
-
def initialize(subject_key, action_key, view_key = nil)
|
8
|
-
@subject_key = subject_key
|
9
|
-
@action_key = action_key
|
10
|
-
@view_key = view_key
|
11
|
-
@view = Consent.find_view(subject_key, view_key) if view_key
|
12
|
-
end
|
13
|
-
|
14
|
-
def action
|
15
|
-
@action ||= Consent.find_action(subject_key, action_key)
|
16
|
-
end
|
17
|
-
|
18
|
-
def valid?
|
19
|
-
action && (@view_key.nil? == @view.nil?)
|
20
|
-
end
|
21
|
-
|
22
|
-
def conditions(*args)
|
23
|
-
@view.nil? ? nil : @view.conditions(*args)
|
24
|
-
end
|
25
|
-
|
26
|
-
def object_conditions(*args)
|
27
|
-
@view.nil? ? nil : @view.object_conditions(*args)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|