passpartu 0.6.0 → 1.0.0

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: f1074ae228e7b5f0cfff3a9a2fc0acd58536a161451cab914b814e8b1bf44470
4
- data.tar.gz: 4ecf5e75ec63192afd3d739b47dd646912de8b594f01e8553fd6f9df0d1dbfb6
3
+ metadata.gz: 982e32959b5022a455e42d2c1de190c0851f358cfd34c699ece8394e6af0d951
4
+ data.tar.gz: 2e81288b0af25837d0d4d97b14562e33f2813ca0b8741adbce66451568a99487
5
5
  SHA512:
6
- metadata.gz: ceeac19430a29384cf70bf5755ed6786e06f76d981d1c42e81a677f8163211f46bc6a4bdb4eca6d9968cc7751d0c234392edfe6227c2dfd2c0c2f1132ab36cb0
7
- data.tar.gz: 5d4aef534482fc686033d67c043e8378dc92c8bfecbb00672d81949fa5a63ccba6c36c3fd492267375a38854085eae4f13af6da8aa20c3df7e1c1c935ee39c40
6
+ metadata.gz: 3cebce1276892e0fd925be52bc3ed817b83b6aeb96d9b056b9d999d288b9cbe891189f36a8d6b904b1dac53bbd90eb10b2d6628e42f727d063bc300abbeb697d
7
+ data.tar.gz: 6caeffe92ffe0f8fe158c0d10c9d4eca18e88ac3acad3c14d7346673ca6740c7335564d53f10a9263f6ae2bcc533077fb18d84cfb25c68cac71717e7b4c01ff7
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Passpartu v0.6.0 - [changelog](https://github.com/coaxsoft/passpartu/blob/master/CHANGELOG.md)
1
+ # Passpartu v1.0.0 - [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
 
@@ -132,6 +132,37 @@ Check user roles AND policy rule
132
132
  user_agent.agent_can?(:orders, :edit, except: [:admin, :manager]) { user_agent.orders.include?(order) }
133
133
  ```
134
134
 
135
+ #### Waterfall check
136
+ Allow or restrict absolutely everything for particular role or/and particular domain.
137
+ ```ruby
138
+ # ./config/initializers/passpartu.rb
139
+
140
+ Passpartu.configure do |config|
141
+ config.check_waterfall = true
142
+ end
143
+ ```
144
+
145
+ ```yml
146
+ # ./config/passpartu.yml
147
+
148
+ super_admin: true
149
+ super_looser: false
150
+ medium_looser:
151
+ orders:
152
+ create: true
153
+ delete: false
154
+ products: true
155
+ ```
156
+ ```ruby
157
+ user_super_admin.can?(:do, :whatever, :want) # true
158
+ user_super_loser.can?(:do, :whatever, :want) # false
159
+ user_medium_loser.can?(:orders, :create) # true
160
+ user_medium_loser.can?(:orders, :delete) # false
161
+ user_medium_loser.can?(:products, :create) # true
162
+ user_medium_loser.can?(:products, :create, :and_delete) # true
163
+ ```
164
+
165
+
135
166
  ##### Real life example
136
167
  You need to check custom rule for agent
137
168
  ```yml
@@ -1,13 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'passpartu/version'
2
4
  require 'yaml'
3
5
  require_relative 'passpartu/patcher'
4
6
  require_relative 'passpartu/verify'
5
7
  require_relative 'passpartu/block_verify'
6
8
  require_relative 'passpartu/validate_result'
9
+ require_relative 'passpartu/check_waterfall'
7
10
  require_relative 'passpartu/user' # for testing only
8
11
 
9
12
  module Passpartu
10
13
  class Error < StandardError; end
14
+ class PolicyYmlNotFoundError < StandardError; end
15
+ class WaterfallError < StandardError; end
11
16
 
12
17
  def self.included(policy_class)
13
18
  Passpartu::Patcher.call(policy_class)
@@ -27,17 +32,23 @@ module Passpartu
27
32
  end
28
33
 
29
34
  class Config
30
- attr_accessor :policy, :raise_policy_missed_error
35
+ attr_accessor :policy, :raise_policy_missed_error, :check_waterfall
31
36
  attr_reader :policy_file
32
37
 
38
+ DEFAULT_POLICY_FILE = './config/passpartu.yml'
39
+
33
40
  def initialize
34
- @policy_file = './config/passpartu.yml'
35
- @policy = YAML.load_file(policy_file)
41
+ @policy_file = DEFAULT_POLICY_FILE
42
+ @policy = YAML.load_file(policy_file) if File.exist?(policy_file)
36
43
  @raise_policy_missed_error = true
44
+ @check_waterfall = false
37
45
  end
38
46
 
39
47
  def policy_file=(file = nil)
40
- @policy_file = file || './config/passpartu.yml'
48
+ @policy_file = file || DEFAULT_POLICY_FILE
49
+
50
+ raise PolicyYmlNotFoundError unless File.exist?(policy_file)
51
+
41
52
  @policy = YAML.load_file(policy_file)
42
53
  end
43
54
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passpartu
2
4
  class BlockVerify < ::Passpartu::Verify
3
5
  def call
@@ -0,0 +1,33 @@
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
@@ -1,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passpartu
2
4
  class Patcher
3
5
  attr_reader :klass
4
6
  def initialize(klass)
7
+ raise PolicyYmlNotFoundError if Passpartu.policy.nil?
8
+
5
9
  @klass = klass
6
10
  end
7
11
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # for testing only
2
4
 
3
5
  module Passpartu
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passpartu
2
4
  class ValidateResult
3
5
  class PolicyMissedError < StandardError; end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passpartu
2
4
  class Verify
3
- CRUD_KEY = 'crud'.freeze
5
+ CRUD_KEY = 'crud'
4
6
 
5
7
  attr_reader :role, :keys, :result, :only, :except, :block
6
8
 
@@ -12,6 +14,8 @@ module Passpartu
12
14
  @only = Array(only).map(&:to_s) if present?(only)
13
15
  @except = Array(exclusion).map(&:to_s) if present?(exclusion) && !@only
14
16
  @block = block
17
+
18
+ raise PolicyYmlNotFoundError if Passpartu.policy.nil?
15
19
  end
16
20
 
17
21
  def self.call(role, keys, only: nil, except: nil, skip: nil, &block)
@@ -21,10 +25,17 @@ module Passpartu
21
25
  def call
22
26
  return false if role_ignore?
23
27
 
24
- check_policy
25
- check_crud if policy_missed? && last_key_crud?
28
+ check_waterfall_if
29
+ default_check
30
+ check_crud_if
26
31
 
27
32
  validate_result
33
+ rescue StandardError => e
34
+ if ['TrueClass does not have #dig method', 'FalseClass does not have #dig method'].include?(e.message)
35
+ raise WaterfallError.new "Looks like you want to use check_waterfall feature, but it's set to 'false'. Otherwise check your #{Passpartu.config.policy_file} for validness"
36
+ else
37
+ raise e
38
+ end
28
39
  end
29
40
 
30
41
  private
@@ -36,17 +47,17 @@ module Passpartu
36
47
  false
37
48
  end
38
49
 
39
- def check_policy
50
+ def default_check
51
+ return unless policy_missed?
52
+
40
53
  @result = Passpartu.policy.dig(role, *keys)
41
54
  end
42
55
 
43
- def check_crud
44
- change_crud_key
45
- check_policy
46
- end
56
+ def check_crud_if
57
+ return unless policy_missed? && last_key_crud?
47
58
 
48
- def change_crud_key
49
59
  @keys[-1] = CRUD_KEY
60
+ default_check
50
61
  end
51
62
 
52
63
  def policy_missed?
@@ -61,6 +72,12 @@ module Passpartu
61
72
  %w[create read update delete].include?(keys[-1])
62
73
  end
63
74
 
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
+
64
81
  def blank?(item)
65
82
  item.respond_to?(:empty?) ? !!item.empty? : !item
66
83
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Passpartu
2
- VERSION = '0.6.0'.freeze
4
+ VERSION = '1.0.0'
3
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: 0.6.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OrestF
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-04-01 00:00:00.000000000 Z
11
+ date: 2020-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -64,6 +64,7 @@ files:
64
64
  - README.md
65
65
  - lib/passpartu.rb
66
66
  - lib/passpartu/block_verify.rb
67
+ - lib/passpartu/check_waterfall.rb
67
68
  - lib/passpartu/patcher.rb
68
69
  - lib/passpartu/user.rb
69
70
  - lib/passpartu/validate_result.rb
@@ -89,7 +90,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
89
90
  - !ruby/object:Gem::Version
90
91
  version: '0'
91
92
  requirements: []
92
- rubygems_version: 3.0.1
93
+ rubyforge_project:
94
+ rubygems_version: 2.7.7
93
95
  signing_key:
94
96
  specification_version: 4
95
97
  summary: Passpartu makes policies great again