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 +4 -4
- data/README.md +33 -4
- data/lib/passpartu.rb +40 -6
- data/lib/passpartu/verify.rb +0 -7
- data/lib/passpartu/version.rb +1 -1
- metadata +3 -4
- data/lib/passpartu/check_waterfall.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6941eb262c351f25dd525ced8ce9d27cf03c90f6977d9e31674b5aa675db2ada
|
4
|
+
data.tar.gz: e9fd5451850cc07bec8b6a2db6e23cadbc9415eb14945a39ab3913857c7e4628
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8986a0743c963712de307a141bfe37405636ec7f952e29ae13c22c2512ec5ae04ef0f4e93e29a8ee5ffd32ebcf39675c7800e58332b451acfc34444d875178a6
|
7
|
+
data.tar.gz: 5d1fde0b670dd30acd04bb819d503588cccaaacbae773076eee10fbd865a16fa370e822c1227d73388d588afd49f3cf96ad759a2db373ef8774d3206d39b3524
|
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
# Passpartu v1.0.
|
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)
|
data/lib/passpartu.rb
CHANGED
@@ -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 :
|
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
|
-
|
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
|
-
|
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
|
-
|
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 {}
|
data/lib/passpartu/verify.rb
CHANGED
@@ -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
|
data/lib/passpartu/version.rb
CHANGED
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.
|
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-
|
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
|
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
|