ingress 0.4.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: edbb4efc674725b3fcb18ed2651773ecab7af973940f185cb93a94251858a4da
4
- data.tar.gz: aadc4a71a1946a19227b1b1a09d37372d056d19020c721a55a1c6cb63a251d20
3
+ metadata.gz: e7edbf639d42a08538dc22f46ead3e66f1891ebe9bdaa0091fafb5e078b130ce
4
+ data.tar.gz: e4a79fc5458b4ea8010b2ad159f7fd6e680f33416fae9a4171cb3dc5fc714058
5
5
  SHA512:
6
- metadata.gz: a63048555be635ef620c670e5f3fe39db3bc56bce272734141e391834b82cf42f3f8bce5e4ab9f7f752cc71b9b76e50307aa2d163bec8c901f5be9ad2fcacbdb
7
- data.tar.gz: 555623681279ba944737bbbb77e2b7b5fd65b365dcd840b83581fdb04527839203669977b1d602fe94e720f91fb7e0ab120c889883109a1a89a65490ac357410
6
+ metadata.gz: e891d1ebccd414e2837390f7fa2cc65afb8657e5729e7ab7c0291bdccb0533952e790c1b8650e31d207e645becaab6ab8f49435f9463a4c95c53e197e5aa78fc
7
+ data.tar.gz: bd15606c39a1009d9c4b4e77e55f6e5034f30d72513fca120d8ae82cf26195fb87cd7cd71d1cb3e0ea750ebe03f3295fae913301ddeaafe3ee52241f2bc9ac2a
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ tags
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.6.3
1
+ 3.4.1
data/README.md CHANGED
@@ -283,6 +283,66 @@ So now the authorization in your system can be defined in a much more OO way, wi
283
283
 
284
284
  This framework has no hooks into Rails (these would be trivial to write if necessary, e.g. you can instantiate the `user_permissions` object on your `ApplicationController` and then do the `can?` checks anywhere you want) and can therefore be used with any web framework, or even outside of the context of a web framework (if such a use case makes sense).
285
285
 
286
+ ### Conditional Lambda
287
+
288
+ Ingress by default does not know about the subject that is given in the conditional lambda. The given subject can be a Class or an Object and it depends on the user to define the correct lambda to handle the given subject.
289
+
290
+ For example, given the following `UserPermissions`:
291
+
292
+ ```
293
+ class UserPermissions < Ingress::Permissions
294
+ define_role_permissions do
295
+ can :read, Post, if: ->(user, given_subject) do
296
+ case [user, given_subject]
297
+ in [_, Post]
298
+ user.id == given_subject.user_id
299
+ in [_, Class]
300
+ true
301
+ else
302
+ false
303
+ end
304
+ end
305
+ end
306
+ ```
307
+
308
+ This is the result of the defined permissions:
309
+
310
+ ```
311
+ user_permissions = UserPermissions.new(user)
312
+ user_permissions.can?(:read, Post) # returns true
313
+ post = user.posts.first # assume we can get the list of posts form the user object
314
+ user_permissions.can?(:read, post) # returns true
315
+ ```
316
+
317
+ Ingress provides 2 convenient interfaces to apply conditional lambda on a Class or an Instance:
318
+
319
+ * if_subject_is_an_instance
320
+ * if_subject_is_a_class
321
+
322
+ These conditional lambdas always take 3 parameters: the `user`, the `subject` (this is either a Class or an Instance), and the `options` (this is additional attributes that may be needed to do the check).
323
+
324
+ They can be chained together like following:
325
+
326
+ ```
327
+ class UserPermissions < Ingress::Permissions
328
+ define_role_permissions do
329
+ can :read, Post,
330
+ if: ->(user, _post) { !user.id.nil? },
331
+ if_subject_is_an_instance: ->(user, post, _options) { user.id == post.user_id },
332
+ if_subject_is_a_class: ->(_user, klass, _options) { klass == Post }
333
+ end
334
+ end
335
+ ```
336
+
337
+ This is the result of the defined permissions:
338
+
339
+ ```
340
+ user_permissions = UserPermissions.new(user)
341
+ user_permissions.can?(:read, Post) # returns true
342
+ post = user.posts.first # assume we can get the list of posts form the user object
343
+ user_permissions.can?(:read, post) # returns true
344
+ ```
345
+
286
346
  ## Development
287
347
 
288
348
  After checking out the repo, run `script/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `script/console` for an interactive prompt that will allow you to experiment.
data/ingress.gemspec CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ["lib"]
24
24
 
25
- spec.add_development_dependency "bundler", ">= 1.10", "< 3"
26
- spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "bundler", ">= 2.6", "< 3"
26
+ spec.add_development_dependency "rake", ">= 13.1.0"
27
27
  spec.add_development_dependency "rspec"
28
28
  end
@@ -6,7 +6,7 @@ module Ingress
6
6
  @allows = allows
7
7
  @action = action
8
8
  @subject = subject
9
- @conditions = [conditions].compact.flatten
9
+ @conditions = conditions
10
10
  end
11
11
 
12
12
  def allows?
@@ -16,7 +16,6 @@ module Ingress
16
16
  def match?(given_action, given_subject, user, options = {})
17
17
  return false unless action_matches?(given_action)
18
18
  return false unless subject_matches?(given_subject)
19
- return true if ignore_conditions?(given_subject)
20
19
 
21
20
  conditions_match?(user, given_subject, options)
22
21
  end
@@ -31,19 +30,11 @@ module Ingress
31
30
 
32
31
  def subject_matches?(given_subject)
33
32
  given_subject == subject ||
34
- given_subject.class == subject ||
33
+ (subject.is_a?(Class) || subject.is_a?(Module) ? given_subject.is_a?(subject) : false) ||
35
34
  given_subject == "*" ||
36
35
  "*" == subject
37
36
  end
38
37
 
39
- def ignore_conditions?(given_subject)
40
- subject_class?(given_subject) && subject_class?(@subject)
41
- end
42
-
43
- def subject_class?(subject)
44
- [Class, Module].include? subject.class
45
- end
46
-
47
38
  def conditions_match?(user, given_subject, options)
48
39
  conditions.all? do |condition|
49
40
  if condition.arity == 2
@@ -15,15 +15,17 @@ module Ingress
15
15
 
16
16
  def can(actions, subjects, options = {}, &block)
17
17
  for_each_action_and_subject(actions, subjects) do |action, subject|
18
- condition = condition_from_options(options, block)
19
- permission_repository.add_permission(role_identifier, true, action, subject, condition)
18
+ conditions = conditions_from(options, block)
19
+
20
+ permission_repository.add_permission(role_identifier, true, action, subject, conditions)
20
21
  end
21
22
  end
22
23
 
23
24
  def cannot(actions, subjects, options = {}, &block)
24
25
  for_each_action_and_subject(actions, subjects) do |action, subject|
25
- condition = condition_from_options(options, block)
26
- permission_repository.add_permission(role_identifier, false, action, subject, condition)
26
+ conditions = conditions_from(options, block)
27
+
28
+ permission_repository.add_permission(role_identifier, false, action, subject, conditions)
27
29
  end
28
30
  end
29
31
 
@@ -41,9 +43,40 @@ module Ingress
41
43
  end
42
44
  end
43
45
 
44
- def condition_from_options(options, block)
45
- if_condition = options[:if] || block
46
- if_condition.respond_to?(:call) ? if_condition : nil
46
+ def conditions_from(options, block)
47
+ generic_condition = generic_condition_from(options[:if] || block)
48
+ instance_condition = if_subject_is_an_instance_condition_from(options[:if_subject_is_an_instance])
49
+ class_condition = if_subject_is_a_class_condition_from(options[:if_subject_is_a_class])
50
+
51
+ [generic_condition, instance_condition, class_condition].compact
52
+ end
53
+
54
+ def generic_condition_from(callback)
55
+ callback if callback&.respond_to?(:call)
56
+ end
57
+
58
+ def if_subject_is_an_instance_condition_from(callback)
59
+ if callback&.respond_to?(:call)
60
+ lambda do |user, given_subject, option|
61
+ if [Class, Module].include?(given_subject.class)
62
+ true
63
+ else
64
+ callback.call(user, given_subject, option)
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ def if_subject_is_a_class_condition_from(callback)
71
+ if callback&.respond_to?(:call)
72
+ lambda do |user, given_subject, option|
73
+ if [Class, Module].include?(given_subject.class)
74
+ callback.call(user, given_subject, option)
75
+ else
76
+ true
77
+ end
78
+ end
79
+ end
47
80
  end
48
81
  end
49
82
  end
@@ -1,3 +1,3 @@
1
1
  module Ingress
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ingress
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alan Skorkin
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2020-01-16 00:00:00.000000000 Z
10
+ date: 2025-05-20 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: bundler
@@ -16,7 +15,7 @@ dependencies:
16
15
  requirements:
17
16
  - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: '1.10'
18
+ version: '2.6'
20
19
  - - "<"
21
20
  - !ruby/object:Gem::Version
22
21
  version: '3'
@@ -26,7 +25,7 @@ dependencies:
26
25
  requirements:
27
26
  - - ">="
28
27
  - !ruby/object:Gem::Version
29
- version: '1.10'
28
+ version: '2.6'
30
29
  - - "<"
31
30
  - !ruby/object:Gem::Version
32
31
  version: '3'
@@ -34,16 +33,16 @@ dependencies:
34
33
  name: rake
35
34
  requirement: !ruby/object:Gem::Requirement
36
35
  requirements:
37
- - - "~>"
36
+ - - ">="
38
37
  - !ruby/object:Gem::Version
39
- version: '10.0'
38
+ version: 13.1.0
40
39
  type: :development
41
40
  prerelease: false
42
41
  version_requirements: !ruby/object:Gem::Requirement
43
42
  requirements:
44
- - - "~>"
43
+ - - ">="
45
44
  - !ruby/object:Gem::Version
46
- version: '10.0'
45
+ version: 13.1.0
47
46
  - !ruby/object:Gem::Dependency
48
47
  name: rspec
49
48
  requirement: !ruby/object:Gem::Requirement
@@ -58,7 +57,6 @@ dependencies:
58
57
  - - ">="
59
58
  - !ruby/object:Gem::Version
60
59
  version: '0'
61
- description:
62
60
  email:
63
61
  - alan@skorks.com
64
62
  executables: []
@@ -90,7 +88,6 @@ licenses:
90
88
  metadata:
91
89
  bug_tracker_uri: https://github.com/skorks/ingress/issues
92
90
  source_code_uri: https://github.com/skorks/ingress
93
- post_install_message:
94
91
  rdoc_options: []
95
92
  require_paths:
96
93
  - lib
@@ -105,8 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
105
102
  - !ruby/object:Gem::Version
106
103
  version: '0'
107
104
  requirements: []
108
- rubygems_version: 3.0.3
109
- signing_key:
105
+ rubygems_version: 3.6.2
110
106
  specification_version: 4
111
107
  summary: Simple role based authorization for Ruby applications
112
108
  test_files: []