graphql_devise 0.11.4 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.travis.yml +7 -0
  4. data/Appraisals +14 -0
  5. data/CHANGELOG.md +56 -0
  6. data/Gemfile +2 -0
  7. data/README.md +219 -20
  8. data/Rakefile +2 -0
  9. data/app/controllers/graphql_devise/application_controller.rb +6 -5
  10. data/app/controllers/graphql_devise/concerns/set_user_by_token.rb +31 -0
  11. data/app/controllers/graphql_devise/graphql_controller.rb +4 -0
  12. data/app/helpers/graphql_devise/application_helper.rb +2 -0
  13. data/app/helpers/graphql_devise/mailer_helper.rb +4 -2
  14. data/app/models/graphql_devise/concerns/model.rb +10 -0
  15. data/app/views/graphql_devise/mailer/confirmation_instructions.html.erb +1 -1
  16. data/app/views/graphql_devise/mailer/reset_password_instructions.html.erb +1 -1
  17. data/config/locales/en.yml +1 -0
  18. data/config/routes.rb +4 -0
  19. data/graphql_devise.gemspec +6 -4
  20. data/lib/generators/graphql_devise/install_generator.rb +30 -5
  21. data/lib/graphql_devise.rb +26 -10
  22. data/lib/graphql_devise/concerns/controller_methods.rb +2 -0
  23. data/lib/graphql_devise/default_operations/mutations.rb +8 -6
  24. data/lib/graphql_devise/default_operations/resolvers.rb +4 -2
  25. data/lib/graphql_devise/engine.rb +2 -0
  26. data/lib/graphql_devise/errors/authentication_error.rb +9 -0
  27. data/lib/graphql_devise/{detailed_user_error.rb → errors/detailed_user_error.rb} +3 -1
  28. data/lib/graphql_devise/errors/error_codes.rb +8 -0
  29. data/lib/graphql_devise/errors/execution_error.rb +6 -0
  30. data/lib/graphql_devise/{user_error.rb → errors/user_error.rb} +3 -1
  31. data/lib/graphql_devise/model/with_email_updater.rb +74 -0
  32. data/lib/graphql_devise/mount_method/operation_preparer.rb +4 -2
  33. data/lib/graphql_devise/mount_method/operation_preparers/custom_operation_preparer.rb +2 -0
  34. data/lib/graphql_devise/mount_method/operation_preparers/default_operation_preparer.rb +8 -2
  35. data/lib/graphql_devise/mount_method/operation_preparers/gql_name_setter.rb +3 -1
  36. data/lib/graphql_devise/mount_method/operation_preparers/mutation_field_setter.rb +5 -2
  37. data/lib/graphql_devise/mount_method/operation_preparers/resolver_type_setter.rb +3 -1
  38. data/lib/graphql_devise/mount_method/operation_preparers/resource_name_setter.rb +4 -2
  39. data/lib/graphql_devise/mount_method/operation_sanitizer.rb +2 -0
  40. data/lib/graphql_devise/mount_method/option_sanitizer.rb +2 -0
  41. data/lib/graphql_devise/mount_method/option_sanitizers/array_checker.rb +2 -0
  42. data/lib/graphql_devise/mount_method/option_sanitizers/class_checker.rb +2 -0
  43. data/lib/graphql_devise/mount_method/option_sanitizers/hash_checker.rb +2 -0
  44. data/lib/graphql_devise/mount_method/option_sanitizers/string_checker.rb +2 -0
  45. data/lib/graphql_devise/mount_method/option_validators/provided_operations_validator.rb +2 -0
  46. data/lib/graphql_devise/mount_method/option_validators/skip_only_validator.rb +2 -0
  47. data/lib/graphql_devise/mount_method/option_validators/supported_operations_validator.rb +2 -0
  48. data/lib/graphql_devise/mount_method/options_validator.rb +2 -0
  49. data/lib/graphql_devise/mount_method/supported_options.rb +2 -0
  50. data/lib/graphql_devise/mutations/base.rb +2 -0
  51. data/lib/graphql_devise/mutations/login.rb +2 -0
  52. data/lib/graphql_devise/mutations/logout.rb +2 -0
  53. data/lib/graphql_devise/mutations/resend_confirmation.rb +5 -5
  54. data/lib/graphql_devise/mutations/send_password_reset.rb +7 -2
  55. data/lib/graphql_devise/mutations/sign_up.rb +5 -6
  56. data/lib/graphql_devise/mutations/update_password.rb +2 -0
  57. data/lib/graphql_devise/rails/routes.rb +7 -72
  58. data/lib/graphql_devise/resolvers/base.rb +2 -0
  59. data/lib/graphql_devise/resolvers/check_password_token.rb +2 -0
  60. data/lib/graphql_devise/resolvers/confirm_account.rb +4 -2
  61. data/lib/graphql_devise/resolvers/dummy.rb +2 -0
  62. data/lib/graphql_devise/resource_loader.rb +89 -0
  63. data/lib/graphql_devise/schema.rb +2 -0
  64. data/lib/graphql_devise/schema_plugin.rb +114 -0
  65. data/lib/graphql_devise/types/authenticatable_type.rb +2 -0
  66. data/lib/graphql_devise/types/credential_type.rb +2 -0
  67. data/lib/graphql_devise/types/mutation_type.rb +2 -0
  68. data/lib/graphql_devise/types/query_type.rb +2 -0
  69. data/lib/graphql_devise/version.rb +3 -1
  70. data/spec/dummy/Rakefile +2 -0
  71. data/spec/dummy/app/controllers/api/v1/graphql_controller.rb +38 -3
  72. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  73. data/spec/dummy/app/graphql/dummy_schema.rb +21 -0
  74. data/spec/dummy/app/graphql/interpreter_schema.rb +11 -0
  75. data/spec/dummy/app/graphql/mutations/login.rb +2 -0
  76. data/spec/dummy/app/graphql/mutations/register_confirmed_user.rb +2 -0
  77. data/spec/dummy/app/graphql/mutations/sign_up.rb +2 -0
  78. data/spec/dummy/app/graphql/mutations/update_user.rb +22 -0
  79. data/spec/dummy/app/graphql/resolvers/public_user.rb +2 -0
  80. data/spec/dummy/app/graphql/resolvers/user_show.rb +2 -0
  81. data/spec/dummy/app/graphql/types/base_object.rb +2 -0
  82. data/spec/dummy/app/graphql/types/custom_admin_type.rb +2 -0
  83. data/spec/dummy/app/graphql/types/mutation_type.rb +4 -1
  84. data/spec/dummy/app/graphql/types/query_type.rb +12 -0
  85. data/spec/dummy/app/graphql/types/user_type.rb +2 -0
  86. data/spec/dummy/app/jobs/application_job.rb +2 -0
  87. data/spec/dummy/app/mailers/application_mailer.rb +2 -0
  88. data/spec/dummy/app/models/admin.rb +2 -0
  89. data/spec/dummy/app/models/application_record.rb +2 -0
  90. data/spec/dummy/app/models/guest.rb +2 -0
  91. data/spec/dummy/app/models/schema_user.rb +13 -0
  92. data/spec/dummy/app/models/user.rb +2 -0
  93. data/spec/dummy/app/models/users.rb +2 -0
  94. data/spec/dummy/app/models/users/customer.rb +2 -0
  95. data/spec/dummy/config.ru +2 -0
  96. data/spec/dummy/config/application.rb +2 -0
  97. data/spec/dummy/config/environment.rb +2 -0
  98. data/spec/dummy/config/environments/development.rb +2 -0
  99. data/spec/dummy/config/environments/production.rb +2 -0
  100. data/spec/dummy/config/environments/test.rb +2 -0
  101. data/spec/dummy/config/initializers/application_controller_renderer.rb +2 -0
  102. data/spec/dummy/config/initializers/backtrace_silencers.rb +2 -0
  103. data/spec/dummy/config/initializers/cors.rb +2 -0
  104. data/spec/dummy/config/initializers/devise_token_auth.rb +2 -0
  105. data/spec/dummy/config/initializers/filter_parameter_logging.rb +2 -0
  106. data/spec/dummy/config/initializers/i18n.rb +2 -0
  107. data/spec/dummy/config/initializers/inflections.rb +2 -0
  108. data/spec/dummy/config/initializers/mime_types.rb +2 -0
  109. data/spec/dummy/config/initializers/wrap_parameters.rb +2 -0
  110. data/spec/dummy/config/puma.rb +2 -0
  111. data/spec/dummy/config/routes.rb +5 -0
  112. data/spec/dummy/config/spring.rb +2 -0
  113. data/spec/dummy/db/migrate/20190815114303_create_users.rb +2 -0
  114. data/spec/dummy/db/migrate/20190824215150_add_auth_available_to_users.rb +2 -0
  115. data/spec/dummy/db/migrate/20190916012505_create_admins.rb +2 -0
  116. data/spec/dummy/db/migrate/20191013213045_create_guests.rb +2 -0
  117. data/spec/dummy/db/migrate/20200321121807_create_users_customers.rb +2 -0
  118. data/spec/dummy/db/migrate/20200621182414_remove_uncofirmed_email_from_admins.rb +7 -0
  119. data/spec/dummy/db/migrate/20200623003142_create_schema_users.rb +46 -0
  120. data/spec/dummy/db/schema.rb +30 -2
  121. data/spec/dummy/db/seeds.rb +2 -0
  122. data/spec/factories/admins.rb +2 -0
  123. data/spec/factories/guests.rb +2 -0
  124. data/spec/factories/schema_users.rb +13 -0
  125. data/spec/factories/users.rb +2 -0
  126. data/spec/factories/users_customers.rb +2 -0
  127. data/spec/generators/graphql_devise/install_generator_spec.rb +23 -0
  128. data/spec/graphql_devise/model/with_email_updater_spec.rb +131 -0
  129. data/spec/graphql_devise_spec.rb +2 -0
  130. data/spec/models/user_spec.rb +2 -0
  131. data/spec/rails_helper.rb +3 -1
  132. data/spec/requests/graphql_controller_spec.rb +82 -0
  133. data/spec/requests/mutations/additional_mutations_spec.rb +2 -0
  134. data/spec/requests/mutations/additional_queries_spec.rb +2 -0
  135. data/spec/requests/mutations/login_spec.rb +2 -0
  136. data/spec/requests/mutations/logout_spec.rb +2 -0
  137. data/spec/requests/mutations/resend_confirmation_spec.rb +46 -29
  138. data/spec/requests/mutations/send_password_reset_spec.rb +42 -12
  139. data/spec/requests/mutations/sign_up_spec.rb +2 -0
  140. data/spec/requests/mutations/update_password_spec.rb +2 -0
  141. data/spec/requests/queries/check_password_token_spec.rb +2 -0
  142. data/spec/requests/queries/confirm_account_spec.rb +9 -1
  143. data/spec/requests/user_controller_spec.rb +237 -23
  144. data/spec/services/mount_method/operation_preparer_spec.rb +10 -3
  145. data/spec/services/mount_method/operation_preparers/custom_operation_preparer_spec.rb +3 -1
  146. data/spec/services/mount_method/operation_preparers/default_operation_preparer_spec.rb +17 -8
  147. data/spec/services/mount_method/operation_preparers/gql_name_setter_spec.rb +2 -0
  148. data/spec/services/mount_method/operation_preparers/mutation_field_setter_spec.rb +20 -4
  149. data/spec/services/mount_method/operation_preparers/resolver_type_setter_spec.rb +2 -0
  150. data/spec/services/mount_method/operation_preparers/resource_name_setter_spec.rb +3 -1
  151. data/spec/services/mount_method/operation_sanitizer_spec.rb +2 -0
  152. data/spec/services/mount_method/option_sanitizer_spec.rb +2 -0
  153. data/spec/services/mount_method/option_sanitizers/array_checker_spec.rb +2 -0
  154. data/spec/services/mount_method/option_sanitizers/class_checker_spec.rb +2 -0
  155. data/spec/services/mount_method/option_sanitizers/hash_checker_spec.rb +2 -0
  156. data/spec/services/mount_method/option_sanitizers/string_checker_spec.rb +2 -0
  157. data/spec/services/mount_method/option_validators/provided_operations_validator_spec.rb +2 -0
  158. data/spec/services/mount_method/option_validators/skip_only_validator_spec.rb +2 -0
  159. data/spec/services/mount_method/option_validators/supported_operations_validator_spec.rb +2 -0
  160. data/spec/services/mount_method/options_validator_spec.rb +2 -0
  161. data/spec/services/resource_loader_spec.rb +84 -0
  162. data/spec/services/schema_plugin_spec.rb +28 -0
  163. data/spec/spec_helper.rb +2 -0
  164. data/spec/support/contexts/graphql_request.rb +2 -0
  165. data/spec/support/factory_bot.rb +2 -0
  166. data/spec/support/matchers/auth_headers_matcher.rb +2 -0
  167. data/spec/support/matchers/not_change_matcher.rb +2 -0
  168. data/spec/support/requests/auth_helpers.rb +2 -0
  169. data/spec/support/requests/json_helpers.rb +2 -0
  170. metadata +120 -87
  171. data/lib/graphql_devise/error_codes.rb +0 -5
  172. data/spec/support/generators/file_helpers.rb +0 -12
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
4
  require 'bundler/setup'
3
5
  rescue LoadError
@@ -1,8 +1,9 @@
1
- module GraphqlDevise
2
- class ApplicationController < DeviseTokenAuth::ApplicationController
3
- private
1
+ # frozen_string_literal: true
4
2
 
5
- def verify_authenticity_token
6
- end
3
+ module GraphqlDevise
4
+ ApplicationController = if Rails::VERSION::MAJOR >= 5
5
+ Class.new(ActionController::API)
6
+ else
7
+ Class.new(ActionController::Base)
7
8
  end
8
9
  end
@@ -1,5 +1,36 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GraphqlDevise
2
4
  module Concerns
3
5
  SetUserByToken = DeviseTokenAuth::Concerns::SetUserByToken
6
+
7
+ SetUserByToken.module_eval do
8
+ attr_accessor :client_id, :token, :resource
9
+
10
+ def full_url_without_params
11
+ request.base_url + request.path
12
+ end
13
+
14
+ def set_resource_by_token(resource)
15
+ set_user_by_token(resource)
16
+ end
17
+
18
+ def graphql_context(resource_name)
19
+ {
20
+ resource_name: resource_name,
21
+ controller: self
22
+ }
23
+ end
24
+
25
+ def build_redirect_headers(access_token, client, redirect_header_options = {})
26
+ {
27
+ DeviseTokenAuth.headers_names[:"access-token"] => access_token,
28
+ DeviseTokenAuth.headers_names[:client] => client,
29
+ :config => params[:config],
30
+ :client_id => client,
31
+ :token => access_token
32
+ }.merge(redirect_header_options)
33
+ end
34
+ end
4
35
  end
5
36
  end
@@ -1,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_dependency 'graphql_devise/application_controller'
2
4
 
3
5
  module GraphqlDevise
4
6
  class GraphqlController < ApplicationController
7
+ include GraphqlDevise::Concerns::SetUserByToken
8
+
5
9
  def auth
6
10
  result = if params[:_json]
7
11
  GraphqlDevise::Schema.multiplex(
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GraphqlDevise
2
4
  module ApplicationHelper
3
5
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GraphqlDevise
2
4
  module MailerHelper
3
5
  def confirmation_query(resource_name:, token:, redirect_url:)
4
- name = "#{resource_name.camelize(:lower)}ConfirmAccount"
6
+ name = "#{resource_name.underscore.tr('/', '_').camelize(:lower)}ConfirmAccount"
5
7
  raw = <<-GRAPHQL
6
8
  query($token:String!,$redirectUrl:String!){
7
9
  #{name}(confirmationToken:$token,redirectUrl:$redirectUrl){
@@ -17,7 +19,7 @@ module GraphqlDevise
17
19
  end
18
20
 
19
21
  def password_reset_query(token:, redirect_url:, resource_name:)
20
- name = "#{resource_name.camelize(:lower)}CheckPasswordToken"
22
+ name = "#{resource_name.underscore.tr('/', '_').camelize(:lower)}CheckPasswordToken"
21
23
  raw = <<-GRAPHQL
22
24
  query($token:String!,$redirectUrl:String!){
23
25
  #{name}(resetPasswordToken:$token,redirectUrl:$redirectUrl){
@@ -1,5 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql_devise/model/with_email_updater'
4
+
1
5
  module GraphqlDevise
2
6
  module Concerns
3
7
  Model = DeviseTokenAuth::Concerns::User
8
+
9
+ Model.module_eval do
10
+ def update_with_email(attributes = {})
11
+ GraphqlDevise::Model::WithEmailUpdater.new(self, attributes).call
12
+ end
13
+ end
4
14
  end
5
15
  end
@@ -2,4 +2,4 @@
2
2
 
3
3
  <p><%= t('.confirm_link_msg') %></p>
4
4
 
5
- <p><%= link_to t('.confirm_account_link'), url_for(controller: 'graphql_devise/graphql', action: :auth, **confirmation_query(resource_name: @resource.class.to_s, redirect_url: message['redirect-url'], token: @token)) %></p>
5
+ <p><%= link_to t('.confirm_account_link'), "#{message['schema_url']}?#{confirmation_query(resource_name: @resource.class.to_s, redirect_url: message['redirect-url'], token: @token).to_query}" %></p>
@@ -2,7 +2,7 @@
2
2
 
3
3
  <p><%= t('.request_reset_link_msg') %></p>
4
4
 
5
- <p><%= link_to t('.password_change_link'), url_for(controller: 'graphql_devise/graphql', action: :auth, **password_reset_query(token: @token, redirect_url: message['redirect-url'], resource_name: @resource.class.to_s)) %></p>
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>
6
6
 
7
7
  <p><%= t('.ignore_mail_msg') %></p>
8
8
  <p><%= t('.no_changes_msg') %></p>
@@ -14,6 +14,7 @@ en:
14
14
  password_not_required: "This account does not require a password. Sign in using your '%{provider}' account instead."
15
15
  reset_token_not_found: "No user found for the specified reset token."
16
16
  reset_token_expired: "Reset password token is no longer valid."
17
+ send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
17
18
  sessions:
18
19
  bad_credentials: "Invalid login credentials. Please try again."
19
20
  not_confirmed: "A confirmation email was sent to your account at '%{email}'. You must follow the instructions in the email before your account can be activated"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  GraphqlDevise::Engine.routes.draw do
2
4
  # Required as Devise forces routes to reload on eager_load
3
5
  unless GraphqlDevise.schema_loaded?
@@ -12,5 +14,7 @@ GraphqlDevise::Engine.routes.draw do
12
14
  GraphqlDevise::Schema.query(GraphqlDevise::Types::QueryType)
13
15
 
14
16
  GraphqlDevise.load_schema
17
+
18
+ Devise.mailer.helper(GraphqlDevise::MailerHelper)
15
19
  end
16
20
  end
@@ -21,13 +21,15 @@ Gem::Specification.new do |spec|
21
21
  spec.bindir = 'exe'
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
23
  spec.require_paths = ['lib']
24
- spec.test_files = Dir['spec/**/*']
24
+ spec.test_files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").select { |f| f.match(%r{^spec/}) }
26
+ end
25
27
 
26
28
  spec.required_ruby_version = '>= 2.2.0'
27
29
 
28
- spec.add_dependency 'devise_token_auth', '>= 0.1.43'
29
- spec.add_dependency 'graphql', '>= 1.8'
30
- spec.add_dependency 'rails', '>= 4.2'
30
+ spec.add_dependency 'devise_token_auth', '>= 0.1.43', '< 2.0'
31
+ spec.add_dependency 'graphql', '>= 1.8', '< 1.12.0'
32
+ spec.add_dependency 'rails', '>= 4.2', '< 6.2'
31
33
 
32
34
  spec.add_development_dependency 'appraisal'
33
35
  spec.add_development_dependency 'coveralls'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GraphqlDevise
2
4
  class InstallGenerator < ::Rails::Generators::Base
3
5
  source_root File.expand_path('templates', __dir__)
@@ -5,6 +7,8 @@ module GraphqlDevise
5
7
  argument :user_class, type: :string, default: 'User'
6
8
  argument :mount_path, type: :string, default: 'auth'
7
9
 
10
+ class_option :mount, type: :string, default: 'separate_route'
11
+
8
12
  def execute_devise_installer
9
13
  generate 'devise:install'
10
14
  end
@@ -29,15 +33,20 @@ module GraphqlDevise
29
33
 
30
34
  def mount_resource_route
31
35
  routes_file = 'config/routes.rb'
32
- gem_route = "mount_graphql_devise_for '#{user_class}', at: '#{mount_path}'"
33
36
  dta_route = "mount_devise_token_auth_for '#{user_class}', at: '#{mount_path}'"
34
37
 
35
- if file_contains_str?(routes_file, gem_route)
38
+ if options['mount'] != 'separate_route'
36
39
  gsub_file(routes_file, /^\s+#{Regexp.escape(dta_route + "\n")}/i, '')
37
-
38
- say_status('skipped', "Routes already exist for #{user_class} at #{mount_path}")
39
40
  else
40
- gsub_file(routes_file, /#{Regexp.escape(dta_route)}/i, gem_route)
41
+ gem_route = "mount_graphql_devise_for '#{user_class}', at: '#{mount_path}'"
42
+
43
+ if file_contains_str?(routes_file, gem_route)
44
+ gsub_file(routes_file, /^\s+#{Regexp.escape(dta_route + "\n")}/i, '')
45
+
46
+ say_status('skipped', "Routes already exist for #{user_class} at #{mount_path}")
47
+ else
48
+ gsub_file(routes_file, /#{Regexp.escape(dta_route)}/i, gem_route)
49
+ end
41
50
  end
42
51
  end
43
52
 
@@ -65,6 +74,22 @@ module GraphqlDevise
65
74
  )
66
75
  end
67
76
 
77
+ def mount_in_schema
78
+ return if options['mount'] == 'separate_route'
79
+
80
+ inject_into_file "app/graphql/#{options['mount'].underscore}.rb", after: "< GraphQL::Schema\n" do
81
+ <<-RUBY
82
+ use GraphqlDevise::SchemaPlugin.new(
83
+ query: Types::QueryType,
84
+ mutation: Types::MutationType,
85
+ resource_loaders: [
86
+ GraphqlDevise::ResourceLoader.new('#{user_class}'),
87
+ ]
88
+ )
89
+ RUBY
90
+ end
91
+ end
92
+
68
93
  private
69
94
 
70
95
  def file_contains_str?(filename, regex_str)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rails'
2
4
  require 'graphql'
3
5
  require 'devise_token_auth'
@@ -18,15 +20,32 @@ module GraphqlDevise
18
20
  @schema_loaded = true
19
21
  end
20
22
 
21
- def self.mount_resource(resource)
22
- @mounted_resources << resource
23
+ def self.resource_mounted?(mapping_name)
24
+ @mounted_resources.include?(mapping_name)
25
+ end
26
+
27
+ def self.mount_resource(mapping_name)
28
+ @mounted_resources << mapping_name
23
29
  end
24
30
 
25
- def self.resource_mounted?(resource)
26
- @mounted_resources.include?(resource)
31
+ def self.add_mapping(mapping_name, resource)
32
+ return if Devise.mappings.key?(mapping_name)
33
+
34
+ Devise.add_mapping(
35
+ mapping_name.to_s.pluralize.to_sym,
36
+ module: :devise, class_name: resource
37
+ )
27
38
  end
28
39
  end
29
40
 
41
+ require 'graphql_devise/engine'
42
+ require 'graphql_devise/version'
43
+ require 'graphql_devise/errors/error_codes'
44
+ require 'graphql_devise/errors/execution_error'
45
+ require 'graphql_devise/errors/user_error'
46
+ require 'graphql_devise/errors/authentication_error'
47
+ require 'graphql_devise/errors/detailed_user_error'
48
+
30
49
  require 'graphql_devise/concerns/controller_methods'
31
50
  require 'graphql_devise/schema'
32
51
  require 'graphql_devise/types/authenticatable_type'
@@ -37,13 +56,10 @@ require 'graphql_devise/default_operations/mutations'
37
56
  require 'graphql_devise/default_operations/resolvers'
38
57
  require 'graphql_devise/resolvers/dummy'
39
58
 
40
- require 'graphql_devise/engine'
41
- require 'graphql_devise/version'
42
- require 'graphql_devise/error_codes'
43
- require 'graphql_devise/user_error'
44
- require 'graphql_devise/detailed_user_error'
45
-
46
59
  require 'graphql_devise/mount_method/option_sanitizer'
47
60
  require 'graphql_devise/mount_method/options_validator'
48
61
  require 'graphql_devise/mount_method/operation_preparer'
49
62
  require 'graphql_devise/mount_method/operation_sanitizer'
63
+
64
+ require 'graphql_devise/resource_loader'
65
+ require 'graphql_devise/schema_plugin'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GraphqlDevise
2
4
  module Concerns
3
5
  module ControllerMethods
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'graphql_devise/mutations/base'
2
4
  require 'graphql_devise/mutations/login'
3
5
  require 'graphql_devise/mutations/logout'
@@ -9,12 +11,12 @@ require 'graphql_devise/mutations/update_password'
9
11
  module GraphqlDevise
10
12
  module DefaultOperations
11
13
  MUTATIONS = {
12
- login: GraphqlDevise::Mutations::Login,
13
- logout: GraphqlDevise::Mutations::Logout,
14
- sign_up: GraphqlDevise::Mutations::SignUp,
15
- update_password: GraphqlDevise::Mutations::UpdatePassword,
16
- send_password_reset: GraphqlDevise::Mutations::SendPasswordReset,
17
- resend_confirmation: GraphqlDevise::Mutations::ResendConfirmation
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 }
18
20
  }.freeze
19
21
  end
20
22
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'graphql_devise/resolvers/base'
2
4
  require 'graphql_devise/resolvers/check_password_token'
3
5
  require 'graphql_devise/resolvers/confirm_account'
@@ -5,8 +7,8 @@ require 'graphql_devise/resolvers/confirm_account'
5
7
  module GraphqlDevise
6
8
  module DefaultOperations
7
9
  QUERIES = {
8
- confirm_account: GraphqlDevise::Resolvers::ConfirmAccount,
9
- check_password_token: GraphqlDevise::Resolvers::CheckPasswordToken
10
+ confirm_account: { klass: GraphqlDevise::Resolvers::ConfirmAccount },
11
+ check_password_token: { klass: GraphqlDevise::Resolvers::CheckPasswordToken }
10
12
  }.freeze
11
13
  end
12
14
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'graphql_devise/rails/routes'
2
4
 
3
5
  module GraphqlDevise
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphqlDevise
4
+ class AuthenticationError < ExecutionError
5
+ def to_h
6
+ super.merge(extensions: { code: ERROR_CODES.fetch(:authentication_error) })
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GraphqlDevise
2
- class DetailedUserError < GraphQL::ExecutionError
4
+ class DetailedUserError < ExecutionError
3
5
  def initialize(message, errors:)
4
6
  @message = message
5
7
  @errors = errors
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphqlDevise
4
+ ERROR_CODES = {
5
+ user_error: 'USER_ERROR',
6
+ authentication_error: 'AUTHENTICATION_ERROR'
7
+ }.freeze
8
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphqlDevise
4
+ class ExecutionError < GraphQL::ExecutionError
5
+ end
6
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module GraphqlDevise
2
- class UserError < GraphQL::ExecutionError
4
+ class UserError < ExecutionError
3
5
  def to_h
4
6
  super.merge(extensions: { code: ERROR_CODES.fetch(:user_error) })
5
7
  end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphqlDevise
4
+ module Model
5
+ class WithEmailUpdater
6
+ def initialize(resource, attributes)
7
+ @attributes = attributes
8
+ @resource = resource
9
+ end
10
+
11
+ def call
12
+ resource_attributes = @attributes.except(:schema_url, :confirmation_success_url)
13
+ return @resource.update(resource_attributes) unless requires_reconfirmation?(resource_attributes)
14
+
15
+ @resource.assign_attributes(resource_attributes)
16
+
17
+ if @resource.email == email_in_database
18
+ return @resource.save
19
+ elsif required_reconfirm_attributes?
20
+ return false unless @resource.valid?
21
+
22
+ store_unconfirmed_email
23
+ saved = @resource.save
24
+ send_confirmation_instructions(saved)
25
+
26
+ saved
27
+ else
28
+ raise(
29
+ GraphqlDevise::Error,
30
+ 'Method `update_with_email` requires attributes `confirmation_success_url` and `schema_url` for email reconfirmation to work'
31
+ )
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def required_reconfirm_attributes?
38
+ @attributes[:schema_url].present? &&
39
+ (@attributes[:confirmation_success_url].present? || DeviseTokenAuth.default_confirm_success_url.present?)
40
+ end
41
+
42
+ def requires_reconfirmation?(resource_attributes)
43
+ resource_attributes.key?(:email) &&
44
+ @resource.devise_modules.include?(:confirmable) &&
45
+ @resource.respond_to?(:unconfirmed_email=)
46
+ end
47
+
48
+ def store_unconfirmed_email
49
+ @resource.unconfirmed_email = @resource.email
50
+ @resource.confirmation_token = nil
51
+ @resource.email = email_in_database
52
+ @resource.send(:generate_confirmation_token)
53
+ end
54
+
55
+ def email_in_database
56
+ if Devise.activerecord51?
57
+ @resource.email_in_database
58
+ else
59
+ @resource.email_was
60
+ end
61
+ end
62
+
63
+ def send_confirmation_instructions(saved)
64
+ return unless saved
65
+
66
+ @resource.send_confirmation_instructions(
67
+ redirect_url: @attributes[:confirmation_success_url] || DeviseTokenAuth.default_confirm_success_url,
68
+ template_path: ['graphql_devise/mailer'],
69
+ schema_url: @attributes[:schema_url]
70
+ )
71
+ end
72
+ end
73
+ end
74
+ end