Skip to content

Commit

Permalink
Fix 5497
Browse files Browse the repository at this point in the history
  • Loading branch information
angrykoala committed Aug 29, 2024
1 parent b4daa27 commit 461ee3a
Show file tree
Hide file tree
Showing 8 changed files with 316 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/stupid-geese-marry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@neo4j/graphql": patch
---

Fix generated cypher for disconnect operations with filters #5497
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ function createDisconnectAndParams({

if (subqueries) {
subquery.push(subqueries);
if (whereStrs.length) {
subquery.push("WITH *");
}
}
}

Expand Down
113 changes: 113 additions & 0 deletions packages/graphql/tests/integration/issues/5497.int.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import type { UniqueType } from "../../utils/graphql-types";
import { TestHelper } from "../../utils/tests-helper";

describe("https://github.com/neo4j/graphql/issues/5467", () => {
const testHelper = new TestHelper();

let User: UniqueType;
let Cabinet: UniqueType;
let Category: UniqueType;
let File: UniqueType;

beforeAll(async () => {
User = testHelper.createUniqueType("User");
Cabinet = testHelper.createUniqueType("Cabinet");
Category = testHelper.createUniqueType("Category");
File = testHelper.createUniqueType("File");

const typeDefs = /* GraphQL */ `
type JWT @jwt {
roles: [String!]!
}
type ${User}
@authorization(
validate: [
{ operations: [CREATE, DELETE], where: { jwt: { roles_INCLUDES: "admin" } } }
{ operations: [READ, UPDATE], where: { node: { id: "$jwt.sub" } } }
]
filter: [{ where: { node: { id: "$jwt.sub" } } }]
) {
id: ID!
cabinets: [${Cabinet}!]! @relationship(type: "HAS_CABINET", direction: OUT)
}
type ${Cabinet} @authorization(filter: [{ where: { node: { user: { id: "$jwt.sub" } } } }]) {
id: ID! @id
categories: [${Category}!]! @relationship(type: "HAS_CATEGORY", direction: OUT)
user: ${User}! @relationship(type: "HAS_CABINET", direction: IN)
}
type ${Category} @authorization(filter: [{ where: { node: { cabinet: { user: { id: "$jwt.sub" } } } } }]) {
id: ID! @id
files: [${File}!]! @relationship(type: "HAS_FILE", direction: OUT)
cabinet: ${Cabinet}! @relationship(type: "HAS_CATEGORY", direction: IN)
}
type ${File} {
id: ID! @unique
category: ${Category} @relationship(type: "HAS_FILE", direction: IN)
}
`;
await testHelper.initNeo4jGraphQL({
typeDefs,
});
});

afterAll(async () => {
await testHelper.close();
});

test("should properly add where filters for auth", async () => {
const query = /* GraphQL */ `
mutation ($fileId: ID!, $newCategoryId: ID) {
${File.operations.update}(
where: { id: $fileId }
disconnect: { category: { where: { node: { NOT: { id: $newCategoryId } } } } }
connect: { category: { where: { node: { id: $newCategoryId } } } }
) {
info {
relationshipsDeleted
relationshipsCreated
}
}
}
`;

const response = await testHelper.executeGraphQL(query, {
variableValues: {
fileId: "old-id",
newCategoryId: "new-id",
},
});

expect(response.errors).toBeFalsy();
expect(response.data).toEqual({
[File.operations.update]: {
info: {
relationshipsDeleted: 0,
relationshipsCreated: 0,
},
},
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,7 @@ describe("Cypher Auth Allow", () => {
OPTIONAL MATCH (this)-[this_disconnect_posts0_rel:HAS_POST]->(this_disconnect_posts0:Post)
OPTIONAL MATCH (this_disconnect_posts0)<-[:HAS_POST]-(authorization__before_this0:User)
WITH *, count(authorization__before_this0) AS creatorCount
WITH *
WHERE this_disconnect_posts0.id = $updateUsers_args_disconnect_posts0_where_Post_this_disconnect_posts0param0 AND (apoc.util.validatePredicate(NOT ($isAuthenticated = true AND ($jwt.sub IS NOT NULL AND this.id = $jwt.sub)), \\"@neo4j/graphql/FORBIDDEN\\", [0]) AND apoc.util.validatePredicate(NOT ($isAuthenticated = true AND (creatorCount <> 0 AND ($jwt.sub IS NOT NULL AND authorization__before_this0.id = $jwt.sub))), \\"@neo4j/graphql/FORBIDDEN\\", [0]))
CALL {
WITH this_disconnect_posts0, this_disconnect_posts0_rel, this
Expand Down Expand Up @@ -728,6 +729,7 @@ describe("Cypher Auth Allow", () => {
WITH *, count(authorization__before_this0) AS creatorCount
OPTIONAL MATCH (this_post0_disconnect0)<-[:HAS_POST]-(authorization__before_this1:User)
WITH *, count(authorization__before_this1) AS creatorCount
WITH *
WHERE (apoc.util.validatePredicate(NOT ($isAuthenticated = true AND (creatorCount <> 0 AND ($jwt.sub IS NOT NULL AND authorization__before_this0.id = $jwt.sub))), \\"@neo4j/graphql/FORBIDDEN\\", [0]) AND apoc.util.validatePredicate(NOT ($isAuthenticated = true AND (creatorCount <> 0 AND ($jwt.sub IS NOT NULL AND authorization__before_this1.id = $jwt.sub))), \\"@neo4j/graphql/FORBIDDEN\\", [0]))
CALL {
WITH this_post0_disconnect0, this_post0_disconnect0_rel, this
Expand All @@ -740,6 +742,7 @@ describe("Cypher Auth Allow", () => {
OPTIONAL MATCH (this_post0_disconnect0)<-[this_post0_disconnect0_creator0_rel:HAS_POST]-(this_post0_disconnect0_creator0:User)
OPTIONAL MATCH (this_post0_disconnect0)<-[:HAS_POST]-(authorization__before_this0:User)
WITH *, count(authorization__before_this0) AS creatorCount
WITH *
WHERE this_post0_disconnect0_creator0.id = $updateComments_args_update_post_disconnect_disconnect_creator_where_User_this_post0_disconnect0_creator0param0 AND (apoc.util.validatePredicate(NOT ($isAuthenticated = true AND (creatorCount <> 0 AND ($jwt.sub IS NOT NULL AND authorization__before_this0.id = $jwt.sub))), \\"@neo4j/graphql/FORBIDDEN\\", [0]) AND apoc.util.validatePredicate(NOT ($isAuthenticated = true AND ($jwt.sub IS NOT NULL AND this_post0_disconnect0_creator0.id = $jwt.sub)), \\"@neo4j/graphql/FORBIDDEN\\", [0]))
CALL {
WITH this_post0_disconnect0_creator0, this_post0_disconnect0_creator0_rel, this_post0_disconnect0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ describe("@auth allow on specific interface implementation", () => {
OPTIONAL MATCH (this)-[this_disconnect_content0_rel:HAS_CONTENT]->(this_disconnect_content0:Post)
OPTIONAL MATCH (this_disconnect_content0)<-[:HAS_CONTENT]-(authorization__before_this0:User)
WITH *, count(authorization__before_this0) AS creatorCount
WITH *
WHERE this_disconnect_content0.id = $updateUsers_args_disconnect_content0_where_Post_this_disconnect_content0param0 AND apoc.util.validatePredicate(NOT ($isAuthenticated = true AND (creatorCount <> 0 AND ($jwt.sub IS NOT NULL AND authorization__before_this0.id = $jwt.sub))), \\"@neo4j/graphql/FORBIDDEN\\", [0])
CALL {
WITH this_disconnect_content0, this_disconnect_content0_rel, this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1200,6 +1200,7 @@ describe("Cypher Auth Where", () => {
OPTIONAL MATCH (this)-[this_content0_disconnect0_rel:HAS_CONTENT]->(this_content0_disconnect0:Post)
OPTIONAL MATCH (this_content0_disconnect0)<-[:HAS_CONTENT]-(authorization__before_this0:User)
WITH *, count(authorization__before_this0) AS creatorCount
WITH *
WHERE (($isAuthenticated = true AND ($jwt.sub IS NOT NULL AND this.id = $jwt.sub)) AND ($isAuthenticated = true AND (creatorCount <> 0 AND ($jwt.sub IS NOT NULL AND authorization__before_this0.id = $jwt.sub))))
CALL {
WITH this_content0_disconnect0, this_content0_disconnect0_rel, this
Expand Down Expand Up @@ -1274,6 +1275,7 @@ describe("Cypher Auth Where", () => {
OPTIONAL MATCH (this)-[this_content0_disconnect0_rel:HAS_CONTENT]->(this_content0_disconnect0:Post)
OPTIONAL MATCH (this_content0_disconnect0)<-[:HAS_CONTENT]-(authorization__before_this0:User)
WITH *, count(authorization__before_this0) AS creatorCount
WITH *
WHERE this_content0_disconnect0.id = $updateUsers_args_update_content0_disconnect0_where_Post_this_content0_disconnect0param0 AND (($isAuthenticated = true AND ($jwt.sub IS NOT NULL AND this.id = $jwt.sub)) AND ($isAuthenticated = true AND (creatorCount <> 0 AND ($jwt.sub IS NOT NULL AND authorization__before_this0.id = $jwt.sub))))
CALL {
WITH this_content0_disconnect0, this_content0_disconnect0_rel, this
Expand Down Expand Up @@ -1361,6 +1363,7 @@ describe("Cypher Auth Where", () => {
OPTIONAL MATCH (this)-[this_disconnect_content0_rel:HAS_CONTENT]->(this_disconnect_content0:Post)
OPTIONAL MATCH (this_disconnect_content0)<-[:HAS_CONTENT]-(authorization__before_this0:User)
WITH *, count(authorization__before_this0) AS creatorCount
WITH *
WHERE (($isAuthenticated = true AND ($jwt.sub IS NOT NULL AND this.id = $jwt.sub)) AND ($isAuthenticated = true AND (creatorCount <> 0 AND ($jwt.sub IS NOT NULL AND authorization__before_this0.id = $jwt.sub))))
CALL {
WITH this_disconnect_content0, this_disconnect_content0_rel, this
Expand Down Expand Up @@ -1437,6 +1440,7 @@ describe("Cypher Auth Where", () => {
OPTIONAL MATCH (this)-[this_disconnect_content0_rel:HAS_CONTENT]->(this_disconnect_content0:Post)
OPTIONAL MATCH (this_disconnect_content0)<-[:HAS_CONTENT]-(authorization__before_this0:User)
WITH *, count(authorization__before_this0) AS creatorCount
WITH *
WHERE this_disconnect_content0.id = $updateUsers_args_disconnect_content0_where_Post_this_disconnect_content0param0 AND (($isAuthenticated = true AND ($jwt.sub IS NOT NULL AND this.id = $jwt.sub)) AND ($isAuthenticated = true AND (creatorCount <> 0 AND ($jwt.sub IS NOT NULL AND authorization__before_this0.id = $jwt.sub))))
CALL {
WITH this_disconnect_content0, this_disconnect_content0_rel, this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1215,6 +1215,7 @@ describe("Cypher Auth Where", () => {
OPTIONAL MATCH (this)-[this_posts0_disconnect0_rel:HAS_POST]->(this_posts0_disconnect0:Post)
OPTIONAL MATCH (this_posts0_disconnect0)<-[:HAS_POST]-(authorization__before_this0:User)
WITH *, count(authorization__before_this0) AS creatorCount
WITH *
WHERE (($isAuthenticated = true AND ($jwt.sub IS NOT NULL AND this.id = $jwt.sub)) AND ($isAuthenticated = true AND (creatorCount <> 0 AND ($jwt.sub IS NOT NULL AND authorization__before_this0.id = $jwt.sub))))
CALL {
WITH this_posts0_disconnect0, this_posts0_disconnect0_rel, this
Expand Down Expand Up @@ -1269,6 +1270,7 @@ describe("Cypher Auth Where", () => {
OPTIONAL MATCH (this)-[this_posts0_disconnect0_rel:HAS_POST]->(this_posts0_disconnect0:Post)
OPTIONAL MATCH (this_posts0_disconnect0)<-[:HAS_POST]-(authorization__before_this0:User)
WITH *, count(authorization__before_this0) AS creatorCount
WITH *
WHERE this_posts0_disconnect0.id = $updateUsers_args_update_posts0_disconnect0_where_Post_this_posts0_disconnect0param0 AND (($isAuthenticated = true AND ($jwt.sub IS NOT NULL AND this.id = $jwt.sub)) AND ($isAuthenticated = true AND (creatorCount <> 0 AND ($jwt.sub IS NOT NULL AND authorization__before_this0.id = $jwt.sub))))
CALL {
WITH this_posts0_disconnect0, this_posts0_disconnect0_rel, this
Expand Down Expand Up @@ -1343,6 +1345,7 @@ describe("Cypher Auth Where", () => {
OPTIONAL MATCH (this)-[this_disconnect_posts0_rel:HAS_POST]->(this_disconnect_posts0:Post)
OPTIONAL MATCH (this_disconnect_posts0)<-[:HAS_POST]-(authorization__before_this0:User)
WITH *, count(authorization__before_this0) AS creatorCount
WITH *
WHERE (($isAuthenticated = true AND ($jwt.sub IS NOT NULL AND this.id = $jwt.sub)) AND ($isAuthenticated = true AND (creatorCount <> 0 AND ($jwt.sub IS NOT NULL AND authorization__before_this0.id = $jwt.sub))))
CALL {
WITH this_disconnect_posts0, this_disconnect_posts0_rel, this
Expand Down Expand Up @@ -1409,6 +1412,7 @@ describe("Cypher Auth Where", () => {
OPTIONAL MATCH (this)-[this_disconnect_posts0_rel:HAS_POST]->(this_disconnect_posts0:Post)
OPTIONAL MATCH (this_disconnect_posts0)<-[:HAS_POST]-(authorization__before_this0:User)
WITH *, count(authorization__before_this0) AS creatorCount
WITH *
WHERE this_disconnect_posts0.id = $updateUsers_args_disconnect_posts0_where_Post_this_disconnect_posts0param0 AND (($isAuthenticated = true AND ($jwt.sub IS NOT NULL AND this.id = $jwt.sub)) AND ($isAuthenticated = true AND (creatorCount <> 0 AND ($jwt.sub IS NOT NULL AND authorization__before_this0.id = $jwt.sub))))
CALL {
WITH this_disconnect_posts0, this_disconnect_posts0_rel, this
Expand Down
Loading

0 comments on commit 461ee3a

Please # to comment.