diff --git a/packages/graphql/src/translate/queryAST/ast/operations/ConnectOperation.ts b/packages/graphql/src/translate/queryAST/ast/operations/ConnectOperation.ts index b32411d72a..153b210f1d 100644 --- a/packages/graphql/src/translate/queryAST/ast/operations/ConnectOperation.ts +++ b/packages/graphql/src/translate/queryAST/ast/operations/ConnectOperation.ts @@ -153,16 +153,15 @@ export class ConnectOperation extends MutationOperation { const filterSubqueries = wrapSubqueriesInCypherCalls(nestedContext, allFilters, [nestedContext.target]); + const predicate = Cypher.and(...allFilters.map((f) => f.getPredicate(nestedContext))); let matchClause: Cypher.Clause; if (filterSubqueries.length > 0) { - const predicate = Cypher.and(...allFilters.map((f) => f.getPredicate(nestedContext))); matchClause = Cypher.utils.concat( new Cypher.Match(matchPattern), ...filterSubqueries, new Cypher.With("*").where(predicate) ); } else { - const predicate = Cypher.and(...allFilters.map((f) => f.getPredicate(nestedContext))); matchClause = new Cypher.Match(matchPattern).where(predicate); } @@ -187,22 +186,13 @@ export class ConnectOperation extends MutationOperation { return input.getSubqueries(connectContext); }); - const authClausesBefore = this.getAuthorizationClauses(nestedContext); - - const authClausesAfter = this.getAuthorizationClausesAfter(nestedContext); - const sourceAuthClausesAfter = this.getSourceAuthorizationClausesAfter(context); - - const authClauses: Cypher.Clause[] = []; - if (authClausesAfter.length > 0 || sourceAuthClausesAfter.length > 0) { - authClauses.push(Cypher.utils.concat(...authClausesAfter, ...sourceAuthClausesAfter)); - } - const clauses = Cypher.utils.concat( matchClause, - ...authClausesBefore, + ...this.getAuthorizationClauses(nestedContext), // THESE ARE "BEFORE" AUTH ...mutationSubqueries, connectClause, - ...authClauses + ...this.getAuthorizationClausesAfter(nestedContext), // THESE ARE "AFTER" AUTH + ...this.getSourceAuthorizationClausesAfter(context) // ONLY RUN "AFTER" AUTH ON THE SOURCE NODE ); const callClause = new Cypher.Call(clauses, [context.target]); @@ -214,19 +204,16 @@ export class ConnectOperation extends MutationOperation { } private getAuthorizationClauses(context: QueryASTContext): Cypher.Clause[] { - const { selections, subqueries, predicates, validations } = this.transpileAuthClauses(context); - const predicate = Cypher.and(...predicates); - const lastSelection = selections[selections.length - 1]; - - if (!predicates.length && !validations.length) { - return []; - } else { - if (lastSelection) { - lastSelection.where(predicate); - return [...subqueries, new Cypher.With("*"), ...selections, ...validations]; + const { subqueries, predicates, validations } = this.transpileAuthClauses(context); + if (!predicates.length) { + if (!validations.length) { + return []; } - return [...subqueries, new Cypher.With("*").where(predicate), ...selections, ...validations]; + return [...subqueries, ...validations]; } + + const predicate = Cypher.and(...predicates); + return [...subqueries, new Cypher.With("*").where(predicate), ...validations]; } private getAuthorizationClausesAfter(context: QueryASTContext): Cypher.Clause[] { diff --git a/packages/graphql/src/translate/queryAST/ast/operations/DisconnectOperation.ts b/packages/graphql/src/translate/queryAST/ast/operations/DisconnectOperation.ts index 2dfa627393..3526c1f745 100644 --- a/packages/graphql/src/translate/queryAST/ast/operations/DisconnectOperation.ts +++ b/packages/graphql/src/translate/queryAST/ast/operations/DisconnectOperation.ts @@ -148,16 +148,15 @@ export class DisconnectOperation extends MutationOperation { const filterSubqueries = wrapSubqueriesInCypherCalls(nestedContext, allFilters, [nestedContext.target]); + const predicate = Cypher.and(...allFilters.map((f) => f.getPredicate(nestedContext))); let matchClause: Cypher.Clause; if (filterSubqueries.length > 0) { - const predicate = Cypher.and(...allFilters.map((f) => f.getPredicate(nestedContext))); matchClause = Cypher.utils.concat( new Cypher.OptionalMatch(matchPattern), ...filterSubqueries, new Cypher.With("*").where(predicate) ); } else { - const predicate = Cypher.and(...allFilters.map((f) => f.getPredicate(nestedContext))); matchClause = new Cypher.OptionalMatch(matchPattern).where(predicate); } @@ -173,30 +172,14 @@ export class DisconnectOperation extends MutationOperation { const deleteClause = new Cypher.With(nestedContext.relationship!).delete(nestedContext.relationship!); - const authClausesBefore = this.getAuthorizationClauses(nestedContext); - const sourceAuthClausesBefore = this.getSourceAuthorizationClausesBefore(context); - - const bothAuthClausesBefore: Cypher.Clause[] = []; - if (authClausesBefore.length === 0 && sourceAuthClausesBefore.length > 0) { - bothAuthClausesBefore.push(new Cypher.With("*"), ...sourceAuthClausesBefore); - } else { - bothAuthClausesBefore.push(Cypher.utils.concat(...authClausesBefore, ...sourceAuthClausesBefore)); - } - - const authClausesAfter = this.getAuthorizationClausesAfter(nestedContext); - const sourceAuthClausesAfter = this.getSourceAuthorizationClausesAfter(context); - - const authClauses: Cypher.Clause[] = []; - if (authClausesAfter.length > 0 || sourceAuthClausesAfter.length > 0) { - authClauses.push(Cypher.utils.concat(...authClausesAfter, ...sourceAuthClausesAfter)); - } - const clauses = Cypher.utils.concat( matchClause, - ...bothAuthClausesBefore, + ...this.getAuthorizationClauses(nestedContext), + ...this.getSourceAuthorizationClauses(context, "BEFORE"), ...mutationSubqueries, deleteClause, - ...authClauses + ...this.getAuthorizationClausesAfter(nestedContext), + ...this.getSourceAuthorizationClauses(context, "AFTER") ); const callClause = new Cypher.Call(clauses, [context.target]); @@ -205,24 +188,19 @@ export class DisconnectOperation extends MutationOperation { projectionExpr: context.returnVariable, clauses: [callClause], }; - - // return { projectionExpr: context.returnVariable, clauses: [clauses] }; } private getAuthorizationClauses(context: QueryASTContext): Cypher.Clause[] { - const { selections, subqueries, predicates, validations } = this.transpileAuthClauses(context); - const predicate = Cypher.and(...predicates); - const lastSelection = selections[selections.length - 1]; - - if (!predicates.length && !validations.length) { - return []; - } else { - if (lastSelection) { - lastSelection.where(predicate); - return [...subqueries, new Cypher.With("*"), ...selections, ...validations]; + const { subqueries, predicates, validations } = this.transpileAuthClauses(context); + if (!predicates.length) { + if (!validations.length) { + return []; } - return [...subqueries, new Cypher.With("*").where(predicate), ...selections, ...validations]; + return [...subqueries, ...validations]; } + + const predicate = Cypher.and(...predicates); + return [...subqueries, new Cypher.With("*").where(predicate), ...validations]; } private getAuthorizationClausesAfter(context: QueryASTContext): Cypher.Clause[] { @@ -240,31 +218,17 @@ export class DisconnectOperation extends MutationOperation { return []; } - private getSourceAuthorizationClausesAfter(context: QueryASTContext): Cypher.Clause[] { - const validationsAfter: Cypher.VoidProcedure[] = []; - for (const authFilter of this.sourceAuthFilters) { - const validationAfter = authFilter.getValidation(context, "AFTER"); - if (validationAfter) { - validationsAfter.push(validationAfter); - } - } - - if (validationsAfter.length > 0) { - return [new Cypher.With("*"), ...validationsAfter]; - } - return []; - } - private getSourceAuthorizationClausesBefore(context: QueryASTContext): Cypher.Clause[] { - const validationsAfter: Cypher.VoidProcedure[] = []; + private getSourceAuthorizationClauses(context: QueryASTContext, when: "BEFORE" | "AFTER"): Cypher.Clause[] { + const validations: Cypher.VoidProcedure[] = []; for (const authFilter of this.sourceAuthFilters) { - const validationAfter = authFilter.getValidation(context, "BEFORE"); - if (validationAfter) { - validationsAfter.push(validationAfter); + const validation = authFilter.getValidation(context, when); + if (validation) { + validations.push(validation); } } - if (validationsAfter.length > 0) { - return [new Cypher.With("*"), ...validationsAfter]; + if (validations.length > 0) { + return [new Cypher.With("*"), ...validations]; } return []; } diff --git a/packages/graphql/src/translate/queryAST/ast/operations/UpdateOperation.ts b/packages/graphql/src/translate/queryAST/ast/operations/UpdateOperation.ts index 5b1488047c..7734eba029 100644 --- a/packages/graphql/src/translate/queryAST/ast/operations/UpdateOperation.ts +++ b/packages/graphql/src/translate/queryAST/ast/operations/UpdateOperation.ts @@ -33,10 +33,7 @@ import type { RelationshipAdapter } from "../../../../schema-model/relationship/ import { wrapSubqueriesInCypherCalls } from "../../utils/wrap-subquery-in-calls"; import type { Filter } from "../filters/Filter"; import { ParamInputField } from "../input-fields/ParamInputField"; -/** - * This is currently just a dummy tree node, - * The whole mutation part is still implemented in the old way, the current scope of this node is just to contains the nested fields. - **/ + export class UpdateOperation extends Operation { public readonly target: ConcreteEntityAdapter; public readonly relationship: RelationshipAdapter | undefined; @@ -128,14 +125,14 @@ export class UpdateOperation extends Operation { if (!authSubqueries.length && !subqueries.length) { return undefined; } - if (authSubqueries.length > 0) { + if (authSubqueries.length && subqueries.length) { return Cypher.utils.concat(...subqueries, new Cypher.With("*"), ...authSubqueries); } - return Cypher.utils.concat(...subqueries); + return Cypher.utils.concat(...subqueries, ...authSubqueries); }) .filter((s) => s !== undefined); - // This is a small optimisation, to avoid subqueries with no changes + // This is a small optimization, to avoid subqueries with no changes // Top level should still be generated for projection if (this.relationship) { if (setParams.length === 0 && mutationSubqueries.length === 0) { @@ -155,14 +152,9 @@ export class UpdateOperation extends Operation { const predicate = this.getPredicate(nestedContext); const matchClause = new Cypher.Match(pattern); - const filtersWith = new Cypher.With("*").where(predicate); - if (filtersWith) { - filtersWith.set(...setParams); - if (mutationSubqueries.length || afterFilterSubqueries.length) { - filtersWith.with("*"); - } - } else { - matchClause.set(...setParams); + const filtersWith = new Cypher.With("*").where(predicate).set(...setParams); + if (afterFilterSubqueries.length) { + filtersWith.with("*"); } const clauses = Cypher.utils.concat( @@ -188,31 +180,23 @@ export class UpdateOperation extends Operation { ); } - return [ - // ...this.getAuthorizationClauses(nestedContext), - // ...this.inputFields.flatMap((inputField) => { - // return inputField.getAuthorizationSubqueries(nestedContext); - // }), - ]; + return []; } private getAuthorizationClauses(context: QueryASTContext): Cypher.Clause[] { - const { selections, subqueries, predicates, validations } = this.transpileAuthClauses(context); - const predicate = Cypher.and(...predicates); - const lastSelection = selections[selections.length - 1]; - + const { subqueries, predicates, validations } = this.transpileAuthClauses(context); const authSubqueries = subqueries.map((sq) => { return new Cypher.Call(sq, "*"); }); - if (!predicates.length && !validations.length) { - return []; - } else { - if (lastSelection) { - lastSelection.where(predicate); - return [...authSubqueries, new Cypher.With("*"), ...selections, ...validations]; + if (!predicates.length) { + if (!validations.length) { + return []; } - return [...authSubqueries, new Cypher.With("*").where(predicate), ...selections, ...validations]; + return [...authSubqueries, ...validations]; } + + const predicate = Cypher.and(...predicates); + return [...authSubqueries, new Cypher.With("*").where(predicate), ...validations]; } private getAuthorizationClausesAfter(context: QueryASTContext): Cypher.Clause[] {