role_call 0.1.0 → 0.1.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/lib/role_call.rb +5 -1
- data/lib/role_call/actor.rb +37 -0
- data/lib/role_call/permission_base.rb +14 -0
- data/lib/role_call/permissions/roles.rb +25 -0
- data/lib/role_call/role_base.rb +10 -0
- data/lib/role_call/roles/permissions.rb +50 -0
- data/lib/role_call/rspec/custom_matchers.rb +6 -0
- data/lib/role_call/rspec/custom_matchers/be_granted_to.rb +29 -0
- data/lib/role_call/rspec/custom_matchers/grant_permissions.rb +29 -0
- data/lib/role_call/rspec/custom_matchers/have_default_key.rb +22 -0
- data/lib/role_call/rspec/custom_matchers/have_key.rb +27 -0
- data/lib/role_call/spec_helper.rb +3 -0
- data/lib/role_call/version.rb +1 -1
- metadata +37 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 383223b658164ace5b6bae492ff85f5ad5cd07dad7ce04244be3c0dfd73f84b5
|
4
|
+
data.tar.gz: 6044c87799f8d888b4411addbf92e99f5e4ed5044619c5b1eec1b9339ddd09ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6d50ed87e4601a23df929c75957d0b09580ceb1fcdf6455a06a2a5f7660e9a5af0ea72758cd573b89186db752b7366eeee5444a2b9a79f371a99c4b92d0ce60
|
7
|
+
data.tar.gz: 75d16aec5180cf8fc57ecbcc30cbcbcfca1f887314fa202b8719b5c6af7465ddfb75a416a27f94d0cbcb57bcd635bc762aaa387263c61fcb19d1b9ff943b9701
|
data/lib/role_call.rb
CHANGED
@@ -3,9 +3,13 @@
|
|
3
3
|
require "active_support"
|
4
4
|
require "active_support/core_ext/enumerable"
|
5
5
|
|
6
|
-
require "
|
6
|
+
require "spicery"
|
7
7
|
|
8
8
|
require "role_call/version"
|
9
9
|
|
10
|
+
require "role_call/permission_base"
|
11
|
+
require "role_call/role_base"
|
12
|
+
require "role_call/actor"
|
13
|
+
|
10
14
|
module RoleCall
|
11
15
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RoleCall
|
4
|
+
module Actor
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
include ShortCircuIt
|
9
|
+
|
10
|
+
memoize :permissions
|
11
|
+
memoize :permission_classes
|
12
|
+
memoize :permissions_map
|
13
|
+
end
|
14
|
+
|
15
|
+
def permitted_to?(object)
|
16
|
+
permissions_map.key?(object.try(:key)) || permissions_map.key?(object) || permissions.include?(object)
|
17
|
+
end
|
18
|
+
|
19
|
+
def permissions
|
20
|
+
permission_classes.map(&:key).uniq
|
21
|
+
end
|
22
|
+
|
23
|
+
def roles
|
24
|
+
[ try(:role) ].compact
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def permission_classes
|
30
|
+
Array.wrap(roles).map(&:permissions).flatten
|
31
|
+
end
|
32
|
+
|
33
|
+
def permissions_map
|
34
|
+
permission_classes.index_by(&:key)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "permissions/roles"
|
4
|
+
|
5
|
+
# A **Permission** are the "keys" that are accumulated across the **Roles** of an **Actor**.
|
6
|
+
module RoleCall
|
7
|
+
class PermissionBase < Spicerack::RootObject
|
8
|
+
include RoleCall::Permissions::Roles
|
9
|
+
|
10
|
+
def self.key
|
11
|
+
name.chomp("Permission").underscore.to_sym
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# A **Permission** is granted to various **Roles** to authorize **Actors** to perform actions.
|
4
|
+
module RoleCall
|
5
|
+
module Permissions
|
6
|
+
module Roles
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
class_attribute :roles, instance_writer: false, default: []
|
11
|
+
end
|
12
|
+
|
13
|
+
class_methods do
|
14
|
+
def inherited(base)
|
15
|
+
base.roles = []
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def granted_to(role)
|
20
|
+
roles << role
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "roles/permissions"
|
4
|
+
|
5
|
+
# A **Role** is authorized to take actions by virtue of having the appropriate **Permissions**.
|
6
|
+
module RoleCall
|
7
|
+
class RoleBase < Spicerack::RootObject
|
8
|
+
include RoleCall::Roles::Permissions
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# A **Role** is a collection of granted **Permissions**.
|
4
|
+
module RoleCall
|
5
|
+
module Roles
|
6
|
+
module Permissions
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
class_attribute :permissions, instance_writer: false, default: []
|
11
|
+
delegate :unpermitted?, to: :class
|
12
|
+
end
|
13
|
+
|
14
|
+
class_methods do
|
15
|
+
def unpermitted?
|
16
|
+
permissions.blank?
|
17
|
+
end
|
18
|
+
|
19
|
+
def inherited(base)
|
20
|
+
base.permissions = permissions.dup
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def grant(*permission_grants)
|
27
|
+
permission_grants = permission_grants.flatten.compact
|
28
|
+
|
29
|
+
ensure_valid_permissions(permission_grants)
|
30
|
+
|
31
|
+
permission_grants.each do |permission|
|
32
|
+
permissions << permission
|
33
|
+
track_permission(permission)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def track_permission(permission)
|
38
|
+
permission.granted_to(self)
|
39
|
+
end
|
40
|
+
|
41
|
+
def ensure_valid_permissions(permission_grants)
|
42
|
+
raise ArgumentError, "a permission is required" if permission_grants.empty?
|
43
|
+
|
44
|
+
invalid_permissions = permission_grants.reject { |permission| permission.respond_to?(:granted_to) }
|
45
|
+
raise ArgumentError, "invalid permissions: #{invalid_permissions.join(", ")}" if invalid_permissions.present?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# RSpec matcher that tests references of roles to permissions.
|
4
|
+
#
|
5
|
+
# class ExamplePermission < ApplicationPermission
|
6
|
+
# end
|
7
|
+
#
|
8
|
+
# class ExampleRole < ApplicationRole
|
9
|
+
# grants ExamplePermission
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# RSpec.describe ExamplePermission, type: :permission do
|
13
|
+
# it { is_expected.to be_granted_to ExampleRole }
|
14
|
+
# end
|
15
|
+
|
16
|
+
RSpec::Matchers.define :be_granted_to do |*roles|
|
17
|
+
match { expect(test_subject.roles).to include *Array.wrap(roles).flatten }
|
18
|
+
description { "include roles #{Array.wrap(roles).flatten}" }
|
19
|
+
failure_message do
|
20
|
+
"expected #{test_subject} to include roles #{Array.wrap(roles).flatten}; #{test_subject.roles}"
|
21
|
+
end
|
22
|
+
failure_message_when_negated do
|
23
|
+
"expected #{test_subject} not to include roles #{Array.wrap(roles).flatten}; #{test_subject.roles}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_subject
|
27
|
+
subject.is_a?(Class) ? subject : subject.class
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# RSpec matcher that tests grants of permissions to roles.
|
4
|
+
#
|
5
|
+
# class ExamplePermission < ApplicationPermission
|
6
|
+
# end
|
7
|
+
#
|
8
|
+
# class ExampleRole < ApplicationRole
|
9
|
+
# grants ExamplePermission
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# RSpec.describe ExampleRole, type: :role do
|
13
|
+
# it { is_expected.to grant_permissions ExamplePermission }
|
14
|
+
# end
|
15
|
+
|
16
|
+
RSpec::Matchers.define :grant_permissions do |*permissions|
|
17
|
+
match { expect(test_subject.permissions).to include *Array.wrap(permissions).flatten }
|
18
|
+
description { "have permissions #{Array.wrap(permissions).flatten}" }
|
19
|
+
failure_message do
|
20
|
+
"expected #{test_subject} to have permissions #{Array.wrap(permissions).flatten}; #{test_subject.permissions}"
|
21
|
+
end
|
22
|
+
failure_message_when_negated do
|
23
|
+
"expected #{test_subject} not to have permissions #{Array.wrap(permissions).flatten}; #{test_subject.permissions}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_subject
|
27
|
+
subject.is_a?(Class) ? subject : subject.class
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# RSpec matcher that tests the key of a permissions.
|
4
|
+
#
|
5
|
+
# class ExamplePermission < ApplicationPermission
|
6
|
+
# end
|
7
|
+
#
|
8
|
+
# RSpec.describe ExamplePermission, type: :permission do
|
9
|
+
# it { is_expected.to have_default_key }
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
|
13
|
+
RSpec::Matchers.define :have_default_key do
|
14
|
+
match { expect(test_subject.key).to eq test_subject.name.chomp("Permission").underscore.to_sym }
|
15
|
+
description { "have default key" }
|
16
|
+
failure_message { "expected #{test_subject} to have default key but had `#{test_subject.key}' instead." }
|
17
|
+
failure_message_when_negated { "expected #{test_subject} not to have default key but did." }
|
18
|
+
|
19
|
+
def test_subject
|
20
|
+
subject.is_a?(Class) ? subject : subject.class
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# RSpec matcher that tests the key of a permissions.
|
4
|
+
#
|
5
|
+
# class ExamplePermission < ApplicationPermission
|
6
|
+
# def self.key
|
7
|
+
# :something_nonstandard
|
8
|
+
# end
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# RSpec.describe ExamplePermission, type: :permission do
|
12
|
+
# it { is_expected.to have_key :something_nonstandard }
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
|
16
|
+
RSpec::Matchers.define :have_key do |expected_key|
|
17
|
+
match { expect(test_subject.key).to eq expected_key }
|
18
|
+
description { "have key #{expected_key}" }
|
19
|
+
failure_message do
|
20
|
+
"expected #{test_subject} to have key `#{expected_key}' but had `#{test_subject.key}' instead."
|
21
|
+
end
|
22
|
+
failure_message_when_negated { "expected #{test_subject} not to have key `#{expected_key}' but did." }
|
23
|
+
|
24
|
+
def test_subject
|
25
|
+
subject.is_a?(Class) ? subject : subject.class
|
26
|
+
end
|
27
|
+
end
|
data/lib/role_call/version.rb
CHANGED
metadata
CHANGED
@@ -1,36 +1,36 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: role_call
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Garside
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 5.2.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 5.2.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: spicery
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.
|
33
|
+
version: 0.22.3.1
|
34
34
|
- - "<"
|
35
35
|
- !ruby/object:Gem::Version
|
36
36
|
version: '1.0'
|
@@ -40,7 +40,7 @@ dependencies:
|
|
40
40
|
requirements:
|
41
41
|
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: 0.
|
43
|
+
version: 0.22.3.1
|
44
44
|
- - "<"
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '1.0'
|
@@ -58,20 +58,6 @@ dependencies:
|
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: 2.0.1
|
61
|
-
- !ruby/object:Gem::Dependency
|
62
|
-
name: faker
|
63
|
-
requirement: !ruby/object:Gem::Requirement
|
64
|
-
requirements:
|
65
|
-
- - "~>"
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: '1.8'
|
68
|
-
type: :development
|
69
|
-
prerelease: false
|
70
|
-
version_requirements: !ruby/object:Gem::Requirement
|
71
|
-
requirements:
|
72
|
-
- - "~>"
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
version: '1.8'
|
75
61
|
- !ruby/object:Gem::Dependency
|
76
62
|
name: pry-byebug
|
77
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -101,54 +87,54 @@ dependencies:
|
|
101
87
|
- !ruby/object:Gem::Version
|
102
88
|
version: '10.0'
|
103
89
|
- !ruby/object:Gem::Dependency
|
104
|
-
name:
|
90
|
+
name: simplecov
|
105
91
|
requirement: !ruby/object:Gem::Requirement
|
106
92
|
requirements:
|
107
93
|
- - "~>"
|
108
94
|
- !ruby/object:Gem::Version
|
109
|
-
version: '
|
95
|
+
version: '0.16'
|
110
96
|
type: :development
|
111
97
|
prerelease: false
|
112
98
|
version_requirements: !ruby/object:Gem::Requirement
|
113
99
|
requirements:
|
114
100
|
- - "~>"
|
115
101
|
- !ruby/object:Gem::Version
|
116
|
-
version: '
|
102
|
+
version: '0.16'
|
117
103
|
- !ruby/object:Gem::Dependency
|
118
|
-
name:
|
104
|
+
name: timecop
|
119
105
|
requirement: !ruby/object:Gem::Requirement
|
120
106
|
requirements:
|
121
|
-
- - "
|
107
|
+
- - ">="
|
122
108
|
- !ruby/object:Gem::Version
|
123
|
-
version:
|
109
|
+
version: 0.9.1
|
124
110
|
type: :development
|
125
111
|
prerelease: false
|
126
112
|
version_requirements: !ruby/object:Gem::Requirement
|
127
113
|
requirements:
|
128
|
-
- - "
|
114
|
+
- - ">="
|
129
115
|
- !ruby/object:Gem::Version
|
130
|
-
version:
|
116
|
+
version: 0.9.1
|
131
117
|
- !ruby/object:Gem::Dependency
|
132
|
-
name:
|
118
|
+
name: shoulda-matchers
|
133
119
|
requirement: !ruby/object:Gem::Requirement
|
134
120
|
requirements:
|
135
|
-
- -
|
121
|
+
- - '='
|
136
122
|
- !ruby/object:Gem::Version
|
137
|
-
version: 0.
|
123
|
+
version: 4.0.1
|
138
124
|
type: :development
|
139
125
|
prerelease: false
|
140
126
|
version_requirements: !ruby/object:Gem::Requirement
|
141
127
|
requirements:
|
142
|
-
- -
|
128
|
+
- - '='
|
143
129
|
- !ruby/object:Gem::Version
|
144
|
-
version: 0.
|
130
|
+
version: 4.0.1
|
145
131
|
- !ruby/object:Gem::Dependency
|
146
132
|
name: rspice
|
147
133
|
requirement: !ruby/object:Gem::Requirement
|
148
134
|
requirements:
|
149
135
|
- - ">="
|
150
136
|
- !ruby/object:Gem::Version
|
151
|
-
version: 0.
|
137
|
+
version: 0.22.3.1
|
152
138
|
- - "<"
|
153
139
|
- !ruby/object:Gem::Version
|
154
140
|
version: '1.0'
|
@@ -158,7 +144,7 @@ dependencies:
|
|
158
144
|
requirements:
|
159
145
|
- - ">="
|
160
146
|
- !ruby/object:Gem::Version
|
161
|
-
version: 0.
|
147
|
+
version: 0.22.3.1
|
162
148
|
- - "<"
|
163
149
|
- !ruby/object:Gem::Version
|
164
150
|
version: '1.0'
|
@@ -168,7 +154,7 @@ dependencies:
|
|
168
154
|
requirements:
|
169
155
|
- - ">="
|
170
156
|
- !ruby/object:Gem::Version
|
171
|
-
version: 0.
|
157
|
+
version: 0.22.3.1
|
172
158
|
- - "<"
|
173
159
|
- !ruby/object:Gem::Version
|
174
160
|
version: '1.0'
|
@@ -178,24 +164,10 @@ dependencies:
|
|
178
164
|
requirements:
|
179
165
|
- - ">="
|
180
166
|
- !ruby/object:Gem::Version
|
181
|
-
version: 0.
|
167
|
+
version: 0.22.3.1
|
182
168
|
- - "<"
|
183
169
|
- !ruby/object:Gem::Version
|
184
170
|
version: '1.0'
|
185
|
-
- !ruby/object:Gem::Dependency
|
186
|
-
name: shoulda-matchers
|
187
|
-
requirement: !ruby/object:Gem::Requirement
|
188
|
-
requirements:
|
189
|
-
- - '='
|
190
|
-
- !ruby/object:Gem::Version
|
191
|
-
version: 4.0.1
|
192
|
-
type: :development
|
193
|
-
prerelease: false
|
194
|
-
version_requirements: !ruby/object:Gem::Requirement
|
195
|
-
requirements:
|
196
|
-
- - '='
|
197
|
-
- !ruby/object:Gem::Version
|
198
|
-
version: 4.0.1
|
199
171
|
description: Describe the roles and permissions of your system with clear, testable,
|
200
172
|
self-documenting code
|
201
173
|
email:
|
@@ -207,8 +179,19 @@ files:
|
|
207
179
|
- LICENSE.txt
|
208
180
|
- README.md
|
209
181
|
- lib/role_call.rb
|
182
|
+
- lib/role_call/actor.rb
|
183
|
+
- lib/role_call/permission_base.rb
|
184
|
+
- lib/role_call/permissions/roles.rb
|
185
|
+
- lib/role_call/role_base.rb
|
186
|
+
- lib/role_call/roles/permissions.rb
|
187
|
+
- lib/role_call/rspec/custom_matchers.rb
|
188
|
+
- lib/role_call/rspec/custom_matchers/be_granted_to.rb
|
189
|
+
- lib/role_call/rspec/custom_matchers/grant_permissions.rb
|
190
|
+
- lib/role_call/rspec/custom_matchers/have_default_key.rb
|
191
|
+
- lib/role_call/rspec/custom_matchers/have_key.rb
|
192
|
+
- lib/role_call/spec_helper.rb
|
210
193
|
- lib/role_call/version.rb
|
211
|
-
homepage: https://
|
194
|
+
homepage: https://github.com/Freshly/role_call
|
212
195
|
licenses:
|
213
196
|
- MIT
|
214
197
|
metadata: {}
|
@@ -227,8 +210,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
227
210
|
- !ruby/object:Gem::Version
|
228
211
|
version: '0'
|
229
212
|
requirements: []
|
230
|
-
|
231
|
-
rubygems_version: 2.7.6
|
213
|
+
rubygems_version: 3.0.3
|
232
214
|
signing_key:
|
233
215
|
specification_version: 4
|
234
216
|
summary: A simple and extensible approach to role-based access control management
|