graphql_devise 0.15.0 → 0.16.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: 6f90be997c50518d79c6b3fdaee2f896aeec557ca5084a6bac7059a518dd8ec3
4
- data.tar.gz: e25b07dee790cd64a48a07970974c6ae3e2a567c9a75321f7af69c693140a342
3
+ metadata.gz: 12c52068c8c538bc35dc67deb2d697101e1fa001419ccdbff23183e854f5f404
4
+ data.tar.gz: 65afe18384fb742e8dbc300d19b227815ebe166997147031bbabd63742738205
5
5
  SHA512:
6
- metadata.gz: 8453243ec0816b2fc828c13f1033b70e97ae71d68c2938af469a435f99a1b26369f0482a4abcda50fbf61c1a9d1fbde12b47a51f6fa42fdbb29afe5aa7f8760e
7
- data.tar.gz: 0fb0ef651e1be37157948ce48e24690ec741e543abf5771ad85f6380a640efb9b772195b16132685887cef9eb8f03d923a12406c99877100c6f13408a70280d8
6
+ metadata.gz: fcf10385aeb27e02f283fa5b5d140f51352508d4a9973dd374edfe78b67a64cfa9b4183e39a8065af5a9697569fac4ed9c21aa007df26fd271b6739c2f9cd5a9
7
+ data.tar.gz: d3f45d87972e29a325375c1868fced4ef377effcfba6be182c7d8c0b34bdfd6032db66097f0304416ff5966b532fea994d135be0ee48a070c2369668acc3beb2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [v0.16.0](https://github.com/graphql-devise/graphql_devise/tree/v0.16.0) (2021-05-20)
4
+
5
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.15.0...v0.16.0)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Allow checking of authenticaded resource via callable object [\#180](https://github.com/graphql-devise/graphql_devise/pull/180) ([mcelicalderon](https://github.com/mcelicalderon))
10
+
11
+ **Merged pull requests:**
12
+
13
+ - Document authenticate with callable [\#181](https://github.com/graphql-devise/graphql_devise/pull/181) ([mcelicalderon](https://github.com/mcelicalderon))
14
+
3
15
  ## [v0.15.0](https://github.com/graphql-devise/graphql_devise/tree/v0.15.0) (2021-05-09)
4
16
 
5
17
  [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.14.3...v0.15.0)
data/README.md CHANGED
@@ -28,8 +28,10 @@ GraphQL interface on top of the [Devise Token Auth](https://github.com/lynndylan
28
28
  * [I18n](#i18n)
29
29
  * [Authenticating Controller Actions](#authenticating-controller-actions)
30
30
  * [Authenticate Resource in the Controller (>= v0.15.0)](#authenticate-resource-in-the-controller--v0150)
31
+ * [Authentication Options](#authentication-options)
31
32
  * [Authenticate Before Reaching Your GQL Schema (Deprecated)](#authenticate-before-reaching-your-gql-schema-deprecated)
32
33
  * [Authenticate in Your GQL Schema (Deprecated)](#authenticate-in-your-gql-schema-deprecated)
34
+ * [Authentication Options](#authentication-options-1)
33
35
  * [Important](#important-2)
34
36
  * [Making Requests](#making-requests)
35
37
  * [Introspection query](#introspection-query)
@@ -45,7 +47,7 @@ GraphQL interface on top of the [Devise Token Auth](https://github.com/lynndylan
45
47
  * [Contributing](#contributing)
46
48
  * [License](#license)
47
49
 
48
- <!-- Added by: mcelicalderon, at: Sat May 8 12:32:03 -05 2021 -->
50
+ <!-- Added by: mcelicalderon, at: Wed May 19 21:25:22 -05 2021 -->
49
51
 
50
52
  <!--te-->
51
53
 
@@ -432,7 +434,13 @@ restricted to authenticated users and you can only do this at the root level fie
432
434
  schema. Configure the plugin as explained [here](#mounting-operations-into-your-own-schema)
433
435
  so this can work.
434
436
 
435
- In you main app's schema this is how you might specify if a field needs to be authenticated or not:
437
+ ##### Authentication Options
438
+ Wether you setup authentications as a default in the plugin, or you do it at the field level,
439
+ these are the options you can use:
440
+ 1. **Any truthy value:** If `current_resource` is not `.present?`, query will return an authentication error.
441
+ 1. **A callable object:** Provided object will be called with `current_resource` as the only argument if `current_resource` is `.present?`. If return value of the callable object is false, query will return an authentication error.
442
+
443
+ In your main app's schema this is how you might specify if a field needs to be authenticated or not:
436
444
  ```ruby
437
445
  module Types
438
446
  class QueryType < Types::BaseObject
@@ -442,13 +450,11 @@ module Types
442
450
  field :public_field, String, null: false, authenticate: false
443
451
  # this field requires authentication
444
452
  field :private_field, String, null: false, authenticate: true
453
+ # this field requires authenticated users to also be admins
454
+ field :admin_field, String, null: false, authenticate: ->(user) { user.admin? }
445
455
  end
446
456
  end
447
457
  ```
448
- **Important:** Currently, the only check the plugin does to see if the user is authenticated or not when executing
449
- the query, is verifying that `context[:current_resource].present?` in the GraphQL context.
450
- So, be careful not to populate that key of the context with values other than what `gql_devise_context`
451
- returns. The option to do more complex verifications will be added in the future.
452
458
 
453
459
  #### Authenticate Before Reaching Your GQL Schema (Deprecated)
454
460
  For this you will need to call `authenticate_<model>!` in a `before_action` controller hook.
@@ -506,7 +512,13 @@ restricted to authenticated users and you can only do this at the root level fie
506
512
  schema. Configure the plugin as explained [here](#mounting-operations-into-your-own-schema)
507
513
  so this can work.
508
514
 
509
- In you main app's schema this is how you might specify if a field needs to be authenticated or not:
515
+ ##### Authentication Options
516
+ Wether you setup authentications as a default in the plugin, or you do it at the field level,
517
+ these are the options you can use:
518
+ 1. **Any truthy value:** If `current_resource` is not `.present?`, query will return an authentication error.
519
+ 1. **A callable object:** Provided object will be called with `current_resource` as the only argument if `current_resource` is `.present?`. If return value of the callable object is false, query will return an authentication error.
520
+
521
+ In your main app's schema this is how you might specify if a field needs to be authenticated or not:
510
522
  ```ruby
511
523
  module Types
512
524
  class QueryType < Types::BaseObject
@@ -516,6 +528,8 @@ module Types
516
528
  field :public_field, String, null: false, authenticate: false
517
529
  # this field requires authentication
518
530
  field :private_field, String, null: false, authenticate: true
531
+ # this field requires authenticated users to also be admins
532
+ field :admin_field, String, null: false, authenticate: ->(user) { user.admin? }
519
533
  end
520
534
  end
521
535
  ```
@@ -46,7 +46,7 @@ module GraphqlDevise
46
46
 
47
47
  if auth_required && !(public_introspection && introspection_field?(field))
48
48
  context = set_current_resource(context)
49
- raise_on_missing_resource(context, field)
49
+ raise_on_missing_resource(context, field, auth_required)
50
50
  end
51
51
 
52
52
  yield
@@ -75,8 +75,12 @@ module GraphqlDevise
75
75
  context
76
76
  end
77
77
 
78
- def raise_on_missing_resource(context, field)
78
+ def raise_on_missing_resource(context, field, auth_required)
79
79
  @unauthenticated_proc.call(field.name) if context[:current_resource].blank?
80
+
81
+ if auth_required.respond_to?(:call) && !auth_required.call(context[:current_resource])
82
+ @unauthenticated_proc.call(field.name)
83
+ end
80
84
  end
81
85
 
82
86
  def context_from_data(trace_data)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GraphqlDevise
4
- VERSION = '0.15.0'.freeze
4
+ VERSION = '0.16.0'.freeze
5
5
  end
@@ -5,6 +5,7 @@ module Types
5
5
  field :user, resolver: Resolvers::UserShow
6
6
  field :public_field, String, null: false, authenticate: false
7
7
  field :private_field, String, null: false, authenticate: true
8
+ field :vip_field, String, null: false, authenticate: ->(user) { user.is_a?(User) && user.vip? }
8
9
 
9
10
  def public_field
10
11
  'Field does not require authentication'
@@ -13,5 +14,9 @@ module Types
13
14
  def private_field
14
15
  'Field will always require authentication'
15
16
  end
17
+
18
+ def vip_field
19
+ 'Field available only for VIP Users'
20
+ end
16
21
  end
17
22
  end
@@ -0,0 +1,5 @@
1
+ class AddVipToUsers < ActiveRecord::Migration[6.1]
2
+ def change
3
+ add_column :users, :vip, :boolean, null: false, default: false
4
+ end
5
+ end
@@ -2,15 +2,15 @@
2
2
  # of editing this file, please use the migrations feature of Active Record to
3
3
  # incrementally modify your database, and then regenerate this schema definition.
4
4
  #
5
- # This file is the source Rails uses to define your schema when running `rails
6
- # db:schema:load`. When creating a new database, `rails db:schema:load` tends to
5
+ # This file is the source Rails uses to define your schema when running `bin/rails
6
+ # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
7
7
  # be faster and is potentially less error prone than running all of your
8
8
  # migrations from scratch. Old migrations may fail to apply correctly if those
9
9
  # migrations use external dependencies or application code.
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(version: 2020_06_23_003142) do
13
+ ActiveRecord::Schema.define(version: 2021_05_16_211417) do
14
14
 
15
15
  create_table "admins", force: :cascade do |t|
16
16
  t.string "provider", default: "email", null: false
@@ -105,6 +105,7 @@ ActiveRecord::Schema.define(version: 2020_06_23_003142) do
105
105
  t.datetime "created_at", null: false
106
106
  t.datetime "updated_at", null: false
107
107
  t.boolean "auth_available", default: true, null: false
108
+ t.boolean "vip", default: false, null: false
108
109
  t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
109
110
  t.index ["email"], name: "index_users_on_email", unique: true
110
111
  t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
@@ -5,6 +5,14 @@ require 'rails_helper'
5
5
  RSpec.describe "Integrations with the user's controller" do
6
6
  include_context 'with graphql query request'
7
7
 
8
+ shared_examples 'returns a must authenticate error' do |field|
9
+ it 'returns a must sign in error' do
10
+ expect(json_response[:errors]).to contain_exactly(
11
+ hash_including(message: "#{field} field requires authentication", extensions: { code: 'AUTHENTICATION_ERROR' })
12
+ )
13
+ end
14
+ end
15
+
8
16
  let(:user) { create(:user, :confirmed) }
9
17
 
10
18
  describe 'publicField' do
@@ -54,11 +62,7 @@ RSpec.describe "Integrations with the user's controller" do
54
62
  end
55
63
 
56
64
  context 'when user is not authenticated' do
57
- it 'returns a must sign in error' do
58
- expect(json_response[:errors]).to contain_exactly(
59
- hash_including(message: 'privateField field requires authentication', extensions: { code: 'AUTHENTICATION_ERROR' })
60
- )
61
- end
65
+ it_behaves_like 'returns a must authenticate error', 'privateField'
62
66
  end
63
67
  end
64
68
 
@@ -82,11 +86,7 @@ RSpec.describe "Integrations with the user's controller" do
82
86
  end
83
87
 
84
88
  context 'when user is not authenticated' do
85
- it 'returns a must sign in error' do
86
- expect(json_response[:errors]).to contain_exactly(
87
- hash_including(message: 'privateField field requires authentication', extensions: { code: 'AUTHENTICATION_ERROR' })
88
- )
89
- end
89
+ it_behaves_like 'returns a must authenticate error', 'privateField'
90
90
  end
91
91
 
92
92
  context 'when using the failing route' do
@@ -111,11 +111,7 @@ RSpec.describe "Integrations with the user's controller" do
111
111
  end
112
112
 
113
113
  context 'when user is not authenticated' do
114
- it 'returns a must sign in error' do
115
- expect(json_response[:errors]).to contain_exactly(
116
- hash_including(message: 'privateField field requires authentication', extensions: { code: 'AUTHENTICATION_ERROR' })
117
- )
118
- end
114
+ it_behaves_like 'returns a must authenticate error', 'privateField'
119
115
  end
120
116
  end
121
117
  end
@@ -141,11 +137,7 @@ RSpec.describe "Integrations with the user's controller" do
141
137
  end
142
138
 
143
139
  context 'when user is not authenticated' do
144
- it 'returns a must sign in error' do
145
- expect(json_response[:errors]).to contain_exactly(
146
- hash_including(message: 'dummyMutation field requires authentication', extensions: { code: 'AUTHENTICATION_ERROR' })
147
- )
148
- end
140
+ it_behaves_like 'returns a must authenticate error', 'dummyMutation'
149
141
  end
150
142
  end
151
143
 
@@ -161,11 +153,7 @@ RSpec.describe "Integrations with the user's controller" do
161
153
  end
162
154
 
163
155
  context 'when user is not authenticated' do
164
- it 'returns a must sign in error' do
165
- expect(json_response[:errors]).to contain_exactly(
166
- hash_including(message: 'dummyMutation field requires authentication', extensions: { code: 'AUTHENTICATION_ERROR' })
167
- )
168
- end
156
+ it_behaves_like 'returns a must authenticate error', 'dummyMutation'
169
157
  end
170
158
  end
171
159
  end
@@ -199,11 +187,7 @@ RSpec.describe "Integrations with the user's controller" do
199
187
  end
200
188
 
201
189
  context 'when user is not authenticated' do
202
- it 'returns a must sign in error' do
203
- expect(json_response[:errors]).to contain_exactly(
204
- hash_including(message: 'user field requires authentication', extensions: { code: 'AUTHENTICATION_ERROR' })
205
- )
206
- end
190
+ it_behaves_like 'returns a must authenticate error', 'user'
207
191
  end
208
192
  end
209
193
 
@@ -271,4 +255,61 @@ RSpec.describe "Integrations with the user's controller" do
271
255
  )
272
256
  end
273
257
  end
258
+
259
+ describe 'vipField' do
260
+ let(:error_message) { 'Field available only for VIP Users' }
261
+ let(:query) do
262
+ <<-GRAPHQL
263
+ query { vipField }
264
+ GRAPHQL
265
+ end
266
+
267
+ context 'when using a regular schema' do
268
+ before { post_request('/api/v1/graphql') }
269
+
270
+ context 'when user is authenticated' do
271
+ let(:headers) { user.create_new_auth_token }
272
+
273
+ context 'when schema user is VIP' do
274
+ let(:user) { create(:user, :confirmed, vip: true) }
275
+
276
+ it 'allows to perform the query' do
277
+ expect(json_response[:data][:vipField]).to eq(error_message)
278
+ end
279
+ end
280
+
281
+ context 'when schema user is not VIP' do
282
+ it_behaves_like 'returns a must authenticate error', 'vipField'
283
+ end
284
+ end
285
+
286
+ context 'when user is not authenticated' do
287
+ it_behaves_like 'returns a must authenticate error', 'vipField'
288
+ end
289
+ end
290
+
291
+ context 'when using the interpreter schema' do
292
+ before { post_request('/api/v1/interpreter') }
293
+
294
+ context 'when user is authenticated' do
295
+ let(:headers) { user.create_new_auth_token }
296
+
297
+ context 'when schema user is VIP' do
298
+ let(:user) { create(:user, :confirmed, vip: true) }
299
+
300
+ it 'allows to perform the query' do
301
+ expect(json_response[:data][:vipField]).to eq(error_message)
302
+ end
303
+ end
304
+
305
+ context 'when schema user is not VIP' do
306
+ it_behaves_like 'returns a must authenticate error', 'vipField'
307
+ end
308
+ end
309
+
310
+ context 'when user is not authenticated' do
311
+ it_behaves_like 'returns a must authenticate error', 'vipField'
312
+ end
313
+ end
314
+ end
274
315
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql_devise
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.0
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mario Celi
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2021-05-09 00:00:00.000000000 Z
12
+ date: 2021-05-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: devise_token_auth
@@ -425,6 +425,7 @@ files:
425
425
  - spec/dummy/db/migrate/20200321121807_create_users_customers.rb
426
426
  - spec/dummy/db/migrate/20200621182414_remove_uncofirmed_email_from_admins.rb
427
427
  - spec/dummy/db/migrate/20200623003142_create_schema_users.rb
428
+ - spec/dummy/db/migrate/20210516211417_add_vip_to_users.rb
428
429
  - spec/dummy/db/schema.rb
429
430
  - spec/dummy/db/seeds.rb
430
431
  - spec/dummy/public/robots.txt
@@ -502,7 +503,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
502
503
  - !ruby/object:Gem::Version
503
504
  version: '0'
504
505
  requirements: []
505
- rubygems_version: 3.1.4
506
+ rubygems_version: 3.0.3
506
507
  signing_key:
507
508
  specification_version: 4
508
509
  summary: GraphQL queries and mutations on top of devise_token_auth
@@ -574,6 +575,7 @@ test_files:
574
575
  - spec/dummy/db/migrate/20200321121807_create_users_customers.rb
575
576
  - spec/dummy/db/migrate/20200621182414_remove_uncofirmed_email_from_admins.rb
576
577
  - spec/dummy/db/migrate/20200623003142_create_schema_users.rb
578
+ - spec/dummy/db/migrate/20210516211417_add_vip_to_users.rb
577
579
  - spec/dummy/db/schema.rb
578
580
  - spec/dummy/db/seeds.rb
579
581
  - spec/dummy/public/robots.txt