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 +4 -4
- data/CHANGELOG.md +45 -0
- data/README.md +94 -80
- data/app/models/graphql_devise/concerns/model.rb +6 -0
- data/lib/generators/graphql_devise/install_generator.rb +1 -1
- data/lib/graphql_devise/concerns/controller_methods.rb +1 -1
- data/lib/graphql_devise/mutations/resend_confirmation.rb +13 -5
- data/lib/graphql_devise/mutations/sign_up.rb +9 -2
- data/lib/graphql_devise/resolvers/confirm_account.rb +4 -1
- data/lib/graphql_devise/version.rb +1 -1
- data/spec/dummy/app/graphql/resolvers/confirm_admin_account.rb +13 -0
- data/spec/dummy/app/graphql/types/admin_type.rb +8 -0
- data/spec/dummy/config/initializers/devise.rb +1 -1
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/db/schema.rb +0 -2
- data/spec/generators/graphql_devise/install_generator_spec.rb +1 -1
- data/spec/requests/mutations/resend_confirmation_spec.rb +27 -4
- data/spec/requests/mutations/sign_up_spec.rb +13 -2
- data/spec/requests/queries/confirm_account_spec.rb +100 -42
- metadata +10 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 005b85ca3899cb7b69c3505680be677fa935f80b3d63480fbf65d7f116775efa
|
4
|
+
data.tar.gz: 8473a4ff5404ec543f57c9d95ad2844a039ba691865ca2d8fbea15a197f6d9b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1accf0a12781a9b53b0f17f25226c3cd8fb8e31e26e435ce1040a132f83f508e06532c202a3789a90dcb0fd54dd10e72d047c5da1b431bb8d1147c319abc4870
|
7
|
+
data.tar.gz: 4d5649f9f7d724cfbd6fc8a06e5acf2e0a3196d5f6ef7e8f4d5a569f39ae9978fc3ab6a956c110a19a7c8783b753e61f40aac9b8dcc77100b52ce14b3f6bff1b
|
data/CHANGELOG.md
CHANGED
@@ -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.
|
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
|
-
|
18
|
-
|
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:
|
45
|
+
<!-- Added by: david, at: mar jul 14 08:08:02 -05 2020 -->
|
43
46
|
|
44
47
|
<!--te-->
|
45
48
|
|
46
49
|
## Introduction
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
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
|
84
|
-
|
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
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
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
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
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
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
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
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
378
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
455
|
-
|
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: '
|
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.
|
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 =
|
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
|
-
|
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
|
-
|
42
|
+
response_payload = { authenticatable: resource }
|
43
|
+
|
44
|
+
response_payload[:credentials] = set_auth_headers(resource) if resource.active_for_authentication?
|
38
45
|
|
39
|
-
|
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
|
@@ -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
|
@@ -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 =
|
145
|
+
config.reconfirmable = false
|
146
146
|
|
147
147
|
# Defines which key will be used when confirming an account
|
148
148
|
# config.confirmation_keys = [:email]
|
data/spec/dummy/config/routes.rb
CHANGED
data/spec/dummy/db/schema.rb
CHANGED
@@ -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: '
|
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
|
9
|
-
let(:
|
10
|
-
let(:
|
11
|
-
let(:
|
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
|
-
|
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 '
|
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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
22
|
-
|
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
|
-
|
25
|
-
|
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
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
36
|
-
|
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
|
-
|
42
|
-
|
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
|
47
|
-
let(:
|
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
|
-
|
50
|
-
|
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
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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.
|
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-
|
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.
|
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
|