kitty_policy 0.1.2 → 0.1.4

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: 36bb0e98df928a03bb4e18761f8e23e7b7868da05d15bb70f81425d76f936da1
4
- data.tar.gz: 6a00a72433c6cc7016f5d62427395d52914bab78fea76e2cdd1faf3b6f526924
3
+ metadata.gz: 73678357b257df80a329b2f02df58f13b536a9dc284cffdbead4fa0b13cbbcc4
4
+ data.tar.gz: 2aa9e8f995983610c9b5ce23ba0bd63c7022dfadeabd0f774bd0cc04e5905273
5
5
  SHA512:
6
- metadata.gz: fc35eeb00ba8e1ec5d43ed4a20fa710fc2e1c347dea3d3f8424809f8eaf5a80300a99bb760d08660cb3ae5a9a32909fd61e6e2336bf95df27af3fdc59f5219ee
7
- data.tar.gz: 81905f36f0b2cc4f2b007b53b5599d05f9be8777818a713706ec93c687fad1fcb76a9f49f27a651c2542e1323c4e389219ea2129e870b0e2d5f97a93d9bd7c2a
6
+ metadata.gz: df68b29d1e647c6ca8ed3fad644d6e886c858e8ec6669dd346f28aaff723e070ea2400d85cc59fa2d919fd41543c167f48565acb696428a56099d2d880faffbd
7
+ data.tar.gz: 83fabb6697e527c6c27c4321fdf6445cf793e3bb6a6f1db64f679a647de79914db3a5b0c80670b006b1b77a089b6d0bf6243f5d14777a2d07cb985cb18e1e32e
@@ -0,0 +1,40 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Ruby
9
+
10
+ on:
11
+ push:
12
+ branches: [ "master" ]
13
+ pull_request:
14
+ branches: [ "master" ]
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ test:
21
+
22
+ runs-on: ubuntu-latest
23
+ strategy:
24
+ matrix:
25
+ ruby-version: ['2.6', '2.7', '3.0']
26
+
27
+ steps:
28
+ - uses: actions/checkout@v3
29
+
30
+ - name: Set up Ruby
31
+ uses: ruby/setup-ruby@0a29871fe2b0200a17a4497bae54fe5df0d973aa # v1.115.3
32
+ with:
33
+ ruby-version: ${{ matrix.ruby-version }}
34
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
35
+
36
+ - name: Run Rubocop
37
+ run: bundle exec rubocop
38
+
39
+ - name: Run RSpec
40
+ run: bundle exec rspec spec
data/.rubocop.yml CHANGED
@@ -8,6 +8,8 @@ AllCops:
8
8
  - db/**/*
9
9
  - vendor/**/*
10
10
  - node_modules/**/*
11
+ NewCops: enable
12
+ SuggestExtensions: false
11
13
 
12
14
  Style/PercentLiteralDelimiters:
13
15
  PreferredDelimiters:
@@ -60,8 +62,17 @@ RSpec/MultipleExpectations:
60
62
  RSpec/ExampleLength:
61
63
  Enabled: false
62
64
 
63
- Capybara/FeatureMethods:
65
+ Lint/AmbiguousBlockAssociation:
64
66
  Enabled: false
65
67
 
66
- Lint/AmbiguousBlockAssociation:
68
+ Gemspec/RequiredRubyVersion:
69
+ Enabled: false
70
+
71
+ RSpec/BeEq:
72
+ Enabled: false
73
+
74
+ RSpec/VerifiedDoubles:
75
+ Enabled: false
76
+
77
+ RSpec/NoExpectationExample:
67
78
  Enabled: false
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.6.2
1
+ 2.7.5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## Version 0.1.4
4
+
5
+ * **[feature]** Added `delegate_ability` method, which delegates ability from one object to other
6
+ * **[fix]** Raises error when "can_" method is defined more than once
7
+
8
+ ## Version 0.1.3
9
+
10
+ * **[feature]** Added `authorize_object` for field authorization (@tgroutars)
11
+ - *no support for connections and arrays*
12
+
3
13
  ## Version 0.1.2
4
14
 
5
15
  * **[fix]** Allow `fallback: []` to work for Relay connections (@rstankov)
data/Gemfile.lock CHANGED
@@ -1,57 +1,64 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kitty_policy (0.1.2)
4
+ kitty_policy (0.1.3)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- ast (2.4.0)
10
- diff-lcs (1.3)
11
- graphql (1.9.7)
12
- jaro_winkler (1.5.3)
13
- parallel (1.17.0)
14
- parser (2.6.3.0)
15
- ast (~> 2.4.0)
16
- rainbow (3.0.0)
17
- rake (10.5.0)
18
- rspec (3.8.0)
19
- rspec-core (~> 3.8.0)
20
- rspec-expectations (~> 3.8.0)
21
- rspec-mocks (~> 3.8.0)
22
- rspec-core (3.8.1)
23
- rspec-support (~> 3.8.0)
24
- rspec-expectations (3.8.4)
9
+ ast (2.4.2)
10
+ diff-lcs (1.5.0)
11
+ graphql (2.0.14)
12
+ json (2.6.2)
13
+ parallel (1.22.1)
14
+ parser (3.1.2.1)
15
+ ast (~> 2.4.1)
16
+ rainbow (3.1.1)
17
+ rake (13.0.6)
18
+ regexp_parser (2.6.0)
19
+ rexml (3.2.5)
20
+ rspec (3.11.0)
21
+ rspec-core (~> 3.11.0)
22
+ rspec-expectations (~> 3.11.0)
23
+ rspec-mocks (~> 3.11.0)
24
+ rspec-core (3.11.0)
25
+ rspec-support (~> 3.11.0)
26
+ rspec-expectations (3.11.1)
25
27
  diff-lcs (>= 1.2.0, < 2.0)
26
- rspec-support (~> 3.8.0)
27
- rspec-mocks (3.8.1)
28
+ rspec-support (~> 3.11.0)
29
+ rspec-mocks (3.11.1)
28
30
  diff-lcs (>= 1.2.0, < 2.0)
29
- rspec-support (~> 3.8.0)
30
- rspec-support (3.8.2)
31
- rubocop (0.72.0)
32
- jaro_winkler (~> 1.5.1)
31
+ rspec-support (~> 3.11.0)
32
+ rspec-support (3.11.1)
33
+ rubocop (1.36.0)
34
+ json (~> 2.3)
33
35
  parallel (~> 1.10)
34
- parser (>= 2.6)
36
+ parser (>= 3.1.2.1)
35
37
  rainbow (>= 2.2.2, < 4.0)
38
+ regexp_parser (>= 1.8, < 3.0)
39
+ rexml (>= 3.2.5, < 4.0)
40
+ rubocop-ast (>= 1.20.1, < 2.0)
36
41
  ruby-progressbar (~> 1.7)
37
- unicode-display_width (>= 1.4.0, < 1.7)
38
- rubocop-rspec (1.33.0)
39
- rubocop (>= 0.60.0)
40
- ruby-progressbar (1.10.1)
41
- unicode-display_width (1.6.0)
42
+ unicode-display_width (>= 1.4.0, < 3.0)
43
+ rubocop-ast (1.21.0)
44
+ parser (>= 3.1.1.0)
45
+ rubocop-rspec (2.13.2)
46
+ rubocop (~> 1.33)
47
+ ruby-progressbar (1.11.0)
48
+ unicode-display_width (2.3.0)
42
49
 
43
50
  PLATFORMS
44
51
  ruby
45
52
 
46
53
  DEPENDENCIES
47
- bundler (~> 2.0)
48
- graphql (~> 1.8)
54
+ bundler (~> 2.3)
55
+ graphql (~> 2.0)
49
56
  kitty_policy!
50
- rake (~> 10.0)
51
- rspec (~> 3.8)
57
+ rake (~> 13.0)
58
+ rspec (~> 3.11)
52
59
  rspec-mocks (~> 3.8)
53
- rubocop (= 0.72.0)
54
- rubocop-rspec (= 1.33.0)
60
+ rubocop (= 1.36.0)
61
+ rubocop-rspec (= 2.13.2)
55
62
 
56
63
  BUNDLED WITH
57
- 2.0.2
64
+ 2.3.10
data/README.md CHANGED
@@ -1,16 +1,15 @@
1
1
  # KittyPolicy
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/kitty_policy.svg)](https://badge.fury.io/rb/kitty_policy)
4
- [![Build Status](https://secure.travis-ci.org/producthunt/kitty-policy.svg)](http://travis-ci.org/producthunt/kitty-policy)
5
4
  [![Code Climate](https://codeclimate.com/github/producthunt/kitty-policy.svg)](https://codeclimate.com/github/producthunt/kitty-policy)
6
5
 
7
6
  Minimalistic authorization library extracted from [Product Hunt](https://www.producthunt.com/).
8
7
 
9
8
  Features:
10
9
 
11
- * small DSL for defining abilities
12
- * not class initializations when performing abilities check
13
- * integrations with [GraphQL gem](https://rubygems.org/gems/graphql).
10
+ - small DSL for defining authorization abilities
11
+ - not class initializations when performing abilities check
12
+ - integrations with [GraphQL gem](https://rubygems.org/gems/graphql).
14
13
 
15
14
  ## Installation
16
15
 
@@ -149,6 +148,31 @@ describe ApplicationPolicy do
149
148
  end
150
149
  ```
151
150
 
151
+ ### Delegating abilities
152
+
153
+ ```ruby
154
+ module ApplicationPolicy
155
+ extend KittyPolicy::DSL
156
+
157
+ can :edit, Post do |user, post|
158
+ user.id == post.user_id
159
+ end
160
+
161
+ # users who can edit post, should edit or delete its media
162
+ can :edit, PostMedia do |user, media|
163
+ can? user, :edit, media.post
164
+ end
165
+
166
+ can :destroy, PostMedia do |user, media|
167
+ can? user, :edit, media.post
168
+ end
169
+
170
+ # this can be expressed with `delegate_ability` helper
171
+
172
+ delegate_ability :edit, PostMedia, to: :post
173
+ delegate_ability :destroy, PostMedia, to: :post, to_ability: :edit
174
+ ```
175
+
152
176
  ### Integration with GraphQL
153
177
 
154
178
  #### Field level authorization
@@ -190,6 +214,32 @@ module Types
190
214
  end
191
215
  ```
192
216
 
217
+ ```ruby
218
+ module Types
219
+ class QueryType < BaseObject
220
+ # With fallback, same as:
221
+ # if ApplicationPolicy.can?(context[:current_user], :view, post)
222
+ # return post
223
+ # else
224
+ # return nil
225
+ # end
226
+ field :post, PostType, null: false, authorize_object: :view, fallback: nil do
227
+ argument :id, ID, required: true
228
+ end
229
+
230
+ # Without fallback, same as:
231
+ # if ApplicationPolicy.can?(context[:current_user], :view, post)
232
+ # return post
233
+ # else
234
+ # raise KittyPolicy::AccessDenied(context[:current_user], :view, post)
235
+ # end
236
+ field :post, PostType, null: false, authorize_object: :view do
237
+ argument :id, ID, required: true
238
+ end
239
+ end
240
+ end
241
+ ```
242
+
193
243
  #### Can resolver
194
244
 
195
245
  Exposes if current user can perform certain action.
data/kitty_policy.gemspec CHANGED
@@ -28,11 +28,12 @@ Gem::Specification.new do |spec|
28
28
  spec.executables = spec.files.grep(%r(^exe/)) { |f| File.basename(f) }
29
29
  spec.require_paths = ['lib']
30
30
 
31
- spec.add_development_dependency 'bundler', '~> 2.0'
32
- spec.add_development_dependency 'graphql', '~> 1.8'
33
- spec.add_development_dependency 'rake', '~> 10.0'
34
- spec.add_development_dependency 'rspec', '~> 3.8'
31
+ spec.add_development_dependency 'bundler', '~> 2.3'
32
+ spec.add_development_dependency 'graphql', '~> 2.0'
33
+ spec.add_development_dependency 'rake', '~> 13.0'
34
+ spec.add_development_dependency 'rspec', '~> 3.11'
35
35
  spec.add_development_dependency 'rspec-mocks', '~> 3.8'
36
- spec.add_development_dependency 'rubocop', '0.72.0'
37
- spec.add_development_dependency 'rubocop-rspec', '1.33.0'
36
+ spec.add_development_dependency 'rubocop', '1.36.0'
37
+ spec.add_development_dependency 'rubocop-rspec', '2.13.2'
38
+ spec.metadata['rubygems_mfa_required'] = 'true'
38
39
  end
@@ -26,10 +26,20 @@ module KittyPolicy
26
26
  block ||= DEFAULT_BLOCK
27
27
 
28
28
  Array(abilities).each do |action|
29
- define_method Helper.method_name(action, subject) do |*args|
29
+ method_name = Helper.method_name(action, subject)
30
+
31
+ raise %(Method "#{method_name}" already exists) if method_defined?(method_name)
32
+
33
+ define_method method_name do |*args|
30
34
  (args[0] || allow_guest) && !!block.call(*args)
31
35
  end
32
36
  end
33
37
  end
38
+
39
+ def delegate_ability(ability, subject, to:, to_ability: ability)
40
+ can(ability, subject) do |user, record|
41
+ can?(user, to_ability, record.public_send(to))
42
+ end
43
+ end
34
44
  end
35
45
  end
@@ -14,7 +14,7 @@ module KittyPolicy
14
14
  current_user_key = @current_user_key
15
15
 
16
16
  Class.new(@base_resolver) do
17
- type ::GraphQL::BOOLEAN_TYPE, null: false
17
+ type ::GraphQL::Types::Boolean, null: false
18
18
 
19
19
  define_method(:resolve) do
20
20
  policy.can?(
@@ -9,8 +9,15 @@ module KittyPolicy
9
9
  end
10
10
 
11
11
  def instrument(_type, field)
12
- return field unless field.metadata.key?(:authorize)
12
+ return instrument_with_authorize(field) if field.metadata.key?(:authorize)
13
+ return instrument_with_authorize_object(field) if field.metadata.key?(:authorize_object)
13
14
 
15
+ field
16
+ end
17
+
18
+ private
19
+
20
+ def instrument_with_authorize(field)
14
21
  policy = @policy
15
22
  current_user_key = @current_user_key
16
23
 
@@ -40,6 +47,31 @@ module KittyPolicy
40
47
  resolve new_resolve
41
48
  end
42
49
  end
50
+
51
+ def instrument_with_authorize_object(field)
52
+ raise "Can't use `authorize_object` on a connection" if field.connection?
53
+ raise "Can't use `authorize_object` on an array" if field.type.list?
54
+
55
+ policy = @policy
56
+ current_user_key = @current_user_key
57
+
58
+ old_resolve = field.resolve_proc
59
+ new_resolve = lambda do |type_or_object, arguments, context|
60
+ object = old_resolve.call(type_or_object, arguments, context)
61
+ if object.nil?
62
+ object
63
+ elsif field.metadata.key?(:fallback)
64
+ policy.can?(context[current_user_key], field.metadata[:authorize_object], object) ? object : field.metadata[:fallback]
65
+ else
66
+ policy.authorize!(context[current_user_key], field.metadata[:authorize_object], object)
67
+ object
68
+ end
69
+ end
70
+
71
+ field.redefine do
72
+ resolve new_resolve
73
+ end
74
+ end
43
75
  end
44
76
 
45
77
  class AssignFallbackKey
@@ -60,10 +92,12 @@ if defined?(::GraphQL::Field)
60
92
  ::GraphQL::Field.accepts_definitions(
61
93
  fallback: KittyPolicy::GraphQL::AssignFallbackKey.new(:fallback),
62
94
  authorize: GraphQL::Define.assign_metadata_key(:authorize),
95
+ authorize_object: GraphQL::Define.assign_metadata_key(:authorize_object),
63
96
  )
64
97
  end
65
98
 
66
99
  if defined?(::GraphQL::Schema::Field)
67
100
  ::GraphQL::Schema::Field.accepts_definition(:fallback)
68
101
  ::GraphQL::Schema::Field.accepts_definition(:authorize)
102
+ ::GraphQL::Schema::Field.accepts_definition(:authorize_object)
69
103
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KittyPolicy
4
- VERSION = '0.1.2'
4
+ VERSION = '0.1.4'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitty_policy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Radoslav Stankov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-03-04 00:00:00.000000000 Z
11
+ date: 2022-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,56 +16,56 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
19
+ version: '2.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.0'
26
+ version: '2.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: graphql
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.8'
33
+ version: '2.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.8'
40
+ version: '2.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: '13.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: '13.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '3.8'
61
+ version: '3.11'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '3.8'
68
+ version: '3.11'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec-mocks
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -86,28 +86,28 @@ dependencies:
86
86
  requirements:
87
87
  - - '='
88
88
  - !ruby/object:Gem::Version
89
- version: 0.72.0
89
+ version: 1.36.0
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - '='
95
95
  - !ruby/object:Gem::Version
96
- version: 0.72.0
96
+ version: 1.36.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rubocop-rspec
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - '='
102
102
  - !ruby/object:Gem::Version
103
- version: 1.33.0
103
+ version: 2.13.2
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - '='
109
109
  - !ruby/object:Gem::Version
110
- version: 1.33.0
110
+ version: 2.13.2
111
111
  description: Can be used for Rails and GraphQL applications
112
112
  email:
113
113
  - rstankov@gmail.com
@@ -115,11 +115,11 @@ executables: []
115
115
  extensions: []
116
116
  extra_rdoc_files: []
117
117
  files:
118
+ - ".github/workflows/ci.yml"
118
119
  - ".gitignore"
119
120
  - ".rspec"
120
121
  - ".rubocop.yml"
121
122
  - ".ruby-version"
122
- - ".travis.yml"
123
123
  - CHANGELOG.md
124
124
  - CODE_OF_CONDUCT.md
125
125
  - Gemfile
@@ -145,6 +145,7 @@ metadata:
145
145
  homepage_uri: https://github.com/producthunt/kitty-policy
146
146
  source_code_uri: https://github.com/producthunt/kitty-policy
147
147
  changelog_uri: https://github.com/producthunt/kitty-policy/blob/master/CHANGELOG.md
148
+ rubygems_mfa_required: 'true'
148
149
  post_install_message:
149
150
  rdoc_options: []
150
151
  require_paths:
@@ -160,7 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
161
  - !ruby/object:Gem::Version
161
162
  version: '0'
162
163
  requirements: []
163
- rubygems_version: 3.0.3
164
+ rubygems_version: 3.1.6
164
165
  signing_key:
165
166
  specification_version: 4
166
167
  summary: General purpose authorization library
data/.travis.yml DELETED
@@ -1,11 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.4
4
- - 2.6
5
- script:
6
- - bundle exec rubocop
7
- - bundle exec rspec spec
8
- notifications:
9
- email: false
10
- before_install:
11
- - gem install bundler