UNPKG

@neo4j/graphql

Version:

A GraphQL to Cypher query execution layer for Neo4j and JavaScript GraphQL implementations

126 lines 5.8 kB
"use strict"; /* * 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. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.ValidJwtDirectives = ValidJwtDirectives; const graphql_1 = require("graphql"); const constants_1 = require("../../../../constants"); const document_validation_error_1 = require("../utils/document-validation-error"); const path_parser_1 = require("../utils/path-parser"); const utils_1 = require("../utils/utils"); function ValidJwtDirectives(context) { const jwtTypes = new Map(); const typeMap = new Map(); const defs = context.getDocument().definitions; const objectsAndInterfaces = defs.filter((d) => d.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION || d.kind === graphql_1.Kind.OBJECT_TYPE_EXTENSION || d.kind === graphql_1.Kind.INTERFACE_TYPE_DEFINITION || d.kind === graphql_1.Kind.INTERFACE_TYPE_EXTENSION); for (const def of objectsAndInterfaces) { const prev = typeMap.get(def.name.value) || []; typeMap.set(def.name.value, prev.concat(def)); if (def.directives?.some((d) => d.name.value === "jwt")) { // first, scaffold with just typenames jwtTypes.set(def.name.value, []); } } // second, populate with definitions for (const typeName of jwtTypes.keys()) { jwtTypes.set(typeName, typeMap.get(typeName) || []); } return { Directive(node, _key, _parent, path, ancestors) { const isJwtDirective = node.name.value === "jwt"; const isJwtClaimDirective = node.name.value === "jwtClaim"; if (!isJwtDirective && !isJwtClaimDirective) { return; } const [pathToNode, traversedDef, parentOfTraversedDef] = (0, path_parser_1.getPathToNode)(path, ancestors); if (!traversedDef) { console.error("No last definition traversed"); return; } let validationResult; let errorPath; if (isJwtDirective) { if (traversedDef.kind !== graphql_1.Kind.OBJECT_TYPE_DEFINITION && traversedDef.kind !== graphql_1.Kind.OBJECT_TYPE_EXTENSION) { // delegate to another rule bc cannot use jwt on fields return; } validationResult = (0, document_validation_error_1.assertValid)(() => assertJwtDirective(traversedDef, jwtTypes)); errorPath = "@jwt"; } else { if (!parentOfTraversedDef) { console.error("No parent of last definition traversed"); return; } validationResult = (0, document_validation_error_1.assertValid)(() => assertJwtClaimDirective(jwtTypes, parentOfTraversedDef)); errorPath = "@jwtClaim"; } const { isValid, errorMsg } = validationResult; if (!isValid) { context.reportError((0, document_validation_error_1.createGraphQLError)({ nodes: [node, traversedDef], path: [...pathToNode, errorPath], errorMsg, })); } }, }; } function assertJwtDirective(objectType, jwtTypes) { const typeNamesForCurrent = [ objectType.name.value, ...(objectType.interfaces || []).map((i) => i.name.value), ]; for (const typeName of jwtTypes.keys()) { if (!typeNamesForCurrent.includes(typeName)) { throw new document_validation_error_1.DocumentValidationError(`Invalid directive usage: Directive @jwt can only be used once in the Type Definitions.`, []); } } const mergedDirectivesForCurrent = []; for (const typeName of typeNamesForCurrent) { const types = jwtTypes.get(typeName); if (!types) { continue; } for (const t of types) { mergedDirectivesForCurrent.push(...(t.directives || [])); if (mergedDirectivesForCurrent.length > 1) { throw new document_validation_error_1.DocumentValidationError(`Invalid directive usage: Directive @jwt cannot be used in combination with other directives.`, []); } const incompatibleFieldsStatus = t.fields?.some((field) => !constants_1.GRAPHQL_BUILTIN_SCALAR_TYPES.includes((0, utils_1.getInnerTypeName)(field.type))); if (incompatibleFieldsStatus === true) { throw new document_validation_error_1.DocumentValidationError(`Invalid directive usage: Fields of a @jwt type can only be Scalars or Lists of Scalars.`, []); } } } } function assertJwtClaimDirective(jwtTypes, node) { const typeNamesForCurrent = [node.name.value, ...(node.interfaces || []).map((i) => i.name.value)]; for (const typeName of typeNamesForCurrent) { if (jwtTypes.has(typeName)) { return; } } throw new document_validation_error_1.DocumentValidationError(`Invalid directive usage: Directive @jwtClaim can only be used in \\"@jwt\\" types.`, []); } //# sourceMappingURL=valid-jwt-directives.js.map