graphql_devise 2.2.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +61 -42
- data/Appraisals +15 -88
- data/CHANGELOG.md +18 -4
- data/README.md +19 -0
- data/config/locales/en.yml +1 -0
- data/config/locales/pt-BR.yml +1 -0
- data/config/routes.rb +1 -1
- data/graphql_devise.gemspec +2 -2
- data/lib/graphql_devise/default_operations.rb +2 -1
- data/lib/graphql_devise/mount_method/operation_preparers/default_operation_preparer.rb +1 -1
- data/lib/graphql_devise/mount_method/operation_sanitizer.rb +41 -14
- data/lib/graphql_devise/mount_method/option_sanitizers/boolean_checker.rb +23 -0
- data/lib/graphql_devise/mount_method/supported_options.rb +3 -1
- data/lib/graphql_devise/mutations/destroy_account.rb +26 -0
- data/lib/graphql_devise/resource_loader.rb +4 -1
- data/lib/graphql_devise/route_mounter.rb +22 -9
- data/lib/graphql_devise/version.rb +1 -1
- data/lib/graphql_devise.rb +11 -2
- data/spec/dummy/config/routes.rb +9 -1
- data/spec/requests/mutations/destroy_account_spec.rb +67 -0
- data/spec/requests/queries/introspection_query_spec.rb +38 -0
- data/spec/services/mount_method/operation_sanitizer_spec.rb +58 -1
- data/spec/services/mount_method/option_sanitizers/boolean_checker_spec.rb +40 -0
- data/spec/spec_helper.rb +4 -2
- metadata +23 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: daddc316d120f12ed4a6a781871ec676a0eb11d6d6a407a438e01460fbd5c668
|
|
4
|
+
data.tar.gz: 73f19c61b7484b7cb7801e99d5889ddffdb8a0c8bfed393bd22e669c5143ccf3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1ca7946d638f1e40e2b0bfe4f427cf1c60fc63e7b947ffb716858ba5278dfbb06717a8919e276e221701729069a8b421f8bd094874b7dc729cbb69e2dbfaaa7c
|
|
7
|
+
data.tar.gz: 31a7f42e8eaa5e268c829ea9b091c8edc3e73f4c0101520eee737de55c8fab1e12d1b67246709e6cca8f7a3278906fb61a675d9f8c439d861422aac26ab17baf
|
data/.circleci/config.yml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
version: 2.1
|
|
2
2
|
orbs:
|
|
3
|
-
coveralls: coveralls/coveralls@
|
|
3
|
+
coveralls: coveralls/coveralls@2.2.5
|
|
4
4
|
|
|
5
5
|
jobs:
|
|
6
6
|
test:
|
|
@@ -12,8 +12,8 @@ jobs:
|
|
|
12
12
|
docker:
|
|
13
13
|
- image: 'ruby:<< parameters.ruby-version >>'
|
|
14
14
|
environment:
|
|
15
|
-
BUNDLE_GEMFILE:
|
|
16
|
-
|
|
15
|
+
BUNDLE_GEMFILE: gemfiles/<< parameters.gemfile >>.gemfile
|
|
16
|
+
BUNDLE_JOBS: '2'
|
|
17
17
|
EAGER_LOAD: 'true'
|
|
18
18
|
RUBYOPT: '-rostruct'
|
|
19
19
|
steps:
|
|
@@ -26,6 +26,13 @@ jobs:
|
|
|
26
26
|
name: Run Specs
|
|
27
27
|
command:
|
|
28
28
|
bundle exec rspec
|
|
29
|
+
- coveralls/upload:
|
|
30
|
+
parallel: true
|
|
31
|
+
coverage_file: ./coverage/.resultset.json
|
|
32
|
+
coverage_format: simplecov
|
|
33
|
+
# Parallel jobs must each report a unique flag_name or Coveralls
|
|
34
|
+
# collapses them into a single job. Keep it free of slashes.
|
|
35
|
+
flag_name: ruby-<< parameters.ruby-version >>-<< parameters.gemfile >>
|
|
29
36
|
report-coverage:
|
|
30
37
|
docker:
|
|
31
38
|
- image: 'cimg/node:22.1.0'
|
|
@@ -46,63 +53,75 @@ workflows:
|
|
|
46
53
|
- '3.3'
|
|
47
54
|
- '3.4'
|
|
48
55
|
gemfile:
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
56
|
+
- rails7.0_graphql2.3
|
|
57
|
+
- rails7.0_graphql2.4
|
|
58
|
+
- rails7.1_graphql2.0
|
|
59
|
+
- rails7.1_graphql2.1
|
|
60
|
+
- rails7.1_graphql2.2
|
|
61
|
+
- rails7.1_graphql2.3
|
|
62
|
+
- rails7.1_graphql2.4
|
|
63
|
+
- rails7.2_graphql2.0
|
|
64
|
+
- rails7.2_graphql2.1
|
|
65
|
+
- rails7.2_graphql2.2
|
|
66
|
+
- rails7.2_graphql2.3
|
|
67
|
+
- rails7.2_graphql2.4
|
|
68
|
+
- rails7.2_graphql2.5
|
|
69
|
+
- rails7.2_graphql2.6
|
|
70
|
+
- rails8.0_graphql2.2
|
|
71
|
+
- rails8.0_graphql2.3
|
|
72
|
+
- rails8.0_graphql2.4
|
|
73
|
+
- rails8.0_graphql2.5
|
|
74
|
+
- rails8.0_graphql2.6
|
|
75
|
+
- rails8.1_graphql2.4
|
|
76
|
+
- rails8.1_graphql2.5
|
|
77
|
+
- rails8.1_graphql2.6
|
|
71
78
|
exclude:
|
|
72
79
|
- ruby-version: '3.0'
|
|
73
|
-
gemfile:
|
|
80
|
+
gemfile: rails7.2_graphql2.0
|
|
81
|
+
- ruby-version: '3.0'
|
|
82
|
+
gemfile: rails7.2_graphql2.1
|
|
83
|
+
- ruby-version: '3.0'
|
|
84
|
+
gemfile: rails7.2_graphql2.2
|
|
85
|
+
- ruby-version: '3.0'
|
|
86
|
+
gemfile: rails7.2_graphql2.3
|
|
74
87
|
- ruby-version: '3.0'
|
|
75
|
-
gemfile:
|
|
88
|
+
gemfile: rails7.2_graphql2.4
|
|
76
89
|
- ruby-version: '3.0'
|
|
77
|
-
gemfile:
|
|
90
|
+
gemfile: rails7.2_graphql2.5
|
|
78
91
|
- ruby-version: '3.0'
|
|
79
|
-
gemfile:
|
|
92
|
+
gemfile: rails7.2_graphql2.6
|
|
80
93
|
- ruby-version: '3.0'
|
|
81
|
-
gemfile:
|
|
94
|
+
gemfile: rails8.0_graphql2.2
|
|
82
95
|
- ruby-version: '3.0'
|
|
83
|
-
gemfile:
|
|
96
|
+
gemfile: rails8.0_graphql2.3
|
|
84
97
|
- ruby-version: '3.0'
|
|
85
|
-
gemfile:
|
|
98
|
+
gemfile: rails8.0_graphql2.4
|
|
86
99
|
- ruby-version: '3.0'
|
|
87
|
-
gemfile:
|
|
100
|
+
gemfile: rails8.0_graphql2.5
|
|
88
101
|
- ruby-version: '3.0'
|
|
89
|
-
gemfile:
|
|
102
|
+
gemfile: rails8.0_graphql2.6
|
|
90
103
|
- ruby-version: '3.0'
|
|
91
|
-
gemfile:
|
|
104
|
+
gemfile: rails8.1_graphql2.4
|
|
92
105
|
- ruby-version: '3.0'
|
|
93
|
-
gemfile:
|
|
106
|
+
gemfile: rails8.1_graphql2.5
|
|
94
107
|
- ruby-version: '3.0'
|
|
95
|
-
gemfile:
|
|
108
|
+
gemfile: rails8.1_graphql2.6
|
|
109
|
+
- ruby-version: '3.1'
|
|
110
|
+
gemfile: rails8.0_graphql2.2
|
|
111
|
+
- ruby-version: '3.1'
|
|
112
|
+
gemfile: rails8.0_graphql2.3
|
|
113
|
+
- ruby-version: '3.1'
|
|
114
|
+
gemfile: rails8.0_graphql2.4
|
|
96
115
|
- ruby-version: '3.1'
|
|
97
|
-
gemfile:
|
|
116
|
+
gemfile: rails8.0_graphql2.5
|
|
98
117
|
- ruby-version: '3.1'
|
|
99
|
-
gemfile:
|
|
118
|
+
gemfile: rails8.0_graphql2.6
|
|
100
119
|
- ruby-version: '3.1'
|
|
101
|
-
gemfile:
|
|
120
|
+
gemfile: rails8.1_graphql2.4
|
|
102
121
|
- ruby-version: '3.1'
|
|
103
|
-
gemfile:
|
|
122
|
+
gemfile: rails8.1_graphql2.5
|
|
104
123
|
- ruby-version: '3.1'
|
|
105
|
-
gemfile:
|
|
124
|
+
gemfile: rails8.1_graphql2.6
|
|
106
125
|
- report-coverage:
|
|
107
126
|
requires:
|
|
108
127
|
- test
|
data/Appraisals
CHANGED
|
@@ -1,37 +1,3 @@
|
|
|
1
|
-
appraise 'rails6.1-graphql1.10' do
|
|
2
|
-
gem 'sqlite3', '~> 1.5.4'
|
|
3
|
-
gem 'devise', '>= 4.7'
|
|
4
|
-
gem 'rails', git: 'https://github.com/rails/rails', branch: '6-1-stable'
|
|
5
|
-
gem 'graphql', '~> 1.10.0'
|
|
6
|
-
gem 'factory_bot', '<= 6.4.4'
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
appraise 'rails6.1-graphql1.11' do
|
|
10
|
-
gem 'sqlite3', '~> 1.5.4'
|
|
11
|
-
gem 'public_suffix', '< 5'
|
|
12
|
-
gem 'devise', '>= 4.7'
|
|
13
|
-
gem 'rails', git: 'https://github.com/rails/rails', branch: '6-1-stable'
|
|
14
|
-
gem 'graphql', '~> 1.11.0'
|
|
15
|
-
gem 'factory_bot', '<= 6.4.4'
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
appraise 'rails6.1-graphql1.12' do
|
|
19
|
-
gem 'sqlite3', '~> 1.5.4'
|
|
20
|
-
gem 'public_suffix', '< 5'
|
|
21
|
-
gem 'devise', '>= 4.7'
|
|
22
|
-
gem 'rails', git: 'https://github.com/rails/rails', branch: '6-1-stable'
|
|
23
|
-
gem 'graphql', '~> 1.12.0'
|
|
24
|
-
gem 'factory_bot', '<= 6.4.4'
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
appraise 'rails6.1-graphql1.13' do
|
|
28
|
-
gem 'sqlite3', '~> 1.5.4'
|
|
29
|
-
gem 'devise', '>= 4.7'
|
|
30
|
-
gem 'rails', git: 'https://github.com/rails/rails', branch: '6-1-stable'
|
|
31
|
-
gem 'graphql', '~> 1.13.0'
|
|
32
|
-
gem 'factory_bot', '<= 6.4.4'
|
|
33
|
-
end
|
|
34
|
-
|
|
35
1
|
appraise 'rails6.1-graphql2.0' do
|
|
36
2
|
gem 'public_suffix', '< 5'
|
|
37
3
|
gem 'sqlite3', '~> 1.5.4'
|
|
@@ -41,60 +7,6 @@ appraise 'rails6.1-graphql2.0' do
|
|
|
41
7
|
gem 'factory_bot', '<= 6.4.4'
|
|
42
8
|
end
|
|
43
9
|
|
|
44
|
-
appraise 'rails7.0-graphql1.11' do
|
|
45
|
-
gem 'sassc-rails'
|
|
46
|
-
gem 'sqlite3', '~> 1.5.4'
|
|
47
|
-
gem 'devise', '>= 4.7'
|
|
48
|
-
gem 'devise_token_auth', '>= 1.2.1'
|
|
49
|
-
gem 'rails', git: 'https://github.com/rails/rails', branch: '7-0-stable'
|
|
50
|
-
gem 'graphql', '~> 1.11.0'
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
appraise 'rails7.0-graphql1.12' do
|
|
54
|
-
gem 'sassc-rails'
|
|
55
|
-
gem 'sqlite3', '~> 1.5.4'
|
|
56
|
-
gem 'devise', '>= 4.7'
|
|
57
|
-
gem 'devise_token_auth', '>= 1.2.1'
|
|
58
|
-
gem 'rails', git: 'https://github.com/rails/rails', branch: '7-0-stable'
|
|
59
|
-
gem 'graphql', '~> 1.12.0'
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
appraise 'rails7.0-graphql1.13' do
|
|
63
|
-
gem 'sassc-rails'
|
|
64
|
-
gem 'sqlite3', '~> 1.5.4'
|
|
65
|
-
gem 'devise', '>= 4.7'
|
|
66
|
-
gem 'devise_token_auth', '>= 1.2.1'
|
|
67
|
-
gem 'rails', git: 'https://github.com/rails/rails', branch: '7-0-stable'
|
|
68
|
-
gem 'graphql', '~> 1.13.0'
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
appraise 'rails7.0-graphql2.0' do
|
|
72
|
-
gem 'sassc-rails'
|
|
73
|
-
gem 'sqlite3', '~> 1.5.4'
|
|
74
|
-
gem 'devise_token_auth', '>= 1.2.1'
|
|
75
|
-
gem 'devise', '>= 4.7'
|
|
76
|
-
gem 'rails', git: 'https://github.com/rails/rails', branch: '7-0-stable'
|
|
77
|
-
gem 'graphql', '>= 2.0', '< 2.1'
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
appraise 'rails7.0-graphql2.1' do
|
|
81
|
-
gem 'sassc-rails'
|
|
82
|
-
gem 'sqlite3', '~> 1.5.4'
|
|
83
|
-
gem 'devise_token_auth', '>= 1.2.1'
|
|
84
|
-
gem 'devise', '>= 4.7'
|
|
85
|
-
gem 'rails', git: 'https://github.com/rails/rails', branch: '7-0-stable'
|
|
86
|
-
gem 'graphql', '>= 2.1', '< 2.2'
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
appraise 'rails7.0-graphql2.2' do
|
|
90
|
-
gem 'sassc-rails'
|
|
91
|
-
gem 'sqlite3', '~> 1.5.4'
|
|
92
|
-
gem 'devise_token_auth', '>= 1.2.1'
|
|
93
|
-
gem 'devise', '>= 4.7'
|
|
94
|
-
gem 'rails', git: 'https://github.com/rails/rails', branch: '7-0-stable'
|
|
95
|
-
gem 'graphql', '>= 2.2', '< 2.3'
|
|
96
|
-
end
|
|
97
|
-
|
|
98
10
|
appraise 'rails7.0-graphql2.3' do
|
|
99
11
|
gem 'sassc-rails'
|
|
100
12
|
gem 'sqlite3', '~> 1.5.4'
|
|
@@ -232,3 +144,18 @@ appraise 'rails8.0-graphql2.6' do
|
|
|
232
144
|
gem 'rails', git: 'https://github.com/rails/rails', branch: '8-0-stable'
|
|
233
145
|
gem 'graphql', '>= 2.6', '< 2.7'
|
|
234
146
|
end
|
|
147
|
+
|
|
148
|
+
appraise 'rails8.1-graphql2.4' do
|
|
149
|
+
gem 'rails', git: 'https://github.com/rails/rails', branch: '8-1-stable'
|
|
150
|
+
gem 'graphql', '>= 2.4', '< 2.5'
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
appraise 'rails8.1-graphql2.5' do
|
|
154
|
+
gem 'rails', git: 'https://github.com/rails/rails', branch: '8-1-stable'
|
|
155
|
+
gem 'graphql', '>= 2.5', '< 2.6'
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
appraise 'rails8.1-graphql2.6' do
|
|
159
|
+
gem 'rails', git: 'https://github.com/rails/rails', branch: '8-1-stable'
|
|
160
|
+
gem 'graphql', '>= 2.6', '< 2.7'
|
|
161
|
+
end
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [v2.4.0](https://github.com/graphql-devise/graphql_devise/tree/v2.4.0) (2026-07-23)
|
|
4
|
+
|
|
5
|
+
[Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v2.3.0...v2.4.0)
|
|
6
|
+
|
|
7
|
+
**Implemented enhancements:**
|
|
8
|
+
|
|
9
|
+
- Add Rails 8.1 support [\#297](https://github.com/graphql-devise/graphql_devise/pull/297) ([mcelicalderon](https://github.com/mcelicalderon))
|
|
10
|
+
- Add opt-in destroy\_account mutation [\#296](https://github.com/graphql-devise/graphql_devise/pull/296) ([mcelicalderon](https://github.com/mcelicalderon))
|
|
11
|
+
|
|
12
|
+
## [v2.3.0](https://github.com/graphql-devise/graphql_devise/tree/v2.3.0) (2026-07-20)
|
|
13
|
+
|
|
14
|
+
[Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v2.2.0...v2.3.0)
|
|
15
|
+
|
|
16
|
+
**Implemented enhancements:**
|
|
17
|
+
|
|
18
|
+
- Disable introspection [\#255](https://github.com/graphql-devise/graphql_devise/issues/255)
|
|
19
|
+
- Support public\_introspection option in mount\_graphql\_devise\_for [\#294](https://github.com/graphql-devise/graphql_devise/pull/294) ([mcelicalderon](https://github.com/mcelicalderon))
|
|
20
|
+
|
|
3
21
|
## [v2.2.0](https://github.com/graphql-devise/graphql_devise/tree/v2.2.0) (2026-05-13)
|
|
4
22
|
|
|
5
23
|
[Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v2.1.1...v2.2.0)
|
|
@@ -463,10 +481,6 @@
|
|
|
463
481
|
|
|
464
482
|
- mutation': Second definition of 'mutation\(...\)' \(GraphqlDevise::Types::MutationType\) is invalid [\#59](https://github.com/graphql-devise/graphql_devise/issues/59)
|
|
465
483
|
|
|
466
|
-
**Merged pull requests:**
|
|
467
|
-
|
|
468
|
-
- Add mailer locale doc [\#44](https://github.com/graphql-devise/graphql_devise/pull/44) ([aarona](https://github.com/aarona))
|
|
469
|
-
|
|
470
484
|
## [v0.9.1](https://github.com/graphql-devise/graphql_devise/tree/v0.9.1) (2019-12-26)
|
|
471
485
|
|
|
472
486
|
[Full Changelog](https://github.com/graphql-devise/graphql_devise/compare/v0.9.0...v0.9.1)
|
data/README.md
CHANGED
|
@@ -287,6 +287,20 @@ You need to provide a hash to this option, and
|
|
|
287
287
|
each key will be the name of the query on the schema. Also, the value provided must be a valid Resolver.
|
|
288
288
|
This is also similar to what you can accomplish with
|
|
289
289
|
[devise_scope](https://www.rubydoc.info/github/heartcombo/devise/master/ActionDispatch/Routing/Mapper%3Adevise_for).
|
|
290
|
+
1. `public_introspection`: Defaults to `true`. When set to `false`, introspection fields (`__schema`, `__type`)
|
|
291
|
+
will require authentication on the gem provided schema mounted on a separate route. Given that this schema never
|
|
292
|
+
sets a `current_resource` in the GraphQL context, this effectively disables introspection on that route.
|
|
293
|
+
Please note the gem provided schema is shared by all mounted resources, so setting this option to `false` on any
|
|
294
|
+
mount will disable introspection for all of them. **This option only works if you are using the mount method.**
|
|
295
|
+
If you are mounting the auth operations into your own schema, use the `public_introspection` option of the
|
|
296
|
+
`SchemaPlugin` instead.
|
|
297
|
+
1. `allow_destroy`: Defaults to `false`. The `destroy_account` operation is opt-in: it is **not** mounted
|
|
298
|
+
automatically, so upgrading the gem will never add a way to delete accounts to an existing schema. Set
|
|
299
|
+
`allow_destroy: true` to mount it (works alongside `skip`, and additively when no `skip`/`only` is given), or
|
|
300
|
+
list `:destroy_account` in the `only` option. While the operation is available but not mounted, a warning is
|
|
301
|
+
logged on boot explaining how to opt in. If you have decided you don't want the mutation and want to silence
|
|
302
|
+
the warning, add `:destroy_account` to the `skip` option (for example `skip: [:destroy_account]`, or combined
|
|
303
|
+
with the flag as `allow_destroy: true, skip: [:destroy_account]`).
|
|
290
304
|
|
|
291
305
|
Additional mutations and queries will be added to the schema regardless
|
|
292
306
|
of other options you might have specified like `skip` or `only`.
|
|
@@ -308,6 +322,7 @@ The following is a list of the symbols you can provide to the `operations`, `ski
|
|
|
308
322
|
:send_password_reset_with_token
|
|
309
323
|
:resend_confirmation_with_token
|
|
310
324
|
:confirm_registration_with_token
|
|
325
|
+
:destroy_account # opt-in, see the `allow_destroy` option above
|
|
311
326
|
```
|
|
312
327
|
|
|
313
328
|
### Configuring Model
|
|
@@ -472,6 +487,7 @@ register | The parameter `confirmUrl` is optional unless you are using the `conf
|
|
|
472
487
|
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 |
|
|
473
488
|
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 |
|
|
474
489
|
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 |
|
|
490
|
+
destroyAccount | Opt-in (see the `allow_destroy` mount option). Requires authentication headers. Destroys the current resource and clears the session so no auth headers are returned. | userDestroyAccount: UserDestroyAccountPayload |
|
|
475
491
|
|
|
476
492
|
### Reset Password Flow
|
|
477
493
|
This gem supports two password recovery flows. The most recently implemented is preferred and
|
|
@@ -575,6 +591,9 @@ standard Devise templates.
|
|
|
575
591
|
`GraphqlDevise::Schema` extends from `GraphQL::Schema`, which allows it to utilize the `disable_introspection_entry_points` method. By calling this method, you can disable introspection entry points in your schema. You can read more about it
|
|
576
592
|
[here](https://github.com/rmosolgo/graphql-ruby/blob/master/guides/schema/introspection.md#disabling-introspection).
|
|
577
593
|
|
|
594
|
+
If you are mounting the auth schema on a separate route, you can also pass `public_introspection: false` to the
|
|
595
|
+
`mount_graphql_devise_for` method. Check the [available mount options](#available-mount-options) section for more information.
|
|
596
|
+
|
|
578
597
|
If you are using the schema plugin and prefer to make introspection queries available only to authenticated users, you can do so by modifying the `public_introspection` option of the plugin. Check the [plugin config section](#mounting-operations-into-your-own-schema) for more information.
|
|
579
598
|
|
|
580
599
|
## Changelog
|
data/config/locales/en.yml
CHANGED
|
@@ -2,6 +2,7 @@ en:
|
|
|
2
2
|
graphql_devise:
|
|
3
3
|
redirect_url_not_allowed: "Redirect to '%{redirect_url}' not allowed."
|
|
4
4
|
registration_failed: "User couldn't be registered"
|
|
5
|
+
destroy_account_failed: "Account couldn't be destroyed"
|
|
5
6
|
resource_build_failed: "Resource couldn't be built, execution stopped."
|
|
6
7
|
not_authenticated: "User is not logged in."
|
|
7
8
|
user_not_found: "User was not found or was not logged in."
|
data/config/locales/pt-BR.yml
CHANGED
|
@@ -2,6 +2,7 @@ pt-BR:
|
|
|
2
2
|
graphql_devise:
|
|
3
3
|
redirect_url_not_allowed: "Redirecionamento para '%{redirect_url}' não permitido."
|
|
4
4
|
registration_failed: "Usuário não pôde ser registrado"
|
|
5
|
+
destroy_account_failed: "A conta não pôde ser excluída"
|
|
5
6
|
resource_build_failed: "O recurso não pôde ser construído, execução interrompida."
|
|
6
7
|
not_authenticated: "Usuário não logado."
|
|
7
8
|
user_not_found: "Usuário não encontrado ou não logado."
|
data/config/routes.rb
CHANGED
|
@@ -4,7 +4,7 @@ GraphqlDevise::Engine.routes.draw do
|
|
|
4
4
|
# Required as Devise forces routes to reload on eager_load
|
|
5
5
|
unless GraphqlDevise.schema_loaded?
|
|
6
6
|
if GraphqlDevise::Types::QueryType.fields.blank?
|
|
7
|
-
GraphqlDevise::Types::QueryType.field(:dummy, resolver: GraphqlDevise::Resolvers::Dummy)
|
|
7
|
+
GraphqlDevise::Types::QueryType.field(:dummy, resolver: GraphqlDevise::Resolvers::Dummy, authenticate: false)
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
if GraphqlDevise::Types::MutationType.fields.present?
|
data/graphql_devise.gemspec
CHANGED
|
@@ -29,11 +29,10 @@ Gem::Specification.new do |spec|
|
|
|
29
29
|
|
|
30
30
|
spec.add_dependency 'devise_token_auth', '>= 0.1.43', '< 2.0'
|
|
31
31
|
spec.add_dependency 'graphql', '>= 1.8', '< 2.7'
|
|
32
|
-
spec.add_dependency 'rails', '>= 6.0', '< 8.
|
|
32
|
+
spec.add_dependency 'rails', '>= 6.0', '< 8.2'
|
|
33
33
|
spec.add_dependency 'zeitwerk'
|
|
34
34
|
|
|
35
35
|
spec.add_development_dependency 'appraisal'
|
|
36
|
-
spec.add_development_dependency 'coveralls_reborn'
|
|
37
36
|
spec.add_development_dependency 'factory_bot'
|
|
38
37
|
spec.add_development_dependency 'faker'
|
|
39
38
|
spec.add_development_dependency 'generator_spec'
|
|
@@ -46,5 +45,6 @@ Gem::Specification.new do |spec|
|
|
|
46
45
|
spec.add_development_dependency 'rubocop-performance', '< 1.6.0'
|
|
47
46
|
spec.add_development_dependency 'rubocop-rails', '< 2.6.0'
|
|
48
47
|
spec.add_development_dependency 'rubocop-rspec', '< 1.39.0'
|
|
48
|
+
spec.add_development_dependency 'simplecov'
|
|
49
49
|
spec.add_development_dependency 'sqlite3'
|
|
50
50
|
end
|
|
@@ -10,7 +10,8 @@ module GraphqlDevise
|
|
|
10
10
|
update_password_with_token: { klass: Mutations::UpdatePasswordWithToken, authenticatable: true },
|
|
11
11
|
send_password_reset_with_token: { klass: Mutations::SendPasswordResetWithToken, authenticatable: false },
|
|
12
12
|
resend_confirmation_with_token: { klass: Mutations::ResendConfirmationWithToken, authenticatable: false },
|
|
13
|
-
confirm_registration_with_token: { klass: Mutations::ConfirmRegistrationWithToken, authenticatable: true }
|
|
13
|
+
confirm_registration_with_token: { klass: Mutations::ConfirmRegistrationWithToken, authenticatable: true },
|
|
14
|
+
destroy_account: { klass: Mutations::DestroyAccount, authenticatable: true, allow_destroy: true }
|
|
14
15
|
}.freeze
|
|
15
16
|
end
|
|
16
17
|
end
|
|
@@ -17,7 +17,7 @@ module GraphqlDevise
|
|
|
17
17
|
@selected_operations.except(*@custom_keys).each_with_object({}) do |(action, operation_info), result|
|
|
18
18
|
mapped_action = "#{mapping_name}_#{action}"
|
|
19
19
|
operation = operation_info[:klass]
|
|
20
|
-
options = operation_info.except(:klass, :deprecation_reason)
|
|
20
|
+
options = operation_info.except(:klass, :deprecation_reason, :allow_destroy)
|
|
21
21
|
|
|
22
22
|
result[mapped_action.to_sym] = [
|
|
23
23
|
OperationPreparers::GqlNameSetter.new(mapped_action),
|
|
@@ -3,29 +3,56 @@
|
|
|
3
3
|
module GraphqlDevise
|
|
4
4
|
module MountMethod
|
|
5
5
|
class OperationSanitizer
|
|
6
|
-
def self.call(default:, only:, skipped:)
|
|
6
|
+
def self.call(default:, only:, skipped:, allow_destroy: false)
|
|
7
7
|
new(
|
|
8
|
-
default:
|
|
9
|
-
only:
|
|
10
|
-
skipped:
|
|
8
|
+
default: default,
|
|
9
|
+
only: only,
|
|
10
|
+
skipped: skipped,
|
|
11
|
+
allow_destroy: allow_destroy
|
|
11
12
|
).call
|
|
12
13
|
end
|
|
13
14
|
|
|
14
|
-
def initialize(default:, only:, skipped:)
|
|
15
|
-
@default
|
|
16
|
-
@only
|
|
17
|
-
@skipped
|
|
15
|
+
def initialize(default:, only:, skipped:, allow_destroy: false)
|
|
16
|
+
@default = default
|
|
17
|
+
@only = only
|
|
18
|
+
@skipped = skipped
|
|
19
|
+
@allow_destroy = allow_destroy
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
def call
|
|
21
|
-
operations
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
# When `only` is provided the list is explicit, so `allow_destroy` operations are included
|
|
24
|
+
# (and never warned about) whenever they are named in it.
|
|
25
|
+
return @default.slice(*@only) if @only.present?
|
|
26
|
+
|
|
27
|
+
selected = @skipped.present? ? @default.except(*@skipped) : @default
|
|
28
|
+
|
|
29
|
+
reject_allow_destroy(selected)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def reject_allow_destroy(operations)
|
|
35
|
+
return operations if @allow_destroy
|
|
36
|
+
|
|
37
|
+
operations.reject do |name, options|
|
|
38
|
+
next false unless requires_allow_destroy?(options)
|
|
39
|
+
|
|
40
|
+
warn_excluded(name)
|
|
41
|
+
true
|
|
27
42
|
end
|
|
28
43
|
end
|
|
44
|
+
|
|
45
|
+
def requires_allow_destroy?(options)
|
|
46
|
+
options.is_a?(Hash) && options[:allow_destroy]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def warn_excluded(name)
|
|
50
|
+
::Rails.logger&.warn(
|
|
51
|
+
"[graphql_devise] The `#{name}` operation is not mounted because it is opt-in. " \
|
|
52
|
+
"Pass `allow_destroy: true` (or add it to the `only:` option) to include it. " \
|
|
53
|
+
"To keep it out and silence this warning, add `#{name}` to the `skip:` option."
|
|
54
|
+
)
|
|
55
|
+
end
|
|
29
56
|
end
|
|
30
57
|
end
|
|
31
58
|
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GraphqlDevise
|
|
4
|
+
module MountMethod
|
|
5
|
+
module OptionSanitizers
|
|
6
|
+
class BooleanChecker
|
|
7
|
+
def initialize(default_boolean = nil)
|
|
8
|
+
@default_boolean = default_boolean
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def call!(value, key)
|
|
12
|
+
return @default_boolean if value.nil?
|
|
13
|
+
|
|
14
|
+
unless value.instance_of?(TrueClass) || value.instance_of?(FalseClass)
|
|
15
|
+
raise InvalidMountOptionsError, "`#{key}` option has an invalid value. `true` or `false` expected."
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
value
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -9,7 +9,9 @@ module GraphqlDevise
|
|
|
9
9
|
skip: OptionSanitizers::ArrayChecker.new(Symbol),
|
|
10
10
|
additional_queries: OptionSanitizers::HashChecker.new(GraphQL::Schema::Resolver),
|
|
11
11
|
additional_mutations: OptionSanitizers::HashChecker.new(GraphQL::Schema::Mutation),
|
|
12
|
-
authenticatable_type: OptionSanitizers::ClassChecker.new(GraphQL::Schema::Member)
|
|
12
|
+
authenticatable_type: OptionSanitizers::ClassChecker.new(GraphQL::Schema::Member),
|
|
13
|
+
public_introspection: OptionSanitizers::BooleanChecker.new(true),
|
|
14
|
+
allow_destroy: OptionSanitizers::BooleanChecker.new(false)
|
|
13
15
|
}.freeze
|
|
14
16
|
end
|
|
15
17
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GraphqlDevise
|
|
4
|
+
module Mutations
|
|
5
|
+
class DestroyAccount < Base
|
|
6
|
+
def resolve
|
|
7
|
+
raise_user_error(I18n.t('graphql_devise.user_not_found')) unless current_resource
|
|
8
|
+
|
|
9
|
+
if current_resource.destroy
|
|
10
|
+
# Clear the controller resource/token so devise_token_auth's `update_auth_header`
|
|
11
|
+
# after_action doesn't try to reload the now deleted record.
|
|
12
|
+
remove_resource
|
|
13
|
+
|
|
14
|
+
yield current_resource if block_given?
|
|
15
|
+
|
|
16
|
+
{ authenticatable: current_resource }
|
|
17
|
+
else
|
|
18
|
+
raise_user_error_list(
|
|
19
|
+
I18n.t('graphql_devise.destroy_account_failed'),
|
|
20
|
+
resource: current_resource
|
|
21
|
+
)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -117,7 +117,10 @@ module GraphqlDevise
|
|
|
117
117
|
additional_operations: clean_options.additional_mutations,
|
|
118
118
|
preparer: MountMethod::OperationPreparers::MutationFieldSetter.new(authenticatable_type),
|
|
119
119
|
selected_operations: MountMethod::OperationSanitizer.call(
|
|
120
|
-
default:
|
|
120
|
+
default: DefaultOperations::MUTATIONS,
|
|
121
|
+
only: clean_options.only,
|
|
122
|
+
skipped: clean_options.skip,
|
|
123
|
+
allow_destroy: clean_options.allow_destroy
|
|
121
124
|
)
|
|
122
125
|
).call
|
|
123
126
|
end
|
|
@@ -1,23 +1,36 @@
|
|
|
1
1
|
module GraphqlDevise
|
|
2
2
|
module RouteMounter
|
|
3
3
|
def mount_graphql_devise_for(resource, options = {})
|
|
4
|
-
routing =
|
|
5
|
-
|
|
6
|
-
if (base_controller = options.delete(:base_controller))
|
|
7
|
-
new_controller = GraphqlDevise.const_set("#{resource}AuthController", Class.new(base_controller))
|
|
8
|
-
new_controller.include(SetUserByToken)
|
|
9
|
-
new_controller.include(AuthControllerMethods)
|
|
10
|
-
|
|
11
|
-
routing = "#{new_controller.to_s.underscore.gsub('_controller','')}#auth"
|
|
12
|
-
end
|
|
4
|
+
routing = auth_routing(resource, options.delete(:base_controller))
|
|
13
5
|
|
|
14
6
|
clean_options = ResourceLoader.new(resource, options, true).call(
|
|
15
7
|
Types::QueryType,
|
|
16
8
|
Types::MutationType
|
|
17
9
|
)
|
|
18
10
|
|
|
11
|
+
require_introspection_auth(clean_options)
|
|
12
|
+
|
|
19
13
|
post clean_options.at, to: routing
|
|
20
14
|
get clean_options.at, to: routing
|
|
21
15
|
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def auth_routing(resource, base_controller)
|
|
20
|
+
return 'graphql_devise/graphql#auth' if base_controller.blank?
|
|
21
|
+
|
|
22
|
+
new_controller = GraphqlDevise.const_set("#{resource}AuthController", Class.new(base_controller))
|
|
23
|
+
new_controller.include(SetUserByToken)
|
|
24
|
+
new_controller.include(AuthControllerMethods)
|
|
25
|
+
|
|
26
|
+
"#{new_controller.to_s.underscore.gsub('_controller', '')}#auth"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def require_introspection_auth(clean_options)
|
|
30
|
+
return if clean_options.public_introspection || GraphqlDevise.introspection_plugin_applied?
|
|
31
|
+
|
|
32
|
+
Schema.use(SchemaPlugin.new(authenticate_default: true, public_introspection: false))
|
|
33
|
+
GraphqlDevise.introspection_plugin_applied!
|
|
34
|
+
end
|
|
22
35
|
end
|
|
23
36
|
end
|
data/lib/graphql_devise.rb
CHANGED
|
@@ -27,8 +27,9 @@ module GraphqlDevise
|
|
|
27
27
|
|
|
28
28
|
class InvalidMountOptionsError < ::GraphqlDevise::Error; end
|
|
29
29
|
|
|
30
|
-
@schema_loaded
|
|
31
|
-
@mounted_resources
|
|
30
|
+
@schema_loaded = false
|
|
31
|
+
@mounted_resources = []
|
|
32
|
+
@introspection_plugin_applied = false
|
|
32
33
|
|
|
33
34
|
def self.schema_loaded?
|
|
34
35
|
@schema_loaded
|
|
@@ -38,6 +39,14 @@ module GraphqlDevise
|
|
|
38
39
|
@schema_loaded = true
|
|
39
40
|
end
|
|
40
41
|
|
|
42
|
+
def self.introspection_plugin_applied?
|
|
43
|
+
@introspection_plugin_applied
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.introspection_plugin_applied!
|
|
47
|
+
@introspection_plugin_applied = true
|
|
48
|
+
end
|
|
49
|
+
|
|
41
50
|
def self.resource_mounted?(model)
|
|
42
51
|
@mounted_resources.include?(model)
|
|
43
52
|
end
|
data/spec/dummy/config/routes.rb
CHANGED
|
@@ -7,13 +7,15 @@ Rails.application.routes.draw do
|
|
|
7
7
|
base_controller: CookiesController,
|
|
8
8
|
operations: { login: Mutations::Login, register: Mutations::Register },
|
|
9
9
|
additional_mutations: { register_confirmed_user: Mutations::RegisterConfirmedUser },
|
|
10
|
-
additional_queries: { public_user: Resolvers::PublicUser }
|
|
10
|
+
additional_queries: { public_user: Resolvers::PublicUser },
|
|
11
|
+
allow_destroy: true
|
|
11
12
|
)
|
|
12
13
|
|
|
13
14
|
mount_graphql_devise_for(
|
|
14
15
|
Admin,
|
|
15
16
|
authenticatable_type: Types::CustomAdminType,
|
|
16
17
|
skip: [:register],
|
|
18
|
+
allow_destroy: true,
|
|
17
19
|
operations: {
|
|
18
20
|
update_password_with_token: Mutations::ResetAdminPasswordWithToken
|
|
19
21
|
},
|
|
@@ -32,6 +34,12 @@ Rails.application.routes.draw do
|
|
|
32
34
|
at: '/api/v1/user_customer/graphql_auth'
|
|
33
35
|
)
|
|
34
36
|
|
|
37
|
+
mount_graphql_devise_for(
|
|
38
|
+
User,
|
|
39
|
+
at: '/api/v1/no_introspection',
|
|
40
|
+
public_introspection: false
|
|
41
|
+
)
|
|
42
|
+
|
|
35
43
|
get '/api/v1/graphql', to: 'api/v1/graphql#graphql'
|
|
36
44
|
post '/api/v1/graphql', to: 'api/v1/graphql#graphql'
|
|
37
45
|
post '/api/v1/interpreter', to: 'api/v1/graphql#interpreter'
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe 'Destroy Account Requests' do
|
|
6
|
+
include_context 'with graphql query request'
|
|
7
|
+
|
|
8
|
+
let(:user) { create(:user, :confirmed) }
|
|
9
|
+
let(:query) do
|
|
10
|
+
<<-GRAPHQL
|
|
11
|
+
mutation {
|
|
12
|
+
userDestroyAccount {
|
|
13
|
+
authenticatable { email }
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
GRAPHQL
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
before { post_request }
|
|
20
|
+
|
|
21
|
+
context 'when user is logged in' do
|
|
22
|
+
let(:headers) { user.create_new_auth_token }
|
|
23
|
+
|
|
24
|
+
it 'destroys the account and does not set auth headers' do
|
|
25
|
+
expect(response).not_to include_auth_headers
|
|
26
|
+
expect(User.exists?(user.id)).to be(false)
|
|
27
|
+
expect(json_response[:data][:userDestroyAccount]).to match(
|
|
28
|
+
authenticatable: { email: user.email }
|
|
29
|
+
)
|
|
30
|
+
expect(json_response[:errors]).to be_nil
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context 'when user is not logged in' do
|
|
35
|
+
it 'returns an error and does not delete anything' do
|
|
36
|
+
expect(response).not_to include_auth_headers
|
|
37
|
+
expect(User.exists?(user.id)).to be(true)
|
|
38
|
+
expect(json_response[:data][:userDestroyAccount]).to be_nil
|
|
39
|
+
expect(json_response[:errors]).to contain_exactly(
|
|
40
|
+
hash_including(message: 'User was not found or was not logged in.', extensions: { code: 'USER_ERROR' })
|
|
41
|
+
)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context 'when using the admin model' do
|
|
46
|
+
let(:query) do
|
|
47
|
+
<<-GRAPHQL
|
|
48
|
+
mutation {
|
|
49
|
+
adminDestroyAccount {
|
|
50
|
+
authenticatable { email }
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
GRAPHQL
|
|
54
|
+
end
|
|
55
|
+
let(:admin) { create(:admin, :confirmed) }
|
|
56
|
+
let(:headers) { admin.create_new_auth_token }
|
|
57
|
+
|
|
58
|
+
it 'destroys the admin account' do
|
|
59
|
+
expect(response).not_to include_auth_headers
|
|
60
|
+
expect(Admin.exists?(admin.id)).to be(false)
|
|
61
|
+
expect(json_response[:data][:adminDestroyAccount]).to match(
|
|
62
|
+
authenticatable: { email: admin.email }
|
|
63
|
+
)
|
|
64
|
+
expect(json_response[:errors]).to be_nil
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -152,4 +152,42 @@ RSpec.describe 'Login Requests' do
|
|
|
152
152
|
end
|
|
153
153
|
end
|
|
154
154
|
end
|
|
155
|
+
|
|
156
|
+
context 'when using the gem provided schema mounted on a route with public_introspection: false' do
|
|
157
|
+
it 'return an error' do
|
|
158
|
+
post_request('/api/v1/no_introspection')
|
|
159
|
+
|
|
160
|
+
expect(json_response[:data]).to be_nil
|
|
161
|
+
expect(json_response[:errors]).to contain_exactly(
|
|
162
|
+
hash_including(
|
|
163
|
+
message: '__schema field requires authentication',
|
|
164
|
+
extensions: { code: 'AUTHENTICATION_ERROR' }
|
|
165
|
+
)
|
|
166
|
+
)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
context 'when executing a regular operation on the same route' do
|
|
170
|
+
let(:password) { '12345678' }
|
|
171
|
+
let(:user) { create(:user, :confirmed, password: password) }
|
|
172
|
+
let(:query) do
|
|
173
|
+
<<-GRAPHQL
|
|
174
|
+
mutation {
|
|
175
|
+
userLogin(
|
|
176
|
+
email: "#{user.email}",
|
|
177
|
+
password: "#{password}"
|
|
178
|
+
) {
|
|
179
|
+
user { email }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
GRAPHQL
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
it 'executes the operation successfully' do
|
|
186
|
+
post_request('/api/v1/no_introspection')
|
|
187
|
+
|
|
188
|
+
expect(json_response[:errors]).to be_nil
|
|
189
|
+
expect(json_response[:data][:userLogin][:user][:email]).to eq(user.email)
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
155
193
|
end
|
|
@@ -4,11 +4,14 @@ require 'rails_helper'
|
|
|
4
4
|
|
|
5
5
|
RSpec.describe GraphqlDevise::MountMethod::OperationSanitizer do
|
|
6
6
|
describe '.call' do
|
|
7
|
-
subject
|
|
7
|
+
subject(:sanitized) do
|
|
8
|
+
described_class.call(default: default, only: only, skipped: skipped, allow_destroy: allow_destroy)
|
|
9
|
+
end
|
|
8
10
|
|
|
9
11
|
let(:op_class1) { Class.new }
|
|
10
12
|
let(:op_class2) { Class.new }
|
|
11
13
|
let(:op_class3) { Class.new }
|
|
14
|
+
let(:allow_destroy) { false }
|
|
12
15
|
|
|
13
16
|
context 'when the operations passed are mutations' do
|
|
14
17
|
let(:skipped) { [] }
|
|
@@ -31,5 +34,59 @@ RSpec.describe GraphqlDevise::MountMethod::OperationSanitizer do
|
|
|
31
34
|
it { is_expected.to eq(operation1: { klass: op_class1 }) }
|
|
32
35
|
end
|
|
33
36
|
end
|
|
37
|
+
|
|
38
|
+
context 'when an operation requires the allow_destroy option' do
|
|
39
|
+
let(:skipped) { [] }
|
|
40
|
+
let(:only) { [] }
|
|
41
|
+
let(:default) do
|
|
42
|
+
{
|
|
43
|
+
operation1: { klass: op_class1 },
|
|
44
|
+
destroy_account: { klass: op_class2, allow_destroy: true }
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context 'when no only/skip option and allow_destroy is off' do
|
|
49
|
+
it 'excludes the operation and logs a warning' do
|
|
50
|
+
expect(Rails.logger).to receive(:warn).with(/destroy_account/)
|
|
51
|
+
expect(sanitized).to eq(operation1: { klass: op_class1 })
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context 'when using skip on other operations without allow_destroy' do
|
|
56
|
+
let(:skipped) { [:operation1] }
|
|
57
|
+
|
|
58
|
+
it 'still excludes the operation and logs a warning' do
|
|
59
|
+
expect(Rails.logger).to receive(:warn).with(/destroy_account/)
|
|
60
|
+
expect(sanitized).to eq({})
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
context 'when the operation itself is skipped' do
|
|
65
|
+
let(:skipped) { [:destroy_account] }
|
|
66
|
+
|
|
67
|
+
it 'excludes the operation without logging a warning' do
|
|
68
|
+
expect(Rails.logger).not_to receive(:warn)
|
|
69
|
+
expect(sanitized).to eq(operation1: { klass: op_class1 })
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context 'when allow_destroy is on' do
|
|
74
|
+
let(:allow_destroy) { true }
|
|
75
|
+
|
|
76
|
+
it 'includes the operation without warning' do
|
|
77
|
+
expect(Rails.logger).not_to receive(:warn)
|
|
78
|
+
expect(sanitized).to eq(default)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context 'when named explicitly in only' do
|
|
83
|
+
let(:only) { [:destroy_account] }
|
|
84
|
+
|
|
85
|
+
it 'includes the operation without warning' do
|
|
86
|
+
expect(Rails.logger).not_to receive(:warn)
|
|
87
|
+
expect(sanitized).to eq(destroy_account: { klass: op_class2, allow_destroy: true })
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
34
91
|
end
|
|
35
92
|
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe GraphqlDevise::MountMethod::OptionSanitizers::BooleanChecker do
|
|
6
|
+
describe '#call!' do
|
|
7
|
+
subject(:clean_value) { described_class.new(default_boolean).call!(value, key) }
|
|
8
|
+
|
|
9
|
+
let(:key) { :any_option }
|
|
10
|
+
let(:default_boolean) { true }
|
|
11
|
+
|
|
12
|
+
context 'when no value is provided' do
|
|
13
|
+
let(:value) { nil }
|
|
14
|
+
|
|
15
|
+
it { is_expected.to eq(default_boolean) }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context 'when provided value is false' do
|
|
19
|
+
let(:value) { false }
|
|
20
|
+
|
|
21
|
+
it 'preserves the explicit false value instead of falling back to the default' do
|
|
22
|
+
expect(clean_value).to eq(false)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'when provided value is true' do
|
|
27
|
+
let(:value) { true }
|
|
28
|
+
|
|
29
|
+
it { is_expected.to eq(true) }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context 'when provided value is not a boolean' do
|
|
33
|
+
let(:value) { 'true' }
|
|
34
|
+
|
|
35
|
+
it 'raises an error' do
|
|
36
|
+
expect { clean_value }.to raise_error(GraphqlDevise::InvalidMountOptionsError, "`#{key}` option has an invalid value. `true` or `false` expected.")
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
if ENV['CI'] && !ENV['SKIP_COVERALLS']
|
|
4
4
|
require 'simplecov'
|
|
5
|
-
require 'coveralls'
|
|
6
5
|
|
|
7
|
-
SimpleCov.
|
|
6
|
+
# SimpleCov writes coverage/.resultset.json, which the Coveralls coverage-reporter
|
|
7
|
+
# (invoked by the coveralls CircleCI orb) picks up and uploads. We no longer upload
|
|
8
|
+
# from within Ruby so that every parallel job and the parallel_finished webhook share
|
|
9
|
+
# the same service number and aggregate into a single Coveralls build.
|
|
8
10
|
SimpleCov.start 'rails' do
|
|
9
11
|
add_filter ['spec']
|
|
10
12
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: graphql_devise
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mario Celi
|
|
@@ -59,7 +59,7 @@ dependencies:
|
|
|
59
59
|
version: '6.0'
|
|
60
60
|
- - "<"
|
|
61
61
|
- !ruby/object:Gem::Version
|
|
62
|
-
version: '8.
|
|
62
|
+
version: '8.2'
|
|
63
63
|
type: :runtime
|
|
64
64
|
prerelease: false
|
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -69,7 +69,7 @@ dependencies:
|
|
|
69
69
|
version: '6.0'
|
|
70
70
|
- - "<"
|
|
71
71
|
- !ruby/object:Gem::Version
|
|
72
|
-
version: '8.
|
|
72
|
+
version: '8.2'
|
|
73
73
|
- !ruby/object:Gem::Dependency
|
|
74
74
|
name: zeitwerk
|
|
75
75
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -98,20 +98,6 @@ dependencies:
|
|
|
98
98
|
- - ">="
|
|
99
99
|
- !ruby/object:Gem::Version
|
|
100
100
|
version: '0'
|
|
101
|
-
- !ruby/object:Gem::Dependency
|
|
102
|
-
name: coveralls_reborn
|
|
103
|
-
requirement: !ruby/object:Gem::Requirement
|
|
104
|
-
requirements:
|
|
105
|
-
- - ">="
|
|
106
|
-
- !ruby/object:Gem::Version
|
|
107
|
-
version: '0'
|
|
108
|
-
type: :development
|
|
109
|
-
prerelease: false
|
|
110
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
111
|
-
requirements:
|
|
112
|
-
- - ">="
|
|
113
|
-
- !ruby/object:Gem::Version
|
|
114
|
-
version: '0'
|
|
115
101
|
- !ruby/object:Gem::Dependency
|
|
116
102
|
name: factory_bot
|
|
117
103
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -280,6 +266,20 @@ dependencies:
|
|
|
280
266
|
- - "<"
|
|
281
267
|
- !ruby/object:Gem::Version
|
|
282
268
|
version: 1.39.0
|
|
269
|
+
- !ruby/object:Gem::Dependency
|
|
270
|
+
name: simplecov
|
|
271
|
+
requirement: !ruby/object:Gem::Requirement
|
|
272
|
+
requirements:
|
|
273
|
+
- - ">="
|
|
274
|
+
- !ruby/object:Gem::Version
|
|
275
|
+
version: '0'
|
|
276
|
+
type: :development
|
|
277
|
+
prerelease: false
|
|
278
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
279
|
+
requirements:
|
|
280
|
+
- - ">="
|
|
281
|
+
- !ruby/object:Gem::Version
|
|
282
|
+
version: '0'
|
|
283
283
|
- !ruby/object:Gem::Dependency
|
|
284
284
|
name: sqlite3
|
|
285
285
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -358,6 +358,7 @@ files:
|
|
|
358
358
|
- lib/graphql_devise/mount_method/operation_sanitizer.rb
|
|
359
359
|
- lib/graphql_devise/mount_method/option_sanitizer.rb
|
|
360
360
|
- lib/graphql_devise/mount_method/option_sanitizers/array_checker.rb
|
|
361
|
+
- lib/graphql_devise/mount_method/option_sanitizers/boolean_checker.rb
|
|
361
362
|
- lib/graphql_devise/mount_method/option_sanitizers/class_checker.rb
|
|
362
363
|
- lib/graphql_devise/mount_method/option_sanitizers/hash_checker.rb
|
|
363
364
|
- lib/graphql_devise/mount_method/option_sanitizers/string_checker.rb
|
|
@@ -368,6 +369,7 @@ files:
|
|
|
368
369
|
- lib/graphql_devise/mount_method/supported_options.rb
|
|
369
370
|
- lib/graphql_devise/mutations/base.rb
|
|
370
371
|
- lib/graphql_devise/mutations/confirm_registration_with_token.rb
|
|
372
|
+
- lib/graphql_devise/mutations/destroy_account.rb
|
|
371
373
|
- lib/graphql_devise/mutations/login.rb
|
|
372
374
|
- lib/graphql_devise/mutations/logout.rb
|
|
373
375
|
- lib/graphql_devise/mutations/register.rb
|
|
@@ -474,6 +476,7 @@ files:
|
|
|
474
476
|
- spec/requests/mutations/additional_mutations_spec.rb
|
|
475
477
|
- spec/requests/mutations/additional_queries_spec.rb
|
|
476
478
|
- spec/requests/mutations/confirm_registration_with_token_spec.rb
|
|
479
|
+
- spec/requests/mutations/destroy_account_spec.rb
|
|
477
480
|
- spec/requests/mutations/login_spec.rb
|
|
478
481
|
- spec/requests/mutations/logout_spec.rb
|
|
479
482
|
- spec/requests/mutations/register_spec.rb
|
|
@@ -492,6 +495,7 @@ files:
|
|
|
492
495
|
- spec/services/mount_method/operation_sanitizer_spec.rb
|
|
493
496
|
- spec/services/mount_method/option_sanitizer_spec.rb
|
|
494
497
|
- spec/services/mount_method/option_sanitizers/array_checker_spec.rb
|
|
498
|
+
- spec/services/mount_method/option_sanitizers/boolean_checker_spec.rb
|
|
495
499
|
- spec/services/mount_method/option_sanitizers/class_checker_spec.rb
|
|
496
500
|
- spec/services/mount_method/option_sanitizers/hash_checker_spec.rb
|
|
497
501
|
- spec/services/mount_method/option_sanitizers/string_checker_spec.rb
|
|
@@ -620,6 +624,7 @@ test_files:
|
|
|
620
624
|
- spec/requests/mutations/additional_mutations_spec.rb
|
|
621
625
|
- spec/requests/mutations/additional_queries_spec.rb
|
|
622
626
|
- spec/requests/mutations/confirm_registration_with_token_spec.rb
|
|
627
|
+
- spec/requests/mutations/destroy_account_spec.rb
|
|
623
628
|
- spec/requests/mutations/login_spec.rb
|
|
624
629
|
- spec/requests/mutations/logout_spec.rb
|
|
625
630
|
- spec/requests/mutations/register_spec.rb
|
|
@@ -638,6 +643,7 @@ test_files:
|
|
|
638
643
|
- spec/services/mount_method/operation_sanitizer_spec.rb
|
|
639
644
|
- spec/services/mount_method/option_sanitizer_spec.rb
|
|
640
645
|
- spec/services/mount_method/option_sanitizers/array_checker_spec.rb
|
|
646
|
+
- spec/services/mount_method/option_sanitizers/boolean_checker_spec.rb
|
|
641
647
|
- spec/services/mount_method/option_sanitizers/class_checker_spec.rb
|
|
642
648
|
- spec/services/mount_method/option_sanitizers/hash_checker_spec.rb
|
|
643
649
|
- spec/services/mount_method/option_sanitizers/string_checker_spec.rb
|