graphql_devise 0.15.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
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