graphql_devise 0.13.1 → 0.13.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 543ed51aaeb46699f17efb47cb13909ebfcd98ee0b97d27207fa0423199d72d2
4
- data.tar.gz: 393496018363cadce3251a7ac4b3b9b0c74f8830fd72414fd97d47453406df2a
3
+ metadata.gz: e90de970ae686dd8437156a6d830b922c1fe4369c10206532073e5bb3f8f75f8
4
+ data.tar.gz: 3a74fe59c81889eb9f5a4bb42710d4cb7e086b9a9bdbd0e9bd09a370ccd7f435
5
5
  SHA512:
6
- metadata.gz: c085a18386d7d2ae725140a1c4a089cebcae117485395145dbc24106fc28a97a6d35b895bb3ae990243c936ed3253467d0a471b85bda3180844421ea85f3a3a0
7
- data.tar.gz: c8a271975c6306edbac33bacace9c00db6286eb988f015cec36007be0d860f6f92b3b9b8c65d5d7b4f5d2f524c8a306815b7a9b56141b759ef53ccfbc8c9d526
6
+ metadata.gz: 0f608b88cf17acc4e8c4d7d54fb4d578afb38d2c7f7a73b9df2cee7b9661cdb6a35b1b45e4a6d7c05e022a334f6c7ed8bf1427b301422c2e27f191a830dde621
7
+ data.tar.gz: 5d5bc1eab5158c5134f18a7f2f85e0653139ee13d67c45efb7050274d41ed6f1a5c2dee0c97c57ca987bd7f74556cbca9ae478b7782aee28f5967308d7bd3c92
@@ -1,5 +1,46 @@
1
1
  # Changelog
2
2
 
3
+ ## [v0.13.6](https://github.com/graphql-devise/graphql_devise/tree/v0.13.6) (2020-12-22)
4
+
5
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.5...v0.13.6)
6
+
7
+ **Security fixes:**
8
+
9
+ - Possible security issue with password reset and redirectUrl [\#136](https://github.com/graphql-devise/graphql_devise/issues/136)
10
+ - Add redirect whitelist validation to all queries and mutations [\#140](https://github.com/graphql-devise/graphql_devise/pull/140) ([mcelicalderon](https://github.com/mcelicalderon))
11
+
12
+ ## [v0.13.5](https://github.com/graphql-devise/graphql_devise/tree/v0.13.5) (2020-11-20)
13
+
14
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.4...v0.13.5)
15
+
16
+ **Implemented enhancements:**
17
+
18
+ - Fixes connection\_config deprecation warning [\#135](https://github.com/graphql-devise/graphql_devise/pull/135) ([artplan1](https://github.com/artplan1))
19
+
20
+ ## [v0.13.4](https://github.com/graphql-devise/graphql_devise/tree/v0.13.4) (2020-08-15)
21
+
22
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.3...v0.13.4)
23
+
24
+ **Implemented enhancements:**
25
+
26
+ - Allow resend of confirmation with unconfirmed email [\#127](https://github.com/graphql-devise/graphql_devise/pull/127) ([j15e](https://github.com/j15e))
27
+
28
+ ## [v0.13.3](https://github.com/graphql-devise/graphql_devise/tree/v0.13.3) (2020-08-13)
29
+
30
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.2...v0.13.3)
31
+
32
+ **Fixed bugs:**
33
+
34
+ - Fix unconfirmed\_email confirmation. Ignore devise reconfirmable config. [\#126](https://github.com/graphql-devise/graphql_devise/pull/126) ([mcelicalderon](https://github.com/mcelicalderon))
35
+
36
+ ## [v0.13.2](https://github.com/graphql-devise/graphql_devise/tree/v0.13.2) (2020-08-12)
37
+
38
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.1...v0.13.2)
39
+
40
+ **Fixed bugs:**
41
+
42
+ - Save resource after generating credentials in resource confirmation [\#125](https://github.com/graphql-devise/graphql_devise/pull/125) ([mcelicalderon](https://github.com/mcelicalderon))
43
+
3
44
  ## [v0.13.1](https://github.com/graphql-devise/graphql_devise/tree/v0.13.1) (2020-07-29)
4
45
 
5
46
  [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.0...v0.13.1)
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
@@ -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,7 +8,6 @@ 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
12
  update_password_error: "Unable to update user password"
13
13
  missing_passwords: "You must fill out the fields labeled 'Password' and 'Password confirmation'."
@@ -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')
@@ -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
@@ -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
 
@@ -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?
@@ -15,13 +17,16 @@ module GraphqlDevise
15
17
  redirect_header_options = { account_confirmation_success: true }
16
18
 
17
19
  redirect_to_link = if controller.signed_in?(resource_name)
18
- resource.build_auth_url(
20
+ url = resource.build_auth_url(
19
21
  redirect_url,
20
22
  redirect_headers(
21
23
  client_and_token(resource.create_token),
22
24
  redirect_header_options
23
25
  )
24
26
  )
27
+ resource.save!
28
+
29
+ url
25
30
  else
26
31
  DeviseTokenAuth::Url.generate(redirect_url, redirect_header_options)
27
32
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GraphqlDevise
4
- VERSION = '0.13.1'.freeze
4
+ VERSION = '0.13.6'.freeze
5
5
  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,9 @@ 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
+ },
17
20
  at: '/api/v1/admin/graphql_auth'
18
21
  )
19
22
 
@@ -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
@@ -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(
@@ -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
@@ -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.1
4
+ version: 0.13.6
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-07-30 00:00:00.000000000 Z
12
+ date: 2020-12-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: devise_token_auth
@@ -364,8 +364,10 @@ files:
364
364
  - spec/dummy/app/graphql/mutations/register_confirmed_user.rb
365
365
  - spec/dummy/app/graphql/mutations/sign_up.rb
366
366
  - spec/dummy/app/graphql/mutations/update_user.rb
367
+ - spec/dummy/app/graphql/resolvers/confirm_admin_account.rb
367
368
  - spec/dummy/app/graphql/resolvers/public_user.rb
368
369
  - spec/dummy/app/graphql/resolvers/user_show.rb
370
+ - spec/dummy/app/graphql/types/admin_type.rb
369
371
  - spec/dummy/app/graphql/types/base_object.rb
370
372
  - spec/dummy/app/graphql/types/custom_admin_type.rb
371
373
  - spec/dummy/app/graphql/types/mutation_type.rb
@@ -474,7 +476,7 @@ licenses:
474
476
  metadata:
475
477
  homepage_uri: https://github.com/graphql-devise/graphql_devise
476
478
  source_code_uri: https://github.com/graphql-devise/graphql_devise
477
- post_install_message:
479
+ post_install_message:
478
480
  rdoc_options: []
479
481
  require_paths:
480
482
  - lib
@@ -489,8 +491,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
489
491
  - !ruby/object:Gem::Version
490
492
  version: '0'
491
493
  requirements: []
492
- rubygems_version: 3.1.4
493
- signing_key:
494
+ rubygems_version: 3.0.8
495
+ signing_key:
494
496
  specification_version: 4
495
497
  summary: GraphQL queries and mutations on top of devise_token_auth
496
498
  test_files:
@@ -505,8 +507,10 @@ test_files:
505
507
  - spec/dummy/app/graphql/mutations/register_confirmed_user.rb
506
508
  - spec/dummy/app/graphql/mutations/sign_up.rb
507
509
  - spec/dummy/app/graphql/mutations/update_user.rb
510
+ - spec/dummy/app/graphql/resolvers/confirm_admin_account.rb
508
511
  - spec/dummy/app/graphql/resolvers/public_user.rb
509
512
  - spec/dummy/app/graphql/resolvers/user_show.rb
513
+ - spec/dummy/app/graphql/types/admin_type.rb
510
514
  - spec/dummy/app/graphql/types/base_object.rb
511
515
  - spec/dummy/app/graphql/types/custom_admin_type.rb
512
516
  - spec/dummy/app/graphql/types/mutation_type.rb