Skip to content

Commit 3ce7744

Browse files
olegrokrosik
andauthored
Properly handle nested input objects in GraphQL (#703)
Also make GraphQL errors neater: eliminate source path from messages. Co-authored-by: Yaroslav Dynnikov <[email protected]>
1 parent 4f74dc1 commit 3ce7744

File tree

12 files changed

+221
-29
lines changed

12 files changed

+221
-29
lines changed

CHANGELOG.md

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,23 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1616

1717
- Implement stateful failover mode.
1818

19-
- Add new field Graphql field `cluster{ issues {topic} }`
19+
- Add new field GraphQL field `cluster{ issues {topic} }`
2020

2121
- Extend issues API for stateful failover
2222

23-
- New option in `cartridge.cfg({upgrade_schema=...}, ...)`
24-
to perform auto upgrade schema to actual tarantool version
25-
(only for leader). It also has bean added for `argparse`.
26-
27-
- GraphQL validation significantly improved: scalar values can't have
28-
subselections; composite types must have subselections; omitting
29-
non-nullable arguments in variable list is forbidden.
23+
- New option in `cartridge.cfg({upgrade_schema=...})`
24+
to automatically upgrade schema to modern tarantool version
25+
(only for leader). It also has been added for `argparse`.
3026

3127
- Indicate replication and failover issues in WebUI.
3228

29+
### Changed
30+
31+
- Make GraphQL validation stricter: scalar values can't have
32+
sub-selections; composite types must have sub-selections; omitting
33+
non-nullable arguments in variable list is forbidden. Your code **may
34+
be affected** if it doesn't conform GraphQL specification.
35+
3336
### Deprecated
3437

3538
Lua API:
@@ -44,7 +47,15 @@ GraphQL API:
4447

4548
### Fixed
4649

47-
- Fix quering failure `cluster {issues {...} }` on uninitialized instance
50+
- Properly handle nested input object in GraphQL:
51+
```graphql
52+
mutation($uuid: String!) {
53+
cluster { edit_topology(servers: [{uuid: $uuid ...}]) {} }
54+
}
55+
```
56+
57+
- Fix bug in GraphQL query `cluster {issues {...} }` on uninitialized
58+
instance.
4859

4960
## [2.0.2] - 2020-03-17
5061

cartridge/graphql.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ local function funcall_wrap(fun_name, operation, field_name)
4040
local res, err = funcall.call(fun_name, ...)
4141

4242
if res == nil then
43-
error(err)
43+
error(err, 0)
4444
end
4545

4646
return res
@@ -104,7 +104,7 @@ local function add_callback(opts)
104104
if opts.prefix then
105105
local obj = vars.callbacks[opts.prefix]
106106
if obj == nil then
107-
error('No such callback prefix ' .. opts.prefix)
107+
error('No such callback prefix ' .. opts.prefix, 0)
108108
end
109109

110110
local oldkind = obj.kind
@@ -148,7 +148,7 @@ local function add_mutation(opts)
148148
if opts.prefix then
149149
local obj = vars.mutations[opts.prefix]
150150
if obj == nil then
151-
error('No such mutation prefix ' .. opts.prefix)
151+
error('No such mutation prefix ' .. opts.prefix, 0)
152152
end
153153

154154
local oldkind = obj.kind

cartridge/graphql/execute.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ local introspection = require(path .. '.introspection')
55
local query_util = require(path .. '.query_util')
66
local validate_variables = require(path .. '.validate_variables')
77

8+
local function error(...)
9+
return _G.error(..., 0)
10+
end
11+
812
local function getFieldResponseKey(field)
913
return field.alias and field.alias.name.value or field.name.value
1014
end

cartridge/graphql/introspection.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ __Type = types.object({
204204
return 'NON_NULL'
205205
end
206206

207-
error('Unknown type ' .. kind)
207+
error('Unknown type ' .. kind, 0)
208208
end
209209
},
210210

cartridge/graphql/rules.lua

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ local util = require(path .. '.util')
44
local introspection = require(path .. '.introspection')
55
local query_util = require(path .. '.query_util')
66

7+
local function error(...)
8+
return _G.error(..., 0)
9+
end
10+
711
local function getParentField(context, name, count)
812
if introspection.fieldMap[name] then return introspection.fieldMap[name] end
913

@@ -413,11 +417,6 @@ function rules.variableDefaultValuesHaveCorrectType(node, context)
413417
end
414418

415419
function rules.variablesAreUsed(node, context)
416-
local operationName = node.name and node.name.value or ''
417-
if context.skipVariableUseCheck[operationName] then
418-
return
419-
end
420-
421420
if node.variableDefinitions then
422421
for _, definition in ipairs(node.variableDefinitions) do
423422
local variableName = definition.variable.name.value

cartridge/graphql/schema.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ local path = (...):gsub('%.[^%.]+$', '')
22
local types = require(path .. '.types')
33
local introspection = require(path .. '.introspection')
44

5+
local function error(...)
6+
return _G.error(..., 0)
7+
end
8+
59
local schema = {}
610
schema.__index = schema
711

cartridge/graphql/types.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ local types_load_error = errors.new_class("types_load_error")
1111

1212
vars:new('registered_types', {})
1313

14+
local function error(...)
15+
return _G.error(..., 0)
16+
end
17+
1418
local types = {}
1519

1620
local function get_env()

cartridge/graphql/util.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
local ffi = require('ffi')
22
local yaml = require('yaml').new({encode_use_tostring = true})
33

4+
local function error(...)
5+
return _G.error(..., 0)
6+
end
7+
48
local function map(t, fn)
59
local res = {}
610
for k, v in pairs(t) do res[k] = fn(v, k) end

cartridge/graphql/validate.lua

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,9 +258,40 @@ local visitors = {
258258
end
259259
end,
260260

261+
children = function(node)
262+
return util.map(node.value.values or {}, function(value)
263+
if value.value ~= nil then
264+
return value.value
265+
end
266+
return value
267+
end)
268+
end,
269+
270+
rules = { rules.uniqueInputObjectFields }
271+
},
272+
273+
inputObject = {
274+
children = function(node)
275+
return util.map(node.values or {}, function(value)
276+
return value.value
277+
end)
278+
end,
279+
261280
rules = { rules.uniqueInputObjectFields }
262281
},
263282

283+
list = {
284+
children = function(node)
285+
return node.values
286+
end,
287+
},
288+
289+
variable = {
290+
enter = function(node, context)
291+
context.variableReferences[node.name.value] = true
292+
end
293+
},
294+
264295
directive = {
265296
children = function(node, context)
266297
return node.arguments
@@ -278,7 +309,6 @@ local function validate(schema, tree)
278309
objects = {},
279310
currentOperation = nil,
280311
variableReferences = nil,
281-
skipVariableUseCheck = {}, -- operation name -> boolean
282312
}
283313

284314
local function visit(node)

cartridge/graphql/validate_variables.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ local types = require(path .. '.types')
33
local util = require(path .. '.util')
44
local check = util.check
55

6+
local function error(...)
7+
return _G.error(..., 0)
8+
end
9+
610
-- Traverse type more or less likewise util.coerceValue do.
711
local function checkVariableValue(variableName, value, variableType)
812
check(variableName, 'variableName', 'string')

0 commit comments

Comments
 (0)