passpartu 1.0.1 → 1.0.2

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: 21336de32d4938c7815f3792fa6fa99be0ec64ee45f2a401eb870b5cd7cfe669
4
- data.tar.gz: 2a5a48df685793599dddd4271919b00d75c08343d95f7d5c8e93b21a4d787d5b
3
+ metadata.gz: 6941eb262c351f25dd525ced8ce9d27cf03c90f6977d9e31674b5aa675db2ada
4
+ data.tar.gz: e9fd5451850cc07bec8b6a2db6e23cadbc9415eb14945a39ab3913857c7e4628
5
5
  SHA512:
6
- metadata.gz: 1940690916391b4053c30a6d4cc00b1c6f49cf4650434cfa95ed5ca57529e9f734bbe197c73d7c4e89becc2dae841f3c8c62b897b5be70bd7d7b15bedc703137
7
- data.tar.gz: 7bfc6007b1aa0490ad4ec21b0e41bddc4b96a3658a8e484e8b5194d3e5fd633772502d03d1d1c9863217f771947b6f7f3a581d17fe8f46e0846e59a4ff54d101
6
+ metadata.gz: 8986a0743c963712de307a141bfe37405636ec7f952e29ae13c22c2512ec5ae04ef0f4e93e29a8ee5ffd32ebcf39675c7800e58332b451acfc34444d875178a6
7
+ data.tar.gz: 5d1fde0b670dd30acd04bb819d503588cccaaacbae773076eee10fbd865a16fa370e822c1227d73388d588afd49f3cf96ad759a2db373ef8774d3206d39b3524
data/README.md CHANGED
@@ -1,8 +1,9 @@
1
- # Passpartu v1.0.1 - [changelog](https://github.com/coaxsoft/passpartu/blob/master/CHANGELOG.md)
1
+ # Passpartu v1.0.2 - [changelog](https://github.com/coaxsoft/passpartu/blob/master/CHANGELOG.md)
2
2
 
3
3
  Passpartu makes policies great again (works awesome with [Pundit](https://rubygems.org/gems/pundit)).
4
4
 
5
5
  Instead of this:
6
+
6
7
  ```ruby
7
8
  class PostPolicy < ApplicationPolicy
8
9
  def update?
@@ -12,6 +13,7 @@ end
12
13
  ```
13
14
 
14
15
  just this:
16
+
15
17
  ```ruby
16
18
  class PostPolicy < ApplicationPolicy
17
19
  def update?
@@ -19,19 +21,24 @@ class PostPolicy < ApplicationPolicy
19
21
  end
20
22
  end
21
23
  ```
24
+
22
25
  ## Usage
26
+
23
27
  Include `Passpartu` into your policy model.
28
+
24
29
  ```ruby
25
30
  class User
26
31
  include Passpartu
27
32
  end
28
33
  ```
34
+
29
35
  NOTE: Your `User` model must respond to `role` method that returns a string or a symbol!
30
36
 
31
37
  Keep all your policies in one place.
32
38
  Create `./config/passpartu.yml` and start writing your policies.
33
39
 
34
40
  #### Example of `passpartu.yml`
41
+
35
42
  ```yml
36
43
  # ./config/passpartu.yml
37
44
  manager: &manager
@@ -65,18 +72,25 @@ admin:
65
72
  ```
66
73
 
67
74
  ## Features
75
+
68
76
  #### CRUD
77
+
69
78
  It's possible to use `crud` key to set values for `create`, `read`, `update`, `delete` at once.
70
79
  `create`, `read`, `update`, `delete` has higher priority than `crud`
80
+
71
81
  In case `crud: true` and `delete: false` - result `false`
72
82
 
83
+
73
84
  #### Only
85
+
74
86
  It's possible to include specific roles to checks
87
+
75
88
  ```ruby
76
89
  user_admin.can?(:orders, :edit) # check policy for admin and returns true if policy true
77
90
  user_admin.can?(:orders, :edit, only: :admin) # returns true because the user is an admin and we included only admin
78
91
  user_manager.can?(:orders, :edit, only: :admin) # returns false because user is manager and we included only admin
79
92
  ```
93
+
80
94
  It's possible to give an array as only attribute
81
95
 
82
96
  ```ruby
@@ -85,18 +99,21 @@ It's possible to give an array as only attribute
85
99
  ```
86
100
 
87
101
  Note: `only` has higher priority than `except/skip`. Do not use both.
102
+
88
103
  ```ruby
89
104
  user_admin.can?(:orders, :edit, only: :admin, except: :admin) # returns true
90
105
  ```
91
106
 
92
-
93
107
  #### Skip (except)
108
+
94
109
  It's possible to exclude roles from checks
110
+
95
111
  ```ruby
96
112
  user_admin.can?(:orders, :edit) # check policy for admin and returns true if policy true
97
113
  user_admin.can?(:orders, :edit, except: :admin) # returns false because user is admin and we excluded admin
98
114
 
99
115
  ```
116
+
100
117
  It's possible to give an array as except attribute
101
118
 
102
119
  ```ruby
@@ -107,6 +124,7 @@ It's possible to give an array as except attribute
107
124
  `skip` alias to `except`
108
125
 
109
126
  Note: `expect` has higher priority than `skip`. Do not use both.
127
+
110
128
  ```ruby
111
129
  user_agent.can?(:orders, :edit, except: [:admin, :manager]) { user_agent.orders.include?(order) }
112
130
  # equals to
@@ -114,7 +132,9 @@ Note: `expect` has higher priority than `skip`. Do not use both.
114
132
  ```
115
133
 
116
134
  #### Per role methods
135
+
117
136
  Check user roles AND policy rule
137
+
118
138
  ```ruby
119
139
  # check if user admin AND returns true if policy true
120
140
  user_admin.admin_can?(:orders, :edit) # true
@@ -124,6 +144,7 @@ Check user roles AND policy rule
124
144
  ```
125
145
 
126
146
  #### Code blocks
147
+
127
148
  ```ruby
128
149
  # check rules as usual AND code in the block
129
150
  user_agent.can?(:orders, :edit, except: [:admin, :manager]) { user_agent.orders.include?(order) }
@@ -133,7 +154,9 @@ Check user roles AND policy rule
133
154
  ```
134
155
 
135
156
  #### Waterfall check
157
+
136
158
  Allow or restrict absolutely everything for particular role or/and particular domain.
159
+
137
160
  ```ruby
138
161
  # ./config/initializers/passpartu.rb
139
162
 
@@ -153,6 +176,7 @@ medium_looser:
153
176
  delete: false
154
177
  products: true
155
178
  ```
179
+
156
180
  ```ruby
157
181
  user_super_admin.can?(:do, :whatever, :want) # true
158
182
  user_super_loser.can?(:do, :whatever, :want) # false
@@ -161,10 +185,10 @@ user_medium_loser.can?(:orders, :delete) # false
161
185
  user_medium_loser.can?(:products, :create) # true
162
186
  user_medium_loser.can?(:products, :create, :and_delete) # true
163
187
  ```
164
-
165
-
166
188
  ##### Real life example
189
+
167
190
  You need to check custom rule for agent
191
+
168
192
  ```yml
169
193
  # ./config/passpartu.yml
170
194
 
@@ -202,9 +226,13 @@ You can configure Passpartu by creating `./config/initializers/passpartu.rb`.
202
226
  Passpartu.configure do |config|
203
227
  config.policy_file = './config/passpartu.yml'
204
228
  config.raise_policy_missed_error = true
229
+ config.check_waterfall = false
205
230
  end
231
+
206
232
  ```
233
+
207
234
  ### Raise policy missed errors
235
+
208
236
  By default Passpartu will raise an PolicyMissedError if policy is missed in `passpartu.yml`. In initializer set `config.raise_policy_missed_error = false` in order to return `false` in case when policy is not defined. This is a good approach to write only "positive" policies (only true) and automatically restricts everything that is not mentioned in `passpartu.yml`
209
237
 
210
238
  ## Installation
@@ -244,4 +272,5 @@ The gem is available as open source under the terms of the [MIT License](https:/
244
272
  Everyone interacting in the Passpartu project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/coaxsoft/passpartu/blob/master/CODE_OF_CONDUCT.md).
245
273
 
246
274
  ## Idea
275
+
247
276
  Initially designed and created by [Orest Falchuk](https://github.com/OrestF)
@@ -6,7 +6,6 @@ require_relative 'passpartu/patcher'
6
6
  require_relative 'passpartu/verify'
7
7
  require_relative 'passpartu/block_verify'
8
8
  require_relative 'passpartu/validate_result'
9
- require_relative 'passpartu/check_waterfall'
10
9
  require_relative 'passpartu/user' # for testing only
11
10
 
12
11
  module Passpartu
@@ -32,14 +31,14 @@ module Passpartu
32
31
  end
33
32
 
34
33
  class Config
35
- attr_accessor :policy, :raise_policy_missed_error
36
- attr_reader :policy_file, :check_waterfall
34
+ attr_accessor :raise_policy_missed_error
35
+ attr_reader :policy_file, :check_waterfall, :policy
37
36
 
38
37
  DEFAULT_POLICY_FILE = './config/passpartu.yml'
39
38
 
40
39
  def initialize
41
40
  @policy_file = DEFAULT_POLICY_FILE
42
- @policy = YAML.load_file(policy_file) if File.exist?(policy_file)
41
+ set_policy(YAML.load_file(policy_file)) if File.exist?(policy_file)
43
42
  @raise_policy_missed_error = true
44
43
  @check_waterfall = false
45
44
  end
@@ -49,15 +48,50 @@ module Passpartu
49
48
 
50
49
  raise PolicyYmlNotFoundError unless File.exist?(policy_file)
51
50
 
52
- @policy = YAML.load_file(policy_file)
51
+ set_policy(YAML.load_file(policy_file))
53
52
  end
54
53
 
55
54
  def check_waterfall=(value)
56
55
  @check_waterfall = value
57
- @raise_policy_missed_error = false if @check_waterfall
56
+
57
+ if @check_waterfall
58
+ @raise_policy_missed_error = false
59
+ set_policy(@policy)
60
+ end
58
61
 
59
62
  @check_waterfall
60
63
  end
64
+
65
+ private
66
+
67
+ def set_policy(value)
68
+ @policy = patch_policy_booleans_if(value)
69
+ end
70
+
71
+ # patch all booleans in hash to support check_waterfall
72
+ def patch_policy_booleans_if(hash)
73
+ return hash unless @check_waterfall
74
+
75
+ hash.transform_values! do |value|
76
+ if value.is_a?(TrueClass)
77
+ value.define_singleton_method(:dig) { |*_keys| true }
78
+ elsif value.is_a?(FalseClass)
79
+ value.define_singleton_method(:dig) { |*_keys| false }
80
+ elsif
81
+ patch_policy_booleans_if(value)
82
+ end
83
+
84
+ value
85
+ end
86
+ end
87
+
88
+ def blank?(item)
89
+ item.respond_to?(:empty?) ? !!item.empty? : !item
90
+ end
91
+
92
+ def present?(item)
93
+ !blank?(item)
94
+ end
61
95
  end
62
96
 
63
97
  configure {}
@@ -25,7 +25,6 @@ module Passpartu
25
25
  def call
26
26
  return false if role_ignore?
27
27
 
28
- check_waterfall_if
29
28
  default_check
30
29
  check_crud_if
31
30
 
@@ -72,12 +71,6 @@ module Passpartu
72
71
  %w[create read update delete].include?(keys[-1])
73
72
  end
74
73
 
75
- def check_waterfall_if
76
- return unless Passpartu.config.check_waterfall && policy_missed?
77
-
78
- @result = Passpartu::CheckWaterfall.call(role, keys)
79
- end
80
-
81
74
  def blank?(item)
82
75
  item.respond_to?(:empty?) ? !!item.empty? : !item
83
76
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Passpartu
4
- VERSION = '1.0.1'
4
+ VERSION = '1.0.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: passpartu
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - OrestF
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-04-26 00:00:00.000000000 Z
11
+ date: 2020-08-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -64,7 +64,6 @@ files:
64
64
  - README.md
65
65
  - lib/passpartu.rb
66
66
  - lib/passpartu/block_verify.rb
67
- - lib/passpartu/check_waterfall.rb
68
67
  - lib/passpartu/patcher.rb
69
68
  - lib/passpartu/user.rb
70
69
  - lib/passpartu/validate_result.rb
@@ -90,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
89
  - !ruby/object:Gem::Version
91
90
  version: '0'
92
91
  requirements: []
93
- rubygems_version: 3.1.2
92
+ rubygems_version: 3.0.1
94
93
  signing_key:
95
94
  specification_version: 4
96
95
  summary: Passpartu makes policies great again
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Passpartu
4
- class CheckWaterfall
5
- attr_reader :waterfall, :policy_hash
6
- def initialize(role, keys)
7
- @waterfall = [role] + keys
8
- @policy_hash = Passpartu.policy
9
- end
10
-
11
- def self.call(role, keys)
12
- new(role, keys).call
13
- end
14
-
15
- def call
16
- patch_boolean_classes
17
- @result = policy_hash.dig(*waterfall)
18
- reset_boolean_classes
19
-
20
- @result
21
- end
22
-
23
- def patch_boolean_classes
24
- TrueClass.define_method(:dig) { |*_keys| true }
25
- FalseClass.define_method(:dig) { |*_keys| false }
26
- end
27
-
28
- def reset_boolean_classes
29
- TrueClass.undef_method(:dig)
30
- FalseClass.undef_method(:dig)
31
- end
32
- end
33
- end