passpartu 1.0.1 → 1.0.2

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: 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