From e8bb3af8b7aa2779331d66481bc364a34c97a8f7 Mon Sep 17 00:00:00 2001 From: a-alle Date: Mon, 18 May 2026 21:42:30 +0100 Subject: [PATCH 1/3] add note on create relationship and delete relationship validation rules in terms of relationship ends --- .../ROOT/pages/security/authorization.adoc | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/modules/ROOT/pages/security/authorization.adoc b/modules/ROOT/pages/security/authorization.adoc index a353e2e8..98494b6b 100644 --- a/modules/ROOT/pages/security/authorization.adoc +++ b/modules/ROOT/pages/security/authorization.adoc @@ -175,7 +175,51 @@ type Post @node @authorization(validate: [ ]) { title: String! content: String! - author: User! @relationship(type: "AUTHORED", direction: IN) + author: User @relationship(type: "AUTHORED", direction: IN) +} +---- + +=== A note on CREATE_RELATIONSHIP and DELETE_RELATIONSHIP + +Creating or deleting a relationship targets both ends of the relationship, therefore the `CREATE_RELATIONSHIP` and `DELETE_RELATIONSHIP` validation rules will run for both target and source node. +Note that for `CREATE_RELATIONSHIP` only the `AFTER` validation rule will run for the source node. + +For example, consider a `Post` type and an `User` type both with CREATE_RELATIONSHIP validation rules for BEFORE and AFTER. +* only an existing author of the post can add another co-author. +* only a user which is not locked can be added as an author to a post. +The rules for each type can be combined into one but we are separating them here for clarity: + +[source, graphql, indent=0] +---- +type Post @node @authorization(validate: [ + { operations: [CREATE_RELATIONSHIP], when: [BEFORE], where: { node: { authors: { some: { id: { eq: "$jwt.sub" } } } } } } # rule 1 + { operations: [CREATE_RELATIONSHIP], when: [AFTER], where: { node: { authors: { some: { id: { eq: "$jwt.sub" } } } } } } # rule 2 +]) { + title: String! + content: String! + authors: [User!]! @relationship(type: "AUTHORED", direction: IN) +} +type User @node @authorization(validate: [ + { operations: [CREATE_RELATIONSHIP], when: [BEFORE], where: { node: { locked: { eq: false } } } } # rule 3 + { operations: [CREATE_RELATIONSHIP], when: [AFTER], where: { node: { locked: { eq: false } } } } # rule 4 +]) { + id: ID! + locked: Boolean! +} +---- + +When executing the following query, the rules that will run are rules 2, 3, and 4. Rule 1 will not run because the relationship has not been created yet, so there is no author of the post to check the id of: + +[source, graphql, indent=0] +---- +mutation { + createPosts( + input: [{ title: "My Post", content: "Amazing content", authors: { connect: { where: { node: { id: { eq: "some-id" } } } } } }] + ) { + posts { + title + } + } } ---- From fdab8dc9f5b464479c860c725c8222519b64f858 Mon Sep 17 00:00:00 2001 From: Alle <111279668+a-alle@users.noreply.github.com> Date: Wed, 20 May 2026 11:04:51 +0100 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Richard Sill <156673635+rsill-neo4j@users.noreply.github.com> --- .../ROOT/pages/security/authorization.adoc | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/modules/ROOT/pages/security/authorization.adoc b/modules/ROOT/pages/security/authorization.adoc index 98494b6b..d865bf05 100644 --- a/modules/ROOT/pages/security/authorization.adoc +++ b/modules/ROOT/pages/security/authorization.adoc @@ -182,33 +182,39 @@ type Post @node @authorization(validate: [ === A note on CREATE_RELATIONSHIP and DELETE_RELATIONSHIP Creating or deleting a relationship targets both ends of the relationship, therefore the `CREATE_RELATIONSHIP` and `DELETE_RELATIONSHIP` validation rules will run for both target and source node. -Note that for `CREATE_RELATIONSHIP` only the `AFTER` validation rule will run for the source node. +Note that for `CREATE_RELATIONSHIP` only the `AFTER` validation applies for the source node. + +For example, consider a `Post` type and a `User` type both with CREATE_RELATIONSHIP validation rules for BEFORE and AFTER: +* Only an existing author of the post can add another co-author. +* Only a user which is not locked can be added as an author to a post. +* -For example, consider a `Post` type and an `User` type both with CREATE_RELATIONSHIP validation rules for BEFORE and AFTER. -* only an existing author of the post can add another co-author. -* only a user which is not locked can be added as an author to a post. The rules for each type can be combined into one but we are separating them here for clarity: [source, graphql, indent=0] ---- type Post @node @authorization(validate: [ - { operations: [CREATE_RELATIONSHIP], when: [BEFORE], where: { node: { authors: { some: { id: { eq: "$jwt.sub" } } } } } } # rule 1 - { operations: [CREATE_RELATIONSHIP], when: [AFTER], where: { node: { authors: { some: { id: { eq: "$jwt.sub" } } } } } } # rule 2 + { operations: [CREATE_RELATIONSHIP], when: [BEFORE], where: { node: { authors: { some: { id: { eq: "$jwt.sub" } } } } } } <1> + { operations: [CREATE_RELATIONSHIP], when: [AFTER], where: { node: { authors: { some: { id: { eq: "$jwt.sub" } } } } } } <2> ]) { title: String! content: String! authors: [User!]! @relationship(type: "AUTHORED", direction: IN) } type User @node @authorization(validate: [ - { operations: [CREATE_RELATIONSHIP], when: [BEFORE], where: { node: { locked: { eq: false } } } } # rule 3 - { operations: [CREATE_RELATIONSHIP], when: [AFTER], where: { node: { locked: { eq: false } } } } # rule 4 + { operations: [CREATE_RELATIONSHIP], when: [BEFORE], where: { node: { locked: { eq: false } } } } <3> + { operations: [CREATE_RELATIONSHIP], when: [AFTER], where: { node: { locked: { eq: false } } } } <4> ]) { id: ID! locked: Boolean! } ---- +<1> Rule 1 +<2> Rule 2 +<3> Rule 3 +<4> Rule 4 -When executing the following query, the rules that will run are rules 2, 3, and 4. Rule 1 will not run because the relationship has not been created yet, so there is no author of the post to check the id of: +When executing the following query, rules 2, 3, and 4 are applied: [source, graphql, indent=0] ---- @@ -223,6 +229,8 @@ mutation { } ---- +Rule 1 isn't applied because the relationship has not been created yet, so there is no author of the post to check the ID of. + == Authorization on fields The `@authorization` directive can be used either on object types or their fields, with the former being used in examples for the most part on this page. From a211e80d64525b55a19d5e9d780d44bf4bcb40a9 Mon Sep 17 00:00:00 2001 From: Alle <111279668+a-alle@users.noreply.github.com> Date: Fri, 22 May 2026 17:31:35 +0100 Subject: [PATCH 3/3] Update modules/ROOT/pages/security/authorization.adoc Co-authored-by: Richard Sill <156673635+rsill-neo4j@users.noreply.github.com> --- modules/ROOT/pages/security/authorization.adoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/ROOT/pages/security/authorization.adoc b/modules/ROOT/pages/security/authorization.adoc index d865bf05..9dd3d311 100644 --- a/modules/ROOT/pages/security/authorization.adoc +++ b/modules/ROOT/pages/security/authorization.adoc @@ -181,7 +181,8 @@ type Post @node @authorization(validate: [ === A note on CREATE_RELATIONSHIP and DELETE_RELATIONSHIP -Creating or deleting a relationship targets both ends of the relationship, therefore the `CREATE_RELATIONSHIP` and `DELETE_RELATIONSHIP` validation rules will run for both target and source node. +Creating or deleting a relationship affects both ends of the relationship. +This means that the `CREATE_RELATIONSHIP` and `DELETE_RELATIONSHIP` validation rules apply to both the source and the target node. Note that for `CREATE_RELATIONSHIP` only the `AFTER` validation applies for the source node. For example, consider a `Post` type and a `User` type both with CREATE_RELATIONSHIP validation rules for BEFORE and AFTER: