From b578a35c091b9e6c80de48e3681dd1701699d487 Mon Sep 17 00:00:00 2001 From: Richard Sill <156673635+rsill-neo4j@users.noreply.github.com> Date: Fri, 8 Nov 2024 10:04:19 +0100 Subject: [PATCH] resolve merge conflicts --- .../ROOT/pages/directives/autogeneration.adoc | 2 +- .../ROOT/pages/directives/custom-logic.adoc | 18 +-- .../pages/directives/database-mapping.adoc | 123 +++++++++++++---- modules/ROOT/pages/directives/index.adoc | 54 ++++---- .../directives/indexes-and-constraints.adoc | 128 +++++++++--------- .../field-configuration.adoc | 2 +- .../type-configuration.adoc | 16 ++- .../integrations/relay-compatibility.adoc | 15 +- .../ROOT/pages/security/authentication.adoc | 2 +- .../ROOT/pages/security/authorization.adoc | 12 +- .../ROOT/pages/security/configuration.adoc | 33 ++++- modules/ROOT/pages/security/index.adoc | 2 +- modules/ROOT/pages/security/operations.adoc | 10 +- .../security/subscriptions-authorization.adoc | 6 +- 14 files changed, 274 insertions(+), 149 deletions(-) diff --git a/modules/ROOT/pages/directives/autogeneration.adoc b/modules/ROOT/pages/directives/autogeneration.adoc index 7688f518..4abef6e6 100644 --- a/modules/ROOT/pages/directives/autogeneration.adoc +++ b/modules/ROOT/pages/directives/autogeneration.adoc @@ -15,7 +15,7 @@ This enables autogeneration of IDs for the field. The format of each generated ID is a UUID generated by the link:https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-randomuuid[`randomUUID()` function]. The field will not be present in input types for mutations. -It is recommended to use xref::/directives/indexes-and-constraints.adoc#_unique_node_property_constraints[`@unique`] in conjunction with this to add a unique node property constraint. +It is recommended to use xref::/directives/indexes-and-constraints.adoc#_unique[`@unique`] in conjunction with this to add a unique node property constraint. === Definition diff --git a/modules/ROOT/pages/directives/custom-logic.adoc b/modules/ROOT/pages/directives/custom-logic.adoc index 88dcb4ae..f032fbb2 100644 --- a/modules/ROOT/pages/directives/custom-logic.adoc +++ b/modules/ROOT/pages/directives/custom-logic.adoc @@ -7,7 +7,9 @@ The `@cypher` directive binds a GraphQL field to the results of a Cypher query. This directive can be used both for properties in a type or as top level queries. -=== Global variables +=== Definition + +==== Global variables Global variables are available for use within the Cypher statement, and can be applied to the `@cypher` directive. @@ -90,14 +92,14 @@ type Query { |=== -=== Return values +==== Return values The return value of Cypher statements must always be of the same type to which the directive is applied. The variable must also be aliased with a name that is the same as the one passed to `columnName`. This can be the name of a node, relationship query, or an alias in the `RETURN` statement of the Cypher statement. -==== Scalar values +===== Scalar values Cypher statements must return a value which matches the scalar type to which the directive was applied. For example: @@ -109,7 +111,7 @@ type Query { } ---- -==== Object types +===== Object types When returning an object type, all fields of the type must be available in the Cypher return value. This can be achieved by either returning the entire object from the Cypher query, or returning a map of the fields which are required for the object type. @@ -152,7 +154,7 @@ type Query { The downside of the latter approach is that you need to adjust the return object as you change your object type definition. -=== Input arguments +==== Input arguments The `@cypher` statement can access the query parameters by prepending `$` to the parameter name. For example: @@ -174,7 +176,7 @@ query { ---- -=== Usage examples +=== Usage The `@cypher` directive can be used in different contexts, such as the ones described in this section. @@ -383,7 +385,7 @@ directive @customResolver( ) on FIELD_DEFINITION ---- -=== The `requires` argument +=== Usage The `requires` argument can be used: @@ -552,7 +554,7 @@ new Neo4jGraphQL({ }) ---- -=== Context values +==== Context values The GraphQL context for the request is available as the third argument in a callback. This maps to the argument pattern for GraphQL resolvers. diff --git a/modules/ROOT/pages/directives/database-mapping.adoc b/modules/ROOT/pages/directives/database-mapping.adoc index 39dcd2bb..7794f7b8 100644 --- a/modules/ROOT/pages/directives/database-mapping.adoc +++ b/modules/ROOT/pages/directives/database-mapping.adoc @@ -8,9 +8,21 @@ This page describes how to use directives for database mapping. Each type in your GraphQL type definitions can be mapped to an entity in your Neo4j database, such as nodes, relationships, and relationship properties. -[[type-definitions-node]] == `@node` +=== Definition + +[source, graphql, indent=0] +---- +"""Informs @neo4j/graphql of node metadata""" +directive @node( + """The labels to map this GraphQL type to in the Neo4j database""" + labels: [String!] +) on OBJECT +---- + +=== Usage + Adding the `@node` directive to your GraphQL type specifies that it represents a Neo4j node. For example, to represent a Neo4j node with the label "Movie" and a single property "title" of type string: @@ -27,12 +39,16 @@ In version 6.x, it's not required to specify every GraphQL type representing a N In the future, types without the `@node` directive will no longer be treated as Neo4j nodes. ==== -When not differently specified, the GraphQL type name is used as a label for the represented Neo4j node. It's possible to explicitly define the Neo4j node labels by using the argument `labels`: +When not differently specified, the GraphQL type name is used as a label for the represented Neo4j node. It's possible to explicitly define the Neo4j node labels by using the parameter `labels`. -[discrete] -=== `labels` +==== The `labels` parameter -This parameter defines the list of label to be used in Neo4j instead of the GraphQL type name: +You can append the optional parameters `labels` to a GraphQL object with the `@node` directive. +This parameter lists the labels to be used in Neo4j instead of the GraphQL type name. + +.Querying a field with the `labels` parameter +==== +Consider the following type definition: [source, graphql, indent=0] ---- @@ -41,7 +57,7 @@ type Dog @node(labels: ["K9"]) { } ---- -This way, the following query: +Here is a query against the `Dog` node: [source, graphql, indent=0] ---- @@ -52,15 +68,20 @@ This way, the following query: } ---- -Generates the Cypher query: +The following Cypher is generated: [source, cypher, indent=0] ---- MATCH (this: K9) RETURN this { .name } as name ---- +==== -If the GraphQL type name should still be used as a label, it needs to be specified as well: +If you want to use the GraphQL type name as a label, specifiy both. + +.Querying a field with two entries for the `labels` parameter +==== +Consider the following type definition: [source, graphql, indent=0] ---- @@ -69,7 +90,8 @@ type Dog @node(labels: ["Dog", "K9"]) { } ---- -This way, the following query: +Here is an example for a query against the `Dog` node + [source, graphql, indent=0] ---- @@ -80,13 +102,14 @@ This way, the following query: } ---- -Generates the Cypher query: +The following Cypher is generated: [source, cypher, indent=0] ---- MATCH (this:Dog:K9) RETURN this { .name } as this ---- +==== [NOTE] ==== @@ -103,12 +126,18 @@ type Dog @node(labels: ["K9", "Dog"]) { } ---- +See xref::/directives/indexes-and-constraints.adoc#_unique[`@unique`] to learn more about the `@unique` directive. + -[discrete] -=== Using `$jwt` and `$context` +==== Using `$jwt` and `$context` In some cases, you may want to generate dynamic labels depending on the user requesting. -For that, you can use the variable `$jwt` to define a custom label in the JWT: +You can use the variable `$jwt` to define a custom label in the JWT. + + +.Querying a field with a `$jwt` variable in the `labels` parameter +==== +Consider the following type definition: [source, graphql, indent=0] ---- @@ -128,13 +157,14 @@ The following query yields a different Cypher query depending on the user JWT: } ---- -Assuming there is a user with the value `"username": "arthur"` in JWT, the Cypher query looks like: +Assuming there is a user with the value `"username": "arthur"` in JWT, the Cypher query looks like this: [source, cypher, indent=0] ---- MATCH (this:arthur) RETURN this { .name } as this ---- +==== Similarly, context values can be passed directly: @@ -145,7 +175,7 @@ type User @node(label: ["$context.appId"]) { } ---- -When running the server with Apollo: +For example, if you are running the server with Apollo: [source, js, indent=0] ---- @@ -160,26 +190,59 @@ await startStandaloneServer(server, { == `@relationship` +=== Definition + +[source, graphql, indent=0] +---- +""" +Instructs @neo4j/graphql to treat this field as a relationship. Opens up the ability to create and connect on this field. +""" +directive @relationship( + type: String! + """Valid and default directions for this relationship.""" + queryDirection: RelationshipQueryDirection = DEFAULT_DIRECTED + direction: RelationshipDirection! + """ + The name of the interface containing the properties for this relationship. + """ + properties: String + """ + Prevent all but these operations from being generated for this relationship + """ + nestedOperations: [RelationshipNestedOperations!]! = [CREATE, UPDATE, DELETE, CONNECT, DISCONNECT, CONNECT_OR_CREATE] + """Prevent aggregation for this relationship""" + aggregate: Boolean = true +) on FIELD_DEFINITION +---- + +=== Usage + Relationships are represented by marking particular fields with a directive -- in this case, `@relationship`. -It defines the relationship type in the database, as well as its direction. +It defines the relationship type in the database, as well as which direction that relationship goes in. -The following type definitions add a second node type, `Actor`, and connect `Movie` and `Actor` via the `ACTED_IN` relationship: +To add two node types, "Movie" and "Actor", and connect the two: [source, graphql, indent=0] ---- -type Movie @node { +type Movie { title: String actors: [Actor!]! @relationship(type: "ACTED_IN", direction: IN) } -type Actor @node { +type Actor { name: String movies: [Movie!]! @relationship(type: "ACTED_IN", direction: OUT) } ---- -Note that, in this case, there is a directive on each "end" of the relationship, but it is not essential. +[NOTE] +==== +The `@relationship` directive is used twice, once on each end of the relationship. +This is the standard way of modeling a relationship with the GraphQL Library. +However, it is not a requirement of the type definitions themselves as relationships can deliberately be underspecified, for example to limit access through the API layer. +==== +See also: xref::/directives/schema-configuration/field-configuration#_relationship[`@relationship` field configuration]. == `@relationshipProperties` @@ -201,12 +264,12 @@ For example, for the "ACTED_IN" relationship, add a property "roles": [source, graphql, indent=0] ---- -type Movie @node { +type Movie { title: String actors: [Actor!]! @relationship(type: "ACTED_IN", direction: IN, properties: "ActedIn") } -type Actor @node { +type Actor { name: String movies: [Movie!]! @relationship(type: "ACTED_IN", direction: OUT, properties: "ActedIn") } @@ -220,9 +283,23 @@ Note that in addition to this type, there is an added key `properties` in the ex For more information, see xref::/types/relationships.adoc[Type definitions -> Relationships]. -[[type-definitions-alias]] == `@alias` +=== Definition + +[source, graphql, indent=0] +---- +""" +Instructs @neo4j/graphql to map a GraphQL field to a Neo4j node or relationship property. +""" +directive @alias( + """The name of the Neo4j property""" + property: String! +) on FIELD_DEFINITION +---- + +=== Usage + This directive maps a GraphQL field to a Neo4j property on a node or relationship. It can be used on any fields that are not `@cypher` or `@relationship` fields. diff --git a/modules/ROOT/pages/directives/index.adoc b/modules/ROOT/pages/directives/index.adoc index 0bad8f45..c9db97f1 100644 --- a/modules/ROOT/pages/directives/index.adoc +++ b/modules/ROOT/pages/directives/index.adoc @@ -5,50 +5,50 @@ The Neo4j GraphQL Library provides the following directives to be used whilst defining types: -== Database mapping +== Security [cols="2,5"] |=== | Directive | Description -| xref::/directives/database-mapping.adoc#_relationship[`@relationship`] -| Configures xref::/types/relationships.adoc[relationships] between object types. +| xref::/security/authentication.adoc[`@authentication`] +| Requires authentication checks when accessing the type. -| xref::/directives/database-mapping.adoc#_relationshipproperties[`@relationshipProperties`] -a| Required to differentiate interfaces that are used for relationship properties, and otherwise. +| xref::/security/authorization.adoc[`@authorization`] +| Specifies authorization rules for queries and mutations on the type. -| xref::/directives/database-mapping.adoc#type-definitions-node[`@node`] -| Specifies the configuration of a GraphQL object type which represents a Neo4j node. +| xref::/security/configuration.adoc#_jwt[`@jwt`] +| Configures the JWT authentication and authorization filters to include additional JWT claims. -| xref::/directives/database-mapping.adoc#type-definitions-alias[`@alias`] -| Maps a GraphQL schema field to a Neo4j property on a node or relationship. +| xref::/security/configuration.adoc#_jwtclaim[`@jwtClaim`] +| Used in combination with `@jwt`. +Configures the JWT authentication and authorization filters to include an additional JWT claim which is either nested or using special characters not supported by GraphQL. -| xref::/types/relationships.adoc#_declarerelationship[`@declareRelationship`] -| Configure relationships to be implemented on object types. +| xref::/security/subscriptions-authorization.adoc[`@subscriptionsAuthorization`] +| Specifies authorization rules for subscriptions on the type. |=== -== Security +== Database mapping [cols="2,5"] |=== | Directive | Description -| xref::/security/authentication.adoc[`@authentication`] -| Requires authentication checks when accessing the type. +| xref::/directives/database-mapping.adoc#_node[`@node`] +| Specifies the configuration of a GraphQL object type which represents a Neo4j node. -| xref::/security/authorization.adoc[`@authorization`] -| Specifies authorization rules for queries and mutations on the type. +| xref::/directives/database-mapping.adoc#_relationship[`@relationship`] +| Configures xref::/types/relationships.adoc[relationships] between object types. Also see xref::/directives/schema-configuration/field-configuration.adoc#_relationship[`@relationship` field configuration]. -| xref::/security/configuration.adoc#_the_jwt_directive[`@jwt`] -| Configures the JWT authentication and authorization filters to include additional JWT claims. +| xref::/directives/database-mapping.adoc#_relationshipproperties[`@relationshipProperties`] +a| Required to differentiate interfaces that are used for relationship properties, and otherwise. -| xref::/security/configuration.adoc#_the_jwtclaim_directive[`@jwtClaim`] -| Used in combination with `@jwt`. -Configures the JWT authentication and authorization filters to include an additional JWT claim which is either nested or using special characters not supported by GraphQL. +| xref::/directives/database-mapping.adoc#_alias[`@alias`] +| Maps a GraphQL schema field to a Neo4j property on a node or relationship. -| xref::/security/subscriptions-authorization.adoc[`@subscriptionsAuthorization`] -| Specifies authorization rules for subscriptions on the type. +| xref::/types/relationships.adoc#_declarerelationship[`@declareRelationship`] +| Configure relationships to be implemented on object types. |=== @@ -84,7 +84,7 @@ Configures the JWT authentication and authorization filters to include an additi | xref::/directives/schema-configuration/type-configuration.adoc#type-definitions-default-values-default[`@default`] | Allows the setting of a default value for a field during object creation. -| xref::/directives/schema-configuration/type-configuration.adoc#type-definitions-plural[`@plural`] +| xref::/directives/schema-configuration/type-configuration.adoc#_plural[`@plural`] | Redefines how to compose the plural of the type for the generated operations. Particularly useful for types that are not correctly pluralized or are non-English words. @@ -105,10 +105,10 @@ Particularly useful for types that are not correctly pluralized or are non-Engli |=== | Directive | Description -| xref::/directives/indexes-and-constraints.adoc#_fulltext_indexes[`@fulltext`] +| xref::/directives/indexes-and-constraints.adoc#_fulltext[`@fulltext`] | Indicates that there should be a fulltext index inserted into the database for the specified Node and its properties. -| xref::/directives/indexes-and-constraints.adoc#_unique_node_property_constraints[`@unique`] +| xref::/directives/indexes-and-constraints.adoc#_unique[`@unique`] | Indicates that there should be a uniqueness constraint in the database for the fields that it is applied to. | xref::/directives/indexes-and-constraints.adoc#_vector_index_search[`@vector`] @@ -146,7 +146,7 @@ of any required fields that is passed as arguments to the custom resolver. |=== | Directive | Description -| xref:/integrations/relay-compatibility.adoc[`@relayId`] +| xref:/integrations/relay-compatibility.adoc#_relayid[`@relayId`] | Specifies that the field should be used as the global node identifier for Relay. |=== diff --git a/modules/ROOT/pages/directives/indexes-and-constraints.adoc b/modules/ROOT/pages/directives/indexes-and-constraints.adoc index d750a1b7..60351153 100644 --- a/modules/ROOT/pages/directives/indexes-and-constraints.adoc +++ b/modules/ROOT/pages/directives/indexes-and-constraints.adoc @@ -5,63 +5,10 @@ This page describes how to use indexes and constraints in the Neo4j GraphQL Library. -== Unique node property constraints -Unique node property constraints map to `@unique` directives used in your type definitions, which has the following definition: +== `@fulltext` -[source, graphql, indent=0] ----- -"""Informs @neo4j/graphql that there should be a uniqueness constraint in the database for the decorated field.""" -directive @unique( - """The name which should be used for this constraint. By default; type name, followed by an underscore, followed by the field name.""" - constraintName: String -) on FIELD_DEFINITION ----- - -Using this directive does not automatically ensure the existence of these constraints, and you will need to create them manually. - -=== Usage - -`@unique` directives can only be used in GraphQL object types representing nodes, for any label specified on them. - -In the following example, a unique constraint is asserted for the label `Colour` and the property `hexadecimal`: - -[source, graphql, indent=0] ----- -type Colour @node { - hexadecimal: String! @unique -} ----- - -In the next example, a unique constraint with name `unique_colour` is asserted for the label `Colour` and the property `hexadecimal`: - -[source, graphql, indent=0] ----- -type Colour @node { - hexadecimal: String! @unique(constraintName: "unique_colour") -} ----- - -The `@node` directive is used to change the database label mapping in this next example, so a unique constraint is asserted for the first label in the list, `Color`, and the property `hexadecimal`: - -[source, graphql, indent=0] ----- -type Colour @node(labels: ["Color"]) { - hexadecimal: String! @unique -} ----- - -In the following example, all labels specified in the `labels` argument of the `@node` directive are also checked when asserting constraints. -If there is a unique constraint specified for the `hexadecimal` property of nodes with the `Hue` label, but not the `Color` label, no error is thrown when running `assertIndexesAndConstraints`. - -[source, graphql, indent=0] ----- -type Colour @node(labels: ["Color", "Hue"]) { - hexadecimal: String! @unique -} ----- - -== Fulltext indexes +=== Definition You can use the `@fulltext` directive to specify a https://neo4j.com/docs/cypher-manual/current/indexes-for-full-text-search/[full-text index] inside Neo4j. For example: @@ -83,7 +30,7 @@ directive @fulltext(indexes: [FullTextInput]!) on OBJECT Using this directive does not automatically ensure the existence of these indexes. They must be created manually. -=== Specifying +=== Usage The `@fulltext` directive can be used on nodes. In this example, a full-text index called "ProductName", for the name `field`, on the `Product` node, is specified: @@ -103,8 +50,6 @@ This index can be created in the database by running the following Cypher: CREATE FULLTEXT INDEX ProductName FOR (n:Product) ON EACH [n.name] ---- -=== Usage - For every index specified, a new top level query is generated by the library. For example, for the previous type definitions, the following query and types are generated: @@ -219,6 +164,68 @@ query { } ---- + +== `@unique` + +=== Definition + +Unique node property constraints map to `@unique` directives used in your type definitions. +They have the following definition: + +[source, graphql, indent=0] +---- +"""Informs @neo4j/graphql that there should be a uniqueness constraint in the database for the decorated field.""" +directive @unique( + """The name which should be used for this constraint. By default; type name, followed by an underscore, followed by the field name.""" + constraintName: String +) on FIELD_DEFINITION +---- + +Using this directive does not automatically ensure the existence of these constraints. +Run a function on server startup. +See section xref::/directives/indexes-and-constraints.adoc#_asserting_constraints[Asserting constraints] for details. + +=== Usage + +`@unique` directives can only be used in GraphQL object types representing nodes, and they are only applicable for the "main" label for the node. + +In the following example, a unique constraint is asserted for the label `Colour` and the property `hexadecimal`: + +[source, graphql, indent=0] +---- +type Colour @node { + hexadecimal: String! @unique +} +---- + +In the next example, a unique constraint with name `unique_colour` is asserted for the label `Colour` and the property `hexadecimal`: + +[source, graphql, indent=0] +---- +type Colour @node { + hexadecimal: String! @unique(constraintName: "unique_colour") +} +---- + +The `@node` directive is used to change the database label mapping in this next example, so a unique constraint is asserted for the first label in the list, `Color`, and the property `hexadecimal`: + +[source, graphql, indent=0] +---- +type Colour @node(labels: ["Color"]) { + hexadecimal: String! @unique +} +---- + +In the following example, all labels specified in the `labels` argument of the `@node` directive are also checked when asserting constraints. +If there is a unique constraint specified for the `hexadecimal` property of nodes with the `Hue` label, but not the `Color` label, no error is thrown and no new constraints are created when running `assertIndexesAndConstraints`. + +[source, graphql, indent=0] +---- +type Colour @node(labels: ["Color", "Hue"]) { + hexadecimal: String! @unique +} +---- + == Asserting constraints In order to ensure that the specified constraints exist in the database, you need to run the function `assertIndexesAndConstraints`. @@ -246,9 +253,8 @@ const schema = await neoSchema.getSchema(); await neoSchema.assertIndexesAndConstraints(); ---- -:description: Directives related to generative AI in the Neo4j GraphQL Library. - -== Vector index search +[#_vector_index_search] +== `@vector` With the `@vector` GraphQL directive you can query your database to perform a vector index search. Queries are performed by passing in either a vector index or a query phrase. diff --git a/modules/ROOT/pages/directives/schema-configuration/field-configuration.adoc b/modules/ROOT/pages/directives/schema-configuration/field-configuration.adoc index 335d6618..afafc388 100644 --- a/modules/ROOT/pages/directives/schema-configuration/field-configuration.adoc +++ b/modules/ROOT/pages/directives/schema-configuration/field-configuration.adoc @@ -4,7 +4,7 @@ :description: This page describes how to use the directives @selectable, @settable, @filterable and `@relationship` to control how fields are exposed. -In case you need to remove fields from a GraphQL Object Type or a GraphQL Input Object Type, consider the following type definitions: +If you need to remove fields from a GraphQL Object Type or a GraphQL Input Object Type, consider the following type definitions: [source, graphql, indent=0] ---- diff --git a/modules/ROOT/pages/directives/schema-configuration/type-configuration.adoc b/modules/ROOT/pages/directives/schema-configuration/type-configuration.adoc index ecf8d372..93802430 100644 --- a/modules/ROOT/pages/directives/schema-configuration/type-configuration.adoc +++ b/modules/ROOT/pages/directives/schema-configuration/type-configuration.adoc @@ -182,9 +182,23 @@ type SomeType @node { ---- -[[type-definitions-plural]] == `@plural` +=== Definition + +[source, graphql, indent=0] +---- +""" +Instructs @neo4j/graphql to use the given value as the plural of the type name +""" +directive @plural( + """The value to use as the plural of the type name.""" + value: String! +) on OBJECT | INTERFACE | UNION +---- + +=== Usage + This directive redefines how to compose the plural of the type for the generated operations. This is particularly useful for types that are not correctly pluralized or are non-English words. Take this type definition as an example: diff --git a/modules/ROOT/pages/integrations/relay-compatibility.adoc b/modules/ROOT/pages/integrations/relay-compatibility.adoc index 045362c2..395f4047 100644 --- a/modules/ROOT/pages/integrations/relay-compatibility.adoc +++ b/modules/ROOT/pages/integrations/relay-compatibility.adoc @@ -35,19 +35,24 @@ type Book implements Node @node { With that, Relay clients are able to refetch `Book` objects using the `node` query field. The following section dives into how to do this with the Neo4j GraphQL Library. -== The `@relayId` directive + +== `@relayId` The Neo4j GraphQL Library provides an abstraction over the required `id` field, allowing the value of any unique property in the database to be used as the object identifier. +This is provided by the `@relayId` directive + +=== Definition -This is provided by the `@relayId` directive, which has the following definition: +The `@relayId` directive has the following definition: [source, graphql] ---- directive @relayId on FIELD_DEFINITION ---- -Considering the same `Book` example, ISBN is normally a unique identifier. -You can configure this like so: +=== Usage + +For books, the ISBN usually is a unique identifier: [source, graphql] ---- @@ -56,7 +61,7 @@ type Book @node { } ---- -When the schema is augmented, this type will be output as: +When the schema is augmented, this type is output as: [source, graphql] ---- diff --git a/modules/ROOT/pages/security/authentication.adoc b/modules/ROOT/pages/security/authentication.adoc index 72f2bde6..0e2b0d17 100644 --- a/modules/ROOT/pages/security/authentication.adoc +++ b/modules/ROOT/pages/security/authentication.adoc @@ -5,7 +5,7 @@ The GraphQL Library offers the `@authentication` directive to configure authenti [IMPORTANT] ==== -Explicit authentication, configured with the `@authentication` directive, is only ever evaluated during Cypher translation time. +Explicit authentication, configured with the `@authentication` directive, is only evaluated during Cypher translation time. Unauthenticated requests with queries requiring authentication never reach the database. ==== diff --git a/modules/ROOT/pages/security/authorization.adoc b/modules/ROOT/pages/security/authorization.adoc index c5da912a..4c220a6a 100644 --- a/modules/ROOT/pages/security/authorization.adoc +++ b/modules/ROOT/pages/security/authorization.adoc @@ -7,7 +7,7 @@ They use predicates to evaluate the data accessed by the Cypher generated from a All authorization rules have an implied requirement for authentication, given that the rules are normally evaluated against values in the JWT payload. -In the case of explicit authentication, configured using the `@authentication` directive, it is only ever evaluated during Cypher translation time. +In the case of explicit authentication, configured using the xref::/security/authentication.adoc#_authentication[`@authentication`] directive, it is only evaluated during Cypher translation time. Unauthenticated requests with queries requiring authentication never reach the database. [WARNING] @@ -16,9 +16,7 @@ The `@authorization` directive does not apply to subscriptions, it only applies Instead, use xref::/security/subscriptions-authorization.adoc[`@subscriptionsAuthorization`] to configure the authorization for subscriptions if you intend to use subscriptions in your API and want the events protected. ==== -== Rules - -=== Filtering +== Filtering rules Filtering rules filter out data which users do not have access to, without throwing any errors. These rules are translated into filtering predicates, which are evaluated against matched data in the database. @@ -42,7 +40,7 @@ type Post @node @authorization(filter: [ } ---- -==== Operations +=== Operations Filtering can be configured to only be performed on certain operations: @@ -72,7 +70,7 @@ In case there is no `operations` argument with a list of operations, the GraphQL ==== -=== Validating +== Validating rules Validating rules throw an error if a query is executed against data which users do not have access to. These rules are evaluated in the database via filtering predicates containing calls to @@ -94,7 +92,7 @@ type User @node @authorization(validate: [ } ---- -==== Operations +=== Operations Validation can be configured to only be performed on certain operations: diff --git a/modules/ROOT/pages/security/configuration.adoc b/modules/ROOT/pages/security/configuration.adoc index 2660cee1..330f0113 100644 --- a/modules/ROOT/pages/security/configuration.adoc +++ b/modules/ROOT/pages/security/configuration.adoc @@ -146,7 +146,19 @@ By default, filtering is available on https://www.rfc-editor.org/rfc/rfc7519#sec Filtering can be configured for additional JWT claims using the `@jwt` directive and, in some circumstances, the `@jwtClaim` directive. -=== The `@jwt` directive +=== `@jwt` + +==== Definition + +[source, graphql, indent=0] +---- +""" +Instructs @neo4j/graphql that the flagged object represents the relevant JWT payload +""" +directive @jwt on OBJECT +---- + +==== Usage If you configure an additional `roles` claim, which is an array of strings located at the root of the JWT payload, add the following to the type definitions: @@ -163,7 +175,24 @@ The type name `JWT` is not mandatory. You can use any name as long as it is decorated with the `@jwt` directive. ==== -=== The `@jwtClaim` directive +=== `@jwtClaim` + +==== Definition + +[source, graphql, indent=0] +---- +""" +Instructs @neo4j/graphql that the flagged field has a mapped path within the JWT Payload. +""" +directive @jwtClaim( + """ + The path of the field in the real JWT as mapped within the JWT Payload. + """ + path: String! +) on FIELD_DEFINITION +---- + +==== Usage A `roles` claim is not necessarily located at the JWT payload root. It can instead be in a nested location, for example under `myApplication`: diff --git a/modules/ROOT/pages/security/index.adoc b/modules/ROOT/pages/security/index.adoc index 9288e803..bfb9bcb4 100644 --- a/modules/ROOT/pages/security/index.adoc +++ b/modules/ROOT/pages/security/index.adoc @@ -10,4 +10,4 @@ auth/authorization/where.adoc, authentication-and-authorization/index.adoc * xref::/security/authorization.adoc[Authorization] - Rule-based authorization filtering and validation with the `@authorization` directive. * xref::/security/subscriptions-authorization.adoc[Subscriptions authorization] - Rule-based authorization for subscriptions with the `@subscriptionsAuthorization` directive. * xref::/security/impersonation-and-user-switching.adoc[Impersonation and user switching] - How to set up impersonation and user switching features. -* xref::/security/operations.adoc[Operations] - GraphQL query examples on how to trigger the evaluation of different authentication and authorization rules. \ No newline at end of file +* xref::/security/operations.adoc[Operation examples] - GraphQL query examples on how to trigger the evaluation of different authentication and authorization rules. \ No newline at end of file diff --git a/modules/ROOT/pages/security/operations.adoc b/modules/ROOT/pages/security/operations.adoc index b7a7a5c4..4c989452 100644 --- a/modules/ROOT/pages/security/operations.adoc +++ b/modules/ROOT/pages/security/operations.adoc @@ -1,4 +1,4 @@ -= Operations += Operation examples //:page-aliases: /authentication-and-authorization/reference/operations.adoc, /security/reference/operations.adoc :description: This page describes how to set up authorization operations in the Neo4j GraphQL Library. @@ -21,9 +21,7 @@ This also applies if the directive has no arguments because `operations` default The following examples apply to the `@authentication` directive, and also any rules within an `@authorization` directive. -== Examples - -=== Query +== Query For a simple query, rules with `READ` in the operations are evaluated for any type being read: @@ -39,7 +37,7 @@ query { } ---- -=== Mutation +== Mutation For `create` mutations, `CREATE` rules on the object are evaluated for each node created, as well as field definition rules: @@ -105,7 +103,7 @@ mutation { } ---- -=== Subscription +== Subscription For a simple subscription to creation events, both `SUBSCRIBE` and `READ` operations trigger rules: diff --git a/modules/ROOT/pages/security/subscriptions-authorization.adoc b/modules/ROOT/pages/security/subscriptions-authorization.adoc index 01eb79de..7f21bc3b 100644 --- a/modules/ROOT/pages/security/subscriptions-authorization.adoc +++ b/modules/ROOT/pages/security/subscriptions-authorization.adoc @@ -7,9 +7,7 @@ These rules are different to authorization rules for queries and mutations becau All subscriptions authorization rules have an implied requirement for authentication, given that the rules are normally evaluated against values in the JWT payload. -== Rules - -=== Filtering +== Filtering rules Filtering rules prevent events which contain information that users don't have access to from reaching them - they will receive no indication that this is the case. These rules are evaluated when the events are returned from the database, before they are broadcasted out to subscribing GraphQL clients. @@ -25,8 +23,6 @@ type User @node @subscriptionsAuthorization(filter: [ } ---- -==== Events - Filtering can be configured to only be performed on certain events: * `CREATED`