graphql_devise 0.13.0 → 0.13.5

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: 34880444c63dfec84dd91addc76574355469fdab6b3e0a00100ab4edde7da869
4
- data.tar.gz: 3e3cbc8dd402f3d2e7450f301b1f0506bd804a1a62ddc7acc5b0c6c07bd892c2
3
+ metadata.gz: 005b85ca3899cb7b69c3505680be677fa935f80b3d63480fbf65d7f116775efa
4
+ data.tar.gz: 8473a4ff5404ec543f57c9d95ad2844a039ba691865ca2d8fbea15a197f6d9b7
5
5
  SHA512:
6
- metadata.gz: 953635cd445812d68d15e20367712b3118abb4bcea774859a80ce7265bc710c9c5917804ddb80f26868e2455591c2a96d14d10d4b5c6ff36315e18680e2d1534
7
- data.tar.gz: 8b4bbba71c257d2be8fbc73e3c07817bc013a755fde9d13c6226f748e2ceebde975888d6f4e411584c3bb45ae4e6777cd1c8023c20a7f4fb35eb51655f44bb16
6
+ metadata.gz: 1accf0a12781a9b53b0f17f25226c3cd8fb8e31e26e435ce1040a132f83f508e06532c202a3789a90dcb0fd54dd10e72d047c5da1b431bb8d1147c319abc4870
7
+ data.tar.gz: 4d5649f9f7d724cfbd6fc8a06e5acf2e0a3196d5f6ef7e8f4d5a569f39ae9978fc3ab6a956c110a19a7c8783b753e61f40aac9b8dcc77100b52ce14b3f6bff1b
@@ -1,5 +1,50 @@
1
1
  # Changelog
2
2
 
3
+ ## [v0.13.5](https://github.com/graphql-devise/graphql_devise/tree/v0.13.5) (2020-11-20)
4
+
5
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.4...v0.13.5)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Fixes connection\_config deprecation warning [\#135](https://github.com/graphql-devise/graphql_devise/pull/135) ([artplan1](https://github.com/artplan1))
10
+
11
+ ## [v0.13.4](https://github.com/graphql-devise/graphql_devise/tree/v0.13.4) (2020-08-15)
12
+
13
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.3...v0.13.4)
14
+
15
+ **Implemented enhancements:**
16
+
17
+ - Allow resend of confirmation with unconfirmed email [\#127](https://github.com/graphql-devise/graphql_devise/pull/127) ([j15e](https://github.com/j15e))
18
+
19
+ ## [v0.13.3](https://github.com/graphql-devise/graphql_devise/tree/v0.13.3) (2020-08-13)
20
+
21
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.2...v0.13.3)
22
+
23
+ **Fixed bugs:**
24
+
25
+ - Fix unconfirmed\_email confirmation. Ignore devise reconfirmable config. [\#126](https://github.com/graphql-devise/graphql_devise/pull/126) ([mcelicalderon](https://github.com/mcelicalderon))
26
+
27
+ ## [v0.13.2](https://github.com/graphql-devise/graphql_devise/tree/v0.13.2) (2020-08-12)
28
+
29
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.1...v0.13.2)
30
+
31
+ **Fixed bugs:**
32
+
33
+ - Save resource after generating credentials in resource confirmation [\#125](https://github.com/graphql-devise/graphql_devise/pull/125) ([mcelicalderon](https://github.com/mcelicalderon))
34
+
35
+ ## [v0.13.1](https://github.com/graphql-devise/graphql_devise/tree/v0.13.1) (2020-07-29)
36
+
37
+ [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.13.0...v0.13.1)
38
+
39
+ **Implemented enhancements:**
40
+
41
+ - Add credentials field on signUp mutation [\#122](https://github.com/graphql-devise/graphql_devise/pull/122) ([mcelicalderon](https://github.com/mcelicalderon))
42
+
43
+ **Closed issues:**
44
+
45
+ - Checking for `performed?` when mounting into your graphql schema. [\#110](https://github.com/graphql-devise/graphql_devise/issues/110)
46
+ - no query string for email reset [\#104](https://github.com/graphql-devise/graphql_devise/issues/104)
47
+
3
48
  ## [v0.13.0](https://github.com/graphql-devise/graphql_devise/tree/v0.13.0) (2020-06-22)
4
49
 
5
50
  [Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.12.3...v0.13.0)
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
 
@@ -14,19 +14,22 @@ GraphQL interface on top of the [Devise Token Auth](https://github.com/lynndylan
14
14
  * [Installation](#installation)
15
15
  * [Running the Generator](#running-the-generator)
16
16
  * [Mounting the Schema in a Separate Route](#mounting-the-schema-in-a-separate-route)
17
- * [Mounting Operations in Your Own Schema](#mounting-operations-in-your-own-schema)
18
- * [Important](#important)
17
+ * [Important](#important)
18
+ * [Mounting Operations in Your Own Schema (> v0.12.0)](#mounting-operations-in-your-own-schema--v0120)
19
+ * [Important](#important-1)
19
20
  * [Usage](#usage)
20
21
  * [Mounting Auth Schema on a Separate Route](#mounting-auth-schema-on-a-separate-route)
21
22
  * [Mounting Operations Into Your Own Schema](#mounting-operations-into-your-own-schema)
22
23
  * [Available Mount Options](#available-mount-options)
23
24
  * [Available Operations](#available-operations)
24
25
  * [Configuring Model](#configuring-model)
26
+ * [Email Reconfirmation](#email-reconfirmation)
25
27
  * [Customizing Email Templates](#customizing-email-templates)
26
28
  * [I18n](#i18n)
27
29
  * [Authenticating Controller Actions](#authenticating-controller-actions)
28
30
  * [Authenticate Before Reaching Your GQL Schema](#authenticate-before-reaching-your-gql-schema)
29
31
  * [Authenticate in Your GQL Schema](#authenticate-in-your-gql-schema)
32
+ * [Important](#important-2)
30
33
  * [Making Requests](#making-requests)
31
34
  * [Mutations](#mutations)
32
35
  * [Queries](#queries)
@@ -39,20 +42,20 @@ GraphQL interface on top of the [Devise Token Auth](https://github.com/lynndylan
39
42
  * [Contributing](#contributing)
40
43
  * [License](#license)
41
44
 
42
- <!-- Added by: mcelicalderon, at: Wed Jun 10 22:10:26 -05 2020 -->
45
+ <!-- Added by: david, at: mar jul 14 08:08:02 -05 2020 -->
43
46
 
44
47
  <!--te-->
45
48
 
46
49
  ## Introduction
47
- This gem heavily relies on two gems, [Devise Token Auth](https://github.com/lynndylanhurley/devise_token_auth) (DTA)
48
- and [Devise](https://github.com/heartcombo/devise) which is a dependency of DTA.
49
- It provides a GraphQL interface on top of DTA which is designed to work with REST APIs. That's why
50
- things like token management, token expiration and everything up until using the actual GraphQL schema is
51
- still controlled by DTA. For that reason you will find that our generator runs these two gems generator and two
52
- initializer files are included. We'll provide more configuration details in the
53
- [configuration section](#more-configuration-options),
54
- but **we recommend you get familiar with [DTA and their docs](https://github.com/lynndylanhurley/devise_token_auth)
55
- in order to use this gem to its full potential**.
50
+ Graphql-Devise heavily relies on 3 gems:
51
+ - [GraphQL Ruby](https://github.com/rmosolgo/graphql-ruby)
52
+ - [Devise Token Auth](https://github.com/lynndylanhurley/devise_token_auth) (DTA)
53
+ - [Devise](https://github.com/heartcombo/devise) (which is a DTA dependency)
54
+
55
+ This gem provides a GraphQL interface on top of DTA which is designed for REST APIs. Features like token management, token expiration and everything up until using the actual GraphQL schema is still controlled by DTA. For that reason the gem's generator invokes DTA and Devise generators and creates initializer files for each one of them.
56
+
57
+ **We strongly recommend getting familiar with [DTA documentation](https://github.com/lynndylanhurley/devise_token_auth) to use this gem to its full potential**.
58
+ More configuration details available in [configuration section](#more-configuration-options)
56
59
 
57
60
  ## Installation
58
61
 
@@ -68,20 +71,21 @@ $ bundle
68
71
  ```
69
72
 
70
73
  ### Running the Generator
71
- Graphql Devise generator will execute `Devise` and `Devise Token Auth`
72
- generators for you. These will make the required changes for the gems to
73
- work correctly. All configurations for [Devise](https://github.com/plataformatec/devise) and
74
- [Devise Token Auth](https://github.com/lynndylanhurley/devise_token_auth) are available,
75
- so you can read the docs there to customize your options.
76
- Configurations are done via initializer files as usual, one per gem.
74
+ Graphql Devise generator will execute `Devise` and `Devise Token Auth` generators to setup the gems in your project. You can customize them to your needs using their initializer files(one per gem) as usual.
77
75
 
78
- #### Mounting the Schema in a Separate Route
79
76
  ```bash
80
77
  $ bundle exec rails generate graphql_devise:install
81
78
  ```
79
+ The generator accepts 2 params:
80
+ - `user_class`: Model name in which `Devise` modules will be included. This uses a `find or create` strategy. Defaults to `User`.
81
+ - `mount_path`: Path in which the dedicated graphql schema for devise will be mounted. Defaults to `/graphql_auth`.
82
82
 
83
- The generator accepts 2 params: `user_class` and `mount_path`. The params
84
- will be used to mount the route in `config/routes.rb`. For instance the executing:
83
+ The option `mount` is available starting from `v0.12.0`. This option will allow you to mount the operations in your own schema instead of a dedicated one. When this option is provided `mount_path` param is not used.
84
+
85
+ #### Mounting the Schema in a Separate Route
86
+
87
+ To configure the gem to use a separate schema, the generator will use `user_class` and `mount_path` params.
88
+ The route will be mounted in `config/routes.rb`. For instance the executing:
85
89
 
86
90
  ```bash
87
91
  $ bundle exec rails g graphql_devise:install Admin api/auth
@@ -99,32 +103,43 @@ Will do the following:
99
103
  `Admin` could be any model name you are going to be using for authentication,
100
104
  and `api/auth` could be any mount path you would like to use for auth.
101
105
 
102
- #### Mounting Operations in Your Own Schema
103
- Now you can provide to the generator an option specifying
104
- the name of your GQL schema. Doing this will skip the insertion of the mount method in the
105
- routes file and will also add our `SchemaPlugin` to the specified schema. `user_class` param is still optional (`Admin`) in the following example.
106
+ ##### Important
107
+ - Remember that by default this gem mounts a completely separate GraphQL schema on a separate controller in the route provided by the `at` option in the `mount_graphql_devise_for` method in the `config/routes.rb` file. If no `at` option is provided, the route will be `/graphql_auth`.
108
+ - Avoid passing the `--mount` option or the gem will try to use an existing schema.
109
+
110
+ #### Mounting Operations in Your Own Schema (> v0.12.0)
111
+ To configure the gem to use your own GQL schema use the `--mount` option.
112
+ For instance the executing:
106
113
 
107
114
  ```bash
108
115
  $ bundle exec rails g graphql_devise:install Admin --mount MySchema
109
116
  ```
110
117
 
111
- ### Important
112
- Remember that by default this gem mounts a completely separate GraphQL schema on a separate controller in the route
113
- provided by the `at` option in the `mount_graphql_devise_for` method in the `config/routes.rb` file. If no `at`
114
- option is provided, the route will be `/graphql_auth`.
118
+ Will do the following:
119
+ - Execute `Devise` install generator
120
+ - Execute `Devise Token Auth` install generator with `Admin` and `api/auth` as params
121
+ - Find or create `Admin` model
122
+ - Add `devise` modules to `Admin` model
123
+ - Other changes that you can find [here](https://devise-token-auth.gitbook.io/devise-token-auth/config)
124
+ - Add `SchemaPlugin` to the specified schema.
125
+
115
126
 
116
- **Starting with `v0.12.0`** you can opt-in to load this gem's queries and mutations into your
117
- own application's schema. You can actually mount a resource's auth schema in a separate route
118
- and in your app's schema at the same time, but that's probably not a common scenario. More on
119
- this in the next section.
127
+ ##### Important
128
+ - When using the `--mount` option the `mount_path` params is ignored.
129
+ - The generator will look for your schema under `app/graphql/` directory. We are expecting the name of the file is the same as the as the one passed in the mount option transformed with `underscore`. In the example, passing `MySchema`, will try to find the file `app/graphql/my_schema.rb`.
130
+ - You can actually mount a resource's auth schema in a separate route and in your app's schema at the same time, but that's probably not a common scenario.
120
131
 
121
132
  ## Usage
122
- ### Mounting Auth Schema on a Separate Route
123
- The generator can do this step for you by default. Remember now you can mount this gem's
124
- auth operations into your own schema as described in [this section](#mounting-operations-into-your-own-schema).
125
133
 
134
+ GraphqlDevise operations can be used in two ways:
135
+ - Using a [separate schema](#mounting-auth-schema-on-a-separate-route) via `mount_graphql_devise_for` helper in the routes file.
136
+ - Using [your own schema](#mounting-operations-into-your-own-schema) by adding a plugin in the class.
137
+
138
+
139
+ Creating a separate schema is the default option, the generator will do that by default.
140
+
141
+ ### Mounting Auth Schema on a Separate Route
126
142
 
127
- Routes can be added using the generator or manually.
128
143
  You can mount this gem's GraphQL auth schema in your routes file like this:
129
144
 
130
145
  ```ruby
@@ -150,11 +165,13 @@ Rails.application.routes.draw do
150
165
  )
151
166
  end
152
167
  ```
168
+ This can be done using the generator or manually.
153
169
  The second argument of the `mount_graphql_devise` method is a hash of options where you can
154
170
  customize how the queries and mutations are mounted into the schema. For a list of available
155
171
  options go [here](#available-mount-options)
156
172
 
157
173
  ### Mounting Operations Into Your Own Schema
174
+
158
175
  Starting with `v0.12.0` you can now mount the GQL operations provided by this gem into your
159
176
  app's main schema.
160
177
 
@@ -302,20 +319,19 @@ The install generator can do this for you if you specify the `user_class` option
302
319
  See [Installation](#installation) for details.
303
320
 
304
321
  ### Email Reconfirmation
305
- DTA and Devise support email reconfirmation. When the `confirmable` module is added to your
306
- resource, an email is sent to the provided email address when the `signUp` mutation is used.
307
- You can also use this gem so every time a user updates the `email` field, a new email gets sent
308
- for the user to confirm the new email address. Only after clicking on the confirmation link,
309
- the email will be updated on the database to use the new value.
310
-
311
- In order to use this feature there are a couple of things to setup first:
312
- 1. Make user your model includes the `:confirmable` module.
313
- 1. Add an `unconfirmed_email` String column to your resource's table.
314
-
315
- After that is done, you simply need to call a different update method on your resource,
316
- `update_with_email`. This method behaves exactly the same as ActiveRecord's `update` method
317
- if the previous steps are not performed, or if you are not updating the `email` attribute.
318
- 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
319
335
  will be raised:
320
336
 
321
337
  1. `schema_url`: The full url where your GQL schema is mounted. You can get this value from the
@@ -339,6 +355,9 @@ user.update_with_email(
339
355
  )
340
356
  ```
341
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
+
342
361
  ### Customizing Email Templates
343
362
  The approach of this gem is a bit different from DeviseTokenAuth. We have placed our templates in `app/views/graphql_devise/mailer`,
344
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:
@@ -354,11 +373,10 @@ GraphQL Devise supports locales. For example, the `graphql_devise.confirmations.
354
373
  Keep in mind that if your app uses multiple locales, you should set the `I18n.locale` accordingly. You can learn how to do this [here](https://guides.rubyonrails.org/i18n.html).
355
374
 
356
375
  ### Authenticating Controller Actions
357
- Just like with Devise or DTA, you will need to authenticate users in your controllers.
358
- For this you have two alternatives.
376
+ When mounting the operation is in you own schema instead of a dedicated one, you will need to authenticate users in your controllers, just like in DTA. There are 2 alternatives to accomplish this.
359
377
 
360
378
  #### Authenticate Before Reaching Your GQL Schema
361
- For this you need to call `authenticate_<model>!` in a before_action hook of your controller.
379
+ For this you will need to call `authenticate_<model>!` in a `before_action` controller hook.
362
380
  In our example our model is `User`, so it would look like this:
363
381
  ```ruby
364
382
  # app/controllers/my_controller.rb
@@ -369,15 +387,14 @@ class MyController < ApplicationController
369
387
  before_action :authenticate_user!
370
388
 
371
389
  def my_action
372
- render json: { current_user: current_user }
390
+ result = DummySchema.execute(params[:query], context: current_user: current_user)
391
+ render json: result unless performed?
373
392
  end
374
393
  end
375
394
  ```
376
395
 
377
- The install generator can do this for you because it executes DTA installer.
378
- See [Installation](#Installation) for details.
379
- If authentication fails for the request for whatever reason, execution of the request is halted
380
- and an error is returned in a REST format as the request never reaches your GQL schema.
396
+ The install generator can include the concern in you application controller.
397
+ If authentication fails for a request, execution will halt and a REST error will be returned since the request never reaches your GQL schema.
381
398
 
382
399
  #### Authenticate in Your GQL Schema
383
400
  For this you will need to add the `GraphqlDevise::SchemaPlugin` to your schema as described
@@ -390,7 +407,8 @@ class MyController < ApplicationController
390
407
  include GraphqlDevise::Concerns::SetUserByToken
391
408
 
392
409
  def my_action
393
- render json: DummySchema.execute(params[:query], context: graphql_context(:user))
410
+ result = DummySchema.execute(params[:query], context: graphql_context(:user))
411
+ render json: result unless performed?
394
412
  end
395
413
  end
396
414
  ```
@@ -427,32 +445,28 @@ module Types
427
445
  end
428
446
  ```
429
447
 
448
+ #### Important
449
+ 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`.
450
+
430
451
  ### Making Requests
431
452
  Here is a list of the available mutations and queries assuming your mounted model is `User`.
432
453
 
433
454
  #### Mutations
434
- 1. `userLogin(email: String!, password: String!): UserLoginPayload`
435
-
436
- This mutation has a second field by default. `credentials` can be fetched directly on the mutation return type.
437
- Credentials are still returned in the headers of the response.
438
-
439
- 1. `userLogout: UserLogoutPayload`
440
- 1. `userSignUp(email: String!, password: String!, passwordConfirmation: String!, confirmSuccessUrl: String): UserSignUpPayload`
441
-
442
- 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`.
443
- 1. `userSendResetPassword(email: String!, redirectUrl: String!): UserSendReserPasswordPayload`
444
- 1. `userUpdatePassword(password: String!, passwordConfirmation: String!, currentPassword: String): UserUpdatePasswordPayload`
445
-
446
- The parameter `currentPassword` is optional if you have `config.check_current_password_before_update` set to
447
- false (disabled by default) on your generated `config/initializers/devise_token_aut.rb` or if the `resource`
448
- 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).
449
- 1. `userResendConfirmation(email: String!, redirectUrl: String!): UserResendConfirmationPayload`
450
455
 
451
- The `UserResendConfirmationPayload` will return the `authenticatable` resource that was sent the confirmation instructions but also has a `message: String!` that can be used to notify a user what to do after the instructions were sent to them
456
+ Operation | Description | Example
457
+ :--- | :--- | :------------------:
458
+ 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
459
+ logout | | userLogout: UserLogoutPayload
460
+ signUp | 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
461
+ sendResetPassword | | userSendResetPassword(email: String!, redirectUrl: String!): UserSendReserPasswordPayload
462
+ updatePassword | 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). | userUpdatePassword(password: String!, passwordConfirmation: String!, currentPassword: String): UserUpdatePasswordPayload
463
+ resendConfirmation | The `UserResendConfirmationPayload` will return the `authenticatable` resource that was sent the confirmation instructions but also has 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
452
464
 
453
465
  #### Queries
454
- 1. `userConfirmAccount(confirmationToken: String!, redirectUrl: String!): User`
455
- 1. `userCheckPasswordToken(resetPasswordToken: String!, redirectUrl: String): User`
466
+ Operation | Description | Example
467
+ :--- | :--- | :------------------:
468
+ confirmAccount | Performs a redirect using the `redirectUrl` param | userConfirmAccount(confirmationToken: String!, redirectUrl: String!): User
469
+ checkPasswordToken | Performs a redirect using the `redirectUrl` param | userCheckPasswordToken(resetPasswordToken: String!, redirectUrl: String): User
456
470
 
457
471
  The reason for having 2 queries is that these 2 are going to be accessed when clicking on
458
472
  the confirmation and reset password email urls. There is no limitation for making mutation
@@ -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
@@ -5,7 +5,7 @@ module GraphqlDevise
5
5
  source_root File.expand_path('templates', __dir__)
6
6
 
7
7
  argument :user_class, type: :string, default: 'User'
8
- argument :mount_path, type: :string, default: 'auth'
8
+ argument :mount_path, type: :string, default: 'graphql_auth'
9
9
 
10
10
  class_option :mount, type: :string, default: 'separate_route'
11
11
 
@@ -90,7 +90,7 @@ module GraphqlDevise
90
90
  end
91
91
 
92
92
  def find_resource(field, value)
93
- if resource_class.try(:connection_config).try(:[], :adapter).try(:include?, 'mysql')
93
+ if resource_class.connection.adapter_name.downcase.include?('mysql')
94
94
  # fix for mysql default case insensitivity
95
95
  resource_class.where("BINARY #{field} = ? AND provider= ?", value, provider).first
96
96
  elsif Gem::Version.new(DeviseTokenAuth::VERSION) < Gem::Version.new('1.1.0')
@@ -9,15 +9,14 @@ 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
+ resource = find_confirmable_resource(email)
16
13
 
17
14
  if resource
18
15
  yield resource if block_given?
19
16
 
20
- raise_user_error(I18n.t('graphql_devise.confirmations.already_confirmed')) if resource.confirmed?
17
+ if resource.confirmed? && !resource.pending_reconfirmation?
18
+ raise_user_error(I18n.t('graphql_devise.confirmations.already_confirmed'))
19
+ end
21
20
 
22
21
  resource.send_confirmation_instructions(
23
22
  redirect_url: redirect_url,
@@ -30,6 +29,15 @@ module GraphqlDevise
30
29
  raise_user_error(I18n.t('graphql_devise.confirmations.user_not_found', email: email))
31
30
  end
32
31
  end
32
+
33
+ private
34
+
35
+ def find_confirmable_resource(email)
36
+ email_insensitive = get_case_insensitive_field(:email, email)
37
+ resource = find_resource(:unconfirmed_email, email_insensitive) if resource_class.reconfirmable
38
+ resource ||= find_resource(:email, email_insensitive)
39
+ resource
40
+ end
33
41
  end
34
42
  end
35
43
  end
@@ -8,6 +8,11 @@ module GraphqlDevise
8
8
  argument :password_confirmation, String, required: true
9
9
  argument :confirm_success_url, String, required: false
10
10
 
11
+ field :credentials,
12
+ GraphqlDevise::Types::CredentialType,
13
+ null: true,
14
+ description: 'Authentication credentials. Null if after signUp resource is not active for authentication (e.g. Email confirmation required).'
15
+
11
16
  def resolve(confirm_success_url: nil, **attrs)
12
17
  resource = build_resource(attrs.merge(provider: provider))
13
18
  raise_user_error(I18n.t('graphql_devise.resource_build_failed')) if resource.blank?
@@ -34,9 +39,11 @@ module GraphqlDevise
34
39
  )
35
40
  end
36
41
 
37
- set_auth_headers(resource) if resource.active_for_authentication?
42
+ response_payload = { authenticatable: resource }
43
+
44
+ response_payload[:credentials] = set_auth_headers(resource) if resource.active_for_authentication?
38
45
 
39
- { authenticatable: resource }
46
+ response_payload
40
47
  else
41
48
  resource.try(:clean_up_passwords)
42
49
  raise_user_error_list(
@@ -15,13 +15,16 @@ module GraphqlDevise
15
15
  redirect_header_options = { account_confirmation_success: true }
16
16
 
17
17
  redirect_to_link = if controller.signed_in?(resource_name)
18
- resource.build_auth_url(
18
+ url = resource.build_auth_url(
19
19
  redirect_url,
20
20
  redirect_headers(
21
21
  client_and_token(resource.create_token),
22
22
  redirect_header_options
23
23
  )
24
24
  )
25
+ resource.save!
26
+
27
+ url
25
28
  else
26
29
  DeviseTokenAuth::Url.generate(redirect_url, redirect_header_options)
27
30
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GraphqlDevise
4
- VERSION = '0.13.0'.freeze
4
+ VERSION = '0.13.5'.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]
@@ -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.
@@ -41,7 +41,7 @@ RSpec.describe GraphqlDevise::InstallGenerator, type: :generator do
41
41
  let(:args) { [] }
42
42
 
43
43
  it 'creates and updated required files' do
44
- assert_file 'config/routes.rb', /^\s{2}mount_graphql_devise_for 'User', at: 'auth'/
44
+ assert_file 'config/routes.rb', /^\s{2}mount_graphql_devise_for 'User', at: 'graphql_auth'/
45
45
  expect(routes_content).not_to match(dta_route)
46
46
 
47
47
  assert_file 'config/initializers/devise.rb'
@@ -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) { Faker::Internet.url }
12
13
  let(:query) do
13
14
  <<-GRAPHQL
14
15
  mutation {
@@ -98,6 +99,28 @@ RSpec.describe 'Resend confirmation' do
98
99
  end
99
100
  end
100
101
 
102
+ context 'when the email was changed' do
103
+ let(:confirmed_at) { 2.seconds.ago }
104
+ let(:email) { 'new-email@wallaceinc.com' }
105
+ let(:new_email) { email }
106
+
107
+ before do
108
+ user.update_with_email(
109
+ email: new_email,
110
+ schema_url: 'http://localhost/test',
111
+ confirmation_success_url: 'https://google.com'
112
+ )
113
+ end
114
+
115
+ it 'sends new confirmation email' do
116
+ expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
117
+ expect(ActionMailer::Base.deliveries.first.to).to contain_exactly(new_email)
118
+ expect(json_response[:data][:userResendConfirmation]).to include(
119
+ message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
120
+ )
121
+ end
122
+ end
123
+
101
124
  context "when the email isn't in the system" do
102
125
  let(:email) { 'nothere@gmail.com' }
103
126
 
@@ -21,6 +21,7 @@ RSpec.describe 'Sign Up process' do
21
21
  passwordConfirmation: "#{password}"
22
22
  confirmSuccessUrl: "#{redirect}"
23
23
  ) {
24
+ credentials { accessToken }
24
25
  user {
25
26
  email
26
27
  name
@@ -43,7 +44,8 @@ RSpec.describe 'Sign Up process' do
43
44
  expect(user.confirmed_at).to be_nil
44
45
  expect(user).to be_valid_password(password)
45
46
  expect(json_response[:data][:userSignUp]).to include(
46
- user: {
47
+ credentials: nil,
48
+ user: {
47
49
  email: email,
48
50
  name: name
49
51
  }
@@ -126,6 +128,7 @@ RSpec.describe 'Sign Up process' do
126
128
  passwordConfirmation: "#{password}"
127
129
  confirmSuccessUrl: "#{redirect}"
128
130
  ) {
131
+ credentials { accessToken client uid }
129
132
  authenticatable {
130
133
  email
131
134
  }
@@ -134,8 +137,16 @@ RSpec.describe 'Sign Up process' do
134
137
  GRAPHQL
135
138
  end
136
139
 
137
- it 'works without the confirmable module' do
140
+ it 'returns credentials as no confirmation is required' do
138
141
  expect { post_request }.to change(Guest, :count).from(0).to(1)
142
+
143
+ expect(json_response[:data][:guestSignUp]).to include(
144
+ authenticatable: { email: email },
145
+ credentials: hash_including(
146
+ uid: email,
147
+ client: Guest.last.tokens.keys.first
148
+ )
149
+ )
139
150
  end
140
151
  end
141
152
  end
@@ -5,60 +5,118 @@ 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) { Faker::Internet.url }
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 unconfirmed_email is present' do
47
+ let(:user) { create(:user, :confirmed, unconfirmed_email: 'vvega@wallaceinc.com') }
23
48
 
24
- context 'when confirmation token is correct' do
25
- let(:token) { user.confirmation_token }
49
+ it 'confirms the unconfirmed email and redirects' do
50
+ expect do
51
+ get_request
52
+ user.reload
53
+ end.to change(user, :email).from(user.email).to('vvega@wallaceinc.com').and(
54
+ change(user, :unconfirmed_email).from('vvega@wallaceinc.com').to(nil)
55
+ )
26
56
 
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
- )
57
+ expect(response).to redirect_to("#{redirect}?account_confirmation_success=true")
58
+ end
59
+ end
33
60
  end
34
61
 
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))
62
+ context 'when reset password token is not found' do
63
+ let(:token) { "#{user.confirmation_token}-invalid" }
40
64
 
41
- expect(response).to redirect_to "#{redirect}?account_confirmation_success=true"
42
- expect(user).to be_active_for_authentication
65
+ it 'does *NOT* confirm the user nor does the redirection' do
66
+ expect do
67
+ get_request
68
+ user.reload
69
+ end.not_to(change(user, :confirmed_at).from(nil))
70
+
71
+ expect(response).not_to be_redirect
72
+ expect(json_response[:errors]).to contain_exactly(
73
+ hash_including(
74
+ message: 'Invalid confirmation token. Please try again',
75
+ extensions: { code: 'USER_ERROR' }
76
+ )
77
+ )
78
+ end
43
79
  end
44
80
  end
45
81
 
46
- context 'when reset password token is not found' do
47
- let(:token) { "#{user.confirmation_token}-invalid" }
82
+ context 'when using the admin model' do
83
+ let(:admin) { create(:admin, confirmed_at: nil) }
84
+ let(:redirect) { Faker::Internet.url }
85
+ let(:query) do
86
+ <<-GRAPHQL
87
+ {
88
+ adminConfirmAccount(
89
+ confirmationToken: "#{token}"
90
+ redirectUrl: "#{redirect}"
91
+ ) {
92
+ email
93
+ }
94
+ }
95
+ GRAPHQL
96
+ end
48
97
 
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))
98
+ context 'when confirmation token is correct' do
99
+ let(:token) { admin.confirmation_token }
54
100
 
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' }
101
+ before do
102
+ admin.send_confirmation_instructions(
103
+ template_path: ['graphql_devise/mailer'],
104
+ controller: 'graphql_devise/graphql',
105
+ schema_url: 'http://not-using-this-value.com/gql'
60
106
  )
61
- )
107
+ end
108
+
109
+ it 'confirms the resource, persists credentials on the DB and redirects to the sent url' do
110
+ expect do
111
+ get_request
112
+ admin.reload
113
+ end.to change(admin, :confirmed_at).from(nil).and(
114
+ change { admin.tokens.keys.count }.from(0).to(1)
115
+ )
116
+
117
+ expect(response).to redirect_to(/\A#{redirect}.+access\-token=/)
118
+ expect(admin).to be_active_for_authentication
119
+ end
62
120
  end
63
121
  end
64
122
  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.0
4
+ version: 0.13.5
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-06-23 00:00:00.000000000 Z
12
+ date: 2020-11-20 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