graphql_devise 0.18.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +7 -2
  3. data/.gitignore +3 -0
  4. data/.rubocop.yml +9 -10
  5. data/Appraisals +70 -18
  6. data/CHANGELOG.md +53 -0
  7. data/README.md +71 -142
  8. data/app/controllers/graphql_devise/graphql_controller.rb +3 -3
  9. data/app/views/graphql_devise/mailer/confirmation_instructions.html.erb +1 -5
  10. data/config/routes.rb +0 -2
  11. data/graphql_devise.gemspec +7 -5
  12. data/lib/graphql_devise/concerns/additional_controller_methods.rb +48 -0
  13. data/lib/graphql_devise/concerns/additional_model_methods.rb +17 -0
  14. data/lib/graphql_devise/concerns/authenticatable.rb +1 -1
  15. data/lib/graphql_devise/concerns/controller_methods.rb +70 -93
  16. data/lib/graphql_devise/concerns/field_authentication.rb +14 -0
  17. data/lib/graphql_devise/concerns/set_user_by_token.rb +1 -1
  18. data/lib/graphql_devise/default_operations.rb +16 -0
  19. data/lib/graphql_devise/engine.rb +0 -2
  20. data/lib/graphql_devise/model/with_email_updater.rb +5 -30
  21. data/lib/graphql_devise/mount_method/operation_preparer.rb +0 -7
  22. data/lib/graphql_devise/mount_method/operation_preparers/custom_operation_preparer.rb +1 -1
  23. data/lib/graphql_devise/mount_method/operation_preparers/default_operation_preparer.rb +1 -1
  24. data/lib/graphql_devise/mount_method/operation_sanitizer.rb +0 -12
  25. data/lib/graphql_devise/mount_method/option_sanitizer.rb +0 -2
  26. data/lib/graphql_devise/mount_method/option_sanitizers/array_checker.rb +2 -2
  27. data/lib/graphql_devise/mount_method/option_sanitizers/class_checker.rb +2 -2
  28. data/lib/graphql_devise/mount_method/option_sanitizers/hash_checker.rb +1 -1
  29. data/lib/graphql_devise/mount_method/option_sanitizers/string_checker.rb +1 -1
  30. data/lib/graphql_devise/mount_method/option_validators/provided_operations_validator.rb +0 -2
  31. data/lib/graphql_devise/mount_method/option_validators/skip_only_validator.rb +1 -1
  32. data/lib/graphql_devise/mount_method/option_validators/supported_operations_validator.rb +1 -1
  33. data/lib/graphql_devise/mount_method/options_validator.rb +0 -3
  34. data/lib/graphql_devise/mount_method/supported_options.rb +0 -5
  35. data/lib/graphql_devise/mutations/base.rb +1 -1
  36. data/lib/graphql_devise/mutations/confirm_registration_with_token.rb +1 -1
  37. data/lib/graphql_devise/mutations/login.rb +1 -1
  38. data/lib/graphql_devise/mutations/register.rb +1 -1
  39. data/lib/graphql_devise/mutations/update_password_with_token.rb +1 -1
  40. data/lib/graphql_devise/resolvers/base.rb +1 -1
  41. data/lib/graphql_devise/resource_loader.rb +71 -39
  42. data/lib/graphql_devise/route_mounter.rb +13 -0
  43. data/lib/graphql_devise/schema_plugin.rb +7 -40
  44. data/lib/graphql_devise/types/authenticatable_type.rb +1 -1
  45. data/lib/graphql_devise/types/base_field.rb +9 -0
  46. data/lib/graphql_devise/types/base_type.rb +8 -0
  47. data/lib/graphql_devise/types/credential_type.rb +1 -1
  48. data/lib/graphql_devise/types/mutation_type.rb +1 -0
  49. data/lib/graphql_devise/types/query_type.rb +1 -0
  50. data/lib/graphql_devise/version.rb +1 -1
  51. data/lib/graphql_devise.rb +21 -29
  52. data/spec/dummy/app/controllers/api/v1/graphql_controller.rb +1 -16
  53. data/spec/dummy/app/graphql/dummy_schema.rb +1 -5
  54. data/spec/dummy/app/graphql/interpreter_schema.rb +6 -2
  55. data/spec/dummy/app/graphql/mutations/base_mutation.rb +6 -0
  56. data/spec/dummy/app/graphql/mutations/update_user.rb +2 -4
  57. data/spec/dummy/app/graphql/types/admin_type.rb +1 -1
  58. data/spec/dummy/app/graphql/types/custom_admin_type.rb +1 -1
  59. data/spec/dummy/app/graphql/types/mutation_type.rb +3 -1
  60. data/spec/dummy/app/graphql/types/query_type.rb +3 -1
  61. data/spec/dummy/app/graphql/types/user_type.rb +1 -1
  62. data/spec/dummy/config/environments/test.rb +1 -1
  63. data/spec/dummy/config/routes.rb +5 -9
  64. data/spec/graphql_devise/model/with_email_updater_spec.rb +17 -35
  65. data/spec/rails_helper.rb +5 -5
  66. data/spec/requests/mutations/resend_confirmation_with_token_spec.rb +2 -3
  67. data/spec/requests/user_controller_spec.rb +1 -33
  68. data/spec/services/resource_loader_spec.rb +14 -3
  69. metadata +55 -48
  70. data/app/controllers/graphql_devise/concerns/additional_controller_methods.rb +0 -72
  71. data/app/controllers/graphql_devise/concerns/set_user_by_token.rb +0 -21
  72. data/app/helpers/graphql_devise/mailer_helper.rb +0 -37
  73. data/app/models/graphql_devise/concerns/additional_model_methods.rb +0 -21
  74. data/app/models/graphql_devise/concerns/model.rb +0 -25
  75. data/lib/graphql_devise/default_operations/mutations.rb +0 -32
  76. data/lib/graphql_devise/default_operations/resolvers.rb +0 -14
  77. data/lib/graphql_devise/mutations/resend_confirmation.rb +0 -45
  78. data/lib/graphql_devise/mutations/send_password_reset.rb +0 -38
  79. data/lib/graphql_devise/mutations/sign_up.rb +0 -61
  80. data/lib/graphql_devise/mutations/update_password.rb +0 -46
  81. data/lib/graphql_devise/rails/routes.rb +0 -15
  82. data/lib/graphql_devise/resolvers/check_password_token.rb +0 -43
  83. data/lib/graphql_devise/resolvers/confirm_account.rb +0 -42
  84. data/spec/dummy/app/graphql/mutations/sign_up.rb +0 -14
  85. data/spec/dummy/app/graphql/resolvers/confirm_admin_account.rb +0 -13
  86. data/spec/requests/mutations/resend_confirmation_spec.rb +0 -153
  87. data/spec/requests/mutations/send_password_reset_spec.rb +0 -103
  88. data/spec/requests/mutations/sign_up_spec.rb +0 -170
  89. data/spec/requests/mutations/update_password_spec.rb +0 -116
  90. data/spec/requests/queries/check_password_token_spec.rb +0 -149
  91. data/spec/requests/queries/confirm_account_spec.rb +0 -137
data/README.md CHANGED
@@ -23,31 +23,30 @@ GraphQL interface on top of the [Devise Token Auth](https://github.com/lynndylan
23
23
  * [Configuring Model](#configuring-model)
24
24
  * [Email Reconfirmation](#email-reconfirmation)
25
25
  * [Current flow](#current-flow)
26
- * [Deprecated flow - Do Not Use](#deprecated-flow---do-not-use)
27
26
  * [Customizing Email Templates](#customizing-email-templates)
28
27
  * [I18n](#i18n)
29
28
  * [Authenticating Controller Actions](#authenticating-controller-actions)
30
29
  * [Authenticate Resource in the Controller (>= v0.15.0)](#authenticate-resource-in-the-controller--v0150)
31
30
  * [Authentication Options](#authentication-options)
32
- * [Authenticate Before Reaching Your GQL Schema (Deprecated)](#authenticate-before-reaching-your-gql-schema-deprecated)
33
- * [Authenticate in an Existing Schema (Deprecated)](#authenticate-in-an-existing-schema-deprecated)
34
- * [Authentication Options](#authentication-options-1)
35
- * [Important](#important)
36
31
  * [Making Requests](#making-requests)
37
32
  * [Introspection query](#introspection-query)
38
33
  * [Mutations](#mutations)
39
- * [Queries](#queries)
40
34
  * [Reset Password Flow](#reset-password-flow)
41
35
  * [More Configuration Options](#more-configuration-options)
42
36
  * [Devise Token Auth Initializer](#devise-token-auth-initializer)
43
37
  * [Devise Initializer](#devise-initializer)
38
+ * [GraphQL 2.0 Support (>= v1.0.0)](#graphql-20-support--v100)
44
39
  * [GraphQL Interpreter](#graphql-interpreter)
45
40
  * [Using Alongside Standard Devise](#using-alongside-standard-devise)
41
+ * [Changelog](#changelog)
46
42
  * [Future Work](#future-work)
43
+ * [Buy Us a Coffee](#buy-us-a-coffee)
44
+ * [BTC](#btc)
45
+ * [ADA](#ada)
47
46
  * [Contributing](#contributing)
48
47
  * [License](#license)
49
48
 
50
- <!-- Added by: david, at: jue jun 24 18:32:27 -05 2021 -->
49
+ <!-- Added by: mcelicalderon, at: Wed Aug 3 22:04:10 -05 2022 -->
51
50
 
52
51
  <!--te-->
53
52
 
@@ -297,17 +296,11 @@ The following is a list of the symbols you can provide to the `operations`, `ski
297
296
  ```ruby
298
297
  :login
299
298
  :logout
300
- :sign_up (deprecated)
301
299
  :register
302
- :update_password (deprecated)
303
300
  :update_password_with_token
304
- :send_password_reset (deprecated)
305
301
  :send_password_reset_with_token
306
- :resend_confirmation (deprecated)
307
302
  :resend_confirmation_with_token
308
303
  :confirm_registration_with_token
309
- :confirm_account (deprecated)
310
- :check_password_token (deprecated)
311
304
  ```
312
305
 
313
306
  ### Configuring Model
@@ -327,7 +320,7 @@ class User < ApplicationRecord
327
320
  :confirmable
328
321
 
329
322
  # including after calling the `devise` method is important.
330
- include GraphqlDevise::Concerns::Model
323
+ include GraphqlDevise::Authenticatable
331
324
  end
332
325
  ```
333
326
 
@@ -369,31 +362,6 @@ user.update_with_email(
369
362
  )
370
363
  ```
371
364
 
372
- #### Deprecated flow - Do Not Use
373
- `update_with_email` requires two additional attributes when email will change or an error
374
- will be raised:
375
-
376
- - `schema_url`: The full url where your GQL schema is mounted. You can get this value from the
377
- controller available in the context of your mutations and queries like this:
378
- ```ruby
379
- context[:controller].full_url_without_params
380
- ```
381
- - `confirmation_success_url`: This the full url where you want users to be redirected after
382
- the email has changed successfully (usually a front-end url). This value is mandatory
383
- unless you have set `default_confirm_success_url` in your devise_token_auth initializer.
384
-
385
- So, it's up to you where you require confirmation of changing emails.
386
- [Here's an example](https://github.com/graphql-devise/graphql_devise/blob/c4dcb17e98f8d84cc5ac002c66ed98a797d3bc82/spec/dummy/app/graphql/mutations/update_user.rb#L13)
387
- on how you might do this. And also a demonstration on the method usage:
388
- ```ruby
389
- user.update_with_email(
390
- name: 'New Name',
391
- email: 'new@domain.com',
392
- schema_url: 'http://localhost:3000/graphql',
393
- confirmation_success_url: 'https://google.com'
394
- )
395
- ```
396
-
397
365
  ### Customizing Email Templates
398
366
  The approach of this gem is a bit different from DeviseTokenAuth. We have placed our templates in `app/views/graphql_devise/mailer`,
399
367
  so if you want to change them, place yours on the same dir structure on your Rails project. You can customize these two templates:
@@ -420,7 +388,7 @@ GQL schema execution like this:
420
388
  # app/controllers/my_controller.rb
421
389
 
422
390
  class MyController < ApplicationController
423
- include GraphqlDevise::Concerns::SetUserByToken
391
+ include GraphqlDevise::SetUserByToken
424
392
 
425
393
  def my_action
426
394
  result = DummySchema.execute(params[:query], context: gql_devise_context(User))
@@ -433,7 +401,7 @@ end
433
401
  # app/controllers/my_controller.rb
434
402
 
435
403
  class MyController < ApplicationController
436
- include GraphqlDevise::Concerns::SetUserByToken
404
+ include GraphqlDevise::SetUserByToken
437
405
 
438
406
  def my_action
439
407
  result = DummySchema.execute(params[:query], context: gql_devise_context(User, Admin))
@@ -479,87 +447,6 @@ module Types
479
447
  end
480
448
  ```
481
449
 
482
- #### Authenticate Before Reaching Your GQL Schema (Deprecated)
483
- For this you will need to call `authenticate_<model>!` in a `before_action` controller hook.
484
- In our example our model is `User`, so it would look like this:
485
- ```ruby
486
- # app/controllers/my_controller.rb
487
-
488
- class MyController < ApplicationController
489
- include GraphqlDevise::Concerns::SetUserByToken
490
-
491
- before_action :authenticate_user!
492
-
493
- def my_action
494
- result = DummySchema.execute(params[:query], context: { current_resource: current_user })
495
- render json: result unless performed?
496
- end
497
- end
498
- ```
499
-
500
- The install generator can include the concern in you application controller.
501
- If authentication fails for a request, execution will halt and a REST error will be returned since the request never reaches your GQL schema.
502
-
503
- #### Authenticate in an Existing Schema (Deprecated)
504
- For this you will need to add the `GraphqlDevise::SchemaPlugin` to your schema as described
505
- [here](#mounting-operations-into-your-own-schema).
506
-
507
- ```ruby
508
- # app/controllers/my_controller.rb
509
-
510
- class MyController < ApplicationController
511
- include GraphqlDevise::Concerns::SetUserByToken
512
-
513
- def my_action
514
- result = DummySchema.execute(params[:query], context: graphql_context(:user))
515
- render json: result unless performed?
516
- end
517
- end
518
- ```
519
- The `graphql_context` method receives a symbol identifying the resource you are trying
520
- to authenticate. So if you mounted the `User` resource, the symbol is `:user`. You can use
521
- this snippet to find the symbol for more complex scenarios
522
- `resource_klass.to_s.underscore.tr('/', '_').to_sym`. `graphql_context` can also take an
523
- array of resources if you mounted more than one into your schema. The gem will try to
524
- authenticate a resource for each element on the array until it finds one.
525
-
526
- Internally in your own mutations and queries a key `current_resource` will be available in
527
- the context if a resource was successfully authenticated or `nil` otherwise.
528
-
529
- Keep in mind that sending multiple values to the `graphql_context` method means that depending
530
- on who makes the request, the context value `current_resource` might contain instances of the
531
- different models you might have mounted into the schema.
532
-
533
- Please note that by using this mechanism your GQL schema will be in control of what queries are
534
- restricted to authenticated users and you can only do this at the root level fields of your GQL
535
- schema. Configure the plugin as explained [here](#mounting-operations-into-your-own-schema)
536
- so this can work.
537
-
538
- ##### Authentication Options
539
- Whether you setup authentications as a default in the plugin, or you do it at the field level,
540
- these are the options you can use:
541
- 1. **Any truthy value:** If `current_resource` is not `.present?`, query will return an authentication error.
542
- 1. **A callable object:** Provided object will be called with `current_resource` as the only argument if `current_resource` is `.present?`. If return value of the callable object is false, query will return an authentication error.
543
-
544
- In your main app's schema this is how you might specify if a field needs to be authenticated or not:
545
- ```ruby
546
- module Types
547
- class QueryType < Types::BaseObject
548
- # user field used the default set in the Plugin's initializer
549
- field :user, resolver: Resolvers::UserShow
550
- # this field will never require authentication
551
- field :public_field, String, null: false, authenticate: false
552
- # this field requires authentication
553
- field :private_field, String, null: false, authenticate: true
554
- # this field requires authenticated users to also be admins
555
- field :admin_field, String, null: false, authenticate: ->(user) { user.admin? }
556
- end
557
- end
558
- ```
559
-
560
- #### Important
561
- Remember to check `performed?` before rendering the result of the graphql operation. This is required because some operations perform a redirect and without this check you will get a `AbstractController::DoubleRenderError`.
562
-
563
450
  ### Making Requests
564
451
  Here is a list of the available mutations and queries assuming your mounted model is `User`.
565
452
 
@@ -572,30 +459,10 @@ Operation | Description | Example
572
459
  :--- | :--- | :------------------:
573
460
  login | This mutation has a second field by default. `credentials` can be fetched directly on the mutation return type.<br>Credentials are still returned in the headers of the response. | userLogin(email: String!, password: String!): UserLoginPayload |
574
461
  logout | requires authentication headers. Deletes current session if successful. | userLogout: UserLogoutPayload |
575
- signUp **(Deprecated)** | The parameter `confirmSuccessUrl` is optional unless you are using the `confirmable` plugin from Devise in your `resource`'s model. If you have `confirmable` set up, you will have to provide it unless you have `config.default_confirm_success_url` set in `config/initializers/devise_token_auth.rb`. | userSignUp(email: String!, password: String!, passwordConfirmation: String!, confirmSuccessUrl: String): UserSignUpPayload |
576
462
  register | The parameter `confirmUrl` is optional unless you are using the `confirmable` plugin from Devise in your `resource`'s model. If you have `confirmable` set up, you will have to provide it unless you have `config.default_confirm_success_url` set in `config/initializers/devise_token_auth.rb`. | userRegister(email: String!, password: String!, passwordConfirmation: String!, confirmUrl: String): UserRegisterPayload |
577
463
  sendPasswordResetWithToken | Sends an email to the provided address with a link to reset the password of the resource. First step of the most recently implemented password reset flow. | userSendPasswordResetWithToken(email: String!, redirectUrl: String!): UserSendPasswordResetWithTokenPayload |
578
464
  updatePasswordWithToken | Uses a `resetPasswordToken` to update the password of a resource. Second and last step of the most recently implemented password reset flow. | userSendPasswordResetWithToken(resetPasswordToken: String!, password: String!, passwordConfirmation: String!): UserUpdatePasswordWithTokenPayload |
579
- resendConfirmation **(Deprecated)** | The `UserResendConfirmationPayload` will return a `message: String!` that can be used to notify a user what to do after the instructions were sent to them | userResendConfirmation(email: String!, redirectUrl: String!): UserResendConfirmationPayload |
580
465
  resendConfirmationWithToken | The `UserResendConfirmationWithTokenPayload` will return a `message: String!` that can be used to notify a user what to do after the instructions were sent to them. Email will contain a link to the provided `confirmUrl` and a `confirmationToken` query param. | userResendConfirmationWithToken(email: String!, confirmUrl: String!): UserResendConfirmationWithTokenPayload |
581
- sendResetPassword **(Deprecated)** | Sends an email to the provided address with a link to reset the password of the resource. **This mutation is part of the first and soon to be deprecated password reset flow.** | userSendResetPassword(email: String!, redirectUrl: String!): UserSendResetPasswordPayload |
582
- updatePassword **(Deprecated)** | The parameter `currentPassword` is optional if you have `config.check_current_password_before_update` set to false (disabled by default) on your generated `config/initializers/devise_token_aut.rb` or if the `resource` model supports the `recoverable` Devise plugin and the `resource`'s `allow_password_change` attribute is set to true (this is done in the `userCheckPasswordToken` query when you click on the sent email's link). **This mutation is part of the first and soon to be deprecated password reset flow.** | userUpdatePassword(password: String!, passwordConfirmation: String!, currentPassword: String): UserUpdatePasswordPayload |
583
-
584
- #### Queries
585
- Operation | Description | Example
586
- :--- | :--- | :------------------:
587
- confirmAccount **(Deprecated)** | Performs a redirect using the `redirectUrl` param | userConfirmAccount(confirmationToken: String!, redirectUrl: String!): User
588
- checkPasswordToken **(Deprecated)** | Performs a redirect using the `redirectUrl` param | userCheckPasswordToken(resetPasswordToken: String!, redirectUrl: String): User
589
-
590
- The reason for having 2 queries is that these 2 are going to be accessed when clicking on
591
- the confirmation and reset password email urls. There is no limitation for making mutation
592
- requests using the `GET` method on the Rails side, but looks like there might be a limitation
593
- on the [Apollo Client](https://www.apollographql.com/docs/apollo-server/v1/requests/#get-requests).
594
-
595
- We will continue to build better docs for the gem after this first release, but in the mean time
596
- you can use [our specs](spec/requests) to better understand how to use the gem.
597
- Also, the [dummy app](spec/dummy) used in our specs will give you
598
- a clear idea on how to configure the gem on your Rails application.
599
466
 
600
467
  ### Reset Password Flow
601
468
  This gem supports two password recovery flows. The most recently implemented is preferred and
@@ -638,6 +505,48 @@ In this section the most important configurations will be highlighted.
638
505
 
639
506
  **Note:** Remember this gem adds a layer on top of Devise, so some configurations might not apply.
640
507
 
508
+ ### GraphQL 2.0 Support (>= v1.0.0)
509
+ This gem now supports [GraphQL Ruby](https://github.com/rmosolgo/graphql-ruby) v2.
510
+ There's one manual step you need to take in order for this to work.
511
+
512
+ You need a custom `field_class` in your `MutationType` and `QueryType`. If you don't have one setup already, you can simply add the one
513
+ this gem provides, like this:
514
+
515
+ ```ruby
516
+ module Types
517
+ class MutationType < BaseObject
518
+ field_class GraphqlDevise::Types::BaseField
519
+ end
520
+ end
521
+
522
+ module Types
523
+ class QueryType < Types::BaseObject
524
+ field_class GraphqlDevise::Types::BaseField
525
+ end
526
+ end
527
+ ```
528
+
529
+ If you already have a `field_class` defined in any of your types, the only thing you need to do is add another `kwarg`
530
+ to that class initializer (`authenticate`) and make that value available through an attribute reader.
531
+
532
+ The next example is this gem's implementation of a custom class, but you can implement your own however you see fit
533
+ as long as you expose an `authenticate` public method with the value that was passed to the initializer.
534
+
535
+ ```ruby
536
+ module GraphqlDevise
537
+ module Types
538
+ class BaseField < GraphQL::Schema::Field
539
+ def initialize(*args, authenticate: nil, **kwargs, &block)
540
+ @authenticate = authenticate
541
+ super(*args, **kwargs, &block)
542
+ end
543
+
544
+ attr_reader :authenticate
545
+ end
546
+ end
547
+ end
548
+ ```
549
+
641
550
  ### GraphQL Interpreter
642
551
  GraphQL-Ruby `>= 1.9.0` includes a new runtime module which you may use for your schema.
643
552
  Eventually, it will become the default. You can read more about it
@@ -653,6 +562,9 @@ information you can check [this answer here](https://github.com/lynndylanhurley/
653
562
  This gem supports the same and should be easier to handle email templates due to the fact we don't override
654
563
  standard Devise templates.
655
564
 
565
+ ## Changelog
566
+ Full list of changes in [CHANGELOG.md](CHANGELOG.md)
567
+
656
568
  ## Future Work
657
569
  We will continue to improve the gem and add better docs.
658
570
 
@@ -661,6 +573,23 @@ We will continue to improve the gem and add better docs.
661
573
  1. Add support for unlockable and other Devise modules.
662
574
  1. Add feature specs for confirm account and reset password flows.
663
575
 
576
+ We will continue to build better docs for the gem after this first release, but in the mean time
577
+ you can use [our specs](spec/requests) to better understand how to use the gem.
578
+ Also, the [dummy app](spec/dummy) used in our specs will give you
579
+ a clear idea on how to configure the gem on your Rails application.
580
+
581
+ ## Buy Us a Coffee
582
+ If you'd like to support our work, you are welcome to do so!
583
+
584
+ ##### BTC
585
+ ```
586
+ bc1qntlmyl24wuf6y5jyn2vg8kduss57dwtyrcflyq
587
+ ```
588
+ ##### ADA
589
+ ```
590
+ addr1q8e8cjzutzptcrfgjgsjl3k4t4xy5ucrmkf2dmq9qn966q8saucty53avujfc9yu9vfk7266auhdx9fz4fsryzeagqds893nfw
591
+ ```
592
+
664
593
  ## Contributing
665
594
 
666
595
  Bug reports and pull requests are welcome on GitHub at https://github.com/graphql-devise/graphql_devise.
@@ -4,17 +4,17 @@ require_dependency 'graphql_devise/application_controller'
4
4
 
5
5
  module GraphqlDevise
6
6
  class GraphqlController < ApplicationController
7
- include GraphqlDevise::SetUserByToken
7
+ include SetUserByToken
8
8
 
9
9
  def auth
10
10
  result = if params[:_json]
11
- GraphqlDevise::Schema.multiplex(
11
+ Schema.multiplex(
12
12
  params[:_json].map do |param|
13
13
  { query: param[:query] }.merge(execute_params(param))
14
14
  end
15
15
  )
16
16
  else
17
- GraphqlDevise::Schema.execute(params[:query], **execute_params(params))
17
+ Schema.execute(params[:query], **execute_params(params))
18
18
  end
19
19
 
20
20
  render json: result unless performed?
@@ -3,9 +3,5 @@
3
3
  <p><%= t('.confirm_link_msg') %></p>
4
4
 
5
5
  <p>
6
- <% if message['schema_url'].present? %>
7
- <%= link_to t('.confirm_account_link'), "#{message['schema_url']}?#{confirmation_query(resource_name: @resource.class.to_s, redirect_url: message['redirect-url'], token: @token).to_query}" %>
8
- <% else %>
9
- <%= link_to t('.confirm_account_link'), "#{CGI.escape(message['redirect-url'].to_s)}?#{{ confirmationToken: @token }.to_query}" %>
10
- <% end %>
6
+ <%= link_to t('.confirm_account_link'), "#{message['redirect-url'].to_s}?#{{ confirmationToken: @token }.to_query}" %>
11
7
  </p>
data/config/routes.rb CHANGED
@@ -14,7 +14,5 @@ GraphqlDevise::Engine.routes.draw do
14
14
  GraphqlDevise::Schema.query(GraphqlDevise::Types::QueryType)
15
15
 
16
16
  GraphqlDevise.load_schema
17
-
18
- Devise.mailer.helper(GraphqlDevise::MailerHelper)
19
17
  end
20
18
  end
@@ -25,11 +25,12 @@ Gem::Specification.new do |spec|
25
25
  `git ls-files -z`.split("\x0").select { |f| f.match(%r{^spec/}) }
26
26
  end
27
27
 
28
- spec.required_ruby_version = '>= 2.2.0'
28
+ spec.required_ruby_version = '>= 2.4.4'
29
29
 
30
30
  spec.add_dependency 'devise_token_auth', '>= 0.1.43', '< 2.0'
31
- spec.add_dependency 'graphql', '>= 1.8', '< 1.14.0'
31
+ spec.add_dependency 'graphql', '>= 1.8', '< 2.1'
32
32
  spec.add_dependency 'rails', '>= 4.2', '< 6.2'
33
+ spec.add_dependency 'zeitwerk'
33
34
 
34
35
  spec.add_development_dependency 'appraisal'
35
36
  spec.add_development_dependency 'coveralls-ruby', '~> 0.2'
@@ -41,8 +42,9 @@ Gem::Specification.new do |spec|
41
42
  spec.add_development_dependency 'pry-byebug'
42
43
  spec.add_development_dependency 'rake', '>= 12.3.3'
43
44
  spec.add_development_dependency 'rspec-rails', '~> 4.0'
44
- spec.add_development_dependency 'rubocop', '0.68.1'
45
- spec.add_development_dependency 'rubocop-performance'
46
- spec.add_development_dependency 'rubocop-rspec'
45
+ spec.add_development_dependency 'rubocop', '< 0.82.0'
46
+ spec.add_development_dependency 'rubocop-performance', '< 1.6.0'
47
+ spec.add_development_dependency 'rubocop-rails', '< 2.6.0'
48
+ spec.add_development_dependency 'rubocop-rspec', '< 1.39.0'
47
49
  spec.add_development_dependency 'sqlite3', '~> 1.3'
48
50
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphqlDevise
4
+ module AdditionalControllerMethods
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ attr_accessor :client_id, :token, :resource
9
+ end
10
+
11
+ def gql_devise_context(*models)
12
+ {
13
+ current_resource: authenticate_model(*models),
14
+ controller: self
15
+ }
16
+ end
17
+
18
+ def authenticate_model(*models)
19
+ models.each do |model|
20
+ set_resource_by_token(model)
21
+ return @resource if @resource.present?
22
+ end
23
+
24
+ nil
25
+ end
26
+
27
+ def resource_class(resource = nil)
28
+ # Return the resource class instead of looking for a Devise mapping if resource is already a resource class
29
+ return resource if resource.respond_to?(:find_by)
30
+
31
+ super
32
+ end
33
+
34
+ def set_resource_by_token(resource)
35
+ set_user_by_token(resource)
36
+ end
37
+
38
+ def build_redirect_headers(access_token, client, redirect_header_options = {})
39
+ {
40
+ DeviseTokenAuth.headers_names[:"access-token"] => access_token,
41
+ DeviseTokenAuth.headers_names[:client] => client,
42
+ :config => params[:config],
43
+ :client_id => client,
44
+ :token => access_token
45
+ }.merge(redirect_header_options)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphqlDevise
4
+ module AdditionalModelMethods
5
+ extend ActiveSupport::Concern
6
+
7
+ class_methods do
8
+ def reconfirmable
9
+ devise_modules.include?(:confirmable) && column_names.include?('unconfirmed_email')
10
+ end
11
+ end
12
+
13
+ def update_with_email(attributes = {})
14
+ GraphqlDevise::Model::WithEmailUpdater.new(self, attributes).call
15
+ end
16
+ end
17
+ end
@@ -6,7 +6,7 @@ module GraphqlDevise
6
6
 
7
7
  included do
8
8
  include DeviseTokenAuth::Concerns::User
9
- include GraphqlDevise::Concerns::AdditionalModelMethods
9
+ include AdditionalModelMethods
10
10
 
11
11
  ::GraphqlDevise.configure_warden_serializer_for_model(self)
12
12
  end
@@ -1,122 +1,99 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GraphqlDevise
4
- module Concerns
5
- module ControllerMethods
6
- extend ActiveSupport::Concern
4
+ module ControllerMethods
5
+ extend ActiveSupport::Concern
7
6
 
8
- private
7
+ private
9
8
 
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
-
16
- def raise_user_error(message)
17
- raise GraphqlDevise::UserError, message
18
- end
19
-
20
- def raise_user_error_list(message, errors:)
21
- raise GraphqlDevise::DetailedUserError.new(message, errors: errors)
22
- end
23
-
24
- def remove_resource
25
- controller.resource = nil
26
- controller.client_id = nil
27
- controller.token = nil
9
+ def check_redirect_url_whitelist!(redirect_url)
10
+ if blacklisted_redirect_url?(redirect_url)
11
+ raise_user_error(I18n.t('graphql_devise.redirect_url_not_allowed', redirect_url: redirect_url))
28
12
  end
13
+ end
29
14
 
30
- def request
31
- controller.request
32
- end
15
+ def raise_user_error(message)
16
+ raise UserError, message
17
+ end
33
18
 
34
- def response
35
- controller.response
36
- end
19
+ def raise_user_error_list(message, errors:)
20
+ raise DetailedUserError.new(message, errors: errors)
21
+ end
37
22
 
38
- def controller
39
- context[:controller]
40
- end
23
+ def remove_resource
24
+ controller.resource = nil
25
+ controller.client_id = nil
26
+ controller.token = nil
27
+ end
41
28
 
42
- def resource_name
43
- GraphqlDevise.to_mapping_name(resource_class)
44
- end
29
+ def response
30
+ controller.response
31
+ end
45
32
 
46
- def resource_class
47
- self.class.instance_variable_get(:@resource_klass)
48
- end
33
+ def controller
34
+ context[:controller]
35
+ end
49
36
 
50
- def recoverable_enabled?
51
- resource_class.devise_modules.include?(:recoverable)
52
- end
37
+ def resource_name
38
+ ::GraphqlDevise.to_mapping_name(resource_class)
39
+ end
53
40
 
54
- def confirmable_enabled?
55
- resource_class.devise_modules.include?(:confirmable)
56
- end
41
+ def resource_class
42
+ self.class.instance_variable_get(:@resource_klass)
43
+ end
57
44
 
58
- def blacklisted_redirect_url?(redirect_url)
59
- DeviseTokenAuth.redirect_whitelist && !DeviseTokenAuth::Url.whitelisted?(redirect_url)
60
- end
45
+ def recoverable_enabled?
46
+ resource_class.devise_modules.include?(:recoverable)
47
+ end
61
48
 
62
- def current_resource
63
- @current_resource ||= controller.send(:set_resource_by_token, resource_class)
64
- end
49
+ def confirmable_enabled?
50
+ resource_class.devise_modules.include?(:confirmable)
51
+ end
65
52
 
66
- def client
67
- if Gem::Version.new(DeviseTokenAuth::VERSION) <= Gem::Version.new('1.1.0')
68
- controller.client_id
69
- else
70
- controller.token.client if controller.token.present?
71
- end
72
- end
53
+ def blacklisted_redirect_url?(redirect_url)
54
+ DeviseTokenAuth.redirect_whitelist && !DeviseTokenAuth::Url.whitelisted?(redirect_url)
55
+ end
73
56
 
74
- def set_auth_headers(resource)
75
- auth_headers = resource.create_new_auth_token
76
- response.headers.merge!(auth_headers)
57
+ def current_resource
58
+ @current_resource ||= controller.send(:set_resource_by_token, resource_class)
59
+ end
77
60
 
78
- auth_headers
61
+ def client
62
+ if Gem::Version.new(DeviseTokenAuth::VERSION) <= Gem::Version.new('1.1.0')
63
+ controller.client_id
64
+ else
65
+ controller.token.client if controller.token.present?
79
66
  end
67
+ end
80
68
 
81
- def client_and_token(token)
82
- if Gem::Version.new(DeviseTokenAuth::VERSION) <= Gem::Version.new('1.1.0')
83
- { client_id: token.first, token: token.last }
84
- else
85
- { client_id: token.client, token: token.token }
86
- end
87
- end
69
+ def set_auth_headers(resource)
70
+ auth_headers = resource.create_new_auth_token
71
+ response.headers.merge!(auth_headers)
88
72
 
89
- def redirect_headers(token_info, redirect_header_options)
90
- controller.send(
91
- :build_redirect_headers,
92
- token_info.fetch(:token),
93
- token_info.fetch(:client_id),
94
- redirect_header_options
95
- )
96
- end
73
+ auth_headers
74
+ end
97
75
 
98
- def find_resource(field, value)
99
- if resource_class.connection.adapter_name.downcase.include?('mysql')
100
- # fix for mysql default case insensitivity
101
- resource_class.where("BINARY #{field} = ? AND provider= ?", value, provider).first
102
- elsif Gem::Version.new(DeviseTokenAuth::VERSION) < Gem::Version.new('1.1.0')
103
- resource_class.find_by(field => value, :provider => provider)
104
- else
105
- resource_class.dta_find_by(field => value, :provider => provider)
106
- end
76
+ def find_resource(field, value)
77
+ if resource_class.connection.adapter_name.downcase.include?('mysql')
78
+ # fix for mysql default case insensitivity
79
+ resource_class.where("BINARY #{field} = ? AND provider= ?", value, provider).first
80
+ elsif Gem::Version.new(DeviseTokenAuth::VERSION) < Gem::Version.new('1.1.0')
81
+ resource_class.find_by(field => value, :provider => provider)
82
+ else
83
+ resource_class.dta_find_by(field => value, :provider => provider)
107
84
  end
85
+ end
108
86
 
109
- def get_case_insensitive_field(field, value)
110
- if resource_class.case_insensitive_keys.include?(field)
111
- value.downcase
112
- else
113
- value
114
- end
87
+ def get_case_insensitive_field(field, value)
88
+ if resource_class.case_insensitive_keys.include?(field)
89
+ value.downcase
90
+ else
91
+ value
115
92
  end
93
+ end
116
94
 
117
- def provider
118
- :email
119
- end
95
+ def provider
96
+ :email
120
97
  end
121
98
  end
122
99
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GraphqlDevise
4
+ module FieldAuthentication
5
+ extend ActiveSupport::Concern
6
+
7
+ def initialize(*args, authenticate: nil, **kwargs, &block)
8
+ @authenticate = authenticate
9
+ super(*args, **kwargs, &block)
10
+ end
11
+
12
+ attr_reader :authenticate
13
+ end
14
+ end