diff --git a/CHANGELOG b/CHANGELOG index 010b914615..e879e115fa 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,9 @@ +v3.3.9 (XXXX-XX-XX) +------------------- + +* fixed issue #3811: gharial api is now checking existence of _from and _to vertices + during edge creation + v3.3.8 (2018-04-24) ------------------- diff --git a/js/apps/system/_api/gharial/APP/gharial.js b/js/apps/system/_api/gharial/APP/gharial.js index a0cfa0fe24..ec459f02e8 100644 --- a/js/apps/system/_api/gharial/APP/gharial.js +++ b/js/apps/system/_api/gharial/APP/gharial.js @@ -26,6 +26,7 @@ const _ = require('lodash'); const joi = require('joi'); +const db = require('@arangodb').db; const dd = require('dedent'); const statuses = require('statuses'); const httperr = require('http-errors'); @@ -738,6 +739,41 @@ router.post('/:graph/edge/:collection', function (req, res) { {errorNum: errors.ERROR_GRAPH_INVALID_EDGE.code} ); } + // check existence of _from and _to vertices + // _from vertex + try { + db._document(req.body._from); + } catch (e) { + if (e.errorNum === errors.ERROR_ARANGO_DOCUMENT_NOT_FOUND.code) { + throw Object.assign( + new httperr.Gone('_from: ' + e.errorMessage), + {errorNum: errors.ERROR_ARANGO_DOCUMENT_NOT_FOUND.code, cause: e} + ); + } else { + throw Object.assign( + new httperr.Gone('_from: ' + e.errorMessage), + {errorNum: errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, cause: e} + ); + } + } + + // _to vertex + try { + db._document(req.body._to); + } catch (e) { + if (e.errorNum === errors.ERROR_ARANGO_DOCUMENT_NOT_FOUND.code) { + throw Object.assign( + new httperr.Gone('_to: ' + e.errorMessage), + {errorNum: errors.ERROR_ARANGO_DOCUMENT_NOT_FOUND.code, cause: e} + ); + } else { + throw Object.assign( + new httperr.Gone('_to: ' + e.errorMessage), + {errorNum: errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, cause: e} + ); + } + } + const g = loadGraph(name); checkCollection(g, collection); let meta; diff --git a/js/client/tests/http/api-gharial-spec.js b/js/client/tests/http/api-gharial-spec.js index 629b445802..cf38342240 100644 --- a/js/client/tests/http/api-gharial-spec.js +++ b/js/client/tests/http/api-gharial-spec.js @@ -64,6 +64,18 @@ describe('_api/gharial', () => { db._graphs.remove(graphName); } catch (e) { } + try { + db._graphs.remove('knows_graph'); + } catch (e) { + } + try { + db._drop('persons'); + } catch (e) { + } + try { + db._drop('knows'); + } catch (e) { + } }; beforeEach(cleanup); @@ -126,7 +138,7 @@ describe('_api/gharial', () => { // This is all async give it some time do { wait(0.1); - req = request.get(url + "/" + graphName); + req = request.get(url + "/" + graphName); } while (req.statusCode !== 200); expect(db._collection(eColName)).to.not.be.null; @@ -135,5 +147,171 @@ describe('_api/gharial', () => { expect(db._collection(oColName2)).to.not.be.null; }); + it('should check if edges can only be created if their _from and _to vertices are existent - should create', () => { + const examples = require('@arangodb/graph-examples/example-graph'); + const exampleGraphName = 'knows_graph'; + const vName = 'persons'; + const eName = 'knows'; + expect(db._collection(eName)).to.be.null; // edgec + expect(db._collection(vName)).to.be.null; // vertexc + const g = examples.loadGraph(exampleGraphName); + expect(g).to.not.be.null; + + const edgeDef = { + _from: 'persons/bob', + _to: 'persons/charlie' + }; + let req = request.post(url + '/' + exampleGraphName + '/edge/knows', { + body: JSON.stringify(edgeDef) + }); + expect(req.statusCode).to.equal(202); + + expect(db._collection(eName)).to.not.be.null; + expect(db._collection(vName)).to.not.be.null; + }); + + it('should check if edges can only be created if their _from and _to vertices are existent - should NOT create - missing from document', () => { + const examples = require('@arangodb/graph-examples/example-graph'); + const exampleGraphName = 'knows_graph'; + const vName = 'persons'; + const eName = 'knows'; + expect(db._collection(eName)).to.be.null; // edgec + expect(db._collection(vName)).to.be.null; // vertexc + const g = examples.loadGraph(exampleGraphName); + expect(g).to.not.be.null; + + const edgeDef = { + _from: 'persons/notavailable', + _to: 'persons/charlie' + }; + let req = request.post(url + '/' + exampleGraphName + '/edge/knows', { + body: JSON.stringify(edgeDef) + }); + expect(req.statusCode).to.equal(410); + expect(req.json.errorNum).to.equal(ERRORS.ERROR_ARANGO_DOCUMENT_NOT_FOUND.code); + + expect(db._collection(eName)).to.not.be.null; + expect(db._collection(vName)).to.not.be.null; + }); + + it('should check if edges can only be created if their _from and _to vertices are existent - should NOT create - missing to document', () => { + const examples = require('@arangodb/graph-examples/example-graph'); + const exampleGraphName = 'knows_graph'; + const vName = 'persons'; + const eName = 'knows'; + expect(db._collection(eName)).to.be.null; // edgec + expect(db._collection(vName)).to.be.null; // vertexc + const g = examples.loadGraph(exampleGraphName); + expect(g).to.not.be.null; + + const edgeDef = { + _from: 'persons/bob', + _to: 'persons/notavailable' + }; + let req = request.post(url + '/' + exampleGraphName + '/edge/knows', { + body: JSON.stringify(edgeDef) + }); + expect(req.statusCode).to.equal(410); + expect(req.json.errorNum).to.equal(ERRORS.ERROR_ARANGO_DOCUMENT_NOT_FOUND.code); + + expect(db._collection(eName)).to.not.be.null; + expect(db._collection(vName)).to.not.be.null; + }); + + it('should check if edges can only be created if their _from and _to vertices are existent - should NOT create - missing both from and to documents', () => { + const examples = require('@arangodb/graph-examples/example-graph'); + const exampleGraphName = 'knows_graph'; + const vName = 'persons'; + const eName = 'knows'; + expect(db._collection(eName)).to.be.null; // edgec + expect(db._collection(vName)).to.be.null; // vertexc + const g = examples.loadGraph(exampleGraphName); + expect(g).to.not.be.null; + + const edgeDef = { + _from: 'persons/notavailable', + _to: 'persons/notavailable' + }; + let req = request.post(url + '/' + exampleGraphName + '/edge/knows', { + body: JSON.stringify(edgeDef) + }); + expect(req.statusCode).to.equal(410); + expect(req.json.errorNum).to.equal(ERRORS.ERROR_ARANGO_DOCUMENT_NOT_FOUND.code); + + expect(db._collection(eName)).to.not.be.null; + expect(db._collection(vName)).to.not.be.null; + }); + + it('should check if edges can only be created if their _from and _to vertices are existent - should NOT create - missing from collection', () => { + const examples = require('@arangodb/graph-examples/example-graph'); + const exampleGraphName = 'knows_graph'; + const vName = 'persons'; + const eName = 'knows'; + expect(db._collection(eName)).to.be.null; // edgec + expect(db._collection(vName)).to.be.null; // vertexc + const g = examples.loadGraph(exampleGraphName); + expect(g).to.not.be.null; + + const edgeDef = { + _from: 'xxx/peter', + _to: 'persons/charlie' + }; + let req = request.post(url + '/' + exampleGraphName + '/edge/knows', { + body: JSON.stringify(edgeDef) + }); + expect(req.statusCode).to.equal(410); + expect(req.json.errorNum).to.equal(ERRORS.ERROR_ARANGO_COLLECTION_NOT_FOUND.code); + + expect(db._collection(eName)).to.not.be.null; + expect(db._collection(vName)).to.not.be.null; + }); + + it('should check if edges can only be created if their _from and _to vertices are existent - should NOT create - missing to collection', () => { + const examples = require('@arangodb/graph-examples/example-graph'); + const exampleGraphName = 'knows_graph'; + const vName = 'persons'; + const eName = 'knows'; + expect(db._collection(eName)).to.be.null; // edgec + expect(db._collection(vName)).to.be.null; // vertexc + const g = examples.loadGraph(exampleGraphName); + expect(g).to.not.be.null; + + const edgeDef = { + _from: 'persons/bob', + _to: 'xxx/charlie' + }; + let req = request.post(url + '/' + exampleGraphName + '/edge/knows', { + body: JSON.stringify(edgeDef) + }); + expect(req.statusCode).to.equal(410); + expect(req.json.errorNum).to.equal(ERRORS.ERROR_ARANGO_COLLECTION_NOT_FOUND.code); + + expect(db._collection(eName)).to.not.be.null; + expect(db._collection(vName)).to.not.be.null; + }); + + it('should check if edges can only be created if their _from and _to vertices are existent - should NOT create - missing from and to collection', () => { + const examples = require('@arangodb/graph-examples/example-graph'); + const exampleGraphName = 'knows_graph'; + const vName = 'persons'; + const eName = 'knows'; + expect(db._collection(eName)).to.be.null; // edgec + expect(db._collection(vName)).to.be.null; // vertexc + const g = examples.loadGraph(exampleGraphName); + expect(g).to.not.be.null; + + const edgeDef = { + _from: 'xxx/peter', + _to: 'xxx/charlie' + }; + let req = request.post(url + '/' + exampleGraphName + '/edge/knows', { + body: JSON.stringify(edgeDef) + }); + expect(req.statusCode).to.equal(410); + expect(req.json.errorNum).to.equal(ERRORS.ERROR_ARANGO_COLLECTION_NOT_FOUND.code); + + expect(db._collection(eName)).to.not.be.null; + expect(db._collection(vName)).to.not.be.null; + }); }); diff --git a/js/common/bootstrap/errors.js b/js/common/bootstrap/errors.js index cbbcf72e8b..75946ac5cd 100644 --- a/js/common/bootstrap/errors.js +++ b/js/common/bootstrap/errors.js @@ -272,7 +272,6 @@ "ERROR_GRAPH_NOT_IN_ORPHAN_COLLECTION" : { "code" : 1928, "message" : "not in orphan collection" }, "ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF" : { "code" : 1929, "message" : "collection already used in edge def" }, "ERROR_GRAPH_EDGE_COLLECTION_NOT_USED" : { "code" : 1930, "message" : "edge collection not used in graph" }, - "ERROR_GRAPH_NOT_AN_ARANGO_COLLECTION" : { "code" : 1931, "message" : " is not an ArangoCollection" }, "ERROR_GRAPH_NO_GRAPH_COLLECTION" : { "code" : 1932, "message" : "collection _graphs does not exist" }, "ERROR_GRAPH_INVALID_EXAMPLE_ARRAY_OBJECT_STRING" : { "code" : 1933, "message" : "Invalid example type. Has to be String, Array or Object" }, "ERROR_GRAPH_INVALID_EXAMPLE_ARRAY_OBJECT" : { "code" : 1934, "message" : "Invalid example type. Has to be Array or Object" }, diff --git a/js/common/modules/@arangodb/general-graph.js b/js/common/modules/@arangodb/general-graph.js index fecd5e467b..c9ee9e416c 100644 --- a/js/common/modules/@arangodb/general-graph.js +++ b/js/common/modules/@arangodb/general-graph.js @@ -96,8 +96,8 @@ var findOrCreateCollectionByName = function (name, type, noCreate, options) { res = true; } else if (!(col instanceof ArangoCollection)) { var err = new ArangoError(); - err.errorNum = arangodb.errors.ERROR_GRAPH_NOT_AN_ARANGO_COLLECTION.code; - err.errorMessage = name + arangodb.errors.ERROR_GRAPH_NOT_AN_ARANGO_COLLECTION.message; + err.errorNum = arangodb.errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code; + err.errorMessage = name + arangodb.errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.message; throw err; } else if (type === ArangoCollection.TYPE_EDGE && col.type() !== type) { var err2 = new ArangoError(); diff --git a/lib/Basics/errors.dat b/lib/Basics/errors.dat index 54ead77105..d672751663 100755 --- a/lib/Basics/errors.dat +++ b/lib/Basics/errors.dat @@ -359,7 +359,6 @@ ERROR_GRAPH_WRONG_COLLECTION_TYPE_VERTEX,1927,"not a vertex collection","the col ERROR_GRAPH_NOT_IN_ORPHAN_COLLECTION,1928,"not in orphan collection","Vertex collection not in orphan collection of the graph.", ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF,1929,"collection already used in edge def","The collection is already used in an edge definition of the graph.", ERROR_GRAPH_EDGE_COLLECTION_NOT_USED,1930,"edge collection not used in graph","The edge collection is not used in any edge definition of the graph.", -ERROR_GRAPH_NOT_AN_ARANGO_COLLECTION,1931," is not an ArangoCollection","The collection is not an ArangoCollection.", ERROR_GRAPH_NO_GRAPH_COLLECTION,1932,"collection _graphs does not exist","collection _graphs does not exist.", ERROR_GRAPH_INVALID_EXAMPLE_ARRAY_OBJECT_STRING,1933,"Invalid example type. Has to be String, Array or Object","Invalid example type. Has to be String, Array or Object.", ERROR_GRAPH_INVALID_EXAMPLE_ARRAY_OBJECT,1934,"Invalid example type. Has to be Array or Object","Invalid example type. Has to be Array or Object.", diff --git a/lib/Basics/voc-errors.cpp b/lib/Basics/voc-errors.cpp index a82539d6eb..1e64652222 100644 --- a/lib/Basics/voc-errors.cpp +++ b/lib/Basics/voc-errors.cpp @@ -268,7 +268,6 @@ void TRI_InitializeErrorMessages () { REG_ERROR(ERROR_GRAPH_NOT_IN_ORPHAN_COLLECTION, "not in orphan collection"); REG_ERROR(ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF, "collection already used in edge def"); REG_ERROR(ERROR_GRAPH_EDGE_COLLECTION_NOT_USED, "edge collection not used in graph"); - REG_ERROR(ERROR_GRAPH_NOT_AN_ARANGO_COLLECTION, " is not an ArangoCollection"); REG_ERROR(ERROR_GRAPH_NO_GRAPH_COLLECTION, "collection _graphs does not exist"); REG_ERROR(ERROR_GRAPH_INVALID_EXAMPLE_ARRAY_OBJECT_STRING, "Invalid example type. Has to be String, Array or Object"); REG_ERROR(ERROR_GRAPH_INVALID_EXAMPLE_ARRAY_OBJECT, "Invalid example type. Has to be Array or Object"); diff --git a/lib/Basics/voc-errors.h b/lib/Basics/voc-errors.h index 78714aa023..44ba6a0171 100644 --- a/lib/Basics/voc-errors.h +++ b/lib/Basics/voc-errors.h @@ -652,8 +652,6 @@ /// The collection is already used in an edge definition of the graph. /// - 1930: @LIT{edge collection not used in graph} /// The edge collection is not used in any edge definition of the graph. -/// - 1931: @LIT{ is not an ArangoCollection} -/// The collection is not an ArangoCollection. /// - 1932: @LIT{collection _graphs does not exist} /// collection _graphs does not exist. /// - 1933: @LIT{Invalid example type. Has to be String, Array or Object} @@ -3515,16 +3513,6 @@ void TRI_InitializeErrorMessages (); #define TRI_ERROR_GRAPH_EDGE_COLLECTION_NOT_USED (1930) -//////////////////////////////////////////////////////////////////////////////// -/// @brief 1931: ERROR_GRAPH_NOT_AN_ARANGO_COLLECTION -/// -/// is not an ArangoCollection -/// -/// The collection is not an ArangoCollection. -//////////////////////////////////////////////////////////////////////////////// - -#define TRI_ERROR_GRAPH_NOT_AN_ARANGO_COLLECTION (1931) - //////////////////////////////////////////////////////////////////////////////// /// @brief 1932: ERROR_GRAPH_NO_GRAPH_COLLECTION /// diff --git a/lib/Rest/GeneralResponse.cpp b/lib/Rest/GeneralResponse.cpp index 480179c011..de0d202b85 100644 --- a/lib/Rest/GeneralResponse.cpp +++ b/lib/Rest/GeneralResponse.cpp @@ -349,7 +349,6 @@ rest::ResponseCode GeneralResponse::responseCode(int code) { case TRI_ERROR_GRAPH_NOT_IN_ORPHAN_COLLECTION: case TRI_ERROR_GRAPH_COLLECTION_USED_IN_EDGE_DEF: case TRI_ERROR_GRAPH_EDGE_COLLECTION_NOT_USED: - case TRI_ERROR_GRAPH_NOT_AN_ARANGO_COLLECTION: case TRI_ERROR_GRAPH_INVALID_EXAMPLE_ARRAY_OBJECT_STRING: case TRI_ERROR_GRAPH_INVALID_EXAMPLE_ARRAY_OBJECT: case TRI_ERROR_GRAPH_INVALID_NUMBER_OF_ARGUMENTS: @@ -366,10 +365,10 @@ rest::ResponseCode GeneralResponse::responseCode(int code) { return ResponseCode::FORBIDDEN; case TRI_ERROR_ARANGO_DATABASE_NOT_FOUND: - case TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND: case TRI_ERROR_ARANGO_VIEW_NOT_FOUND: case TRI_ERROR_ARANGO_COLLECTION_NOT_LOADED: case TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND: + case TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND: case TRI_ERROR_ARANGO_ENDPOINT_NOT_FOUND: case TRI_ERROR_ARANGO_INDEX_NOT_FOUND: case TRI_ERROR_CURSOR_NOT_FOUND: