role_call 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ad375b91373f25bf7d1424ae82e46af3f9a689249e5d3cebd7c5703e172219f
4
- data.tar.gz: e9b5c8fcde350b7511fc21d7b49d3ca9471b8ed5c8681f6054afce87a88c514e
3
+ metadata.gz: 383223b658164ace5b6bae492ff85f5ad5cd07dad7ce04244be3c0dfd73f84b5
4
+ data.tar.gz: 6044c87799f8d888b4411addbf92e99f5e4ed5044619c5b1eec1b9339ddd09ce
5
5
  SHA512:
6
- metadata.gz: c9d2ef9d20f908256b2613763c659b0164066de3c30d823de59be0de6f2ad7ab1c1516ef100edbb85e657862616b74dcb7e2fc407ff443c4c6160bb1e244cf74
7
- data.tar.gz: d56eff26436385219c548f28112eb67327678357a7e79372d2b830f08d00d8c812af6ff303d76862b770d3a56b157e7bf724c2cc1f17d909265e8d72bbf8c1b5
6
+ metadata.gz: e6d50ed87e4601a23df929c75957d0b09580ceb1fcdf6455a06a2a5f7660e9a5af0ea72758cd573b89186db752b7366eeee5444a2b9a79f371a99c4b92d0ce60
7
+ data.tar.gz: 75d16aec5180cf8fc57ecbcc30cbcbcfca1f887314fa202b8719b5c6af7465ddfb75a416a27f94d0cbcb57bcd635bc762aaa387263c61fcb19d1b9ff943b9701
@@ -3,9 +3,13 @@
3
3
  require "active_support"
4
4
  require "active_support/core_ext/enumerable"
5
5
 
6
- require "spicerack"
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,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "custom_matchers/be_granted_to"
4
+ require_relative "custom_matchers/grant_permissions"
5
+ require_relative "custom_matchers/have_default_key"
6
+ require_relative "custom_matchers/have_key"
@@ -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
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "rspec/custom_matchers"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RoleCall
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
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.0
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: 2019-11-04 00:00:00.000000000 Z
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: spicerack
28
+ name: spicery
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.17.3
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.17.3
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: rspec
90
+ name: simplecov
105
91
  requirement: !ruby/object:Gem::Requirement
106
92
  requirements:
107
93
  - - "~>"
108
94
  - !ruby/object:Gem::Version
109
- version: '3.0'
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: '3.0'
102
+ version: '0.16'
117
103
  - !ruby/object:Gem::Dependency
118
- name: simplecov
104
+ name: timecop
119
105
  requirement: !ruby/object:Gem::Requirement
120
106
  requirements:
121
- - - "~>"
107
+ - - ">="
122
108
  - !ruby/object:Gem::Version
123
- version: '0.16'
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: '0.16'
116
+ version: 0.9.1
131
117
  - !ruby/object:Gem::Dependency
132
- name: timecop
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.9.1
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.9.1
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.17.3
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.17.3
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.17.3
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.17.3
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://www.freshly.com/
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
- rubyforge_project:
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