Skip to content

Commit 53b2436

Browse files
tobias-tenglerfacebook-github-bot
authored andcommitted
Validate edgeTypeName argument points to an existing type (#4621)
Summary: Currently you can input any string for the `edgeTypeName` argument on the `prependNode` and `appendNode` directives. This change enforces that the value you supply points to an existing object type within the schema. Pull Request resolved: #4621 Differential Revision: D54206758 Pulled By: captbaritone fbshipit-source-id: 79b5250dd1c53e799fc8a12b9b77fe3e49ad649d
1 parent 232985f commit 53b2436

15 files changed

+349
-10
lines changed

compiler/crates/common/src/feature_flags.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ pub struct FeatureFlags {
123123
/// in @refetchable transform
124124
#[serde(default)]
125125
pub prefer_fetchable_in_refetch_queries: bool,
126+
127+
/// Disable validation of the `edgeTypeName` argument on `@prependNode` and `@appendNode`.
128+
#[serde(default)]
129+
pub disable_edge_type_name_validation_on_declerative_connection_directives: FeatureFlag,
126130
}
127131

128132
fn default_as_true() -> bool {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
==================================== INPUT ====================================
2+
# expected-to-throw
3+
4+
mutation appendNodeLiteralEdgeTypeNameInvalidCommentCreateMutation(
5+
$connections: [ID!]!
6+
$input: CommentCreateInput
7+
) {
8+
commentCreate(input: $input) {
9+
comment
10+
@appendNode(connections: $connections, edgeTypeName: "CommentEdge") {
11+
id
12+
}
13+
}
14+
}
15+
==================================== ERROR ====================================
16+
✖︎ Expected the 'edgeTypeName' argument value on @appendNode to be the name of an object type. 'CommentEdge' does not refer to a known object type. Did you mean `CommentsEdge`, `Comment`, or `SegmentsEdge`?
17+
18+
append-node-literal-edge-type-name-invalid.graphql:9:60
19+
8 │ comment
20+
9 │ @appendNode(connections: $connections, edgeTypeName: "CommentEdge") {
21+
│ ^^^^^^^^^^^^^
22+
10 │ id
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# expected-to-throw
2+
3+
mutation appendNodeLiteralEdgeTypeNameInvalidCommentCreateMutation(
4+
$connections: [ID!]!
5+
$input: CommentCreateInput
6+
) {
7+
commentCreate(input: $input) {
8+
comment
9+
@appendNode(connections: $connections, edgeTypeName: "CommentEdge") {
10+
id
11+
}
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
==================================== INPUT ====================================
2+
# expected-to-throw
3+
4+
mutation appendNodeLiteralEdgeTypeNameNotObjectTypeMutation(
5+
$connections: [ID!]!
6+
$input: CommentCreateInput
7+
) {
8+
commentCreate(input: $input) {
9+
comment
10+
@appendNode(connections: $connections, edgeTypeName: "Node") {
11+
id
12+
}
13+
}
14+
}
15+
==================================== ERROR ====================================
16+
✖︎ Expected the 'edgeTypeName' argument value on @appendNode to be the name of an object type. 'Node' does not refer to a known object type.
17+
18+
append-node-literal-edge-type-name-not-object-type.graphql:9:60
19+
8 │ comment
20+
9 │ @appendNode(connections: $connections, edgeTypeName: "Node") {
21+
│ ^^^^^^
22+
10 │ id
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# expected-to-throw
2+
3+
mutation appendNodeLiteralEdgeTypeNameNotObjectTypeMutation(
4+
$connections: [ID!]!
5+
$input: CommentCreateInput
6+
) {
7+
commentCreate(input: $input) {
8+
comment
9+
@appendNode(connections: $connections, edgeTypeName: "Node") {
10+
id
11+
}
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
==================================== INPUT ====================================
2+
mutation appendNodeLiteralEdgeTypeNameVariableMutation(
3+
$connections: [ID!]!
4+
$input: CommentCreateInput
5+
$edgeTypeName: String!
6+
) {
7+
commentCreate(input: $input) {
8+
comment
9+
@appendNode(connections: $connections, edgeTypeName: $edgeTypeName) {
10+
id
11+
}
12+
}
13+
}
14+
==================================== OUTPUT ===================================
15+
{
16+
"fragment": {
17+
"argumentDefinitions": [
18+
{
19+
"defaultValue": null,
20+
"kind": "LocalArgument",
21+
"name": "connections"
22+
},
23+
{
24+
"defaultValue": null,
25+
"kind": "LocalArgument",
26+
"name": "edgeTypeName"
27+
},
28+
{
29+
"defaultValue": null,
30+
"kind": "LocalArgument",
31+
"name": "input"
32+
}
33+
],
34+
"kind": "Fragment",
35+
"metadata": null,
36+
"name": "appendNodeLiteralEdgeTypeNameVariableMutation",
37+
"selections": [
38+
{
39+
"alias": null,
40+
"args": [
41+
{
42+
"kind": "Variable",
43+
"name": "input",
44+
"variableName": "input"
45+
}
46+
],
47+
"concreteType": "CommentCreateResponsePayload",
48+
"kind": "LinkedField",
49+
"name": "commentCreate",
50+
"plural": false,
51+
"selections": [
52+
{
53+
"alias": null,
54+
"args": null,
55+
"concreteType": "Comment",
56+
"kind": "LinkedField",
57+
"name": "comment",
58+
"plural": false,
59+
"selections": [
60+
{
61+
"alias": null,
62+
"args": null,
63+
"kind": "ScalarField",
64+
"name": "id",
65+
"storageKey": null
66+
}
67+
],
68+
"storageKey": null
69+
}
70+
],
71+
"storageKey": null
72+
}
73+
],
74+
"type": "Mutation",
75+
"abstractKey": null
76+
},
77+
"kind": "Request",
78+
"operation": {
79+
"argumentDefinitions": [
80+
{
81+
"defaultValue": null,
82+
"kind": "LocalArgument",
83+
"name": "connections"
84+
},
85+
{
86+
"defaultValue": null,
87+
"kind": "LocalArgument",
88+
"name": "input"
89+
},
90+
{
91+
"defaultValue": null,
92+
"kind": "LocalArgument",
93+
"name": "edgeTypeName"
94+
}
95+
],
96+
"kind": "Operation",
97+
"name": "appendNodeLiteralEdgeTypeNameVariableMutation",
98+
"selections": [
99+
{
100+
"alias": null,
101+
"args": [
102+
{
103+
"kind": "Variable",
104+
"name": "input",
105+
"variableName": "input"
106+
}
107+
],
108+
"concreteType": "CommentCreateResponsePayload",
109+
"kind": "LinkedField",
110+
"name": "commentCreate",
111+
"plural": false,
112+
"selections": [
113+
{
114+
"alias": null,
115+
"args": null,
116+
"concreteType": "Comment",
117+
"kind": "LinkedField",
118+
"name": "comment",
119+
"plural": false,
120+
"selections": [
121+
{
122+
"alias": null,
123+
"args": null,
124+
"kind": "ScalarField",
125+
"name": "id",
126+
"storageKey": null
127+
}
128+
],
129+
"storageKey": null
130+
},
131+
{
132+
"alias": null,
133+
"args": null,
134+
"filters": null,
135+
"handle": "appendNode",
136+
"key": "",
137+
"kind": "LinkedHandle",
138+
"name": "comment",
139+
"handleArgs": [
140+
{
141+
"kind": "Variable",
142+
"name": "connections",
143+
"variableName": "connections"
144+
},
145+
{
146+
"kind": "Variable",
147+
"name": "edgeTypeName",
148+
"variableName": "edgeTypeName"
149+
}
150+
]
151+
}
152+
],
153+
"storageKey": null
154+
}
155+
]
156+
},
157+
"params": {
158+
"cacheID": "c6c4a56d7ea1db74c1935491b7a2e10a",
159+
"id": null,
160+
"metadata": {},
161+
"name": "appendNodeLiteralEdgeTypeNameVariableMutation",
162+
"operationKind": "mutation",
163+
"text": null
164+
}
165+
}
166+
167+
QUERY:
168+
169+
mutation appendNodeLiteralEdgeTypeNameVariableMutation(
170+
$input: CommentCreateInput
171+
) {
172+
commentCreate(input: $input) {
173+
comment {
174+
id
175+
}
176+
}
177+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
mutation appendNodeLiteralEdgeTypeNameVariableMutation(
2+
$connections: [ID!]!
3+
$input: CommentCreateInput
4+
$edgeTypeName: String!
5+
) {
6+
commentCreate(input: $input) {
7+
comment
8+
@appendNode(connections: $connections, edgeTypeName: $edgeTypeName) {
9+
id
10+
}
11+
}
12+
}

compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/append-node-literal-edge-type-name.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ mutation appendNodeLiteralEdgeTypeNameCommentCreateMutation(
55
) {
66
commentCreate(input: $input) {
77
comment
8-
@appendNode(connections: $connections, edgeTypeName: "CommentEdge") {
8+
@appendNode(connections: $connections, edgeTypeName: "CommentsEdge") {
99
id
1010
}
1111
}
@@ -134,7 +134,7 @@ mutation appendNodeLiteralEdgeTypeNameCommentCreateMutation(
134134
{
135135
"kind": "Literal",
136136
"name": "edgeTypeName",
137-
"value": "CommentEdge"
137+
"value": "CommentsEdge"
138138
}
139139
]
140140
}

compiler/crates/relay-compiler/tests/compile_relay_artifacts/fixtures/append-node-literal-edge-type-name.graphql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ mutation appendNodeLiteralEdgeTypeNameCommentCreateMutation(
44
) {
55
commentCreate(input: $input) {
66
comment
7-
@appendNode(connections: $connections, edgeTypeName: "CommentEdge") {
7+
@appendNode(connections: $connections, edgeTypeName: "CommentsEdge") {
88
id
99
}
1010
}

compiler/crates/relay-compiler/tests/compile_relay_artifacts_test.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<742eb57a3eb061bcf247ff05572ac49d>>
7+
* @generated SignedSource<<a462cf5b6b402f99514438fe2a6c56fe>>
88
*/
99

1010
mod compile_relay_artifacts;
@@ -145,6 +145,27 @@ async fn append_node_literal_edge_type_name() {
145145
test_fixture(transform_fixture, file!(), "append-node-literal-edge-type-name.graphql", "compile_relay_artifacts/fixtures/append-node-literal-edge-type-name.expected", input, expected).await;
146146
}
147147

148+
#[tokio::test]
149+
async fn append_node_literal_edge_type_name_invalid() {
150+
let input = include_str!("compile_relay_artifacts/fixtures/append-node-literal-edge-type-name-invalid.graphql");
151+
let expected = include_str!("compile_relay_artifacts/fixtures/append-node-literal-edge-type-name-invalid.expected");
152+
test_fixture(transform_fixture, file!(), "append-node-literal-edge-type-name-invalid.graphql", "compile_relay_artifacts/fixtures/append-node-literal-edge-type-name-invalid.expected", input, expected).await;
153+
}
154+
155+
#[tokio::test]
156+
async fn append_node_literal_edge_type_name_not_object_type() {
157+
let input = include_str!("compile_relay_artifacts/fixtures/append-node-literal-edge-type-name-not-object-type.graphql");
158+
let expected = include_str!("compile_relay_artifacts/fixtures/append-node-literal-edge-type-name-not-object-type.expected");
159+
test_fixture(transform_fixture, file!(), "append-node-literal-edge-type-name-not-object-type.graphql", "compile_relay_artifacts/fixtures/append-node-literal-edge-type-name-not-object-type.expected", input, expected).await;
160+
}
161+
162+
#[tokio::test]
163+
async fn append_node_literal_edge_type_name_variable() {
164+
let input = include_str!("compile_relay_artifacts/fixtures/append-node-literal-edge-type-name-variable.graphql");
165+
let expected = include_str!("compile_relay_artifacts/fixtures/append-node-literal-edge-type-name-variable.expected");
166+
test_fixture(transform_fixture, file!(), "append-node-literal-edge-type-name-variable.graphql", "compile_relay_artifacts/fixtures/append-node-literal-edge-type-name-variable.expected", input, expected).await;
167+
}
168+
148169
#[tokio::test]
149170
async fn auto_filled_argument_on_defer() {
150171
let input = include_str!("compile_relay_artifacts/fixtures/auto-filled-argument-on-defer.graphql");

0 commit comments

Comments
 (0)