From 38730f37b80737d69da88e13f36901ec39f93468 Mon Sep 17 00:00:00 2001 From: Christiaan Scheermeijer Date: Fri, 19 Mar 2021 12:25:51 +0100 Subject: [PATCH 1/5] chore(project): prevent usage of private properties --- src/helpers/SchemaHelper.js | 21 +++++++++++---------- src/queries/SearchQuery.js | 13 +++++++++---- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/helpers/SchemaHelper.js b/src/helpers/SchemaHelper.js index d763f28..2cfb675 100644 --- a/src/helpers/SchemaHelper.js +++ b/src/helpers/SchemaHelper.js @@ -4,7 +4,6 @@ import { info, warning } from '../utils/logger' class SchemaHelper { constructor (schema) { this.schema = (typeof schema === 'object') ? schema : defaultSchema - this.schemaTypeMap = this.schema._typeMap } /** @@ -13,12 +12,12 @@ class SchemaHelper { * @returns {GraphQLField<*, *>|GraphQLInputField} */ findPropertyType (parentType, propertyName) { - const typeMap = this.schema._typeMap[parentType] + const typeMap = this.schema.getType(parentType) if (typeof typeMap === 'undefined') { throw Error('Type could not be retrieved from schema') } - const propertyType = typeMap._fields[propertyName] + const propertyType = typeMap.getFields()[propertyName] if (typeof propertyType === 'undefined') { throw Error('Property type could not be retrieved from schema') } @@ -32,7 +31,7 @@ class SchemaHelper { */ findInterfaceImplementingTypes (interfaceName) { const implementations = this.findInterface(interfaceName) - if (implementations instanceof Array === false || !implementations.length) { + if (!Array.isArray(implementations) || !implementations.length) { return null } @@ -44,7 +43,7 @@ class SchemaHelper { * @returns {*|Array} */ findInterface (interfaceName) { - return this.schema._implementationsMap[interfaceName] + return this.schema.getImplementations(interfaceName) } /** @@ -52,7 +51,8 @@ class SchemaHelper { * @returns {*} */ findPossibleTypes (unionName) { - const possibleTypes = this.schema._possibleTypeMap[unionName] + const possibleTypes = this.schema.getImplementations(unionName) + if (typeof possibleTypes !== 'object') { return null } @@ -79,7 +79,7 @@ class SchemaHelper { */ getTypeNames () { return Object - .values(this.schemaTypeMap) + .values(this.schema.getTypeMap()) .filter(type => type.astNode && type.astNode.kind === 'ObjectTypeDefinition' && !!type.astNode.interfaces.length) .map(type => type.name) } @@ -90,7 +90,8 @@ class SchemaHelper { */ getTypeFields (typeName) { const schemaType = this.getSchemaType(typeName) - const typeFields = schemaType._fields + const typeFields = schemaType && schemaType.getFields() + if (typeof typeFields === 'undefined') { info('No typeFields (type could be scalar)') return null @@ -130,7 +131,7 @@ class SchemaHelper { * @returns {*} */ getSchemaType (typeName) { - const schemaType = this.schemaTypeMap[typeName] + const schemaType = this.schema.getType(typeName) if (typeof schemaType === 'undefined') { throw Error('Type could not be retrieved from schema') } @@ -145,7 +146,7 @@ class SchemaHelper { const relationDetails = {} const directives = propertyType.astNode.directives - if (directives instanceof Array === false) { + if (!Array.isArray(directives)) { throw Error('Type property directives could not be retrieved from schema') } diff --git a/src/queries/SearchQuery.js b/src/queries/SearchQuery.js index db57eee..e5f9675 100644 --- a/src/queries/SearchQuery.js +++ b/src/queries/SearchQuery.js @@ -7,8 +7,13 @@ class SearchQuery { this.params = params this.resolveInfo = resolveInfo - this.doEvaluateTypeSubset = !(!(this.params.onTypes instanceof Array) || this.params.onTypes.length === 0 || this.params.onTypes.length === this.resolveInfo.schema._typeMap.SearchableInterfaceType._values.length) - this.doEvaluateFieldSubset = !(!(this.params.onFields instanceof Array) || this.params.onFields.length === 0 || this.params.onFields.length === this.resolveInfo.schema._typeMap.SearchableMetadataFields._values.length) + this.searchableInterfaceType = this.resolveInfo.schema.getType('SearchableInterfaceType') + this.searchableMetadataFields = this.resolveInfo.schema.getType('SearchableMetadataFields') + + const { onTypes, onFields } = this.params + + this.doEvaluateTypeSubset = Array.isArray(onTypes) && onTypes.length && onTypes.length !== this.searchableInterfaceType.getValues().length + this.doEvaluateFieldSubset = Array.isArray(onFields) && onFields.length && onFields.length !== this.searchableMetadataFields.getValues().length } /** @@ -66,7 +71,7 @@ class SearchQuery { _generateQueryClause () { // if only a subset of fields need to be evaluated: build query clause for [substring]~ on all eligible fields if (this.doEvaluateFieldSubset) { - const fieldNames = this.doEvaluateFieldSubset ? this.params.onFields : this.resolveInfo.schema._typeMap.SearchableMetadataFields._values.map(field => { return field.name }) + const fieldNames = this.doEvaluateFieldSubset ? this.params.onFields : this.searchableMetadataFields.getValues().map(field => { return field.name }) return fieldNames .map(field => this._generateFieldSubStringClause(field)) @@ -84,7 +89,7 @@ class SearchQuery { // if only a subset of types need to be evaluated: build type clause for [substring]~ on all eligible fields let typeClause = '' if (this.doEvaluateTypeSubset) { - const typeNames = this.doEvaluateTypeSubset ? this.params.onTypes : this.resolveInfo.schema._typeMap.SearchableInterfaceType._values.map(type => { return `'${type.name}'` }) + const typeNames = this.doEvaluateTypeSubset ? this.params.onTypes : this.searchableInterfaceType.getValues().map(type => { return `'${type.name}'` }) typeClause = `WHERE HEAD(labels(\`node\`)) IN ['${typeNames.join('\', \'')}']` } From 35874156f46d6621b0b77b34e957f77a8ab6a060 Mon Sep 17 00:00:00 2001 From: Christiaan Scheermeijer Date: Fri, 19 Mar 2021 14:35:27 +0100 Subject: [PATCH 2/5] feat(project): create property and propertyValue `wasDerivedFrom` relation --- src/commands/RequestControlActionCommand.js | 107 ++++++++++--------- src/routes/helpers/jsonld/PropertyValue.json | 14 ++- src/schema/type/PropertyValue.graphql | 11 ++ 3 files changed, 80 insertions(+), 52 deletions(-) diff --git a/src/commands/RequestControlActionCommand.js b/src/commands/RequestControlActionCommand.js index 102f51c..7db6ad3 100644 --- a/src/commands/RequestControlActionCommand.js +++ b/src/commands/RequestControlActionCommand.js @@ -20,7 +20,7 @@ class RequestControlActionCommand { * @returns {Promise} */ get create () { - const requestInput = this._retrieveRequestInput() + const requestInput = this.params.controlAction const entryPointQuery = this._generateTemplateQuery(requestInput) info(entryPointQuery) return this.session.run(entryPointQuery) @@ -46,37 +46,20 @@ class RequestControlActionCommand { } /** - * @returns {Object} + * Get aliases for the given property identifier + * @param template + * @param propertyIdentifier + * @return {{templatePropertyAlias: string, nodeAlias: string, propertyAlias: string}} * @private */ - _retrieveRequestInput () { - const requestInput = this.params.controlAction - if (typeof requestInput !== 'object' || typeof requestInput.entryPointIdentifier !== 'string' || typeof requestInput.potentialActionIdentifier !== 'string') { - throw new UserInputError('Request Input error: either empty or missing `entryPointIdentifier` or `potentialActionIdentifier` parameter') - } - - let nodeCounter = 1 - // hydrate propertyObject aliases - if (Array.isArray(requestInput.propertyObject)) { - requestInput.propertyObject = requestInput.propertyObject.map(node => { - node.alias = `node_${nodeCounter}` - node.propertyValueAlias = `propertyValue_${nodeCounter}` - nodeCounter++ + _getAliasesForProperty (template, propertyIdentifier) { + const count = template.potentialAction.object.findIndex(({ identifier }) => identifier === propertyIdentifier) + 1 - return node - }) + return { + templatePropertyAlias: `templateProperty_${count}`, + propertyAlias: `property_${count}`, + nodeAlias: `node_${count}` } - // hydrate propertyValueObject aliases - if (Array.isArray(requestInput.propertyValueObject)) { - requestInput.propertyValueObject = requestInput.propertyValueObject.map(node => { - node.propertyValueAlias = `propertyValue_${nodeCounter}` - nodeCounter++ - - return node - }) - } - - return requestInput } /** @@ -103,22 +86,17 @@ class RequestControlActionCommand { * @private */ _generateCreateQuery (template, requestInput) { - const nodeAliasesClause = (Array.isArray(requestInput.propertyObject) && requestInput.propertyObject.length > 0) - ? `, ${requestInput.propertyObject.map(object => { - return `\`${object.alias}\`` - }).join(', ')}` - : '' - const propertySelections = this._generateMatchPropertyNodes(requestInput) + const { selections, aliases } = this._generatePropertyMatchClauses(requestInput, template) return [ `MATCH (\`entryPoint\`:\`EntryPoint\` {\`identifier\`:"${requestInput.entryPointIdentifier}"})${this.queryHelper.generateRelationClause('EntryPoint', 'potentialAction')}(\`potentialControlAction\`:\`ControlAction\` {\`identifier\`:"${requestInput.potentialActionIdentifier}"})`, - propertySelections ? `, ${propertySelections}` : '', - `WITH \`entryPoint\`, \`potentialControlAction\`${nodeAliasesClause}`, + selections ? `, ${selections}` : '', + `WITH \`entryPoint\`, \`potentialControlAction\`${aliases ? `, ${aliases}` : ''}`, 'LIMIT 1', `CREATE (\`entryPoint\`)${this.queryHelper.generateRelationClause('ControlAction', 'target', null, true)}(\`controlAction\`:\`ControlAction\`:\`ActionInterface\`:\`ProvenanceActivityInterface\`:\`ProvenanceEntityInterface\`:\`ThingInterface\` {${this._generateControlActionPropertyClause(template.potentialAction)}})${this.queryHelper.generateRelationClause('ControlAction', 'wasDerivedFrom')}(\`potentialControlAction\`)`, - `WITH \`entryPoint\`, \`potentialControlAction\`, \`controlAction\`${nodeAliasesClause}`, + `WITH \`entryPoint\`, \`potentialControlAction\`, \`controlAction\`${aliases ? `, ${aliases}` : ''}`, this._generateCreatePropertyValuesClause(template, requestInput), - this._generateNodeValueRelationsClause(requestInput.propertyObject), + this._generateNodeValueRelationsClause(requestInput.propertyObject, template), this._generateReturnClause(template, requestInput) ].filter(line => typeof line === 'string' && line.length > 0).join(' ') } @@ -256,17 +234,31 @@ class RequestControlActionCommand { /** * @param requestInput - * @returns {string} + * @param template + * @returns {Object} * @private */ - _generateMatchPropertyNodes (requestInput) { - if (!Array.isArray(requestInput.propertyObject) || !requestInput.propertyObject.length > 0) { - return '' - } + _generatePropertyMatchClauses (requestInput, template) { + // create match clauses for all template property + const propertyMatchClauses = template.potentialAction.object.map(object => { + const { templatePropertyAlias } = this._getAliasesForProperty(template, object.identifier) + + return [templatePropertyAlias, `(\`${templatePropertyAlias}\`:\`${object._schemaType}\` {\`identifier\`:"${object.identifier}"})`] + }) + + // create match clauses for each Property node + const nodeMatchClauses = (requestInput.propertyObject || []).map(node => { + const { nodeAlias } = this._getAliasesForProperty(template, node.potentialActionPropertyIdentifier) + + return [nodeAlias, `(\`${nodeAlias}\`:\`${node.nodeType}\` {\`identifier\`:"${node.nodeIdentifier}"})`] + }) + + const allPairs = [...propertyMatchClauses, ...nodeMatchClauses] - return requestInput.propertyObject.map(node => { - return `(\`${node.alias}\`:\`${node.nodeType}\` {\`identifier\`:"${node.nodeIdentifier}"})` - }).join(', ') + return { + selections: allPairs.map(([, query]) => query).join(', '), + aliases: allPairs.map(([alias]) => `\`${alias}\``).join(', ') + } } /** @@ -294,20 +286,31 @@ class RequestControlActionCommand { if (!matchingRequestProperty) { throw new UserInputError('Required node property is missing from input: ' + templateProperty.identifier + ' ' + templateProperty.title) } + + const { templatePropertyAlias, propertyAlias } = this._getAliasesForProperty(template, templateProperty.identifier) + + const wasDerivedFromRelationClause = this.queryHelper.generateRelationClause('PropertyValue', 'wasDerivedFrom') + const wasDerivedFromClause = `${wasDerivedFromRelationClause}(\`${templatePropertyAlias}\`)` + // compose PropertyValue clause - return `(\`controlAction\`)${objectRelationClause}(\`${matchingRequestProperty.propertyValueAlias}\`:\`PropertyValue\`:\`ThingInterface\` {${this._composeControlActionPropertyClause(templateProperty, matchingRequestProperty)}})` + return `(\`controlAction\`)${objectRelationClause}(\`${propertyAlias}\`:\`PropertyValue\`:\`ThingInterface\` {${this._composeControlActionPropertyClause(templateProperty, matchingRequestProperty)}})${wasDerivedFromClause}` } case 'PropertyValueSpecification': { const matchingRequestPropertyValue = requestInput.propertyValueObject.find(requestPropertyValue => { return requestPropertyValue.potentialActionPropertyValueSpecificationIdentifier === templateProperty.identifier }) + const { templatePropertyAlias, propertyAlias } = this._getAliasesForProperty(template, templateProperty.identifier) + + const wasDerivedFromRelationClause = this.queryHelper.generateRelationClause('PropertyValue', 'wasDerivedFrom') + const wasDerivedFromClause = `${wasDerivedFromRelationClause}(\`${templatePropertyAlias}\`)` + // compose PropertyValue clause if (typeof matchingRequestPropertyValue === 'object') { const valuesClause = this._composeControlActionPropertyValueClause(templateProperty, matchingRequestPropertyValue) // compose PropertyValue clause - return `(\`controlAction\`)${objectRelationClause}(\`${matchingRequestPropertyValue.propertyValueAlias}\`:\`PropertyValue\`:\`ThingInterface\` {${valuesClause}})` + return `(\`controlAction\`)${objectRelationClause}(\`${propertyAlias}\`:\`PropertyValue\`:\`ThingInterface\` {${valuesClause}})${wasDerivedFromClause}` } // use the default value if given in the template PropertyValue @@ -318,7 +321,7 @@ class RequestControlActionCommand { }) // use a random PropertyValue alias, we are not referring to it - return `(\`controlAction\`)${objectRelationClause}(\`propertyValue_${Math.round(Math.random() * 100)}\`:\`PropertyValue\`:\`ThingInterface\` {${valuesClause}})` + return `(\`controlAction\`)${objectRelationClause}(\`propertyValue_${Math.round(Math.random() * 100)}\`:\`PropertyValue\`:\`ThingInterface\` {${valuesClause}})${wasDerivedFromClause}` } // throw error if this property is required @@ -342,16 +345,18 @@ class RequestControlActionCommand { /** * @param requestProperties + * @param template * @returns {string} * @private */ - _generateNodeValueRelationsClause (requestProperties) { + _generateNodeValueRelationsClause (requestProperties, template) { if (!Array.isArray(requestProperties) || requestProperties.length <= 0) { return '' } const segments = requestProperties.map(requestProperty => { - return `(\`${requestProperty.propertyValueAlias}\`)${this.queryHelper.generateRelationClause('PropertyValue', 'nodeValue')}(\`${requestProperty.alias}\`)` + const { propertyAlias, nodeAlias } = this._getAliasesForProperty(template, requestProperty.potentialActionPropertyIdentifier) + return `(\`${propertyAlias}\`)${this.queryHelper.generateRelationClause('PropertyValue', 'nodeValue')}(\`${nodeAlias}\`)` }) return `CREATE ${segments.join(', ')}` diff --git a/src/routes/helpers/jsonld/PropertyValue.json b/src/routes/helpers/jsonld/PropertyValue.json index 03ffab4..a100b62 100644 --- a/src/routes/helpers/jsonld/PropertyValue.json +++ b/src/routes/helpers/jsonld/PropertyValue.json @@ -93,6 +93,18 @@ "url": [ "https://schema.org/url" ], + "wasGeneratedBy": [ + "http://www.w3.org/ns/prov#wasGeneratedBy" + ], + "wasDerivedFrom": [ + "http://www.w3.org/ns/prov#wasDerivedFrom" + ], + "wasAttributedTo": [ + "http://www.w3.org/ns/prov#wasAttributedTo" + ], + "used": [ + "http://www.w3.org/ns/prov#used" + ], "propertyID": [ "https://schema.org/propertyID" ], @@ -108,4 +120,4 @@ "https://schema.org/valueReference" ] } -} \ No newline at end of file +} diff --git a/src/schema/type/PropertyValue.graphql b/src/schema/type/PropertyValue.graphql index 31a3b02..50f8a11 100644 --- a/src/schema/type/PropertyValue.graphql +++ b/src/schema/type/PropertyValue.graphql @@ -61,6 +61,17 @@ type PropertyValue implements ThingInterface { "https://schema.org/url" url: String + ###################################### + ### ProvenanceEntityInterface properties ### + "http://www.w3.org/ns/prov#wasGeneratedBy" + wasGeneratedBy: [ActionInterface] @relation(name: "WAS_GENERATED_BY", direction: OUT) + "http://www.w3.org/ns/prov#wasDerivedFrom" + wasDerivedFrom: [ThingInterface] @relation(name: "WAS_DERIVED_FROM", direction: OUT) + "http://www.w3.org/ns/prov#wasAttributedTo" + wasAttributedTo: [LegalPersonInterface] @relation(name: "WAS_ATTRIBUTED_TO", direction: OUT) + "http://www.w3.org/ns/prov#used" + used: [ThingInterface] @relation(name: "USED", direction: OUT) + ################################ ### PropertyValue properties ### #maxValue: Int From ff13b9c36ed5160076b6dc9bd487d8f9fcf6fc28 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Sat, 20 Mar 2021 04:14:11 +0000 Subject: [PATCH 3/5] fix: upgrade walk-sync from 2.0.2 to 2.2.0 Snyk has created this PR to upgrade walk-sync from 2.0.2 to 2.2.0. See this package in npm: https://www.npmjs.com/package/walk-sync See this project in Snyk: https://app.snyk.io/org/videodock/project/1cc4fd7a-6dc4-4c9c-9651-99bcc318fbcb?utm_source=github&utm_medium=upgrade-pr --- package-lock.json | 9 +++++---- package.json | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6e0d0d5..5b5dc22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17277,13 +17277,14 @@ } }, "walk-sync": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/walk-sync/-/walk-sync-2.0.2.tgz", - "integrity": "sha512-dCZkrxfHjPn7tIvdYrX3uMD/R0beVrHpA8lROQ5wWrl8psJgR6xwCkwqTFes0dNujbS2o/ITpvSYgIFsLsf13A==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/walk-sync/-/walk-sync-2.2.0.tgz", + "integrity": "sha512-IC8sL7aB4/ZgFcGI2T1LczZeFWZ06b3zoHH7jBPyHxOtIIz1jppWHjjEXkOFvFojBVAK9pV7g47xOZ4LW3QLfg==", "requires": { "@types/minimatch": "^3.0.3", "ensure-posix-path": "^1.1.0", - "matcher-collection": "^2.0.0" + "matcher-collection": "^2.0.0", + "minimatch": "^3.0.4" } }, "walker": { diff --git a/package.json b/package.json index 244b13d..360453b 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "neo4j-driver": "4.2.1", "neo4j-graphql-js": "^2.19.2", "validator": "12.1.0", - "walk-sync": "2.0.2" + "walk-sync": "2.2.0" }, "devDependencies": { "@babel/cli": "^7.13.10", From 3a532414e025a1b72206f50a2dd38cfbe4bba947 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Sat, 20 Mar 2021 04:14:15 +0000 Subject: [PATCH 4/5] fix: upgrade graphql-tag from 2.11.0 to 2.12.1 Snyk has created this PR to upgrade graphql-tag from 2.11.0 to 2.12.1. See this package in npm: https://www.npmjs.com/package/graphql-tag See this project in Snyk: https://app.snyk.io/org/videodock/project/1cc4fd7a-6dc4-4c9c-9651-99bcc318fbcb?utm_source=github&utm_medium=upgrade-pr --- package-lock.json | 9 ++++++--- package.json | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6e0d0d5..1d88f8f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8862,9 +8862,12 @@ } }, "graphql-tag": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.11.0.tgz", - "integrity": "sha512-VmsD5pJqWJnQZMUeRwrDhfgoyqcfwEkvtpANqcoUG8/tOLkwNgU9mzub/Mc78OJMhHjx7gfAMTxzdG43VGg3bA==" + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.1.tgz", + "integrity": "sha512-LPewEE1vzGkHnCO8zdOGogKsHHBdtpGyihow1UuMwp6RnZa0lAS7NcbvltLOuo4pi5diQCPASAXZkQq44ffixA==", + "requires": { + "tslib": "^1.14.1" + } }, "graphql-tools": { "version": "4.0.8", diff --git a/package.json b/package.json index 244b13d..f59f687 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "express": "4.17.1", "graphql": "^15.5.0", "graphql-auth-directives": "^2.2.2", - "graphql-tag": "^2.11.0", + "graphql-tag": "^2.12.1", "graphql-tools": "^4.0.8", "js-green-licenses": "^3.0.0", "jsonwebtoken": "^8.5.1", From 19f0727f12b6fda39d0d715ed345877753e0f30b Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Sat, 20 Mar 2021 04:14:22 +0000 Subject: [PATCH 5/5] fix: upgrade neo4j-driver from 4.2.1 to 4.2.2 Snyk has created this PR to upgrade neo4j-driver from 4.2.1 to 4.2.2. See this package in npm: https://www.npmjs.com/package/neo4j-driver See this project in Snyk: https://app.snyk.io/org/videodock/project/1cc4fd7a-6dc4-4c9c-9651-99bcc318fbcb?utm_source=github&utm_medium=upgrade-pr --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6e0d0d5..428b62e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13929,9 +13929,9 @@ "dev": true }, "neo4j-driver": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/neo4j-driver/-/neo4j-driver-4.2.1.tgz", - "integrity": "sha512-5Zkb7yIsoManNvVW1dePeotb+qcLOEdFPScdIUaHAvhU/guiqvc2OHwjpIXWjz+4xdKTXZ4YWJBEr2ZaW9f+MQ==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/neo4j-driver/-/neo4j-driver-4.2.2.tgz", + "integrity": "sha512-2XItlip3L8g4ONCu3XgrdhHAgPEomNFEzfc3oNkeKBTSHtykStwKkssWGZrwnZx+l0GbQ1KkeZBVqLtuxGK7wA==", "requires": { "@babel/runtime": "^7.5.5", "rxjs": "^6.6.3", diff --git a/package.json b/package.json index 244b13d..cb75cff 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "js-green-licenses": "^3.0.0", "jsonwebtoken": "^8.5.1", "micromatch": "^4.0.2", - "neo4j-driver": "4.2.1", + "neo4j-driver": "4.2.2", "neo4j-graphql-js": "^2.19.2", "validator": "12.1.0", "walk-sync": "2.0.2"