passpartu 0.3.1 → 0.5.0

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: 0fdefd549a1c4e1cc70e938cfd9e14d1b39ee0686ee011796dd59abf1a3710a3
4
- data.tar.gz: 65579c55e57bdbb8a4de830f2819aaede0aea5c195ad951808a91a88f30263c3
3
+ metadata.gz: cd628d50b6e52acefe4f503c5ada9cec0b224b70be8791fa07f8c5586f93def4
4
+ data.tar.gz: 5314cf52de8c7cf581768ed8842edb1164b3a57c9aa56456a5ed8e5f0dbfd1e9
5
5
  SHA512:
6
- metadata.gz: fd3b87dc5660861a05ac0d76f9bfa87bb6b16cf108e4784ec8a99680030fe3e8631350a901fdc15e87853acb42a4faba971b9cf7b142eafb3536e8b911da0424
7
- data.tar.gz: 2ff8ee8f80752d51fc0fbc332d77bb3441072bdd2df67a1f3e83507160734ff800a5d6c28f529d53317045b8c3f7e9e16279c9dbae2270c32dbc07e91cadf821
6
+ metadata.gz: 7ddafd099269680b9f05dbe140fdd9ebae94eff8072e81073cd5db3840bc8d87d4a8171db637de242df0f19c16043123972f9a8b518228d2e2712aab6559385c
7
+ data.tar.gz: 3f3cab407da0abde8da14764df233c625020d12f8c0d631912d6d009c90bc6fb69d23024aa7d272dc3247009824160df64b816561ec05be43d0fc630b5687d7d
data/README.md CHANGED
@@ -67,6 +67,69 @@ It's possible to use `crud` key to set values for `create`, `read`, `update`, `d
67
67
  `create`, `read`, `update`, `delete` has higher priority than `crud`
68
68
  In case `crud: true` and `delete: false` - result `false`
69
69
 
70
+
71
+ #### Except
72
+ It's possible to exclude role from checks
73
+ ```ruby
74
+ user_admin.can?(:orders, :edit) # check policy for admin and returns true if policy true
75
+ user_admin.can?(:orders, :edit, except: :admin) # returns false because user is admin and we excluded admin
76
+
77
+ ```
78
+ It's possible to give an array as except attribute
79
+
80
+ ```ruby
81
+ user_admin.can?(:orders, :edit, except: [:admin, :manager]) # returns false
82
+ user_manager.can?(:orders, :edit, except: [:admin, :manager]) # returns false
83
+ ```
84
+
85
+ #### Per role methods
86
+ Check user roles AND policy rule
87
+ ```ruby
88
+ # check if user admin AND returns true if policy true
89
+ user_admin.admin_can?(:orders, :edit) # true
90
+
91
+ # check if user manager AND returns true if policy true
92
+ user_admin.manager_can?(:orders, :edit) # false
93
+ ```
94
+
95
+ #### Code blocks
96
+ ```ruby
97
+ # check rules as usual AND code in the block
98
+ user_agent.can?(:orders, :edit, except: [:admin, :manager]) { user_agent.orders.include?(order) }
99
+
100
+ # OR
101
+ user_agent.agent_can?(:orders, :edit, except: [:admin, :manager]) { user_agent.orders.include?(order) }
102
+ ```
103
+
104
+ ##### Real life example
105
+ You need to check custom rule for agent
106
+ ```yml
107
+ # ./config/passpartu.yml
108
+
109
+ admin:
110
+ order:
111
+ create: true
112
+ edit: true
113
+ delete: true
114
+ manager:
115
+ order:
116
+ create: true
117
+ edit: true
118
+ delete: false
119
+ agent:
120
+ order:
121
+ create: true
122
+ edit: true
123
+ delete: false
124
+ ```
125
+
126
+ ```ruby
127
+ user.can?(:order, :edit, except: :agent) || user.agent_can?(:order, :edit) { user.orders.include?(order) }
128
+ ```
129
+
130
+ 1. This code returns `true` if user is `admin` or `manager`
131
+ 1. This code returns `true` if user is `agent` AND if agent policy set to `true` AND if given block returns true
132
+
70
133
  ## Configuration
71
134
 
72
135
  You can configure Passpartu by creating `./config/initializers/passpartu.rb`.
@@ -2,6 +2,7 @@ require 'passpartu/version'
2
2
  require 'yaml'
3
3
  require_relative 'passpartu/patcher'
4
4
  require_relative 'passpartu/verify'
5
+ require_relative 'passpartu/block_verify'
5
6
  require_relative 'passpartu/validate_result'
6
7
  require_relative 'passpartu/user' # for testing only
7
8
 
@@ -0,0 +1,10 @@
1
+ module Passpartu
2
+ class BlockVerify < ::Passpartu::Verify
3
+ def call
4
+ policy_result = super
5
+ return policy_result if block.nil?
6
+
7
+ policy_result && block.call
8
+ end
9
+ end
10
+ end
@@ -11,8 +11,14 @@ module Passpartu
11
11
 
12
12
  def call
13
13
  klass.class_eval do
14
- define_method('can?') do |*keys|
15
- Passpartu::Verify.call(role, keys)
14
+ define_method('can?') do |*keys, except: nil, &block|
15
+ Passpartu::BlockVerify.call(role, keys, except: except, &block)
16
+ end
17
+
18
+ Passpartu.policy.keys.each do |policy_role|
19
+ define_method("#{policy_role}_can?") do |*keys, except: nil, &block|
20
+ role.to_s == policy_role && Passpartu::BlockVerify.call(role, keys, except: except, &block)
21
+ end
16
22
  end
17
23
  end
18
24
  end
@@ -2,18 +2,22 @@ module Passpartu
2
2
  class Verify
3
3
  CRUD_KEY = 'crud'.freeze
4
4
 
5
- attr_reader :role, :keys, :result
6
- def initialize(role, keys)
7
- @role = role
5
+ attr_reader :role, :keys, :result, :except, :block
6
+ def initialize(role, keys, except, block)
7
+ @role = role.to_s
8
8
  @keys = keys.map(&:to_s)
9
+ @except = Array(except).map(&:to_s) if present?(except)
10
+ @block = block
9
11
  end
10
12
 
11
- def self.call(role, keys)
12
- new(role, keys).call
13
+ def self.call(role, keys, except: nil, &block)
14
+ new(role, keys, except, block).call
13
15
  end
14
16
 
15
17
  def call
16
- check
18
+ return false if role_excepted?
19
+
20
+ check_policy
17
21
  check_crud if policy_missed? && last_key_crud?
18
22
 
19
23
  validate_result
@@ -21,13 +25,19 @@ module Passpartu
21
25
 
22
26
  private
23
27
 
24
- def check
25
- @result = Passpartu.policy.dig(role.to_s, *keys)
28
+ def role_excepted?
29
+ return false if blank?(except)
30
+
31
+ except.include?(role)
32
+ end
33
+
34
+ def check_policy
35
+ @result = Passpartu.policy.dig(role, *keys)
26
36
  end
27
37
 
28
38
  def check_crud
29
39
  change_crud_key
30
- check
40
+ check_policy
31
41
  end
32
42
 
33
43
  def change_crud_key
@@ -45,5 +55,13 @@ module Passpartu
45
55
  def last_key_crud?
46
56
  %w[create read update delete].include?(keys[-1])
47
57
  end
58
+
59
+ def blank?(item)
60
+ item.respond_to?(:empty?) ? !!item.empty? : !item
61
+ end
62
+
63
+ def present?(item)
64
+ !blank?(item)
65
+ end
48
66
  end
49
67
  end
@@ -1,3 +1,3 @@
1
1
  module Passpartu
2
- VERSION = '0.3.1'.freeze
2
+ VERSION = '0.5.0'.freeze
3
3
  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.3.1
4
+ version: 0.5.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-03-15 00:00:00.000000000 Z
11
+ date: 2019-03-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -63,6 +63,7 @@ extra_rdoc_files: []
63
63
  files:
64
64
  - README.md
65
65
  - lib/passpartu.rb
66
+ - lib/passpartu/block_verify.rb
66
67
  - lib/passpartu/patcher.rb
67
68
  - lib/passpartu/user.rb
68
69
  - lib/passpartu/validate_result.rb