graphql_devise 0.13.2 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +41 -0
  3. data/README.md +20 -17
  4. data/app/models/graphql_devise/concerns/model.rb +6 -0
  5. data/app/views/graphql_devise/mailer/reset_password_instructions.html.erb +7 -1
  6. data/config/locales/en.yml +2 -1
  7. data/lib/graphql_devise/concerns/controller_methods.rb +7 -1
  8. data/lib/graphql_devise/default_operations/mutations.rb +10 -6
  9. data/lib/graphql_devise/mutations/resend_confirmation.rb +15 -5
  10. data/lib/graphql_devise/mutations/send_password_reset.rb +2 -0
  11. data/lib/graphql_devise/mutations/send_password_reset_with_token.rb +37 -0
  12. data/lib/graphql_devise/mutations/sign_up.rb +1 -3
  13. data/lib/graphql_devise/mutations/update_password_with_token.rb +38 -0
  14. data/lib/graphql_devise/resolvers/check_password_token.rb +1 -0
  15. data/lib/graphql_devise/resolvers/confirm_account.rb +2 -0
  16. data/lib/graphql_devise/version.rb +1 -1
  17. data/spec/dummy/app/graphql/mutations/reset_admin_password_with_token.rb +13 -0
  18. data/spec/dummy/app/graphql/resolvers/confirm_admin_account.rb +13 -0
  19. data/spec/dummy/app/graphql/types/admin_type.rb +8 -0
  20. data/spec/dummy/config/initializers/devise.rb +1 -1
  21. data/spec/dummy/config/initializers/devise_token_auth.rb +2 -0
  22. data/spec/dummy/config/routes.rb +4 -0
  23. data/spec/dummy/db/schema.rb +0 -2
  24. data/spec/requests/mutations/additional_mutations_spec.rb +0 -1
  25. data/spec/requests/mutations/resend_confirmation_spec.rb +42 -4
  26. data/spec/requests/mutations/send_password_reset_spec.rb +16 -1
  27. data/spec/requests/mutations/send_password_reset_with_token_spec.rb +78 -0
  28. data/spec/requests/mutations/sign_up_spec.rb +19 -1
  29. data/spec/requests/mutations/update_password_with_token_spec.rb +119 -0
  30. data/spec/requests/queries/check_password_token_spec.rb +16 -1
  31. data/spec/requests/queries/confirm_account_spec.rb +115 -42
  32. metadata +18 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f3d25f0672c378bfd003351aa997e61fdfce123ed3b391ed5bddce60c86c4f28
4
- data.tar.gz: 0052cc77751cf44d704cfc8c7f462c5ee1aed58c91ad7ba1e80068b085149f88
3
+ metadata.gz: 623b4df681f9e3ae95598c67885cbc261d4e73c5d6bd2cb070ea9c39b4305dbb
4
+ data.tar.gz: 4efd72cc4b7b61d44b03cdf062db5a47c3bbce831c9101801b1a0a6d6af91701
5
5
  SHA512:
6
- metadata.gz: 3ee604289ff30fe95a1947ee63a58c05b2a05a659657253e29ed526213bea1558d6162597daf08be56a131a0c3c3100dc2affe1b821674f493d03939ad1540ee
7
- data.tar.gz: cd6b4af9fda08c2310e6a47d3d9db8b451031bbbf05b0f214ca71a230d248d64c65cc18a92711b46676d20f047f669d5cdcb1fe6df3a42748109ff3bfae7d709
6
+ metadata.gz: 0510a69ab752c9f5047f1d4dd3a7f6721c974b5d3af979b73cacd9a5456cd0cdc695766fce66e6b2ed70879a9faa24104fb71140ec12e900c51e4925bf4fc850
7
+ data.tar.gz: afb8d1f441dde3094e11f9ff12e9555d7d0ada530d086a3836f371855ce1f784e48be0e93d3c0c20bef5e0bae5328cd7a4e17168e747edb57a43b03fbfec5ee4
@@ -1,5 +1,46 @@
1
1
  # Changelog
2
2
 
3
+ ## [v0.14.0](https://github.com/graphql-devise/graphql_devise/tree/v0.14.0) (2021-01-19)
4
+
5
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.6...v0.14.0)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Alternate reset password flow, only 2 steps, no redirect [\#146](https://github.com/graphql-devise/graphql_devise/pull/146) ([mcelicalderon](https://github.com/mcelicalderon))
10
+
11
+ ## [v0.13.6](https://github.com/graphql-devise/graphql_devise/tree/v0.13.6) (2020-12-22)
12
+
13
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.5...v0.13.6)
14
+
15
+ **Security fixes:**
16
+
17
+ - Possible security issue with password reset and redirectUrl [\#136](https://github.com/graphql-devise/graphql_devise/issues/136)
18
+ - Add redirect whitelist validation to all queries and mutations [\#140](https://github.com/graphql-devise/graphql_devise/pull/140) ([mcelicalderon](https://github.com/mcelicalderon))
19
+
20
+ ## [v0.13.5](https://github.com/graphql-devise/graphql_devise/tree/v0.13.5) (2020-11-20)
21
+
22
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.4...v0.13.5)
23
+
24
+ **Implemented enhancements:**
25
+
26
+ - Fixes connection\_config deprecation warning [\#135](https://github.com/graphql-devise/graphql_devise/pull/135) ([artplan1](https://github.com/artplan1))
27
+
28
+ ## [v0.13.4](https://github.com/graphql-devise/graphql_devise/tree/v0.13.4) (2020-08-15)
29
+
30
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.3...v0.13.4)
31
+
32
+ **Implemented enhancements:**
33
+
34
+ - Allow resend of confirmation with unconfirmed email [\#127](https://github.com/graphql-devise/graphql_devise/pull/127) ([j15e](https://github.com/j15e))
35
+
36
+ ## [v0.13.3](https://github.com/graphql-devise/graphql_devise/tree/v0.13.3) (2020-08-13)
37
+
38
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.2...v0.13.3)
39
+
40
+ **Fixed bugs:**
41
+
42
+ - Fix unconfirmed\_email confirmation. Ignore devise reconfirmable config. [\#126](https://github.com/graphql-devise/graphql_devise/pull/126) ([mcelicalderon](https://github.com/mcelicalderon))
43
+
3
44
  ## [v0.13.2](https://github.com/graphql-devise/graphql_devise/tree/v0.13.2) (2020-08-12)
4
45
 
5
46
  [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.1...v0.13.2)
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # GraphqlDevise
2
- [![Build Status](https://travis-ci.org/graphql-devise/graphql_devise.svg?branch=master)](https://travis-ci.org/graphql-devise/graphql_devise)
2
+ [![Build Status](https://travis-ci.com/graphql-devise/graphql_devise.svg?branch=master)](https://travis-ci.com/graphql-devise/graphql_devise)
3
3
  [![Coverage Status](https://coveralls.io/repos/github/graphql-devise/graphql_devise/badge.svg?branch=master)](https://coveralls.io/github/graphql-devise/graphql_devise?branch=master)
4
4
  [![Gem Version](https://badge.fury.io/rb/graphql_devise.svg)](https://badge.fury.io/rb/graphql_devise)
5
5
 
@@ -47,7 +47,8 @@ GraphQL interface on top of the [Devise Token Auth](https://github.com/lynndylan
47
47
  <!--te-->
48
48
 
49
49
  ## Introduction
50
- Graphql-Devise heavily relies on two gems:
50
+ Graphql-Devise heavily relies on 3 gems:
51
+ - [GraphQL Ruby](https://github.com/rmosolgo/graphql-ruby)
51
52
  - [Devise Token Auth](https://github.com/lynndylanhurley/devise_token_auth) (DTA)
52
53
  - [Devise](https://github.com/heartcombo/devise) (which is a DTA dependency)
53
54
 
@@ -107,7 +108,7 @@ and `api/auth` could be any mount path you would like to use for auth.
107
108
  - Avoid passing the `--mount` option or the gem will try to use an existing schema.
108
109
 
109
110
  #### Mounting Operations in Your Own Schema (> v0.12.0)
110
- To configure the gem to use your own GQL schema use the `--mount` option.
111
+ To configure the gem to use your own GQL schema use the `--mount` option.
111
112
  For instance the executing:
112
113
 
113
114
  ```bash
@@ -318,20 +319,19 @@ The install generator can do this for you if you specify the `user_class` option
318
319
  See [Installation](#installation) for details.
319
320
 
320
321
  ### Email Reconfirmation
321
- DTA and Devise support email reconfirmation. When the `confirmable` module is added to your
322
- resource, an email is sent to the provided email address when the `signUp` mutation is used.
323
- You can also use this gem so every time a user updates the `email` field, a new email gets sent
324
- for the user to confirm the new email address. Only after clicking on the confirmation link,
325
- the email will be updated on the database to use the new value.
326
-
327
- In order to use this feature there are a couple of things to setup first:
328
- 1. Make user your model includes the `:confirmable` module.
329
- 1. Add an `unconfirmed_email` String column to your resource's table.
330
-
331
- After that is done, you simply need to call a different update method on your resource,
332
- `update_with_email`. This method behaves exactly the same as ActiveRecord's `update` method
333
- if the previous steps are not performed, or if you are not updating the `email` attribute.
334
- It is also mandatory to provide two additional attributes when email will change or an error
322
+ Email reconfirmation is supported just like in Devise and DTA, but we want reconfirmable
323
+ in this gem to work on model basis instead of having a global configuration like in Devise.
324
+ **For this reason Devise's global `reconfirmable` setting is ignored.**
325
+
326
+ For a resource to be considered reconfirmable it has to meet 2 conditions:
327
+ 1. Include the `:confirmable` module.
328
+ 1. Has an `unconfirmed_email` column in the resource's table.
329
+
330
+ In order to trigger the reconfirmation email in a reconfirmable resource, you simply needi
331
+ to call a different update method on your resource,`update_with_email`.
332
+ When the resource is not reconfirmable or the email is not updated, this method behaves exactly
333
+ the same as ActiveRecord's `update`.
334
+ `update_with_email` requires two additional attributes when email will change or an error
335
335
  will be raised:
336
336
 
337
337
  1. `schema_url`: The full url where your GQL schema is mounted. You can get this value from the
@@ -355,6 +355,9 @@ user.update_with_email(
355
355
  )
356
356
  ```
357
357
 
358
+ We want reconfirmable in this gem to work separately
359
+ from DTA's or Devise (too much complexity in the model based on callbacks).
360
+
358
361
  ### Customizing Email Templates
359
362
  The approach of this gem is a bit different from DeviseTokenAuth. We have placed our templates in `app/views/graphql_devise/mailer`,
360
363
  so if you want to change them, place yours on the same dir structure on your Rails project. You can customize these two templates:
@@ -7,6 +7,12 @@ module GraphqlDevise
7
7
  Model = DeviseTokenAuth::Concerns::User
8
8
 
9
9
  Model.module_eval do
10
+ class_methods do
11
+ def reconfirmable
12
+ devise_modules.include?(:confirmable) && column_names.include?('unconfirmed_email')
13
+ end
14
+ end
15
+
10
16
  def update_with_email(attributes = {})
11
17
  GraphqlDevise::Model::WithEmailUpdater.new(self, attributes).call
12
18
  end
@@ -2,7 +2,13 @@
2
2
 
3
3
  <p><%= t('.request_reset_link_msg') %></p>
4
4
 
5
- <p><%= link_to t('.password_change_link'), "#{message['schema_url']}?#{password_reset_query(token: @token, redirect_url: message['redirect-url'], resource_name: @resource.class.to_s).to_query}" %></p>
5
+ <p>
6
+ <% if message['schema_url'].present? %>
7
+ <%= link_to t('.password_change_link'), "#{message['schema_url']}?#{password_reset_query(token: @token, redirect_url: message['redirect-url'], resource_name: @resource.class.to_s).to_query}" %>
8
+ <% else %>
9
+ <%= link_to t('.password_change_link'), "#{message['redirect-url'].to_s}?#{{ reset_password_token: @token }.to_query}" %>
10
+ <% end %>
11
+ </p>
6
12
 
7
13
  <p><%= t('.ignore_mail_msg') %></p>
8
14
  <p><%= t('.no_changes_msg') %></p>
@@ -1,5 +1,6 @@
1
1
  en:
2
2
  graphql_devise:
3
+ redirect_url_not_allowed: "Redirect to '%{redirect_url}' not allowed."
3
4
  registration_failed: "User couldn't be registered"
4
5
  resource_build_failed: "Resource couldn't be built, execution stopped."
5
6
  not_authenticated: "User is not logged in."
@@ -7,8 +8,8 @@ en:
7
8
  invalid_resource: "Errors present in the resource."
8
9
  registrations:
9
10
  missing_confirm_redirect_url: "Missing 'confirm_success_url' parameter. Required when confirmable module is enabled."
10
- redirect_url_not_allowed: "Redirect to '%{redirect_url}' not allowed."
11
11
  passwords:
12
+ password_recovery_disabled: "You must enable password recovery for this model."
12
13
  update_password_error: "Unable to update user password"
13
14
  missing_passwords: "You must fill out the fields labeled 'Password' and 'Password confirmation'."
14
15
  password_not_required: "This account does not require a password. Sign in using your '%{provider}' account instead."
@@ -7,6 +7,12 @@ module GraphqlDevise
7
7
 
8
8
  private
9
9
 
10
+ def check_redirect_url_whitelist!(redirect_url)
11
+ if blacklisted_redirect_url?(redirect_url)
12
+ raise_user_error(I18n.t('graphql_devise.redirect_url_not_allowed', redirect_url: redirect_url))
13
+ end
14
+ end
15
+
10
16
  def raise_user_error(message)
11
17
  raise GraphqlDevise::UserError, message
12
18
  end
@@ -90,7 +96,7 @@ module GraphqlDevise
90
96
  end
91
97
 
92
98
  def find_resource(field, value)
93
- if resource_class.try(:connection_config).try(:[], :adapter).try(:include?, 'mysql')
99
+ if resource_class.connection.adapter_name.downcase.include?('mysql')
94
100
  # fix for mysql default case insensitivity
95
101
  resource_class.where("BINARY #{field} = ? AND provider= ?", value, provider).first
96
102
  elsif Gem::Version.new(DeviseTokenAuth::VERSION) < Gem::Version.new('1.1.0')
@@ -5,18 +5,22 @@ require 'graphql_devise/mutations/login'
5
5
  require 'graphql_devise/mutations/logout'
6
6
  require 'graphql_devise/mutations/resend_confirmation'
7
7
  require 'graphql_devise/mutations/send_password_reset'
8
+ require 'graphql_devise/mutations/send_password_reset_with_token'
8
9
  require 'graphql_devise/mutations/sign_up'
9
10
  require 'graphql_devise/mutations/update_password'
11
+ require 'graphql_devise/mutations/update_password_with_token'
10
12
 
11
13
  module GraphqlDevise
12
14
  module DefaultOperations
13
15
  MUTATIONS = {
14
- login: { klass: GraphqlDevise::Mutations::Login, authenticatable: true },
15
- logout: { klass: GraphqlDevise::Mutations::Logout, authenticatable: true },
16
- sign_up: { klass: GraphqlDevise::Mutations::SignUp, authenticatable: true },
17
- update_password: { klass: GraphqlDevise::Mutations::UpdatePassword, authenticatable: true },
18
- send_password_reset: { klass: GraphqlDevise::Mutations::SendPasswordReset, authenticatable: false },
19
- resend_confirmation: { klass: GraphqlDevise::Mutations::ResendConfirmation, authenticatable: false }
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 }
20
24
  }.freeze
21
25
  end
22
26
  end
@@ -9,15 +9,16 @@ module GraphqlDevise
9
9
  field :message, String, null: false
10
10
 
11
11
  def resolve(email:, redirect_url:)
12
- resource = find_resource(
13
- :email,
14
- get_case_insensitive_field(:email, email)
15
- )
12
+ check_redirect_url_whitelist!(redirect_url)
13
+
14
+ resource = find_confirmable_resource(email)
16
15
 
17
16
  if resource
18
17
  yield resource if block_given?
19
18
 
20
- raise_user_error(I18n.t('graphql_devise.confirmations.already_confirmed')) if resource.confirmed?
19
+ if resource.confirmed? && !resource.pending_reconfirmation?
20
+ raise_user_error(I18n.t('graphql_devise.confirmations.already_confirmed'))
21
+ end
21
22
 
22
23
  resource.send_confirmation_instructions(
23
24
  redirect_url: redirect_url,
@@ -30,6 +31,15 @@ module GraphqlDevise
30
31
  raise_user_error(I18n.t('graphql_devise.confirmations.user_not_found', email: email))
31
32
  end
32
33
  end
34
+
35
+ private
36
+
37
+ def find_confirmable_resource(email)
38
+ email_insensitive = get_case_insensitive_field(:email, email)
39
+ resource = find_resource(:unconfirmed_email, email_insensitive) if resource_class.reconfirmable
40
+ resource ||= find_resource(:email, email_insensitive)
41
+ resource
42
+ end
33
43
  end
34
44
  end
35
45
  end
@@ -9,6 +9,8 @@ module GraphqlDevise
9
9
  field :message, String, null: false
10
10
 
11
11
  def resolve(email:, redirect_url:)
12
+ check_redirect_url_whitelist!(redirect_url)
13
+
12
14
  resource = find_resource(:email, get_case_insensitive_field(:email, email))
13
15
 
14
16
  if resource
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphqlDevise
4
+ module Mutations
5
+ class SendPasswordResetWithToken < Base
6
+ argument :email, String, required: true
7
+ argument :redirect_url, String, required: true
8
+
9
+ field :message, String, null: false
10
+
11
+ def resolve(email:, redirect_url:)
12
+ check_redirect_url_whitelist!(redirect_url)
13
+
14
+ resource = find_resource(:email, get_case_insensitive_field(:email, email))
15
+
16
+ if resource
17
+ yield resource if block_given?
18
+
19
+ resource.send_reset_password_instructions(
20
+ email: email,
21
+ provider: 'email',
22
+ redirect_url: redirect_url,
23
+ template_path: ['graphql_devise/mailer']
24
+ )
25
+
26
+ if resource.errors.empty?
27
+ { message: I18n.t('graphql_devise.passwords.send_instructions') }
28
+ else
29
+ raise_user_error_list(I18n.t('graphql_devise.invalid_resource'), errors: resource.errors.full_messages)
30
+ end
31
+ else
32
+ raise_user_error(I18n.t('graphql_devise.user_not_found'))
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -22,9 +22,7 @@ module GraphqlDevise
22
22
  raise_user_error(I18n.t('graphql_devise.registrations.missing_confirm_redirect_url'))
23
23
  end
24
24
 
25
- if blacklisted_redirect_url?(redirect_url)
26
- raise_user_error(I18n.t('graphql_devise.registrations.redirect_url_not_allowed', redirect_url: redirect_url))
27
- end
25
+ check_redirect_url_whitelist!(redirect_url)
28
26
 
29
27
  resource.skip_confirmation_notification! if resource.respond_to?(:skip_confirmation_notification!)
30
28
 
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphqlDevise
4
+ module Mutations
5
+ class UpdatePasswordWithToken < Base
6
+ argument :password, String, required: true
7
+ argument :password_confirmation, String, required: true
8
+ argument :reset_password_token, String, required: true
9
+
10
+ field :credentials,
11
+ GraphqlDevise::Types::CredentialType,
12
+ null: true,
13
+ description: 'Authentication credentials. Resource must be signed_in for credentials to be returned.'
14
+
15
+ def resolve(reset_password_token:, **attrs)
16
+ raise_user_error(I18n.t('graphql_devise.passwords.password_recovery_disabled')) unless recoverable_enabled?
17
+
18
+ resource = resource_class.with_reset_password_token(reset_password_token)
19
+ raise_user_error(I18n.t('graphql_devise.passwords.reset_token_not_found')) if resource.blank?
20
+ raise_user_error(I18n.t('graphql_devise.passwords.reset_token_expired')) unless resource.reset_password_period_valid?
21
+
22
+ if resource.update(attrs)
23
+ yield resource if block_given?
24
+
25
+ response_payload = { authenticatable: resource }
26
+ response_payload[:credentials] = set_auth_headers(resource) if controller.signed_in?(resource_name)
27
+
28
+ response_payload
29
+ else
30
+ raise_user_error_list(
31
+ I18n.t('graphql_devise.passwords.update_password_error'),
32
+ errors: resource.errors.full_messages
33
+ )
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -27,6 +27,7 @@ module GraphqlDevise
27
27
  )
28
28
 
29
29
  if redirect_url.present?
30
+ check_redirect_url_whitelist!(redirect_url)
30
31
  controller.redirect_to(resource.build_auth_url(redirect_url, built_redirect_headers))
31
32
  else
32
33
  set_auth_headers(resource)
@@ -7,6 +7,8 @@ module GraphqlDevise
7
7
  argument :redirect_url, String, required: true
8
8
 
9
9
  def resolve(confirmation_token:, redirect_url:)
10
+ check_redirect_url_whitelist!(redirect_url)
11
+
10
12
  resource = resource_class.confirm_by_token(confirmation_token)
11
13
 
12
14
  if resource.errors.empty?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GraphqlDevise
4
- VERSION = '0.13.2'.freeze
4
+ VERSION = '0.14.0'.freeze
5
5
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutations
4
+ class ResetAdminPasswordWithToken < GraphqlDevise::Mutations::UpdatePasswordWithToken
5
+ field :authenticatable, Types::AdminType, null: false
6
+
7
+ def resolve(reset_password_token:, **attrs)
8
+ super do |admin|
9
+ controller.sign_in(admin)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resolvers
4
+ class ConfirmAdminAccount < GraphqlDevise::Resolvers::ConfirmAccount
5
+ type Types::AdminType, null: false
6
+
7
+ def resolve(confirmation_token:, redirect_url:)
8
+ super do |admin|
9
+ controller.sign_in(admin)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Types
4
+ class AdminType < GraphQL::Schema::Object
5
+ field :id, Int, null: false
6
+ field :email, String, null: false
7
+ end
8
+ end
@@ -142,7 +142,7 @@ Devise.setup do |config|
142
142
  # initial account confirmation) to be applied. Requires additional unconfirmed_email
143
143
  # db field (see migrations). Until confirmed, new email is stored in
144
144
  # unconfirmed_email column, and copied to email column on successful confirmation.
145
- config.reconfirmable = true
145
+ config.reconfirmable = false
146
146
 
147
147
  # Defines which key will be used when confirming an account
148
148
  # config.confirmation_keys = [:email]
@@ -39,6 +39,8 @@ DeviseTokenAuth.setup do |config|
39
39
 
40
40
  config.default_confirm_success_url = 'https://google.com'
41
41
 
42
+ config.redirect_whitelist = ['https://google.com']
43
+
42
44
  # By default we will use callbacks for single omniauth.
43
45
  # It depends on fields like email, provider and uid.
44
46
  # config.default_callbacks = true
@@ -14,6 +14,10 @@ Rails.application.routes.draw do
14
14
  'Admin',
15
15
  authenticatable_type: Types::CustomAdminType,
16
16
  skip: [:sign_up, :check_password_token],
17
+ operations: {
18
+ confirm_account: Resolvers::ConfirmAdminAccount,
19
+ update_password_with_token: Mutations::ResetAdminPasswordWithToken
20
+ },
17
21
  at: '/api/v1/admin/graphql_auth'
18
22
  )
19
23
 
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # This file is auto-generated from the current state of the database. Instead
4
2
  # of editing this file, please use the migrations feature of Active Record to
5
3
  # incrementally modify your database, and then regenerate this schema definition.
@@ -9,7 +9,6 @@ RSpec.describe 'Additional Mutations' do
9
9
  let(:password) { Faker::Internet.password }
10
10
  let(:password_confirmation) { password }
11
11
  let(:email) { Faker::Internet.email }
12
- let(:redirect) { Faker::Internet.url }
13
12
 
14
13
  context 'when using the user model' do
15
14
  let(:query) do
@@ -5,10 +5,11 @@ require 'rails_helper'
5
5
  RSpec.describe 'Resend confirmation' do
6
6
  include_context 'with graphql query request'
7
7
 
8
- let!(:user) { create(:user, confirmed_at: nil, email: 'mwallace@wallaceinc.com') }
9
- let(:email) { user.email }
10
- let(:id) { user.id }
11
- let(:redirect) { Faker::Internet.url }
8
+ let(:confirmed_at) { nil }
9
+ let!(:user) { create(:user, confirmed_at: nil, email: 'mwallace@wallaceinc.com') }
10
+ let(:email) { user.email }
11
+ let(:id) { user.id }
12
+ let(:redirect) { 'https://google.com' }
12
13
  let(:query) do
13
14
  <<-GRAPHQL
14
15
  mutation {
@@ -22,6 +23,21 @@ RSpec.describe 'Resend confirmation' do
22
23
  GRAPHQL
23
24
  end
24
25
 
26
+ context 'when redirect_url is not whitelisted' do
27
+ let(:redirect) { 'https://not-safe.com' }
28
+
29
+ it 'returns a not whitelisted redirect url error' do
30
+ expect { post_request }.to not_change(ActionMailer::Base.deliveries, :count)
31
+
32
+ expect(json_response[:errors]).to containing_exactly(
33
+ hash_including(
34
+ message: "Redirect to '#{redirect}' not allowed.",
35
+ extensions: { code: 'USER_ERROR' }
36
+ )
37
+ )
38
+ end
39
+ end
40
+
25
41
  context 'when params are correct' do
26
42
  context 'when using the gem schema' do
27
43
  it 'sends an email to the user with confirmation url and returns a success message' do
@@ -98,6 +114,28 @@ RSpec.describe 'Resend confirmation' do
98
114
  end
99
115
  end
100
116
 
117
+ context 'when the email was changed' do
118
+ let(:confirmed_at) { 2.seconds.ago }
119
+ let(:email) { 'new-email@wallaceinc.com' }
120
+ let(:new_email) { email }
121
+
122
+ before do
123
+ user.update_with_email(
124
+ email: new_email,
125
+ schema_url: 'http://localhost/test',
126
+ confirmation_success_url: 'https://google.com'
127
+ )
128
+ end
129
+
130
+ it 'sends new confirmation email' do
131
+ expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
132
+ expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(new_email)
133
+ expect(json_response[:data][:userResendConfirmation]).to include(
134
+ message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
135
+ )
136
+ end
137
+ end
138
+
101
139
  context "when the email isn't in the system" do
102
140
  let(:email) { 'nothere@gmail.com' }
103
141
 
@@ -7,7 +7,7 @@ RSpec.describe 'Send Password Reset Requests' do
7
7
 
8
8
  let!(:user) { create(:user, :confirmed, email: 'jwinnfield@wallaceinc.com') }
9
9
  let(:email) { user.email }
10
- let(:redirect_url) { Faker::Internet.url }
10
+ let(:redirect_url) { 'https://google.com' }
11
11
  let(:query) do
12
12
  <<-GRAPHQL
13
13
  mutation {
@@ -21,6 +21,21 @@ RSpec.describe 'Send Password Reset Requests' do
21
21
  GRAPHQL
22
22
  end
23
23
 
24
+ context 'when redirect_url is not whitelisted' do
25
+ let(:redirect_url) { 'https://not-safe.com' }
26
+
27
+ it 'returns a not whitelisted redirect url error' do
28
+ expect { post_request }.to not_change(ActionMailer::Base.deliveries, :count)
29
+
30
+ expect(json_response[:errors]).to containing_exactly(
31
+ hash_including(
32
+ message: "Redirect to '#{redirect_url}' not allowed.",
33
+ extensions: { code: 'USER_ERROR' }
34
+ )
35
+ )
36
+ end
37
+ end
38
+
24
39
  context 'when params are correct' do
25
40
  context 'when using the gem schema' do
26
41
  it 'sends password reset email' do
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe 'Send Password Reset Requests' do
6
+ include_context 'with graphql query request'
7
+
8
+ let!(:user) { create(:user, :confirmed, email: 'jwinnfield@wallaceinc.com') }
9
+ let(:email) { user.email }
10
+ let(:redirect_url) { 'https://google.com' }
11
+ let(:query) do
12
+ <<-GRAPHQL
13
+ mutation {
14
+ userSendPasswordResetWithToken(
15
+ email: "#{email}",
16
+ redirectUrl: "#{redirect_url}"
17
+ ) {
18
+ message
19
+ }
20
+ }
21
+ GRAPHQL
22
+ end
23
+
24
+ context 'when redirect_url is not whitelisted' do
25
+ let(:redirect_url) { 'https://not-safe.com' }
26
+
27
+ it 'returns a not whitelisted redirect url error' do
28
+ expect { post_request }.to not_change(ActionMailer::Base.deliveries, :count)
29
+
30
+ expect(json_response[:errors]).to containing_exactly(
31
+ hash_including(
32
+ message: "Redirect to '#{redirect_url}' not allowed.",
33
+ extensions: { code: 'USER_ERROR' }
34
+ )
35
+ )
36
+ end
37
+ end
38
+
39
+ context 'when params are correct' do
40
+ context 'when using the gem schema' do
41
+ it 'sends password reset email' do
42
+ expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
43
+
44
+ expect(json_response[:data][:userSendPasswordResetWithToken]).to include(
45
+ message: 'You will receive an email with instructions on how to reset your password in a few minutes.'
46
+ )
47
+
48
+ email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
49
+ link = email.css('a').first
50
+
51
+ expect(link['href']).to include(redirect_url + '?reset_password_token')
52
+ end
53
+ end
54
+ end
55
+
56
+ context 'when email address uses different casing' do
57
+ let(:email) { 'jWinnfield@wallaceinc.com' }
58
+
59
+ it 'honors devise configuration for case insensitive fields' do
60
+ expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
61
+ expect(json_response[:data][:userSendPasswordResetWithToken]).to include(
62
+ message: 'You will receive an email with instructions on how to reset your password in a few minutes.'
63
+ )
64
+ end
65
+ end
66
+
67
+ context 'when user email is not found' do
68
+ let(:email) { 'nothere@gmail.com' }
69
+
70
+ before { post_request }
71
+
72
+ it 'returns an error' do
73
+ expect(json_response[:errors]).to contain_exactly(
74
+ hash_including(message: 'User was not found or was not logged in.', extensions: { code: 'USER_ERROR' })
75
+ )
76
+ end
77
+ end
78
+ end
@@ -8,7 +8,7 @@ RSpec.describe 'Sign Up process' do
8
8
  let(:name) { Faker::Name.name }
9
9
  let(:password) { Faker::Internet.password }
10
10
  let(:email) { Faker::Internet.email }
11
- let(:redirect) { Faker::Internet.url }
11
+ let(:redirect) { 'https://google.com' }
12
12
 
13
13
  context 'when using the user model' do
14
14
  let(:query) do
@@ -31,6 +31,24 @@ RSpec.describe 'Sign Up process' do
31
31
  GRAPHQL
32
32
  end
33
33
 
34
+ context 'when redirect_url is not whitelisted' do
35
+ let(:redirect) { 'https://not-safe.com' }
36
+
37
+ it 'returns a not whitelisted redirect url error' do
38
+ expect { post_request }.to(
39
+ not_change(User, :count)
40
+ .and(not_change(ActionMailer::Base.deliveries, :count))
41
+ )
42
+
43
+ expect(json_response[:errors]).to containing_exactly(
44
+ hash_including(
45
+ message: "Redirect to '#{redirect}' not allowed.",
46
+ extensions: { code: 'USER_ERROR' }
47
+ )
48
+ )
49
+ end
50
+ end
51
+
34
52
  context 'when params are correct' do
35
53
  it 'creates a new resource that requires confirmation' do
36
54
  expect { post_request }.to(
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails_helper'
4
+
5
+ RSpec.describe 'Update Password With Token' do
6
+ include_context 'with graphql query request'
7
+
8
+ let(:password) { '12345678' }
9
+ let(:password_confirmation) { password }
10
+
11
+ context 'when using the user model' do
12
+ let(:user) { create(:user, :confirmed) }
13
+ let(:query) do
14
+ <<-GRAPHQL
15
+ mutation {
16
+ userUpdatePasswordWithToken(
17
+ resetPasswordToken: "#{token}",
18
+ password: "#{password}",
19
+ passwordConfirmation: "#{password_confirmation}"
20
+ ) {
21
+ authenticatable { email }
22
+ credentials { accessToken }
23
+ }
24
+ }
25
+ GRAPHQL
26
+ end
27
+
28
+ context 'when reset password token is valid' do
29
+ let(:token) { user.send(:set_reset_password_token) }
30
+
31
+ it 'updates the password' do
32
+ expect do
33
+ post_request
34
+ user.reload
35
+ end.to change(user, :encrypted_password)
36
+
37
+ expect(user).to be_valid_password(password)
38
+ expect(json_response[:data][:userUpdatePasswordWithToken][:credentials]).to be_nil
39
+ expect(json_response[:data][:userUpdatePasswordWithToken][:authenticatable]).to include(email: user.email)
40
+ end
41
+
42
+ context 'when token has expired' do
43
+ it 'returns an expired token error' do
44
+ travel_to 10.hours.ago do
45
+ token
46
+ end
47
+
48
+ post_request
49
+
50
+ expect(json_response[:errors]).to contain_exactly(
51
+ hash_including(message: 'Reset password token is no longer valid.', extensions: { code: 'USER_ERROR' })
52
+ )
53
+ end
54
+ end
55
+
56
+ context 'when password confirmation does not match' do
57
+ let(:password_confirmation) { 'does not match' }
58
+
59
+ it 'returns an error' do
60
+ post_request
61
+
62
+ expect(json_response[:errors]).to contain_exactly(
63
+ hash_including(
64
+ message: 'Unable to update user password',
65
+ extensions: { code: 'USER_ERROR', detailed_errors: ["Password confirmation doesn't match Password"] }
66
+ )
67
+ )
68
+ end
69
+ end
70
+ end
71
+
72
+ context 'when reset password token is not found' do
73
+ let(:token) { user.send(:set_reset_password_token) + 'invalid' }
74
+
75
+ it 'returns an error' do
76
+ post_request
77
+
78
+ expect(json_response[:errors]).to contain_exactly(
79
+ hash_including(message: 'No user found for the specified reset token.', extensions: { code: 'USER_ERROR' })
80
+ )
81
+ end
82
+ end
83
+ end
84
+
85
+ context 'when using the admin model' do
86
+ let(:admin) { create(:admin, :confirmed) }
87
+ let(:query) do
88
+ <<-GRAPHQL
89
+ mutation {
90
+ adminUpdatePasswordWithToken(
91
+ resetPasswordToken: "#{token}",
92
+ password: "#{password}",
93
+ passwordConfirmation: "#{password_confirmation}"
94
+ ) {
95
+ authenticatable { email }
96
+ credentials { uid }
97
+ }
98
+ }
99
+ GRAPHQL
100
+ end
101
+
102
+ context 'when reset password token is valid' do
103
+ let(:token) { admin.send(:set_reset_password_token) }
104
+
105
+ it 'updates the password' do
106
+ expect do
107
+ post_request
108
+ admin.reload
109
+ end.to change(admin, :encrypted_password)
110
+
111
+ expect(admin).to be_valid_password(password)
112
+ expect(json_response[:data][:adminUpdatePasswordWithToken]).to include(
113
+ credentials: { uid: admin.email },
114
+ authenticatable: { email: admin.email }
115
+ )
116
+ end
117
+ end
118
+ end
119
+ end
@@ -54,6 +54,21 @@ RSpec.describe 'Check Password Token Requests' do
54
54
  expect(response.body).to include('uid=')
55
55
  expect(response.body).to include('expiry=')
56
56
  end
57
+
58
+ context 'when redirect_url is not whitelisted' do
59
+ let(:redirect_url) { 'https://not-safe.com' }
60
+
61
+ before { post_request }
62
+
63
+ it 'returns a not whitelisted redirect url error' do
64
+ expect(json_response[:errors]).to containing_exactly(
65
+ hash_including(
66
+ message: "Redirect to '#{redirect_url}' not allowed.",
67
+ extensions: { code: 'USER_ERROR' }
68
+ )
69
+ )
70
+ end
71
+ end
57
72
  end
58
73
 
59
74
  context 'when token has expired' do
@@ -74,7 +89,7 @@ RSpec.describe 'Check Password Token Requests' do
74
89
  context 'when reset password token is not found' do
75
90
  let(:token) { user.send(:set_reset_password_token) + 'invalid' }
76
91
 
77
- it 'redirects to redirect url' do
92
+ it 'returns an error message' do
78
93
  get_request
79
94
 
80
95
  expect(json_response[:errors]).to contain_exactly(
@@ -5,60 +5,133 @@ require 'rails_helper'
5
5
  RSpec.describe 'Account confirmation' do
6
6
  include_context 'with graphql query request'
7
7
 
8
- let(:user) { create(:user, confirmed_at: nil) }
9
- let(:redirect) { Faker::Internet.url }
10
- let(:query) do
11
- <<-GRAPHQL
12
- {
13
- userConfirmAccount(
14
- confirmationToken: "#{token}"
15
- redirectUrl: "#{redirect}"
16
- ) {
17
- email
18
- name
8
+ context 'when using the user model' do
9
+ let(:user) { create(:user, confirmed_at: nil) }
10
+ let(:redirect) { 'https://google.com' }
11
+ let(:query) do
12
+ <<-GRAPHQL
13
+ {
14
+ userConfirmAccount(
15
+ confirmationToken: "#{token}"
16
+ redirectUrl: "#{redirect}"
17
+ ) {
18
+ email
19
+ name
20
+ }
19
21
  }
20
- }
21
- GRAPHQL
22
- end
22
+ GRAPHQL
23
+ end
24
+
25
+ context 'when confirmation token is correct' do
26
+ let(:token) { user.confirmation_token }
27
+
28
+ before do
29
+ user.send_confirmation_instructions(
30
+ template_path: ['graphql_devise/mailer'],
31
+ controller: 'graphql_devise/graphql',
32
+ schema_url: 'http://not-using-this-value.com/gql'
33
+ )
34
+ end
35
+
36
+ it 'confirms the resource and redirects to the sent url' do
37
+ expect do
38
+ get_request
39
+ user.reload
40
+ end.to(change(user, :confirmed_at).from(nil))
41
+
42
+ expect(response).to redirect_to("#{redirect}?account_confirmation_success=true")
43
+ expect(user).to be_active_for_authentication
44
+ end
45
+
46
+ context 'when redirect_url is not whitelisted' do
47
+ let(:redirect) { 'https://not-safe.com' }
48
+
49
+ it 'returns a not whitelisted redirect url error' do
50
+ expect { post_request }.to not_change(ActionMailer::Base.deliveries, :count)
23
51
 
24
- context 'when confirmation token is correct' do
25
- let(:token) { user.confirmation_token }
52
+ expect(json_response[:errors]).to containing_exactly(
53
+ hash_including(
54
+ message: "Redirect to '#{redirect}' not allowed.",
55
+ extensions: { code: 'USER_ERROR' }
56
+ )
57
+ )
58
+ end
59
+ end
26
60
 
27
- before do
28
- user.send_confirmation_instructions(
29
- template_path: ['graphql_devise/mailer'],
30
- controller: 'graphql_devise/graphql',
31
- schema_url: 'http://not-using-this-value.com/gql'
32
- )
61
+ context 'when unconfirmed_email is present' do
62
+ let(:user) { create(:user, :confirmed, unconfirmed_email: 'vvega@wallaceinc.com') }
63
+
64
+ it 'confirms the unconfirmed email and redirects' do
65
+ expect do
66
+ get_request
67
+ user.reload
68
+ end.to change(user, :email).from(user.email).to('vvega@wallaceinc.com').and(
69
+ change(user, :unconfirmed_email).from('vvega@wallaceinc.com').to(nil)
70
+ )
71
+
72
+ expect(response).to redirect_to("#{redirect}?account_confirmation_success=true")
73
+ end
74
+ end
33
75
  end
34
76
 
35
- it 'confirms the resource and redirects to the sent url' do
36
- expect do
37
- get_request
38
- user.reload
39
- end.to(change(user, :confirmed_at).from(nil))
77
+ context 'when reset password token is not found' do
78
+ let(:token) { "#{user.confirmation_token}-invalid" }
79
+
80
+ it 'does *NOT* confirm the user nor does the redirection' do
81
+ expect do
82
+ get_request
83
+ user.reload
84
+ end.not_to(change(user, :confirmed_at).from(nil))
40
85
 
41
- expect(response).to redirect_to "#{redirect}?account_confirmation_success=true"
42
- expect(user).to be_active_for_authentication
86
+ expect(response).not_to be_redirect
87
+ expect(json_response[:errors]).to contain_exactly(
88
+ hash_including(
89
+ message: 'Invalid confirmation token. Please try again',
90
+ extensions: { code: 'USER_ERROR' }
91
+ )
92
+ )
93
+ end
43
94
  end
44
95
  end
45
96
 
46
- context 'when reset password token is not found' do
47
- let(:token) { "#{user.confirmation_token}-invalid" }
97
+ context 'when using the admin model' do
98
+ let(:admin) { create(:admin, confirmed_at: nil) }
99
+ let(:redirect) { 'https://google.com' }
100
+ let(:query) do
101
+ <<-GRAPHQL
102
+ {
103
+ adminConfirmAccount(
104
+ confirmationToken: "#{token}"
105
+ redirectUrl: "#{redirect}"
106
+ ) {
107
+ email
108
+ }
109
+ }
110
+ GRAPHQL
111
+ end
112
+
113
+ context 'when confirmation token is correct' do
114
+ let(:token) { admin.confirmation_token }
48
115
 
49
- it 'does *NOT* confirm the user nor does the redirection' do
50
- expect do
51
- get_request
52
- user.reload
53
- end.not_to(change(user, :confirmed_at).from(nil))
116
+ before do
117
+ admin.send_confirmation_instructions(
118
+ template_path: ['graphql_devise/mailer'],
119
+ controller: 'graphql_devise/graphql',
120
+ schema_url: 'http://not-using-this-value.com/gql'
121
+ )
122
+ end
54
123
 
55
- expect(response).not_to be_redirect
56
- expect(json_response[:errors]).to contain_exactly(
57
- hash_including(
58
- message: 'Invalid confirmation token. Please try again',
59
- extensions: { code: 'USER_ERROR' }
124
+ it 'confirms the resource, persists credentials on the DB and redirects to the sent url' do
125
+ expect do
126
+ get_request
127
+ admin.reload
128
+ end.to change(admin, :confirmed_at).from(nil).and(
129
+ change { admin.tokens.keys.count }.from(0).to(1)
60
130
  )
61
- )
131
+
132
+ expect(response).to redirect_to(/\A#{redirect}.+access\-token=/)
133
+ expect(admin).to be_active_for_authentication
134
+ end
62
135
  end
63
136
  end
64
137
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: graphql_devise
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.2
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mario Celi
8
8
  - David Revelo
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2020-08-12 00:00:00.000000000 Z
12
+ date: 2021-01-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: devise_token_auth
@@ -338,8 +338,10 @@ files:
338
338
  - lib/graphql_devise/mutations/logout.rb
339
339
  - lib/graphql_devise/mutations/resend_confirmation.rb
340
340
  - lib/graphql_devise/mutations/send_password_reset.rb
341
+ - lib/graphql_devise/mutations/send_password_reset_with_token.rb
341
342
  - lib/graphql_devise/mutations/sign_up.rb
342
343
  - lib/graphql_devise/mutations/update_password.rb
344
+ - lib/graphql_devise/mutations/update_password_with_token.rb
343
345
  - lib/graphql_devise/rails/routes.rb
344
346
  - lib/graphql_devise/resolvers/base.rb
345
347
  - lib/graphql_devise/resolvers/check_password_token.rb
@@ -362,10 +364,13 @@ files:
362
364
  - spec/dummy/app/graphql/interpreter_schema.rb
363
365
  - spec/dummy/app/graphql/mutations/login.rb
364
366
  - spec/dummy/app/graphql/mutations/register_confirmed_user.rb
367
+ - spec/dummy/app/graphql/mutations/reset_admin_password_with_token.rb
365
368
  - spec/dummy/app/graphql/mutations/sign_up.rb
366
369
  - spec/dummy/app/graphql/mutations/update_user.rb
370
+ - spec/dummy/app/graphql/resolvers/confirm_admin_account.rb
367
371
  - spec/dummy/app/graphql/resolvers/public_user.rb
368
372
  - spec/dummy/app/graphql/resolvers/user_show.rb
373
+ - spec/dummy/app/graphql/types/admin_type.rb
369
374
  - spec/dummy/app/graphql/types/base_object.rb
370
375
  - spec/dummy/app/graphql/types/custom_admin_type.rb
371
376
  - spec/dummy/app/graphql/types/mutation_type.rb
@@ -437,8 +442,10 @@ files:
437
442
  - spec/requests/mutations/logout_spec.rb
438
443
  - spec/requests/mutations/resend_confirmation_spec.rb
439
444
  - spec/requests/mutations/send_password_reset_spec.rb
445
+ - spec/requests/mutations/send_password_reset_with_token_spec.rb
440
446
  - spec/requests/mutations/sign_up_spec.rb
441
447
  - spec/requests/mutations/update_password_spec.rb
448
+ - spec/requests/mutations/update_password_with_token_spec.rb
442
449
  - spec/requests/queries/check_password_token_spec.rb
443
450
  - spec/requests/queries/confirm_account_spec.rb
444
451
  - spec/requests/user_controller_spec.rb
@@ -474,7 +481,7 @@ licenses:
474
481
  metadata:
475
482
  homepage_uri: https://github.com/graphql-devise/graphql_devise
476
483
  source_code_uri: https://github.com/graphql-devise/graphql_devise
477
- post_install_message:
484
+ post_install_message:
478
485
  rdoc_options: []
479
486
  require_paths:
480
487
  - lib
@@ -489,8 +496,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
489
496
  - !ruby/object:Gem::Version
490
497
  version: '0'
491
498
  requirements: []
492
- rubygems_version: 3.1.4
493
- signing_key:
499
+ rubygems_version: 3.0.8
500
+ signing_key:
494
501
  specification_version: 4
495
502
  summary: GraphQL queries and mutations on top of devise_token_auth
496
503
  test_files:
@@ -503,10 +510,13 @@ test_files:
503
510
  - spec/dummy/app/graphql/interpreter_schema.rb
504
511
  - spec/dummy/app/graphql/mutations/login.rb
505
512
  - spec/dummy/app/graphql/mutations/register_confirmed_user.rb
513
+ - spec/dummy/app/graphql/mutations/reset_admin_password_with_token.rb
506
514
  - spec/dummy/app/graphql/mutations/sign_up.rb
507
515
  - spec/dummy/app/graphql/mutations/update_user.rb
516
+ - spec/dummy/app/graphql/resolvers/confirm_admin_account.rb
508
517
  - spec/dummy/app/graphql/resolvers/public_user.rb
509
518
  - spec/dummy/app/graphql/resolvers/user_show.rb
519
+ - spec/dummy/app/graphql/types/admin_type.rb
510
520
  - spec/dummy/app/graphql/types/base_object.rb
511
521
  - spec/dummy/app/graphql/types/custom_admin_type.rb
512
522
  - spec/dummy/app/graphql/types/mutation_type.rb
@@ -578,8 +588,10 @@ test_files:
578
588
  - spec/requests/mutations/logout_spec.rb
579
589
  - spec/requests/mutations/resend_confirmation_spec.rb
580
590
  - spec/requests/mutations/send_password_reset_spec.rb
591
+ - spec/requests/mutations/send_password_reset_with_token_spec.rb
581
592
  - spec/requests/mutations/sign_up_spec.rb
582
593
  - spec/requests/mutations/update_password_spec.rb
594
+ - spec/requests/mutations/update_password_with_token_spec.rb
583
595
  - spec/requests/queries/check_password_token_spec.rb
584
596
  - spec/requests/queries/confirm_account_spec.rb
585
597
  - spec/requests/user_controller_spec.rb