diff --git a/src/NeptuneSchema.js b/src/NeptuneSchema.js index e139e0e..7970097 100644 --- a/src/NeptuneSchema.js +++ b/src/NeptuneSchema.js @@ -57,34 +57,54 @@ function consoleOut(text) { } } +function sanitize(text) { + // TODO implement sanitization logic + // placeholder for sanitization of query text that cannot be parameterized + return text; +} -async function queryNeptune(q) { +/** + * Executes a neptune query + * @param query the query to execute + * @param params optional query params + * @returns {Promise} + */ +async function queryNeptune(query, params = {}) { if (useSDK) { - const response = await queryNeptuneSDK(q); - return response; + const response = await queryNeptuneSDK(query, params); + return response; } else { - try { - const response = await axios.post(`https://${HOST}:${PORT}/${language}`, `query=${encodeURIComponent(q)}`); - return response.data; + try { + let data = { + query: query, + parameters: JSON.stringify(params) + }; + const response = await axios.post(`https://${HOST}:${PORT}/${language}`, data, { + headers: { + 'Content-Type': 'application/json' + } + }); + return response.data; } catch (error) { console.error("Http query request failed: ", error.message); - consoleOut("Trying with the AWS SDK"); - const response = await queryNeptuneSDK(q); + consoleOut("Trying with the AWS SDK"); + const response = await queryNeptuneSDK(query, params); useSDK = true; - return response; + return response; } } } -async function queryNeptuneSDK(q) { +async function queryNeptuneSDK(query, params = {}) { try { const config = { endpoint: `https://${HOST}:${PORT}` }; const client = new NeptunedataClient(config); const input = { - openCypherQuery: q + openCypherQuery: query, + parameters: JSON.stringify(params) }; const command = new ExecuteOpenCypherQueryCommand(input); const response = await client.send(command); @@ -133,7 +153,7 @@ async function getEdgesNames() { async function findFromAndToLabels(edgeStructure) { - let query = `MATCH (from)-[r:${edgeStructure.label}]->(to) RETURN DISTINCT labels(from) as fromLabel, labels(to) as toLabel`; + let query = `MATCH (from)-[r:${sanitize(edgeStructure.label)}]->(to) RETURN DISTINCT labels(from) as fromLabel, labels(to) as toLabel`; let response = await queryNeptune(query); for (let result of response.results) { for (let fromLabel of result.fromLabel) { @@ -190,9 +210,10 @@ function addUpdateEdgeProperty(edgeName, name, value) { async function getEdgeProperties(edge) { - let query = `MATCH ()-[n:${edge.label}]->() RETURN properties(n) as properties LIMIT ${SAMPLE}`; + let query = `MATCH ()-[n:${sanitize(edge.label)}]->() RETURN properties(n) as properties LIMIT $sample`; + let parameters = {sample: SAMPLE}; try { - let response = await queryNeptune(query); + let response = await queryNeptune(query, parameters); let result = response.results; result.forEach(e => { Object.keys(e.properties).forEach(key => { @@ -214,9 +235,10 @@ async function getEdgesProperties() { async function getNodeProperties(node) { - let query = `MATCH (n:${node.label}) RETURN properties(n) as properties LIMIT ${SAMPLE}`; + let query = `MATCH (n:${sanitize(node.label)}) RETURN properties(n) as properties LIMIT $sample`; + let parameters = {sample: SAMPLE}; try { - let response = await queryNeptune(query); + let response = await queryNeptune(query, parameters); let result = response.results; result.forEach(e => { Object.keys(e.properties).forEach(key => { @@ -238,10 +260,10 @@ async function getNodesProperties() { async function checkEdgeDirectionCardinality(d) { - let queryFrom = `MATCH (from:${d.from})-[r:${d.edge.label}]->(to:${d.to}) WITH to, count(from) as rels WHERE rels > 1 RETURN rels LIMIT 1`; + let queryFrom = `MATCH (from:${sanitize(d.from)})-[r:${sanitize(d.edge.label)}]->(to:${sanitize(d.to)}) WITH to, count(from) as rels WHERE rels > 1 RETURN rels LIMIT 1`; let responseFrom = await queryNeptune(queryFrom); let resultFrom = responseFrom.results[0]; - let queryTo = `MATCH (from:${d.from})-[r:${d.edge.label}]->(to:${d.to}) WITH from, count(to) as rels WHERE rels > 1 RETURN rels LIMIT 1`; + let queryTo = `MATCH (from:${sanitize(d.from)})-[r:${sanitize(d.edge.label)}]->(to:${sanitize(d.to)}) WITH from, count(to) as rels WHERE rels > 1 RETURN rels LIMIT 1`; let responseTo = await queryNeptune(queryTo); let resultTo = responseTo.results[0]; let c = '';