graphql_devise 0.15.0 → 0.18.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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +7 -0
  3. data/CHANGELOG.md +42 -0
  4. data/README.md +89 -50
  5. data/app/views/graphql_devise/mailer/confirmation_instructions.html.erb +7 -1
  6. data/graphql_devise.gemspec +1 -1
  7. data/lib/graphql_devise/default_operations/mutations.rb +14 -8
  8. data/lib/graphql_devise/default_operations/resolvers.rb +2 -2
  9. data/lib/graphql_devise/model/with_email_updater.rb +34 -8
  10. data/lib/graphql_devise/mount_method/operation_preparers/default_operation_preparer.rb +1 -1
  11. data/lib/graphql_devise/mount_method/operation_sanitizer.rb +13 -1
  12. data/lib/graphql_devise/mutations/confirm_registration_with_token.rb +30 -0
  13. data/lib/graphql_devise/mutations/login.rb +2 -0
  14. data/lib/graphql_devise/mutations/register.rb +60 -0
  15. data/lib/graphql_devise/mutations/resend_confirmation_with_token.rb +44 -0
  16. data/lib/graphql_devise/mutations/sign_up.rb +1 -1
  17. data/lib/graphql_devise/schema_plugin.rb +6 -2
  18. data/lib/graphql_devise/version.rb +1 -1
  19. data/spec/dummy/app/graphql/dummy_schema.rb +4 -3
  20. data/spec/dummy/app/graphql/mutations/register.rb +14 -0
  21. data/spec/dummy/app/graphql/types/query_type.rb +5 -0
  22. data/spec/dummy/config/routes.rb +5 -4
  23. data/spec/dummy/db/migrate/20210516211417_add_vip_to_users.rb +5 -0
  24. data/spec/dummy/db/schema.rb +4 -3
  25. data/spec/graphql_devise/model/with_email_updater_spec.rb +97 -68
  26. data/spec/requests/mutations/confirm_registration_with_token_spec.rb +117 -0
  27. data/spec/requests/mutations/register_spec.rb +166 -0
  28. data/spec/requests/mutations/resend_confirmation_with_token_spec.rb +137 -0
  29. data/spec/requests/user_controller_spec.rb +71 -30
  30. data/spec/services/mount_method/operation_sanitizer_spec.rb +3 -3
  31. metadata +18 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6f90be997c50518d79c6b3fdaee2f896aeec557ca5084a6bac7059a518dd8ec3
4
- data.tar.gz: e25b07dee790cd64a48a07970974c6ae3e2a567c9a75321f7af69c693140a342
3
+ metadata.gz: a59e0e9162a90d33da8e0d9738c6960db2286acd49db59d85bdc4c352402205b
4
+ data.tar.gz: c1255d172a2825dcc54f21f68151a64985346f2f2e3d4b236a77ff8ce40c40e4
5
5
  SHA512:
6
- metadata.gz: 8453243ec0816b2fc828c13f1033b70e97ae71d68c2938af469a435f99a1b26369f0482a4abcda50fbf61c1a9d1fbde12b47a51f6fa42fdbb29afe5aa7f8760e
7
- data.tar.gz: 0fb0ef651e1be37157948ce48e24690ec741e543abf5771ad85f6380a640efb9b772195b16132685887cef9eb8f03d923a12406c99877100c6f13408a70280d8
6
+ metadata.gz: 2df583c0be8b0df69c62c5663b7176a54b0e762b4800bdb01b6f90f8835446878fb7c45a5722f78a45a5903681e946c167f80d9d8b7cc23dfc872b7a956ec187
7
+ data.tar.gz: ae453c594be804358d5dec8a3f8f0526867352b2f77346e42c1c2ccab093df22d9c3f520b70e5e680afd292ab8d316efae3004f4555e4e0ac975e09b7ee0eb5d
data/Appraisals CHANGED
@@ -3,6 +3,7 @@ appraise 'rails4.2-graphql1.8' do
3
3
  gem 'bundler', '~> 1.17'
4
4
  gem 'rails', github: 'rails/rails', branch: '4-2-stable'
5
5
  gem 'graphql', '~> 1.8.0'
6
+ gem 'devise_token_auth', '< 1.2'
6
7
  gem 'rspec-rails', '< 4.0'
7
8
  end
8
9
 
@@ -19,6 +20,7 @@ appraise 'rails5.0-graphql1.9' do
19
20
  gem 'sqlite3', '~> 1.3.6'
20
21
  gem 'rails', github: 'rails/rails', branch: '5-0-stable'
21
22
  gem 'graphql', '~> 1.9.0'
23
+ gem 'devise_token_auth', '< 1.2'
22
24
  gem 'rspec-rails', '< 4.0'
23
25
  end
24
26
 
@@ -35,6 +37,7 @@ appraise 'rails5.1-graphql1.9' do
35
37
  gem 'sqlite3', '~> 1.3.6'
36
38
  gem 'rails', github: 'rails/rails', branch: '5-1-stable'
37
39
  gem 'graphql', '~> 1.9.0'
40
+ gem 'devise_token_auth', '< 1.2'
38
41
  gem 'rspec-rails', '< 4.0'
39
42
  end
40
43
 
@@ -51,6 +54,7 @@ appraise 'rails5.2-graphql1.9' do
51
54
  gem 'sqlite3', '~> 1.3.6'
52
55
  gem 'rails', github: 'rails/rails', branch: '5-2-stable'
53
56
  gem 'graphql', '~> 1.9.0'
57
+ gem 'devise_token_auth', '< 1.2'
54
58
  gem 'rspec-rails', '< 4.0'
55
59
  end
56
60
 
@@ -58,6 +62,7 @@ appraise 'rails5.2-graphql1.10' do
58
62
  gem 'sqlite3', '~> 1.3.6'
59
63
  gem 'rails', github: 'rails/rails', branch: '5-2-stable'
60
64
  gem 'graphql', '~> 1.10.0'
65
+ gem 'devise_token_auth', '< 1.2'
61
66
  gem 'rspec-rails', '< 4.0'
62
67
  end
63
68
 
@@ -65,6 +70,7 @@ appraise 'rails5.2-graphql1.11' do
65
70
  gem 'sqlite3', '~> 1.3.6'
66
71
  gem 'rails', github: 'rails/rails', branch: '5-2-stable'
67
72
  gem 'graphql', '~> 1.11.0'
73
+ gem 'devise_token_auth', '< 1.2'
68
74
  gem 'rspec-rails', '< 4.0'
69
75
  end
70
76
 
@@ -72,6 +78,7 @@ appraise 'rails5.2-graphql1.12' do
72
78
  gem 'sqlite3', '~> 1.3.6'
73
79
  gem 'rails', github: 'rails/rails', branch: '5-2-stable'
74
80
  gem 'graphql', '~> 1.12.0'
81
+ gem 'devise_token_auth', '< 1.2'
75
82
  gem 'rspec-rails', '< 4.0'
76
83
  end
77
84
 
data/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # Changelog
2
2
 
3
+ ## [v0.17.1](https://github.com/graphql-devise/graphql_devise/tree/v0.17.1) (2021-08-02)
4
+
5
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.17.0...v0.17.1)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Set context\[:current\_resource\] upon login [\#193](https://github.com/graphql-devise/graphql_devise/pull/193) ([TomasBarry](https://github.com/TomasBarry))
10
+
11
+ **Merged pull requests:**
12
+
13
+ - Improve README [\#190](https://github.com/graphql-devise/graphql_devise/pull/190) ([00dav00](https://github.com/00dav00))
14
+
15
+ ## [v0.17.0](https://github.com/graphql-devise/graphql_devise/tree/v0.17.0) (2021-06-09)
16
+
17
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.16.0...v0.17.0)
18
+
19
+ **Implemented enhancements:**
20
+
21
+ - Another click in confirm account results in error [\#184](https://github.com/graphql-devise/graphql_devise/issues/184)
22
+ - Add resendConfirmationWithToken mutation [\#186](https://github.com/graphql-devise/graphql_devise/pull/186) ([mcelicalderon](https://github.com/mcelicalderon))
23
+ - Add register mutation and alternate confirmation flow [\#185](https://github.com/graphql-devise/graphql_devise/pull/185) ([mcelicalderon](https://github.com/mcelicalderon))
24
+
25
+ **Deprecated:**
26
+
27
+ - Deprecate mutations and queries that required a redirect [\#187](https://github.com/graphql-devise/graphql_devise/pull/187) ([mcelicalderon](https://github.com/mcelicalderon))
28
+
29
+ **Merged pull requests:**
30
+
31
+ - Document new registration and confirmation flow [\#188](https://github.com/graphql-devise/graphql_devise/pull/188) ([mcelicalderon](https://github.com/mcelicalderon))
32
+
33
+ ## [v0.16.0](https://github.com/graphql-devise/graphql_devise/tree/v0.16.0) (2021-05-20)
34
+
35
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.15.0...v0.16.0)
36
+
37
+ **Implemented enhancements:**
38
+
39
+ - Allow checking of authenticaded resource via callable object [\#180](https://github.com/graphql-devise/graphql_devise/pull/180) ([mcelicalderon](https://github.com/mcelicalderon))
40
+
41
+ **Merged pull requests:**
42
+
43
+ - Document authenticate with callable [\#181](https://github.com/graphql-devise/graphql_devise/pull/181) ([mcelicalderon](https://github.com/mcelicalderon))
44
+
3
45
  ## [v0.15.0](https://github.com/graphql-devise/graphql_devise/tree/v0.15.0) (2021-05-09)
4
46
 
5
47
  [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.14.3...v0.15.0)
data/README.md CHANGED
@@ -14,23 +14,25 @@ GraphQL interface on top of the [Devise Token Auth](https://github.com/lynndylan
14
14
  * [Installation](#installation)
15
15
  * [Running the Generator](#running-the-generator)
16
16
  * [Mounting the Schema in a Separate Route](#mounting-the-schema-in-a-separate-route)
17
- * [Important](#important)
18
- * [Mounting Operations in Your Own Schema (&gt; v0.12.0)](#mounting-operations-in-your-own-schema--v0120)
19
- * [Important](#important-1)
17
+ * [Mounting Operations in an Existing Schema (&gt; v0.12.0)](#mounting-operations-in-an-existing-schema--v0120)
20
18
  * [Usage](#usage)
21
19
  * [Mounting Auth Schema on a Separate Route](#mounting-auth-schema-on-a-separate-route)
22
- * [Mounting Operations Into Your Own Schema](#mounting-operations-into-your-own-schema)
20
+ * [Mounting Operations In an Existing Schema](#mounting-operations-in-an-existing-schema)
23
21
  * [Available Mount Options](#available-mount-options)
24
22
  * [Available Operations](#available-operations)
25
23
  * [Configuring Model](#configuring-model)
26
24
  * [Email Reconfirmation](#email-reconfirmation)
25
+ * [Current flow](#current-flow)
26
+ * [Deprecated flow - Do Not Use](#deprecated-flow---do-not-use)
27
27
  * [Customizing Email Templates](#customizing-email-templates)
28
28
  * [I18n](#i18n)
29
29
  * [Authenticating Controller Actions](#authenticating-controller-actions)
30
30
  * [Authenticate Resource in the Controller (&gt;= 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
- * [Authenticate in Your GQL Schema (Deprecated)](#authenticate-in-your-gql-schema-deprecated)
33
- * [Important](#important-2)
33
+ * [Authenticate in an Existing Schema (Deprecated)](#authenticate-in-an-existing-schema-deprecated)
34
+ * [Authentication Options](#authentication-options-1)
35
+ * [Important](#important)
34
36
  * [Making Requests](#making-requests)
35
37
  * [Introspection query](#introspection-query)
36
38
  * [Mutations](#mutations)
@@ -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: david, at: jue jun 24 18:32:27 -05 2021 -->
49
51
 
50
52
  <!--te-->
51
53
 
@@ -79,11 +81,10 @@ Graphql Devise generator will execute `Devise` and `Devise Token Auth` generator
79
81
  ```bash
80
82
  $ bundle exec rails generate graphql_devise:install
81
83
  ```
82
- The generator accepts 2 params:
84
+ The generator accepts 2 params and 1 option:
83
85
  - `user_class`: Model name in which `Devise` modules will be included. This uses a `find or create` strategy. Defaults to `User`.
84
86
  - `mount_path`: Path in which the dedicated graphql schema for devise will be mounted. Defaults to `/graphql_auth`.
85
-
86
- The option `mount` is available starting from `v0.12.0`. This option will allow you to mount the operations in your own schema instead of a dedicated one. When this option is provided `mount_path` param is not used.
87
+ - `--mount`: This options is available starting from `v0.12.0`, it allows you to mount the operations in your own schema instead of a dedicated one. When provided `mount_path` param is ignored.
87
88
 
88
89
  #### Mounting the Schema in a Separate Route
89
90
 
@@ -106,12 +107,12 @@ Will do the following:
106
107
  `Admin` could be any model name you are going to be using for authentication,
107
108
  and `api/auth` could be any mount path you would like to use for auth.
108
109
 
109
- ##### Important
110
+ **Important**
110
111
  - Remember that by default this gem mounts a completely separate GraphQL schema on a separate controller in the route provided by the `at` option in the `mount_graphql_devise_for` method in the `config/routes.rb` file. If no `at` option is provided, the route will be `/graphql_auth`.
111
- - Avoid passing the `--mount` option or the gem will try to use an existing schema.
112
+ - Avoid passing the `--mount` option if you want to use a separate route and schema.
112
113
 
113
- #### Mounting Operations in Your Own Schema (> v0.12.0)
114
- To configure the gem to use your own GQL schema use the `--mount` option.
114
+ #### Mounting Operations in an Existing Schema (> v0.12.0)
115
+ To configure the gem to use an existing GQL schema use the `--mount` option.
115
116
  For instance the executing:
116
117
 
117
118
  ```bash
@@ -127,8 +128,8 @@ Will do the following:
127
128
  - Add `SchemaPlugin` to the specified schema.
128
129
 
129
130
 
130
- ##### Important
131
- - When using the `--mount` option the `mount_path` params is ignored.
131
+ **Important**
132
+ - When using the `--mount` option the `mount_path` param is ignored.
132
133
  - The generator will look for your schema under `app/graphql/` directory. We are expecting the name of the file is the same as the as the one passed in the mount option transformed with `underscore`. In the example, passing `MySchema`, will try to find the file `app/graphql/my_schema.rb`.
133
134
  - You can actually mount a resource's auth schema in a separate route and in your app's schema at the same time, but that's probably not a common scenario.
134
135
 
@@ -156,7 +157,7 @@ Rails.application.routes.draw do
156
157
  operations: {
157
158
  login: Mutations::Login
158
159
  },
159
- skip: [:sign_up],
160
+ skip: [:register],
160
161
  additional_mutations: {
161
162
  # generates mutation { adminUserSignUp }
162
163
  admin_user_sign_up: Mutations::AdminUserSignUp
@@ -173,10 +174,10 @@ The second argument of the `mount_graphql_devise` method is a hash of options wh
173
174
  customize how the queries and mutations are mounted into the schema. For a list of available
174
175
  options go [here](#available-mount-options)
175
176
 
176
- ### Mounting Operations Into Your Own Schema
177
+ ### Mounting Operations In an Existing Schema
177
178
 
178
- Starting with `v0.12.0` you can now mount the GQL operations provided by this gem into your
179
- app's main schema.
179
+ Starting with `v0.12.0` you can mount the GQL operations provided by this gem into an
180
+ existing schema in you app.
180
181
 
181
182
  ```ruby
182
183
  # app/graphql/dummy_schema.rb
@@ -188,7 +189,7 @@ class DummySchema < GraphQL::Schema
188
189
  query: Types::QueryType,
189
190
  mutation: Types::MutationType,
190
191
  resource_loaders: [
191
- GraphqlDevise::ResourceLoader.new(User, only: [:login, :confirm_account])
192
+ GraphqlDevise::ResourceLoader.new(User, only: [:login, :confirm_registration_with_token])
192
193
  ]
193
194
  )
194
195
 
@@ -296,13 +297,17 @@ The following is a list of the symbols you can provide to the `operations`, `ski
296
297
  ```ruby
297
298
  :login
298
299
  :logout
299
- :sign_up
300
- :confirm_account
301
- :send_password_reset
302
- :check_password_token
303
- :update_password
304
- :send_password_reset_with_token
300
+ :sign_up (deprecated)
301
+ :register
302
+ :update_password (deprecated)
305
303
  :update_password_with_token
304
+ :send_password_reset (deprecated)
305
+ :send_password_reset_with_token
306
+ :resend_confirmation (deprecated)
307
+ :resend_confirmation_with_token
308
+ :confirm_registration_with_token
309
+ :confirm_account (deprecated)
310
+ :check_password_token (deprecated)
306
311
  ```
307
312
 
308
313
  ### Configuring Model
@@ -330,6 +335,9 @@ The install generator can do this for you if you specify the `user_class` option
330
335
  See [Installation](#installation) for details.
331
336
 
332
337
  ### Email Reconfirmation
338
+ We want reconfirmable in this gem to work separately
339
+ from DTA's or Devise (too much complexity in the model based on callbacks).
340
+
333
341
  Email reconfirmation is supported just like in Devise and DTA, but we want reconfirmable
334
342
  in this gem to work on model basis instead of having a global configuration like in Devise.
335
343
  **For this reason Devise's global `reconfirmable` setting is ignored.**
@@ -338,19 +346,39 @@ For a resource to be considered reconfirmable it has to meet 2 conditions:
338
346
  1. Include the `:confirmable` module.
339
347
  1. Has an `unconfirmed_email` column in the resource's table.
340
348
 
341
- In order to trigger the reconfirmation email in a reconfirmable resource, you simply needi
349
+ In order to trigger the reconfirmation email in a reconfirmable resource, you simply need
342
350
  to call a different update method on your resource,`update_with_email`.
343
351
  When the resource is not reconfirmable or the email is not updated, this method behaves exactly
344
352
  the same as ActiveRecord's `update`.
353
+
354
+ #### Current flow
355
+ `update_with_email` requires one additional attribute when email will change or an error
356
+ will be raised:
357
+
358
+ - `confirmation_url`: The full url of your client application. The confirmation email will contain this url plus
359
+ a confirmation token. You need to call `confirmRegistrationWithToken` with the given token on
360
+ your client application.
361
+
362
+ So, it's up to you where you require confirmation of changing emails.
363
+ Here's a demonstration on the method usage:
364
+ ```ruby
365
+ user.update_with_email(
366
+ name: 'New Name',
367
+ email: 'new@domain.com',
368
+ confirmation_url: 'https://google.com'
369
+ )
370
+ ```
371
+
372
+ #### Deprecated flow - Do Not Use
345
373
  `update_with_email` requires two additional attributes when email will change or an error
346
374
  will be raised:
347
375
 
348
- 1. `schema_url`: The full url where your GQL schema is mounted. You can get this value from the
376
+ - `schema_url`: The full url where your GQL schema is mounted. You can get this value from the
349
377
  controller available in the context of your mutations and queries like this:
350
378
  ```ruby
351
379
  context[:controller].full_url_without_params
352
380
  ```
353
- 1. `confirmation_success_url`: This the full url where you want users to be redirected after
381
+ - `confirmation_success_url`: This the full url where you want users to be redirected after
354
382
  the email has changed successfully (usually a front-end url). This value is mandatory
355
383
  unless you have set `default_confirm_success_url` in your devise_token_auth initializer.
356
384
 
@@ -366,9 +394,6 @@ user.update_with_email(
366
394
  )
367
395
  ```
368
396
 
369
- We want reconfirmable in this gem to work separately
370
- from DTA's or Devise (too much complexity in the model based on callbacks).
371
-
372
397
  ### Customizing Email Templates
373
398
  The approach of this gem is a bit different from DeviseTokenAuth. We have placed our templates in `app/views/graphql_devise/mailer`,
374
399
  so if you want to change them, place yours on the same dir structure on your Rails project. You can customize these two templates:
@@ -432,7 +457,13 @@ restricted to authenticated users and you can only do this at the root level fie
432
457
  schema. Configure the plugin as explained [here](#mounting-operations-into-your-own-schema)
433
458
  so this can work.
434
459
 
435
- In you main app's schema this is how you might specify if a field needs to be authenticated or not:
460
+ ##### Authentication Options
461
+ Whether you setup authentications as a default in the plugin, or you do it at the field level,
462
+ these are the options you can use:
463
+ 1. **Any truthy value:** If `current_resource` is not `.present?`, query will return an authentication error.
464
+ 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.
465
+
466
+ In your main app's schema this is how you might specify if a field needs to be authenticated or not:
436
467
  ```ruby
437
468
  module Types
438
469
  class QueryType < Types::BaseObject
@@ -442,13 +473,11 @@ module Types
442
473
  field :public_field, String, null: false, authenticate: false
443
474
  # this field requires authentication
444
475
  field :private_field, String, null: false, authenticate: true
476
+ # this field requires authenticated users to also be admins
477
+ field :admin_field, String, null: false, authenticate: ->(user) { user.admin? }
445
478
  end
446
479
  end
447
480
  ```
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
481
 
453
482
  #### Authenticate Before Reaching Your GQL Schema (Deprecated)
454
483
  For this you will need to call `authenticate_<model>!` in a `before_action` controller hook.
@@ -471,7 +500,7 @@ end
471
500
  The install generator can include the concern in you application controller.
472
501
  If authentication fails for a request, execution will halt and a REST error will be returned since the request never reaches your GQL schema.
473
502
 
474
- #### Authenticate in Your GQL Schema (Deprecated)
503
+ #### Authenticate in an Existing Schema (Deprecated)
475
504
  For this you will need to add the `GraphqlDevise::SchemaPlugin` to your schema as described
476
505
  [here](#mounting-operations-into-your-own-schema).
477
506
 
@@ -506,7 +535,13 @@ restricted to authenticated users and you can only do this at the root level fie
506
535
  schema. Configure the plugin as explained [here](#mounting-operations-into-your-own-schema)
507
536
  so this can work.
508
537
 
509
- In you main app's schema this is how you might specify if a field needs to be authenticated or not:
538
+ ##### Authentication Options
539
+ Whether you setup authentications as a default in the plugin, or you do it at the field level,
540
+ these are the options you can use:
541
+ 1. **Any truthy value:** If `current_resource` is not `.present?`, query will return an authentication error.
542
+ 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.
543
+
544
+ In your main app's schema this is how you might specify if a field needs to be authenticated or not:
510
545
  ```ruby
511
546
  module Types
512
547
  class QueryType < Types::BaseObject
@@ -516,6 +551,8 @@ module Types
516
551
  field :public_field, String, null: false, authenticate: false
517
552
  # this field requires authentication
518
553
  field :private_field, String, null: false, authenticate: true
554
+ # this field requires authenticated users to also be admins
555
+ field :admin_field, String, null: false, authenticate: ->(user) { user.admin? }
519
556
  end
520
557
  end
521
558
  ```
@@ -533,20 +570,22 @@ If you are using the schema plugin, you can require authentication before doing
533
570
 
534
571
  Operation | Description | Example
535
572
  :--- | :--- | :------------------:
536
- login | This mutation has a second field by default. `credentials` can be fetched directly on the mutation return type.<br>Credentials are still returned in the headers of the response. | userLogin(email: String!, password: String!): UserLoginPayload
537
- logout | | userLogout: UserLogoutPayload
538
- signUp | The parameter `confirmSuccessUrl` is optional unless you are using the `confirmable` plugin from Devise in your `resource`'s model. If you have `confirmable` set up, you will have to provide it unless you have `config.default_confirm_success_url` set in `config/initializers/devise_token_auth.rb`. | userSignUp(email: String!, password: String!, passwordConfirmation: String!, confirmSuccessUrl: String): UserSignUpPayload
539
- sendPasswordResetWithToken | Sends an email to the provided address with a link to reset the password of the resource. First step of the most recently implemented password reset flow. | userSendPasswordResetWithToken(email: String!, redirectUrl: String!): UserSendPasswordResetWithTokenPayload
540
- updatePasswordWithToken | Uses a `resetPasswordToken` to update the password of a resource. Second and last step of the most recently implemented password reset flow. | userSendPasswordResetWithToken(resetPasswordToken: String!, password: String!, passwordConfirmation: String!): UserUpdatePasswordWithTokenPayload
541
- resendConfirmation | The `UserResendConfirmationPayload` will return the `authenticatable` resource that was sent the confirmation instructions but also has a `message: String!` that can be used to notify a user what to do after the instructions were sent to them | userResendConfirmation(email: String!, redirectUrl: String!): UserResendConfirmationPayload
542
- sendResetPassword | Sends an email to the provided address with a link to reset the password of the resource. **This mutation is part of the first and soon to be deprecated password reset flow.** | userSendResetPassword(email: String!, redirectUrl: String!): UserSendReserPasswordPayload
543
- updatePassword | The parameter `currentPassword` is optional if you have `config.check_current_password_before_update` set to false (disabled by default) on your generated `config/initializers/devise_token_aut.rb` or if the `resource` model supports the `recoverable` Devise plugin and the `resource`'s `allow_password_change` attribute is set to true (this is done in the `userCheckPasswordToken` query when you click on the sent email's link). **This mutation is part of the first and soon to be deprecated password reset flow.** | userUpdatePassword(password: String!, passwordConfirmation: String!, currentPassword: String): UserUpdatePasswordPayload
573
+ login | This mutation has a second field by default. `credentials` can be fetched directly on the mutation return type.<br>Credentials are still returned in the headers of the response. | userLogin(email: String!, password: String!): UserLoginPayload |
574
+ logout | requires authentication headers. Deletes current session if successful. | userLogout: UserLogoutPayload |
575
+ signUp **(Deprecated)** | The parameter `confirmSuccessUrl` is optional unless you are using the `confirmable` plugin from Devise in your `resource`'s model. If you have `confirmable` set up, you will have to provide it unless you have `config.default_confirm_success_url` set in `config/initializers/devise_token_auth.rb`. | userSignUp(email: String!, password: String!, passwordConfirmation: String!, confirmSuccessUrl: String): UserSignUpPayload |
576
+ register | The parameter `confirmUrl` is optional unless you are using the `confirmable` plugin from Devise in your `resource`'s model. If you have `confirmable` set up, you will have to provide it unless you have `config.default_confirm_success_url` set in `config/initializers/devise_token_auth.rb`. | userRegister(email: String!, password: String!, passwordConfirmation: String!, confirmUrl: String): UserRegisterPayload |
577
+ sendPasswordResetWithToken | Sends an email to the provided address with a link to reset the password of the resource. First step of the most recently implemented password reset flow. | userSendPasswordResetWithToken(email: String!, redirectUrl: String!): UserSendPasswordResetWithTokenPayload |
578
+ updatePasswordWithToken | Uses a `resetPasswordToken` to update the password of a resource. Second and last step of the most recently implemented password reset flow. | userSendPasswordResetWithToken(resetPasswordToken: String!, password: String!, passwordConfirmation: String!): UserUpdatePasswordWithTokenPayload |
579
+ resendConfirmation **(Deprecated)** | The `UserResendConfirmationPayload` will return a `message: String!` that can be used to notify a user what to do after the instructions were sent to them | userResendConfirmation(email: String!, redirectUrl: String!): UserResendConfirmationPayload |
580
+ resendConfirmationWithToken | The `UserResendConfirmationWithTokenPayload` will return a `message: String!` that can be used to notify a user what to do after the instructions were sent to them. Email will contain a link to the provided `confirmUrl` and a `confirmationToken` query param. | userResendConfirmationWithToken(email: String!, confirmUrl: String!): UserResendConfirmationWithTokenPayload |
581
+ sendResetPassword **(Deprecated)** | Sends an email to the provided address with a link to reset the password of the resource. **This mutation is part of the first and soon to be deprecated password reset flow.** | userSendResetPassword(email: String!, redirectUrl: String!): UserSendResetPasswordPayload |
582
+ updatePassword **(Deprecated)** | The parameter `currentPassword` is optional if you have `config.check_current_password_before_update` set to false (disabled by default) on your generated `config/initializers/devise_token_aut.rb` or if the `resource` model supports the `recoverable` Devise plugin and the `resource`'s `allow_password_change` attribute is set to true (this is done in the `userCheckPasswordToken` query when you click on the sent email's link). **This mutation is part of the first and soon to be deprecated password reset flow.** | userUpdatePassword(password: String!, passwordConfirmation: String!, currentPassword: String): UserUpdatePasswordPayload |
544
583
 
545
584
  #### Queries
546
585
  Operation | Description | Example
547
586
  :--- | :--- | :------------------:
548
- confirmAccount | Performs a redirect using the `redirectUrl` param | userConfirmAccount(confirmationToken: String!, redirectUrl: String!): User
549
- checkPasswordToken | Performs a redirect using the `redirectUrl` param | userCheckPasswordToken(resetPasswordToken: String!, redirectUrl: String): User
587
+ confirmAccount **(Deprecated)** | Performs a redirect using the `redirectUrl` param | userConfirmAccount(confirmationToken: String!, redirectUrl: String!): User
588
+ checkPasswordToken **(Deprecated)** | Performs a redirect using the `redirectUrl` param | userCheckPasswordToken(resetPasswordToken: String!, redirectUrl: String): User
550
589
 
551
590
  The reason for having 2 queries is that these 2 are going to be accessed when clicking on
552
591
  the confirmation and reset password email urls. There is no limitation for making mutation
@@ -2,4 +2,10 @@
2
2
 
3
3
  <p><%= t('.confirm_link_msg') %></p>
4
4
 
5
- <p><%= link_to t('.confirm_account_link'), "#{message['schema_url']}?#{confirmation_query(resource_name: @resource.class.to_s, redirect_url: message['redirect-url'], token: @token).to_query}" %></p>
5
+ <p>
6
+ <% if message['schema_url'].present? %>
7
+ <%= link_to t('.confirm_account_link'), "#{message['schema_url']}?#{confirmation_query(resource_name: @resource.class.to_s, redirect_url: message['redirect-url'], token: @token).to_query}" %>
8
+ <% else %>
9
+ <%= link_to t('.confirm_account_link'), "#{CGI.escape(message['redirect-url'].to_s)}?#{{ confirmationToken: @token }.to_query}" %>
10
+ <% end %>
11
+ </p>
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.required_ruby_version = '>= 2.2.0'
29
29
 
30
30
  spec.add_dependency 'devise_token_auth', '>= 0.1.43', '< 2.0'
31
- spec.add_dependency 'graphql', '>= 1.8', '< 1.13.0'
31
+ spec.add_dependency 'graphql', '>= 1.8', '< 1.14.0'
32
32
  spec.add_dependency 'rails', '>= 4.2', '< 6.2'
33
33
 
34
34
  spec.add_development_dependency 'appraisal'
@@ -4,23 +4,29 @@ require 'graphql_devise/mutations/base'
4
4
  require 'graphql_devise/mutations/login'
5
5
  require 'graphql_devise/mutations/logout'
6
6
  require 'graphql_devise/mutations/resend_confirmation'
7
+ require 'graphql_devise/mutations/resend_confirmation_with_token'
7
8
  require 'graphql_devise/mutations/send_password_reset'
8
9
  require 'graphql_devise/mutations/send_password_reset_with_token'
9
10
  require 'graphql_devise/mutations/sign_up'
11
+ require 'graphql_devise/mutations/register'
10
12
  require 'graphql_devise/mutations/update_password'
11
13
  require 'graphql_devise/mutations/update_password_with_token'
14
+ require 'graphql_devise/mutations/confirm_registration_with_token'
12
15
 
13
16
  module GraphqlDevise
14
17
  module DefaultOperations
15
18
  MUTATIONS = {
16
- login: { klass: GraphqlDevise::Mutations::Login, authenticatable: true },
17
- logout: { klass: GraphqlDevise::Mutations::Logout, authenticatable: true },
18
- sign_up: { klass: GraphqlDevise::Mutations::SignUp, authenticatable: true },
19
- update_password: { klass: GraphqlDevise::Mutations::UpdatePassword, authenticatable: true },
20
- update_password_with_token: { klass: GraphqlDevise::Mutations::UpdatePasswordWithToken, authenticatable: true },
21
- send_password_reset: { klass: GraphqlDevise::Mutations::SendPasswordReset, authenticatable: false },
22
- send_password_reset_with_token: { klass: GraphqlDevise::Mutations::SendPasswordResetWithToken, authenticatable: false },
23
- resend_confirmation: { klass: GraphqlDevise::Mutations::ResendConfirmation, authenticatable: false }
19
+ login: { klass: GraphqlDevise::Mutations::Login, authenticatable: true },
20
+ logout: { klass: GraphqlDevise::Mutations::Logout, authenticatable: true },
21
+ sign_up: { klass: GraphqlDevise::Mutations::SignUp, authenticatable: true, deprecation_reason: 'use register instead' },
22
+ register: { klass: GraphqlDevise::Mutations::Register, authenticatable: true },
23
+ update_password: { klass: GraphqlDevise::Mutations::UpdatePassword, authenticatable: true, deprecation_reason: 'use update_password_with_token instead' },
24
+ update_password_with_token: { klass: GraphqlDevise::Mutations::UpdatePasswordWithToken, authenticatable: true },
25
+ send_password_reset: { klass: GraphqlDevise::Mutations::SendPasswordReset, authenticatable: false, deprecation_reason: 'use send_password_reset_with_token instead' },
26
+ send_password_reset_with_token: { klass: GraphqlDevise::Mutations::SendPasswordResetWithToken, authenticatable: false },
27
+ resend_confirmation: { klass: GraphqlDevise::Mutations::ResendConfirmation, authenticatable: false, deprecation_reason: 'use resend_confirmation_with_token instead' },
28
+ resend_confirmation_with_token: { klass: GraphqlDevise::Mutations::ResendConfirmationWithToken, authenticatable: false },
29
+ confirm_registration_with_token: { klass: GraphqlDevise::Mutations::ConfirmRegistrationWithToken, authenticatable: true }
24
30
  }.freeze
25
31
  end
26
32
  end
@@ -7,8 +7,8 @@ require 'graphql_devise/resolvers/confirm_account'
7
7
  module GraphqlDevise
8
8
  module DefaultOperations
9
9
  QUERIES = {
10
- confirm_account: { klass: GraphqlDevise::Resolvers::ConfirmAccount },
11
- check_password_token: { klass: GraphqlDevise::Resolvers::CheckPasswordToken }
10
+ confirm_account: { klass: GraphqlDevise::Resolvers::ConfirmAccount, deprecation_reason: 'use the new confirmation flow as it does not require this query anymore' },
11
+ check_password_token: { klass: GraphqlDevise::Resolvers::CheckPasswordToken, deprecation_reason: 'use the new password reset flow as it does not require this query anymore' }
12
12
  }.freeze
13
13
  end
14
14
  end
@@ -4,12 +4,14 @@ module GraphqlDevise
4
4
  module Model
5
5
  class WithEmailUpdater
6
6
  def initialize(resource, attributes)
7
- @attributes = attributes
7
+ @attributes = attributes.with_indifferent_access
8
8
  @resource = resource
9
9
  end
10
10
 
11
11
  def call
12
- resource_attributes = @attributes.except(:schema_url, :confirmation_success_url)
12
+ check_deprecated_attributes
13
+
14
+ resource_attributes = @attributes.except(:schema_url, :confirmation_success_url, :confirmation_url)
13
15
  return @resource.update(resource_attributes) unless requires_reconfirmation?(resource_attributes)
14
16
 
15
17
  @resource.assign_attributes(resource_attributes)
@@ -27,16 +29,31 @@ module GraphqlDevise
27
29
  else
28
30
  raise(
29
31
  GraphqlDevise::Error,
30
- 'Method `update_with_email` requires attributes `confirmation_success_url` and `schema_url` for email reconfirmation to work'
32
+ 'Method `update_with_email` requires attribute `confirmation_url` for email reconfirmation to work'
31
33
  )
32
34
  end
33
35
  end
34
36
 
35
37
  private
36
38
 
39
+ def check_deprecated_attributes
40
+ if [@attributes[:schema_url], @attributes[:confirmation_success_url]].any?(&:present?)
41
+ ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc, caller)
42
+ Providing `schema_url` and `confirmation_success_url` to `update_with_email` is deprecated and will be
43
+ removed in a future version of this gem.
44
+
45
+ Now you must only provide `confirmation_url` and the email will contain the new format of the confirmation
46
+ url that needs to be used with the new `confirmRegistrationWithToken` on the client application.
47
+ DEPRECATION
48
+ end
49
+ end
50
+
37
51
  def required_reconfirm_attributes?
38
- @attributes[:schema_url].present? &&
39
- (@attributes[:confirmation_success_url].present? || DeviseTokenAuth.default_confirm_success_url.present?)
52
+ if @attributes[:schema_url].present?
53
+ [@attributes[:confirmation_success_url], DeviseTokenAuth.default_confirm_success_url].any?(&:present?)
54
+ else
55
+ [@attributes[:confirmation_url], DeviseTokenAuth.default_confirm_success_url].any?(&:present?)
56
+ end
40
57
  end
41
58
 
42
59
  def requires_reconfirmation?(resource_attributes)
@@ -60,13 +77,22 @@ module GraphqlDevise
60
77
  end
61
78
  end
62
79
 
80
+ def confirmation_method_params
81
+ if @attributes[:schema_url].present?
82
+ {
83
+ redirect_url: @attributes[:confirmation_success_url] || DeviseTokenAuth.default_confirm_success_url,
84
+ schema_url: @attributes[:schema_url]
85
+ }
86
+ else
87
+ { redirect_url: @attributes[:confirmation_url] || DeviseTokenAuth.default_confirm_success_url }
88
+ end
89
+ end
90
+
63
91
  def send_confirmation_instructions(saved)
64
92
  return unless saved
65
93
 
66
94
  @resource.send_confirmation_instructions(
67
- redirect_url: @attributes[:confirmation_success_url] || DeviseTokenAuth.default_confirm_success_url,
68
- template_path: ['graphql_devise/mailer'],
69
- schema_url: @attributes[:schema_url]
95
+ confirmation_method_params.merge(template_path: ['graphql_devise/mailer'])
70
96
  )
71
97
  end
72
98
  end
@@ -17,7 +17,7 @@ module GraphqlDevise
17
17
  @selected_operations.except(*@custom_keys).each_with_object({}) do |(action, operation_info), result|
18
18
  mapped_action = "#{mapping_name}_#{action}"
19
19
  operation = operation_info[:klass]
20
- options = operation_info.except(:klass)
20
+ options = operation_info.except(:klass, :deprecation_reason)
21
21
 
22
22
  result[mapped_action.to_sym] = [
23
23
  OperationPreparers::GqlNameSetter.new(mapped_action),
@@ -18,13 +18,25 @@ module GraphqlDevise
18
18
  end
19
19
 
20
20
  def call
21
- if @only.present?
21
+ operations = if @only.present?
22
22
  @default.slice(*@only)
23
23
  elsif @skipped.present?
24
24
  @default.except(*@skipped)
25
25
  else
26
26
  @default
27
27
  end
28
+
29
+ operations.each do |operation, values|
30
+ next if values[:deprecation_reason].blank?
31
+
32
+ ActiveSupport::Deprecation.warn(<<-DEPRECATION.strip_heredoc, caller)
33
+ `#{operation}` is deprecated and will be removed in a future version of this gem.
34
+ #{values[:deprecation_reason]}
35
+
36
+ You can supress this message by skipping `#{operation}` on your ResourceLoader or the
37
+ mount_graphql_devise_for method on your routes file.
38
+ DEPRECATION
39
+ end
28
40
  end
29
41
  end
30
42
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphqlDevise
4
+ module Mutations
5
+ class ConfirmRegistrationWithToken < Base
6
+ argument :confirmation_token, String, required: true
7
+
8
+ field :credentials,
9
+ GraphqlDevise::Types::CredentialType,
10
+ null: true,
11
+ description: 'Authentication credentials. Null unless user is signed in after confirmation.'
12
+
13
+ def resolve(confirmation_token:)
14
+ resource = resource_class.confirm_by_token(confirmation_token)
15
+
16
+ if resource.errors.empty?
17
+ yield resource if block_given?
18
+
19
+ response_payload = { authenticatable: resource }
20
+
21
+ response_payload[:credentials] = set_auth_headers(resource) if resource.active_for_authentication?
22
+
23
+ response_payload
24
+ else
25
+ raise_user_error(I18n.t('graphql_devise.confirmations.invalid_token'))
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end