Skip to content

Commit

Permalink
@Skip and @include should not allowed for subscription root
Browse files Browse the repository at this point in the history
fixes #48
  • Loading branch information
jangko committed Apr 30, 2021
1 parent bdb4c20 commit bec29bf
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 16 deletions.
3 changes: 3 additions & 0 deletions graphql/graphql.nim
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type
ErrOperationNotFound
ErrScalarError
ErrEnumError
ErrDirNotAllowed

FieldRef* = ref FieldObj
FieldObj* = object
Expand Down Expand Up @@ -235,6 +236,8 @@ proc error*(ctx: GraphqlRef, err: GraphqlError, node: Node, msg: varargs[string,
"'$1' got '$2': $3" % [$node, msg[0], msg[1]]
of ErrEnumError:
"'$1' got '$2'('$3'), expect '$4'" % [$node, msg[0], msg[1], msg[2]]
of ErrDirNotAllowed:
"directive '$1' is not allowed at subscription root field" % [$node]
else:
"ASSERT: UNSPECIFIED ERR KIND: " & $err
)
Expand Down
18 changes: 13 additions & 5 deletions graphql/validator.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1184,7 +1184,7 @@ proc mutationMutation(ctx: GraphqlRef, symNode: Node) =
visit validateVarUsage(symNode)
ctx.skipOrInclude(fieldSet, symNode, ctx.rootMutation)

proc countRootFields(sels: Node, root = true): int =
proc countRootFields(ctx: GraphqlRef, sels: Node, root = true): int =
var count = 0
for field in sels:
case field.kind
Expand All @@ -1193,13 +1193,20 @@ proc countRootFields(sels: Node, root = true): int =
let spread = FragmentSpread(field)
let name = spread.name
let frag = Fragment(name.sym.ast)
if root: inc(count, countRootFields(frag.sels, false))
fieldsCount := countRootFields(frag.sels, false)
if root: inc(count, fieldsCount)
of nkInlineFragment:
# typeCond, dirs, sels
let frag = InlineFragment(field)
if root: inc(count, countRootFields(frag.sels, false))
fieldsCount := countRootFields(frag.sels, false)
if root: inc(count, fieldsCount)
of nkField:
# alias, name, args, dirs, sels
let dirs = Field(field).dirs
for dir in dirs:
let name = dir.name
invalid toKeyword(name.sym.name) in {kwSkip, kwInclude}:
ctx.error(ErrDirNotAllowed, name)
let name = Field(field).name
if toKeyword(name.name) notin introsKeywords:
inc count
Expand All @@ -1215,8 +1222,9 @@ proc subscriptionSubscription(ctx: GraphqlRef, symNode: Node) =
var fieldSet: FieldSet
visit fieldSelection(symNode, node.sels, ctx.rootSubs, fieldSet)
visit fieldInSetCanMerge(fieldSet)
invalid countRootFields(node.sels) != 1:
ctx.error(ErrOnlyOne, node.Node, "root selection")
rootFieldsCount := countRootFields(node.sels)
invalid rootFieldsCount != 1:
ctx.error(ErrOnlyOne, node.Node, "root subscription field")
visit validateVarUsage(symNode)
ctx.skipOrInclude(fieldSet, symNode, ctx.rootSubs)

Expand Down
65 changes: 54 additions & 11 deletions tests/validation/op_subscription.toml
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ subscription {
"""

[[units]]
name = "only one root selection ok"
name = "only one root subscription field ok"
code = """
type Subscription {
name: String
Expand All @@ -412,8 +412,8 @@ subscription {
"""

[[units]]
name = "only one root selection"
error = "[6, 14]: Error: only one 'root selection' allowed"
name = "only one root subscription field"
error = "[6, 14]: Error: only one 'root subscription field' allowed"
code = """
type Subscription {
name: String
Expand All @@ -427,8 +427,8 @@ subscription {
"""

[[units]]
name = "only one root selection inline fragment"
error = "[8, 14]: Error: only one 'root selection' allowed"
name = "only one root subscription field inline fragment"
error = "[8, 14]: Error: only one 'root subscription field' allowed"
code = """
type Subscription {
name: String
Expand All @@ -448,7 +448,7 @@ subscription {
"""

[[units]]
name = "only one root selection inline fragment ok"
name = "only one root subscription field inline fragment ok"
code = """
type Subscription {
name: String
Expand All @@ -467,7 +467,7 @@ subscription {
"""

[[units]]
name = "only one root selection spread fragment ok"
name = "only one root subscription field spread fragment ok"
code = """
type Subscription {
name: String
Expand All @@ -482,8 +482,8 @@ subscription {
"""

[[units]]
name = "only one root selection spread fragment"
error = "[9, 14]: Error: only one 'root selection' allowed"
name = "only one root subscription field spread fragment"
error = "[9, 14]: Error: only one 'root subscription field' allowed"
code = """
type Subscription {
name: String
Expand Down Expand Up @@ -685,7 +685,7 @@ subscription ($myarg: String = "123") {

[[units]]
name = "only one non-introspection field allowed at root"
error = "[4, 14]: Error: only one 'root selection' allowed"
error = "[4, 14]: Error: only one 'root subscription field' allowed"
code = """
type Subscription {
name: String
Expand Down Expand Up @@ -723,4 +723,47 @@ subscription sub {
name
}
}
"""
"""


[[units]]
name = "@skip not allowed in subscription root field"
error = "[10, 15]: Error: directive 'skip' is not allowed at subscription root field"
code = """
type Message {
body: String
sender: String
}
type Subscription {
name: String
newMessage: Message
}
subscription sub {
newMessage @skip(if: true) {
__typename
body
sender
}
}
"""

[[units]]
name = "@include not allowed in subscription root field"
error = "[10, 15]: Error: directive 'include' is not allowed at subscription root field"
code = """
type Message {
body: String
sender: String
}
type Subscription {
name: String
newMessage: Message
}
subscription sub {
newMessage @include(if: true) {
__typename
body
sender
}
}
"""

0 comments on commit bec29bf

Please sign in to comment.