graphql_devise 0.18.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +7 -2
- data/.gitignore +3 -0
- data/.rubocop.yml +9 -10
- data/Appraisals +70 -18
- data/CHANGELOG.md +53 -0
- data/README.md +71 -142
- data/app/controllers/graphql_devise/graphql_controller.rb +3 -3
- data/app/views/graphql_devise/mailer/confirmation_instructions.html.erb +1 -5
- data/config/routes.rb +0 -2
- data/graphql_devise.gemspec +7 -5
- data/lib/graphql_devise/concerns/additional_controller_methods.rb +48 -0
- data/lib/graphql_devise/concerns/additional_model_methods.rb +17 -0
- data/lib/graphql_devise/concerns/authenticatable.rb +1 -1
- data/lib/graphql_devise/concerns/controller_methods.rb +70 -93
- data/lib/graphql_devise/concerns/field_authentication.rb +14 -0
- data/lib/graphql_devise/concerns/set_user_by_token.rb +1 -1
- data/lib/graphql_devise/default_operations.rb +16 -0
- data/lib/graphql_devise/engine.rb +0 -2
- data/lib/graphql_devise/model/with_email_updater.rb +5 -30
- data/lib/graphql_devise/mount_method/operation_preparer.rb +0 -7
- data/lib/graphql_devise/mount_method/operation_preparers/custom_operation_preparer.rb +1 -1
- data/lib/graphql_devise/mount_method/operation_preparers/default_operation_preparer.rb +1 -1
- data/lib/graphql_devise/mount_method/operation_sanitizer.rb +0 -12
- data/lib/graphql_devise/mount_method/option_sanitizer.rb +0 -2
- data/lib/graphql_devise/mount_method/option_sanitizers/array_checker.rb +2 -2
- data/lib/graphql_devise/mount_method/option_sanitizers/class_checker.rb +2 -2
- data/lib/graphql_devise/mount_method/option_sanitizers/hash_checker.rb +1 -1
- data/lib/graphql_devise/mount_method/option_sanitizers/string_checker.rb +1 -1
- data/lib/graphql_devise/mount_method/option_validators/provided_operations_validator.rb +0 -2
- data/lib/graphql_devise/mount_method/option_validators/skip_only_validator.rb +1 -1
- data/lib/graphql_devise/mount_method/option_validators/supported_operations_validator.rb +1 -1
- data/lib/graphql_devise/mount_method/options_validator.rb +0 -3
- data/lib/graphql_devise/mount_method/supported_options.rb +0 -5
- data/lib/graphql_devise/mutations/base.rb +1 -1
- data/lib/graphql_devise/mutations/confirm_registration_with_token.rb +1 -1
- data/lib/graphql_devise/mutations/login.rb +1 -1
- data/lib/graphql_devise/mutations/register.rb +1 -1
- data/lib/graphql_devise/mutations/update_password_with_token.rb +1 -1
- data/lib/graphql_devise/resolvers/base.rb +1 -1
- data/lib/graphql_devise/resource_loader.rb +71 -39
- data/lib/graphql_devise/route_mounter.rb +13 -0
- data/lib/graphql_devise/schema_plugin.rb +7 -40
- data/lib/graphql_devise/types/authenticatable_type.rb +1 -1
- data/lib/graphql_devise/types/base_field.rb +9 -0
- data/lib/graphql_devise/types/base_type.rb +8 -0
- data/lib/graphql_devise/types/credential_type.rb +1 -1
- data/lib/graphql_devise/types/mutation_type.rb +1 -0
- data/lib/graphql_devise/types/query_type.rb +1 -0
- data/lib/graphql_devise/version.rb +1 -1
- data/lib/graphql_devise.rb +21 -29
- data/spec/dummy/app/controllers/api/v1/graphql_controller.rb +1 -16
- data/spec/dummy/app/graphql/dummy_schema.rb +1 -5
- data/spec/dummy/app/graphql/interpreter_schema.rb +6 -2
- data/spec/dummy/app/graphql/mutations/base_mutation.rb +6 -0
- data/spec/dummy/app/graphql/mutations/update_user.rb +2 -4
- data/spec/dummy/app/graphql/types/admin_type.rb +1 -1
- data/spec/dummy/app/graphql/types/custom_admin_type.rb +1 -1
- data/spec/dummy/app/graphql/types/mutation_type.rb +3 -1
- data/spec/dummy/app/graphql/types/query_type.rb +3 -1
- data/spec/dummy/app/graphql/types/user_type.rb +1 -1
- data/spec/dummy/config/environments/test.rb +1 -1
- data/spec/dummy/config/routes.rb +5 -9
- data/spec/graphql_devise/model/with_email_updater_spec.rb +17 -35
- data/spec/rails_helper.rb +5 -5
- data/spec/requests/mutations/resend_confirmation_with_token_spec.rb +2 -3
- data/spec/requests/user_controller_spec.rb +1 -33
- data/spec/services/resource_loader_spec.rb +14 -3
- metadata +55 -48
- data/app/controllers/graphql_devise/concerns/additional_controller_methods.rb +0 -72
- data/app/controllers/graphql_devise/concerns/set_user_by_token.rb +0 -21
- data/app/helpers/graphql_devise/mailer_helper.rb +0 -37
- data/app/models/graphql_devise/concerns/additional_model_methods.rb +0 -21
- data/app/models/graphql_devise/concerns/model.rb +0 -25
- data/lib/graphql_devise/default_operations/mutations.rb +0 -32
- data/lib/graphql_devise/default_operations/resolvers.rb +0 -14
- data/lib/graphql_devise/mutations/resend_confirmation.rb +0 -45
- data/lib/graphql_devise/mutations/send_password_reset.rb +0 -38
- data/lib/graphql_devise/mutations/sign_up.rb +0 -61
- data/lib/graphql_devise/mutations/update_password.rb +0 -46
- data/lib/graphql_devise/rails/routes.rb +0 -15
- data/lib/graphql_devise/resolvers/check_password_token.rb +0 -43
- data/lib/graphql_devise/resolvers/confirm_account.rb +0 -42
- data/spec/dummy/app/graphql/mutations/sign_up.rb +0 -14
- data/spec/dummy/app/graphql/resolvers/confirm_admin_account.rb +0 -13
- data/spec/requests/mutations/resend_confirmation_spec.rb +0 -153
- data/spec/requests/mutations/send_password_reset_spec.rb +0 -103
- data/spec/requests/mutations/sign_up_spec.rb +0 -170
- data/spec/requests/mutations/update_password_spec.rb +0 -116
- data/spec/requests/queries/check_password_token_spec.rb +0 -149
- data/spec/requests/queries/confirm_account_spec.rb +0 -137
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module ActionDispatch::Routing
|
4
|
-
class Mapper
|
5
|
-
def mount_graphql_devise_for(resource, options = {})
|
6
|
-
clean_options = GraphqlDevise::ResourceLoader.new(resource, options, true).call(
|
7
|
-
GraphqlDevise::Types::QueryType,
|
8
|
-
GraphqlDevise::Types::MutationType
|
9
|
-
)
|
10
|
-
|
11
|
-
post clean_options.at, to: 'graphql_devise/graphql#auth'
|
12
|
-
get clean_options.at, to: 'graphql_devise/graphql#auth'
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module GraphqlDevise
|
4
|
-
module Resolvers
|
5
|
-
class CheckPasswordToken < Base
|
6
|
-
argument :reset_password_token, String, required: true
|
7
|
-
argument :redirect_url, String, required: false
|
8
|
-
|
9
|
-
def resolve(reset_password_token:, redirect_url: nil)
|
10
|
-
resource = resource_class.with_reset_password_token(reset_password_token)
|
11
|
-
raise_user_error(I18n.t('graphql_devise.passwords.reset_token_not_found')) if resource.blank?
|
12
|
-
|
13
|
-
if resource.reset_password_period_valid?
|
14
|
-
token_info = client_and_token(resource.create_token)
|
15
|
-
|
16
|
-
resource.skip_confirmation! if confirmable_enabled? && !resource.confirmed_at
|
17
|
-
resource.allow_password_change = true if recoverable_enabled?
|
18
|
-
|
19
|
-
resource.save!
|
20
|
-
|
21
|
-
yield resource if block_given?
|
22
|
-
|
23
|
-
redirect_header_options = { reset_password: true }
|
24
|
-
built_redirect_headers = redirect_headers(
|
25
|
-
token_info,
|
26
|
-
redirect_header_options
|
27
|
-
)
|
28
|
-
|
29
|
-
if redirect_url.present?
|
30
|
-
check_redirect_url_whitelist!(redirect_url)
|
31
|
-
controller.redirect_to(resource.build_auth_url(redirect_url, built_redirect_headers))
|
32
|
-
else
|
33
|
-
set_auth_headers(resource)
|
34
|
-
end
|
35
|
-
|
36
|
-
resource
|
37
|
-
else
|
38
|
-
raise_user_error(I18n.t('graphql_devise.passwords.reset_token_expired'))
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module GraphqlDevise
|
4
|
-
module Resolvers
|
5
|
-
class ConfirmAccount < Base
|
6
|
-
argument :confirmation_token, String, required: true
|
7
|
-
argument :redirect_url, String, required: true
|
8
|
-
|
9
|
-
def resolve(confirmation_token:, redirect_url:)
|
10
|
-
check_redirect_url_whitelist!(redirect_url)
|
11
|
-
|
12
|
-
resource = resource_class.confirm_by_token(confirmation_token)
|
13
|
-
|
14
|
-
if resource.errors.empty?
|
15
|
-
yield resource if block_given?
|
16
|
-
|
17
|
-
redirect_header_options = { account_confirmation_success: true }
|
18
|
-
|
19
|
-
redirect_to_link = if controller.signed_in?(resource_name)
|
20
|
-
url = resource.build_auth_url(
|
21
|
-
redirect_url,
|
22
|
-
redirect_headers(
|
23
|
-
client_and_token(resource.create_token),
|
24
|
-
redirect_header_options
|
25
|
-
)
|
26
|
-
)
|
27
|
-
resource.save!
|
28
|
-
|
29
|
-
url
|
30
|
-
else
|
31
|
-
DeviseTokenAuth::Url.generate(redirect_url, redirect_header_options)
|
32
|
-
end
|
33
|
-
|
34
|
-
controller.redirect_to(redirect_to_link)
|
35
|
-
resource
|
36
|
-
else
|
37
|
-
raise_user_error(I18n.t('graphql_devise.confirmations.invalid_token'))
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mutations
|
4
|
-
class SignUp < GraphqlDevise::Mutations::SignUp
|
5
|
-
argument :name, String, required: false
|
6
|
-
|
7
|
-
field :user, Types::UserType, null: true
|
8
|
-
|
9
|
-
def resolve(email:, **attrs)
|
10
|
-
original_payload = super
|
11
|
-
original_payload.merge(user: original_payload[:authenticatable])
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,13 +0,0 @@
|
|
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
|
@@ -1,153 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'rails_helper'
|
4
|
-
|
5
|
-
RSpec.describe 'Resend confirmation' do
|
6
|
-
include_context 'with graphql query request'
|
7
|
-
|
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' }
|
13
|
-
let(:query) do
|
14
|
-
<<-GRAPHQL
|
15
|
-
mutation {
|
16
|
-
userResendConfirmation(
|
17
|
-
email:"#{email}",
|
18
|
-
redirectUrl:"#{redirect}"
|
19
|
-
) {
|
20
|
-
message
|
21
|
-
}
|
22
|
-
}
|
23
|
-
GRAPHQL
|
24
|
-
end
|
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
|
-
|
41
|
-
context 'when params are correct' do
|
42
|
-
context 'when using the gem schema' do
|
43
|
-
it 'sends an email to the user with confirmation url and returns a success message' do
|
44
|
-
expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
|
45
|
-
expect(json_response[:data][:userResendConfirmation]).to include(
|
46
|
-
message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
|
47
|
-
)
|
48
|
-
|
49
|
-
email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
|
50
|
-
link = email.css('a').first
|
51
|
-
confirm_link_msg_text = email.css('p')[1].inner_html
|
52
|
-
confirm_account_link_text = link.inner_html
|
53
|
-
|
54
|
-
expect(link['href']).to include('/api/v1/graphql_auth?')
|
55
|
-
expect(confirm_link_msg_text).to eq('You can confirm your account email through the link below:')
|
56
|
-
expect(confirm_account_link_text).to eq('Confirm my account')
|
57
|
-
|
58
|
-
expect do
|
59
|
-
get link['href']
|
60
|
-
user.reload
|
61
|
-
end.to change(user, :confirmed_at).from(NilClass).to(ActiveSupport::TimeWithZone)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
context 'when using a custom schema' do
|
66
|
-
let(:custom_path) { '/api/v1/graphql' }
|
67
|
-
|
68
|
-
it 'sends an email to the user with confirmation url and returns a success message' do
|
69
|
-
expect { post_request(custom_path) }.to change(ActionMailer::Base.deliveries, :count).by(1)
|
70
|
-
expect(json_response[:data][:userResendConfirmation]).to include(
|
71
|
-
message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
|
72
|
-
)
|
73
|
-
|
74
|
-
email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
|
75
|
-
link = email.css('a').first
|
76
|
-
confirm_link_msg_text = email.css('p')[1].inner_html
|
77
|
-
confirm_account_link_text = link.inner_html
|
78
|
-
|
79
|
-
expect(link['href']).to include("#{custom_path}?")
|
80
|
-
expect(confirm_link_msg_text).to eq('You can confirm your account email through the link below:')
|
81
|
-
expect(confirm_account_link_text).to eq('Confirm my account')
|
82
|
-
|
83
|
-
expect do
|
84
|
-
get link['href']
|
85
|
-
user.reload
|
86
|
-
end.to change(user, :confirmed_at).from(NilClass).to(ActiveSupport::TimeWithZone)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
context 'when email address uses different casing' do
|
91
|
-
let(:email) { 'mWallace@wallaceinc.com' }
|
92
|
-
|
93
|
-
it 'honors devise configuration for case insensitive fields' do
|
94
|
-
expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
|
95
|
-
expect(json_response[:data][:userResendConfirmation]).to include(
|
96
|
-
message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
|
97
|
-
)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
context 'when the user has already been confirmed' do
|
102
|
-
before { user.confirm }
|
103
|
-
|
104
|
-
it 'does *NOT* send an email and raises an error' do
|
105
|
-
expect { post_request }.to not_change(ActionMailer::Base.deliveries, :count)
|
106
|
-
expect(json_response[:data][:userResendConfirmation]).to be_nil
|
107
|
-
expect(json_response[:errors]).to contain_exactly(
|
108
|
-
hash_including(
|
109
|
-
message: 'Email was already confirmed, please try signing in',
|
110
|
-
extensions: { code: 'USER_ERROR' }
|
111
|
-
)
|
112
|
-
)
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
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
|
-
|
139
|
-
context "when the email isn't in the system" do
|
140
|
-
let(:email) { 'nothere@gmail.com' }
|
141
|
-
|
142
|
-
it 'does *NOT* send an email and raises an error' do
|
143
|
-
expect { post_request }.to not_change(ActionMailer::Base.deliveries, :count)
|
144
|
-
expect(json_response[:data][:userResendConfirmation]).to be_nil
|
145
|
-
expect(json_response[:errors]).to contain_exactly(
|
146
|
-
hash_including(
|
147
|
-
message: "Unable to find user with email '#{email}'.",
|
148
|
-
extensions: { code: 'USER_ERROR' }
|
149
|
-
)
|
150
|
-
)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
@@ -1,103 +0,0 @@
|
|
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
|
-
userSendPasswordReset(
|
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][:userSendPasswordReset]).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
|
-
expect(link['href']).to include('/api/v1/graphql_auth?')
|
51
|
-
|
52
|
-
expect do
|
53
|
-
get link['href']
|
54
|
-
user.reload
|
55
|
-
end.to change(user, :allow_password_change).from(false).to(true)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
context 'when using a custom schema' do
|
60
|
-
let(:custom_path) { '/api/v1/graphql' }
|
61
|
-
|
62
|
-
it 'sends password reset email' do
|
63
|
-
expect { post_request(custom_path) }.to change(ActionMailer::Base.deliveries, :count).by(1)
|
64
|
-
|
65
|
-
expect(json_response[:data][:userSendPasswordReset]).to include(
|
66
|
-
message: 'You will receive an email with instructions on how to reset your password in a few minutes.'
|
67
|
-
)
|
68
|
-
|
69
|
-
email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
|
70
|
-
link = email.css('a').first
|
71
|
-
expect(link['href']).to include("#{custom_path}?")
|
72
|
-
|
73
|
-
expect do
|
74
|
-
get link['href']
|
75
|
-
user.reload
|
76
|
-
end.to change(user, :allow_password_change).from(false).to(true)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
context 'when email address uses different casing' do
|
82
|
-
let(:email) { 'jWinnfield@wallaceinc.com' }
|
83
|
-
|
84
|
-
it 'honors devise configuration for case insensitive fields' do
|
85
|
-
expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
|
86
|
-
expect(json_response[:data][:userSendPasswordReset]).to include(
|
87
|
-
message: 'You will receive an email with instructions on how to reset your password in a few minutes.'
|
88
|
-
)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
context 'when user email is not found' do
|
93
|
-
let(:email) { 'nothere@gmail.com' }
|
94
|
-
|
95
|
-
before { post_request }
|
96
|
-
|
97
|
-
it 'returns an error' do
|
98
|
-
expect(json_response[:errors]).to contain_exactly(
|
99
|
-
hash_including(message: 'User was not found or was not logged in.', extensions: { code: 'USER_ERROR' })
|
100
|
-
)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
@@ -1,170 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'rails_helper'
|
4
|
-
|
5
|
-
RSpec.describe 'Sign Up process' do
|
6
|
-
include_context 'with graphql query request'
|
7
|
-
|
8
|
-
let(:name) { Faker::Name.name }
|
9
|
-
let(:password) { Faker::Internet.password }
|
10
|
-
let(:email) { Faker::Internet.email }
|
11
|
-
let(:redirect) { 'https://google.com' }
|
12
|
-
|
13
|
-
context 'when using the user model' do
|
14
|
-
let(:query) do
|
15
|
-
<<-GRAPHQL
|
16
|
-
mutation {
|
17
|
-
userSignUp(
|
18
|
-
email: "#{email}"
|
19
|
-
name: "#{name}"
|
20
|
-
password: "#{password}"
|
21
|
-
passwordConfirmation: "#{password}"
|
22
|
-
confirmSuccessUrl: "#{redirect}"
|
23
|
-
) {
|
24
|
-
credentials { accessToken }
|
25
|
-
user {
|
26
|
-
email
|
27
|
-
name
|
28
|
-
}
|
29
|
-
}
|
30
|
-
}
|
31
|
-
GRAPHQL
|
32
|
-
end
|
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
|
-
|
52
|
-
context 'when params are correct' do
|
53
|
-
it 'creates a new resource that requires confirmation' do
|
54
|
-
expect { post_request }.to(
|
55
|
-
change(User, :count).by(1)
|
56
|
-
.and(change(ActionMailer::Base.deliveries, :count).by(1))
|
57
|
-
)
|
58
|
-
|
59
|
-
user = User.last
|
60
|
-
|
61
|
-
expect(user).not_to be_active_for_authentication
|
62
|
-
expect(user.confirmed_at).to be_nil
|
63
|
-
expect(user).to be_valid_password(password)
|
64
|
-
expect(json_response[:data][:userSignUp]).to include(
|
65
|
-
credentials: nil,
|
66
|
-
user: {
|
67
|
-
email: email,
|
68
|
-
name: name
|
69
|
-
}
|
70
|
-
)
|
71
|
-
|
72
|
-
email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
|
73
|
-
link = email.css('a').first
|
74
|
-
|
75
|
-
expect do
|
76
|
-
get link['href']
|
77
|
-
user.reload
|
78
|
-
end.to change { user.active_for_authentication? }.to(true)
|
79
|
-
end
|
80
|
-
|
81
|
-
context 'when email address uses different casing' do
|
82
|
-
let(:email) { 'miaWallace@wallaceinc.com' }
|
83
|
-
|
84
|
-
it 'honors devise configuration for case insensitive fields' do
|
85
|
-
expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
|
86
|
-
expect(User.last.email).to eq('miawallace@wallaceinc.com')
|
87
|
-
expect(json_response[:data][:userSignUp]).to include(user: { email: 'miawallace@wallaceinc.com', name: name })
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
context 'when required params are missing' do
|
93
|
-
let(:email) { '' }
|
94
|
-
|
95
|
-
it 'does *NOT* create resource a resource nor send an email' do
|
96
|
-
expect { post_request }.to(
|
97
|
-
not_change(User, :count)
|
98
|
-
.and(not_change(ActionMailer::Base.deliveries, :count))
|
99
|
-
)
|
100
|
-
|
101
|
-
expect(json_response[:data][:userSignUp]).to be_nil
|
102
|
-
expect(json_response[:errors]).to containing_exactly(
|
103
|
-
hash_including(
|
104
|
-
message: "User couldn't be registered",
|
105
|
-
extensions: { code: 'USER_ERROR', detailed_errors: ["Email can't be blank"] }
|
106
|
-
)
|
107
|
-
)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
context 'when using the admin model' do
|
113
|
-
let(:query) do
|
114
|
-
<<-GRAPHQL
|
115
|
-
mutation {
|
116
|
-
adminSignUp(
|
117
|
-
email: "#{email}"
|
118
|
-
password: "#{password}"
|
119
|
-
passwordConfirmation: "#{password}"
|
120
|
-
confirmSuccessUrl: "#{redirect}"
|
121
|
-
) {
|
122
|
-
authenticatable {
|
123
|
-
email
|
124
|
-
}
|
125
|
-
}
|
126
|
-
}
|
127
|
-
GRAPHQL
|
128
|
-
end
|
129
|
-
|
130
|
-
before { post_request }
|
131
|
-
|
132
|
-
it 'skips the sign up mutation' do
|
133
|
-
expect(json_response[:errors]).to contain_exactly(
|
134
|
-
hash_including(message: "Field 'adminSignUp' doesn't exist on type 'Mutation'")
|
135
|
-
)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
context 'when using the guest model' do
|
140
|
-
let(:query) do
|
141
|
-
<<-GRAPHQL
|
142
|
-
mutation {
|
143
|
-
guestSignUp(
|
144
|
-
email: "#{email}"
|
145
|
-
password: "#{password}"
|
146
|
-
passwordConfirmation: "#{password}"
|
147
|
-
confirmSuccessUrl: "#{redirect}"
|
148
|
-
) {
|
149
|
-
credentials { accessToken client uid }
|
150
|
-
authenticatable {
|
151
|
-
email
|
152
|
-
}
|
153
|
-
}
|
154
|
-
}
|
155
|
-
GRAPHQL
|
156
|
-
end
|
157
|
-
|
158
|
-
it 'returns credentials as no confirmation is required' do
|
159
|
-
expect { post_request }.to change(Guest, :count).from(0).to(1)
|
160
|
-
|
161
|
-
expect(json_response[:data][:guestSignUp]).to include(
|
162
|
-
authenticatable: { email: email },
|
163
|
-
credentials: hash_including(
|
164
|
-
uid: email,
|
165
|
-
client: Guest.last.tokens.keys.first
|
166
|
-
)
|
167
|
-
)
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
@@ -1,116 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'rails_helper'
|
4
|
-
|
5
|
-
RSpec.describe 'Update Password Requests' do
|
6
|
-
shared_examples 'successful password update' do
|
7
|
-
it 'updates the password' do
|
8
|
-
expect do
|
9
|
-
post_request
|
10
|
-
user.reload
|
11
|
-
end.to change(user, :encrypted_password)
|
12
|
-
|
13
|
-
expect(response).to include_auth_headers
|
14
|
-
expect(json_response[:data][:userUpdatePassword]).to match(
|
15
|
-
authenticatable: { email: user.email }
|
16
|
-
)
|
17
|
-
expect(json_response[:errors]).to be_nil
|
18
|
-
expect(user).to be_valid_password(password)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
include_context 'with graphql query request'
|
23
|
-
|
24
|
-
let(:password) { 'safePassw0rd!' }
|
25
|
-
let(:password_confirmation) { 'safePassw0rd!' }
|
26
|
-
let(:original_password) { 'current_password' }
|
27
|
-
let(:current_password) { original_password }
|
28
|
-
let(:allow_password_change) { false }
|
29
|
-
let(:user) { create(:user, :confirmed, password: original_password, allow_password_change: allow_password_change) }
|
30
|
-
let(:query) do
|
31
|
-
<<-GRAPHQL
|
32
|
-
mutation {
|
33
|
-
userUpdatePassword(
|
34
|
-
password: "#{password}",
|
35
|
-
passwordConfirmation: "#{password_confirmation}",
|
36
|
-
currentPassword: "#{current_password}"
|
37
|
-
) {
|
38
|
-
authenticatable { email }
|
39
|
-
}
|
40
|
-
}
|
41
|
-
GRAPHQL
|
42
|
-
end
|
43
|
-
|
44
|
-
context 'when user is logged in' do
|
45
|
-
let(:headers) { user.create_new_auth_token }
|
46
|
-
|
47
|
-
context 'when currentPassword is not provided' do
|
48
|
-
let(:current_password) { nil }
|
49
|
-
|
50
|
-
context 'when allow_password_change is true' do
|
51
|
-
let(:allow_password_change) { true }
|
52
|
-
|
53
|
-
it_behaves_like 'successful password update'
|
54
|
-
|
55
|
-
it 'sets allow_password_change to false' do
|
56
|
-
expect do
|
57
|
-
post_request
|
58
|
-
user.reload
|
59
|
-
end.to change(user, :allow_password_change).from(true).to(false)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context 'when allow_password_change is false' do
|
64
|
-
it 'does not update the password' do
|
65
|
-
expect do
|
66
|
-
post_request
|
67
|
-
user.reload
|
68
|
-
end.not_to change(user, :encrypted_password)
|
69
|
-
|
70
|
-
expect(response).to include_auth_headers
|
71
|
-
expect(json_response[:data][:userUpdatePassword]).to be_nil
|
72
|
-
expect(json_response[:errors]).to contain_exactly(
|
73
|
-
hash_including(
|
74
|
-
message: 'Unable to update user password',
|
75
|
-
extensions: { code: 'USER_ERROR', detailed_errors: ["Current password can't be blank"] }
|
76
|
-
)
|
77
|
-
)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
context 'when currentPassword is provided' do
|
83
|
-
context 'when allow_password_change is true' do
|
84
|
-
let(:allow_password_change) { true }
|
85
|
-
|
86
|
-
it_behaves_like 'successful password update'
|
87
|
-
|
88
|
-
it 'sets allow_password_change to false' do
|
89
|
-
expect do
|
90
|
-
post_request
|
91
|
-
user.reload
|
92
|
-
end.to change(user, :allow_password_change).from(true).to(false)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
context 'when allow_password_change is false' do
|
97
|
-
it_behaves_like 'successful password update'
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
context 'when user is not logged in' do
|
103
|
-
it 'does not update the password' do
|
104
|
-
expect do
|
105
|
-
post_request
|
106
|
-
user.reload
|
107
|
-
end.not_to change(user, :encrypted_password)
|
108
|
-
|
109
|
-
expect(response).not_to include_auth_headers
|
110
|
-
expect(json_response[:data][:userUpdatePassword]).to be_nil
|
111
|
-
expect(json_response[:errors]).to contain_exactly(
|
112
|
-
hash_including(message: 'User is not logged in.', extensions: { code: 'USER_ERROR' })
|
113
|
-
)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|