1
0
Fork 0

allow using `returnOld` and `returnNew` attributes in HTTP REST APIs … (#4479)

This commit is contained in:
Jan 2018-02-09 14:50:56 +01:00 committed by GitHub
parent 8da61a9875
commit 42dd337152
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 367 additions and 41 deletions

View File

@ -1,6 +1,15 @@
devel
-----
* support `returnOld` and `returnNew` attributes for in the following HTTP REST
APIs:
* /_api/gharial/<graph>/vertex/<collection>
* /_api/gharial/<graph>/edge/<collection>
The exception from this is that the HTTP DELETE verb for these APIs does not
support `returnOld` because that would make the existing API incompatible
* fixed issue #4160: Run arangod with "--database.auto-upgrade" option always crash silently without error log
* fix issue #4457: create /var/tmp/arangod with correct user in supervisor mode

View File

@ -110,9 +110,12 @@ describe ArangoDB do
return doc
end
def create_vertex (waitForSync, graph_name, collection, body)
def create_vertex (waitForSync, graph_name, collection, body, options = {})
cmd = vertex_endpoint(graph_name, collection)
cmd = cmd + "?waitForSync=#{waitForSync}"
options.each do |key,value|
cmd = cmd + "&" + key + "=" + value.to_s
end
doc = ArangoDB.post(cmd, :body => JSON.dump(body))
return doc
end
@ -123,36 +126,48 @@ describe ArangoDB do
return doc
end
def update_vertex (waitForSync, graph_name, collection, key, body, keepNull = '')
def update_vertex (waitForSync, graph_name, collection, key, body, keepNull = '', options = {})
cmd = vertex_endpoint(graph_name, collection, key)
cmd = cmd + "?waitForSync=#{waitForSync}"
if keepNull != '' then
cmd = cmd + "&keepNull=#{keepNull}"
end
options.each do |key,value|
cmd = cmd + "&" + key + "=" + value.to_s
end
doc = ArangoDB.patch(cmd, :body => JSON.dump(body))
return doc
end
def replace_vertex (waitForSync, graph_name, collection, key, body)
def replace_vertex (waitForSync, graph_name, collection, key, body, options = {})
cmd = vertex_endpoint(graph_name, collection, key)
cmd = cmd + "?waitForSync=#{waitForSync}"
options.each do |key,value|
cmd = cmd + "&" + key + "=" + value.to_s
end
doc = ArangoDB.put(cmd, :body => JSON.dump(body))
return doc
end
def delete_vertex (waitForSync, graph_name, collection, key)
def delete_vertex (waitForSync, graph_name, collection, key, options = {})
cmd = vertex_endpoint(graph_name, collection, key)
cmd = cmd + "?waitForSync=#{waitForSync}"
options.each do |key,value|
cmd = cmd + "&" + key + "=" + value.to_s
end
doc = ArangoDB.delete(cmd)
return doc
end
def create_edge (waitForSync, graph_name, collection, from, to, body)
def create_edge (waitForSync, graph_name, collection, from, to, body, options = {})
cmd = edge_endpoint(graph_name, collection)
cmd = cmd + "?waitForSync=#{waitForSync}"
body["_from"] = from
body["_to"] = to
options.each do |key,value|
cmd = cmd + "&" + key + "=" + value.to_s
end
doc = ArangoDB.post(cmd, :body => JSON.dump(body))
return doc
end
@ -163,26 +178,35 @@ describe ArangoDB do
return doc
end
def update_edge (waitForSync, graph_name, collection, key, body, keepNull = '')
def update_edge (waitForSync, graph_name, collection, key, body, keepNull = '', options = {})
cmd = edge_endpoint(graph_name, collection, key)
cmd = cmd + "?waitForSync=#{waitForSync}"
if keepNull != '' then
cmd = cmd + "&keepNull=#{keepNull}"
end
options.each do |key,value|
cmd = cmd + "&" + key + "=" + value.to_s
end
doc = ArangoDB.patch(cmd, :body => JSON.dump(body))
return doc
end
def replace_edge (waitForSync, graph_name, collection, key, body)
def replace_edge (waitForSync, graph_name, collection, key, body, options = {})
cmd = edge_endpoint(graph_name, collection, key)
cmd = cmd + "?waitForSync=#{waitForSync}"
options.each do |key,value|
cmd = cmd + "&" + key + "=" + value.to_s
end
doc = ArangoDB.put(cmd, :body => JSON.dump(body))
return doc
end
def delete_edge (waitForSync, graph_name, collection, key)
def delete_edge (waitForSync, graph_name, collection, key, options = {})
cmd = edge_endpoint(graph_name, collection, key)
cmd = cmd + "?waitForSync=#{waitForSync}"
options.each do |key,value|
cmd = cmd + "&" + key + "=" + value.to_s
end
doc = ArangoDB.delete(cmd)
return doc
end
@ -417,6 +441,22 @@ describe ArangoDB do
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(sync ? 201 : 202)
doc.parsed_response['vertex']['_rev'].should eq(doc.headers['etag'])
doc.parsed_response['old'].should eq(nil)
doc.parsed_response['new'].should eq(nil)
end
it "can create a vertex, returnNew" do
name = "Alice"
doc = create_vertex( sync, graph_name, user_collection, {"name" => name}, { "returnNew" => "true" })
doc.code.should eq(sync ? 201 : 202)
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(sync ? 201 : 202)
doc.parsed_response['vertex']['_rev'].should eq(doc.headers['etag'])
doc.parsed_response['old'].should eq(nil)
doc.parsed_response['new']['_key'].should_not eq(nil)
doc.parsed_response['new']['name'].should eq(name)
end
it "can get a vertex" do
@ -457,6 +497,39 @@ describe ArangoDB do
doc.parsed_response['code'].should eq(sync ? 200 : 202)
doc.parsed_response['vertex']['_rev'].should eq(doc.headers['etag'])
doc.parsed_response['vertex']['_key'].should eq(key)
doc.parsed_response['old'].should eq(nil)
doc.parsed_response['new'].should eq(nil)
doc = get_vertex(graph_name, user_collection, key)
doc.parsed_response['vertex']['name'].should eq(nil)
doc.parsed_response['vertex']['name2'].should eq(name)
doc.parsed_response['vertex']['_rev'].should eq(doc.headers['etag'])
oldTag.should_not eq(doc.headers['etag'])
doc.parsed_response['vertex']['_key'].should eq(key)
end
it "can replace a vertex, returnOld" do
name = "Alice"
doc = create_vertex( sync, graph_name, user_collection, {"name" => name})
key = doc.parsed_response['vertex']['_key']
oldTag = doc.parsed_response['vertex']['_rev']
oldTag.should eq(doc.headers['etag'])
name = "Bob"
doc = replace_vertex( sync, graph_name, user_collection, key, {"name2" => name}, { "returnOld" => "true", "returnNew" => true })
doc.code.should eq(sync ? 200 : 202)
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(sync ? 200 : 202)
doc.parsed_response['vertex']['_rev'].should eq(doc.headers['etag'])
doc.parsed_response['vertex']['_key'].should eq(key)
doc.parsed_response['old']['_key'].should eq(key)
doc.parsed_response['old']['name'].should eq("Alice")
doc.parsed_response['old']['name2'].should eq(nil)
doc.parsed_response['new']['_key'].should eq(key)
doc.parsed_response['new']['name'].should eq(nil)
doc.parsed_response['new']['name2'].should eq("Bob")
doc = get_vertex(graph_name, user_collection, key)
doc.parsed_response['vertex']['name'].should eq(nil)
@ -488,6 +561,36 @@ describe ArangoDB do
doc.parsed_response['code'].should eq(sync ? 200 : 202)
doc.parsed_response['vertex']['_rev'].should eq(doc.headers['etag'])
doc.parsed_response['vertex']['_key'].should eq(key)
doc.parsed_response['old'].should eq(nil)
doc.parsed_response['new'].should eq(nil)
doc = get_vertex(graph_name, user_collection, key)
doc.parsed_response['vertex']['name'].should eq(name)
doc.parsed_response['vertex']['name2'].should eq(name2)
doc.parsed_response['vertex']['_rev'].should eq(doc.headers['etag'])
doc.parsed_response['vertex']['_key'].should eq(key)
end
it "can update a vertex, returnOld" do
name = "Alice"
doc = create_vertex( sync, graph_name, user_collection, {"name" => name})
key = doc.parsed_response['vertex']['_key']
name2 = "Bob"
doc = update_vertex( sync, graph_name, user_collection, key, {"name2" => name2}, "", { "returnOld" => "true", "returnNew" => "true" })
doc.code.should eq(sync ? 200 : 202)
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(sync ? 200 : 202)
doc.parsed_response['vertex']['_rev'].should eq(doc.headers['etag'])
doc.parsed_response['vertex']['_key'].should eq(key)
doc.parsed_response['old']['_key'].should eq(key)
doc.parsed_response['old']['name'].should eq(name)
doc.parsed_response['old']['name2'].should eq(nil)
doc.parsed_response['new']['_key'].should eq(key)
doc.parsed_response['new']['name'].should eq(name)
doc.parsed_response['new']['name2'].should eq(name2)
doc = get_vertex(graph_name, user_collection, key)
doc.parsed_response['vertex']['name'].should eq(name)
@ -545,6 +648,8 @@ describe ArangoDB do
doc.code.should eq(sync ? 200 : 202)
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(sync ? 200 : 202)
doc.parsed_response['old'].should eq(nil)
doc.parsed_response['new'].should eq(nil)
doc = get_vertex(graph_name, user_collection, key)
doc.code.should eq(404)
@ -552,7 +657,28 @@ describe ArangoDB do
doc.parsed_response['errorMessage'].should include("document not found")
doc.parsed_response['code'].should eq(404)
end
it "can delete a vertex, returnOld" do
name = "Alice"
doc = create_vertex( sync, graph_name, user_collection, {"name" => name})
key = doc.parsed_response['vertex']['_key']
doc = delete_vertex( sync, graph_name, user_collection, key, { "returnOld" => "true" })
doc.code.should eq(sync ? 200 : 202)
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(sync ? 200 : 202)
doc.parsed_response['removed'].should eq(true)
doc.parsed_response['old']['_key'].should eq(key)
doc.parsed_response['old']['name'].should eq(name)
doc.parsed_response['new'].should eq(nil)
doc = get_vertex(graph_name, user_collection, key)
doc.code.should eq(404)
doc.parsed_response['error'].should eq(true)
doc.parsed_response['errorMessage'].should include("document not found")
doc.parsed_response['code'].should eq(404)
end
it "can not delete a non existing vertex" do
key = "unknownKey"
@ -587,10 +713,30 @@ describe ArangoDB do
v2.code.should eq(sync ? 201 : 202)
v2 = v2.parsed_response['vertex']['_id']
doc = create_edge( sync, graph_name, friend_collection, v1, v2, {})
doc.code.should eq(202)
doc.code.should eq(sync ? 201 : 202)
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(202)
doc.parsed_response['code'].should eq(sync ? 201 : 202)
doc.parsed_response['edge']['_rev'].should eq(doc.headers['etag'])
doc.parsed_response['old'].should eq(nil)
doc.parsed_response['new'].should eq(nil)
end
it "can create an edge, returnNew" do
v1 = create_vertex( sync, graph_name, user_collection, {})
v1.code.should eq(sync ? 201 : 202)
v1 = v1.parsed_response['vertex']['_id']
v2 = create_vertex( sync, graph_name, user_collection, {})
v2.code.should eq(sync ? 201 : 202)
v2 = v2.parsed_response['vertex']['_id']
doc = create_edge( sync, graph_name, friend_collection, v1, v2, { "value" => "foo" }, { "returnNew" => "true" })
doc.code.should eq(sync ? 201 : 202)
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(sync ? 201 : 202)
doc.parsed_response['edge']['_rev'].should eq(doc.headers['etag'])
doc.parsed_response['old'].should eq(nil)
doc.parsed_response['new']['value'].should eq("foo")
end
it "can get an edge" do
@ -602,7 +748,7 @@ describe ArangoDB do
v2 = v2.parsed_response['vertex']['_id']
type = "married"
doc = create_edge( sync, graph_name, friend_collection, v1, v2, {"type" => type})
doc.code.should eq(202)
doc.code.should eq(sync ? 201 : 202)
key = doc.parsed_response['edge']['_key']
doc = get_edge(graph_name, friend_collection, key)
@ -633,7 +779,7 @@ describe ArangoDB do
v2 = v2.parsed_response['vertex']['_id']
type = "married"
doc = create_edge( sync, graph_name, friend_collection, v1, v2, {"type" => type})
doc.code.should eq(202)
doc.code.should eq(sync ? 201 : 202)
key = doc.parsed_response['edge']['_key']
oldTag = doc.parsed_response['edge']['_rev']
oldTag.should eq(doc.headers['etag'])
@ -645,6 +791,51 @@ describe ArangoDB do
doc.parsed_response['code'].should eq(sync ? 200 : 202)
doc.parsed_response['edge']['_rev'].should eq(doc.headers['etag'])
doc.parsed_response['edge']['_key'].should eq(key)
doc.parsed_response['old'].should eq(nil)
doc.parsed_response['new'].should eq(nil)
doc = get_edge(graph_name, friend_collection, key)
doc.parsed_response['edge']['type2'].should eq(type)
doc.parsed_response['edge']['type'].should eq(nil)
doc.parsed_response['edge']['_rev'].should eq(doc.headers['etag'])
oldTag.should_not eq(doc.headers['etag'])
doc.parsed_response['edge']['_key'].should eq(key)
end
it "can replace an edge, returnOld" do
v1 = create_vertex( sync, graph_name, user_collection, {})
v1.code.should eq(sync ? 201 : 202)
v1 = v1.parsed_response['vertex']['_id']
v2 = create_vertex( sync, graph_name, user_collection, {})
v2.code.should eq(sync ? 201 : 202)
v2 = v2.parsed_response['vertex']['_id']
type = "married"
doc = create_edge( sync, graph_name, friend_collection, v1, v2, {"type" => type})
doc.code.should eq(sync ? 201 : 202)
key = doc.parsed_response['edge']['_key']
oldTag = doc.parsed_response['edge']['_rev']
oldTag.should eq(doc.headers['etag'])
type = "divorced"
doc = replace_edge( sync, graph_name, friend_collection, key, {"type2" => type, "_from" => v1, "_to" => v2}, { "returnOld" => "true", "returnNew" => "true" })
doc.code.should eq(sync ? 200 : 202)
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(sync ? 200 : 202)
doc.parsed_response['edge']['_rev'].should eq(doc.headers['etag'])
doc.parsed_response['edge']['_key'].should eq(key)
doc.parsed_response['old']['_key'].should eq(key)
doc.parsed_response['old']['type'].should eq("married")
doc.parsed_response['old']['type2'].should eq(nil)
doc.parsed_response['old']['_from'].should eq(v1)
doc.parsed_response['old']['_to'].should eq(v2)
doc.parsed_response['new']['_key'].should eq(key)
doc.parsed_response['new']['type'].should eq(nil)
doc.parsed_response['new']['type2'].should eq("divorced")
doc.parsed_response['new']['_from'].should eq(v1)
doc.parsed_response['new']['_to'].should eq(v2)
doc = get_edge(graph_name, friend_collection, key)
doc.parsed_response['edge']['type2'].should eq(type)
@ -673,7 +864,7 @@ describe ArangoDB do
v2 = v2.parsed_response['vertex']['_id']
type = "married"
doc = create_edge( sync, graph_name, friend_collection, v1, v2, {"type" => type})
doc.code.should eq(202)
doc.code.should eq(sync ? 201 : 202)
key = doc.parsed_response['edge']['_key']
type2 = "divorced"
@ -683,6 +874,46 @@ describe ArangoDB do
doc.parsed_response['code'].should eq(sync ? 200 : 202)
doc.parsed_response['edge']['_rev'].should eq(doc.headers['etag'])
doc.parsed_response['edge']['_key'].should eq(key)
doc.parsed_response['old'].should eq(nil)
doc.parsed_response['new'].should eq(nil)
doc = get_edge(graph_name, friend_collection, key)
doc.parsed_response['edge']['type'].should eq(type)
doc.parsed_response['edge']['type2'].should eq(type2)
doc.parsed_response['edge']['_rev'].should eq(doc.headers['etag'])
doc.parsed_response['edge']['_key'].should eq(key)
end
it "can update an edge, returnOld" do
v1 = create_vertex( sync, graph_name, user_collection, {})
v1.code.should eq(sync ? 201 : 202)
v1 = v1.parsed_response['vertex']['_id']
v2 = create_vertex( sync, graph_name, user_collection, {})
v2.code.should eq(sync ? 201 : 202)
v2 = v2.parsed_response['vertex']['_id']
type = "married"
doc = create_edge( sync, graph_name, friend_collection, v1, v2, {"type" => type})
doc.code.should eq(sync ? 201 : 202)
key = doc.parsed_response['edge']['_key']
type2 = "divorced"
doc = update_edge( sync, graph_name, friend_collection, key, {"type2" => type2}, "", { "returnOld" => "true", "returnNew" => "true" })
doc.code.should eq(sync ? 200 : 202)
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(sync ? 200 : 202)
doc.parsed_response['edge']['_rev'].should eq(doc.headers['etag'])
doc.parsed_response['edge']['_key'].should eq(key)
doc.parsed_response['old']['_key'].should eq(key)
doc.parsed_response['old']['type'].should eq("married")
doc.parsed_response['old']['type2'].should eq(nil)
doc.parsed_response['old']['_from'].should eq(v1)
doc.parsed_response['old']['_to'].should eq(v2)
doc.parsed_response['new']['_key'].should eq(key)
doc.parsed_response['new']['type'].should eq("married")
doc.parsed_response['new']['type2'].should eq("divorced")
doc.parsed_response['new']['_from'].should eq(v1)
doc.parsed_response['new']['_to'].should eq(v2)
doc = get_edge(graph_name, friend_collection, key)
doc.parsed_response['edge']['type'].should eq(type)
@ -700,7 +931,7 @@ describe ArangoDB do
v2 = v2.parsed_response['vertex']['_id']
type = "married"
doc = create_edge( sync, graph_name, friend_collection, v1, v2, {"type" => type})
doc.code.should eq(202)
doc.code.should eq(sync ? 201 : 202)
key = doc.parsed_response['edge']['_key']
doc = update_edge( sync, graph_name, friend_collection, key, {"type" => nil}, "")
@ -720,7 +951,7 @@ describe ArangoDB do
v2 = v2.parsed_response['vertex']['_id']
type = "married"
doc = create_edge( sync, graph_name, friend_collection, v1, v2, {"type" => type})
doc.code.should eq(202)
doc.code.should eq(sync ? 201 : 202)
key = doc.parsed_response['edge']['_key']
doc = update_edge( sync, graph_name, friend_collection, key, {"type" => nil}, true)
@ -740,7 +971,7 @@ describe ArangoDB do
v2 = v2.parsed_response['vertex']['_id']
type = "married"
doc = create_edge( sync, graph_name, friend_collection, v1, v2, {"type" => type})
doc.code.should eq(202)
doc.code.should eq(sync ? 201 : 202)
key = doc.parsed_response['edge']['_key']
doc = update_edge( sync, graph_name, friend_collection, key, {"type" => nil}, false)
@ -769,13 +1000,43 @@ describe ArangoDB do
v2 = v2.parsed_response['vertex']['_id']
type = "married"
doc = create_edge( sync, graph_name, friend_collection, v1, v2, {"type" => type})
doc.code.should eq(202)
doc.code.should eq(sync ? 201 : 202)
key = doc.parsed_response['edge']['_key']
doc = delete_edge( sync, graph_name, friend_collection, key)
doc.code.should eq(sync ? 200 : 202)
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(sync ? 200 : 202)
doc.parsed_response['old'].should eq(nil)
doc.parsed_response['new'].should eq(nil)
doc = get_edge(graph_name, friend_collection, key)
doc.code.should eq(404)
doc.parsed_response['error'].should eq(true)
doc.parsed_response['errorMessage'].should include("document not found")
doc.parsed_response['code'].should eq(404)
end
it "can delete an edge, returnOld" do
v1 = create_vertex( sync, graph_name, user_collection, {})
v1.code.should eq(sync ? 201 : 202)
v1 = v1.parsed_response['vertex']['_id']
v2 = create_vertex( sync, graph_name, user_collection, {})
v2.code.should eq(sync ? 201 : 202)
v2 = v2.parsed_response['vertex']['_id']
type = "married"
doc = create_edge( sync, graph_name, friend_collection, v1, v2, {"type" => type})
doc.code.should eq(sync ? 201 : 202)
key = doc.parsed_response['edge']['_key']
doc = delete_edge( sync, graph_name, friend_collection, key, { "returnOld" => "true" })
doc.code.should eq(sync ? 200 : 202)
doc.parsed_response['error'].should eq(false)
doc.parsed_response['code'].should eq(sync ? 200 : 202)
doc.parsed_response['old']['_from'].should eq(v1)
doc.parsed_response['old']['_to'].should eq(v2)
doc.parsed_response['old']['type'].should eq(type)
doc.parsed_response['new'].should eq(nil)
doc = get_edge(graph_name, friend_collection, key)
doc.code.should eq(404)

View File

@ -129,16 +129,29 @@ function checkCollection (g, collection) {
}
}
function setResponse (res, name, body, code) {
function setResponse (res, name, body, code, returnOld, returnNew) {
res.status(code);
if (body._rev) {
res.set('etag', body._rev);
}
res.json({
error: false,
[name]: body,
code
});
let result = { error: false, code };
if (returnOld) {
result.old = body.old;
delete body.old;
}
if (returnNew) {
result.new = body.new;
delete body.new;
}
if (name === undefined) {
// special hack currently used for HTTP DELETE only
for (let att in body) {
result[att] = body[att];
}
} else {
result[name] = body;
}
res.json(result);
}
function matchVertexRevision (req, rev) {
@ -205,6 +218,12 @@ const definitionEdgeCollectionName = joi.string()
const waitForSyncFlag = phpCompatFlag
.description('define if the request should wait until synced to disk.');
const returnOldFlag = phpCompatFlag
.description('define if the request should wait return the old version of the updated document.');
const returnNewFlag = phpCompatFlag
.description('define if the request should wait return the new version of the updated document.');
const vertexKey = joi.string()
.description('_key attribute of one specific vertex');
@ -549,13 +568,14 @@ router.delete('/:graph/edge/:definition', function (req, res) {
router.post('/:graph/vertex/:collection', function (req, res) {
const waitForSync = Boolean(req.queryParams.waitForSync);
const returnNew = Boolean(req.queryParams.returnNew);
const name = req.pathParams.graph;
const collection = req.pathParams.collection;
const g = loadGraph(name);
checkCollection(g, collection);
let meta;
try {
meta = g[collection].save(req.body, {waitForSync});
meta = g[collection].save(req.body, {waitForSync, returnNew});
} catch (e) {
if (e.isArangoError && e.errorNum === errors.ERROR_GRAPH_INVALID_EDGE.code) {
throw Object.assign(
@ -565,11 +585,12 @@ router.post('/:graph/vertex/:collection', function (req, res) {
}
throw e;
}
setResponse(res, 'vertex', meta, waitForSync ? CREATED : ACCEPTED);
setResponse(res, 'vertex', meta, waitForSync ? CREATED : ACCEPTED, false, returnNew);
})
.pathParam('graph', graphName)
.pathParam('collection', vertexCollectionName)
.queryParam('waitForSync', waitForSyncFlag)
.queryParam('returnNew', returnNewFlag)
.body(joi.any().required(), 'The document to be stored')
.error('bad request', 'The edge definition is invalid.')
.error('not found', 'Graph or collection not found.')
@ -607,6 +628,8 @@ router.get('/:graph/vertex/:collection/:key', function (req, res) {
router.put('/:graph/vertex/:collection/:key', function (req, res) {
const waitForSync = Boolean(req.queryParams.waitForSync);
const returnOld = Boolean(req.queryParams.returnOld);
const returnNew = Boolean(req.queryParams.returnNew);
const name = req.pathParams.graph;
const collection = req.pathParams.collection;
const key = req.pathParams.key;
@ -626,13 +649,15 @@ router.put('/:graph/vertex/:collection/:key', function (req, res) {
throw e;
}
matchVertexRevision(req, doc._rev);
const meta = g[collection].replace(id, req.body, {waitForSync});
setResponse(res, 'vertex', meta, waitForSync ? OK : ACCEPTED);
const meta = g[collection].replace(id, req.body, {waitForSync, returnOld, returnNew});
setResponse(res, 'vertex', meta, waitForSync ? OK : ACCEPTED, returnOld, returnNew);
})
.pathParam('graph', graphName)
.pathParam('collection', vertexCollectionName)
.pathParam('key', vertexKey)
.queryParam('waitForSync', waitForSyncFlag)
.queryParam('returnOld', returnOldFlag)
.queryParam('returnNew', returnNewFlag)
.body(joi.any().required(), 'The document to be stored')
.error('bad request', 'The vertex is invalid.')
.error('not found', 'The vertex does not exist.')
@ -645,6 +670,8 @@ router.put('/:graph/vertex/:collection/:key', function (req, res) {
router.patch('/:graph/vertex/:collection/:key', function (req, res) {
const waitForSync = Boolean(req.queryParams.waitForSync);
const keepNull = Boolean(req.queryParams.keepNull);
const returnOld = Boolean(req.queryParams.returnOld);
const returnNew = Boolean(req.queryParams.returnNew);
const name = req.pathParams.graph;
const collection = req.pathParams.collection;
const key = req.pathParams.key;
@ -664,13 +691,15 @@ router.patch('/:graph/vertex/:collection/:key', function (req, res) {
throw e;
}
matchVertexRevision(req, doc._rev);
const meta = g[collection].update(id, req.body, {waitForSync, keepNull});
setResponse(res, 'vertex', meta, waitForSync ? OK : ACCEPTED);
const meta = g[collection].update(id, req.body, {waitForSync, keepNull, returnOld, returnNew});
setResponse(res, 'vertex', meta, waitForSync ? OK : ACCEPTED, returnOld, returnNew);
})
.pathParam('graph', graphName)
.pathParam('collection', vertexCollectionName)
.pathParam('key', vertexKey)
.queryParam('waitForSync', waitForSyncFlag)
.queryParam('returnOld', returnOldFlag)
.queryParam('returnNew', returnNewFlag)
.queryParam('keepNull', keepNullFlag)
.body(joi.any().required(), 'The values that should be modified')
.error('bad request', 'The vertex is invalid.')
@ -683,6 +712,7 @@ router.patch('/:graph/vertex/:collection/:key', function (req, res) {
router.delete('/:graph/vertex/:collection/:key', function (req, res) {
const waitForSync = Boolean(req.queryParams.waitForSync);
const returnOld = Boolean(req.queryParams.returnOld);
const name = req.pathParams.graph;
const collection = req.pathParams.collection;
const key = req.pathParams.key;
@ -714,12 +744,17 @@ router.delete('/:graph/vertex/:collection/:key', function (req, res) {
}
throw e;
}
setResponse(res, 'removed', didRemove, waitForSync ? OK : ACCEPTED);
let meta = { removed: didRemove };
if (returnOld) {
meta.old = doc;
}
setResponse(res, undefined, meta, waitForSync ? OK : ACCEPTED, returnOld, false);
})
.pathParam('graph', graphName)
.pathParam('collection', vertexCollectionName)
.pathParam('key', vertexKey)
.queryParam('waitForSync', waitForSyncFlag)
.queryParam('returnOld', returnOldFlag)
.error('not found', 'The vertex does not exist.')
.summary('Delete a vertex.')
.description(dd`
@ -730,6 +765,8 @@ router.delete('/:graph/vertex/:collection/:key', function (req, res) {
// Edge Operations
router.post('/:graph/edge/:collection', function (req, res) {
const waitForSync = Boolean(req.queryParams.waitForSync);
const returnNew = Boolean(req.queryParams.returnNew);
const name = req.pathParams.graph;
const collection = req.pathParams.collection;
if (!req.body._from || !req.body._to) {
@ -742,7 +779,7 @@ router.post('/:graph/edge/:collection', function (req, res) {
checkCollection(g, collection);
let meta;
try {
meta = g[collection].save(req.body);
meta = g[collection].save(req.body, {waitForSync, returnNew});
} catch (e) {
if (e.errorNum !== errors.ERROR_GRAPH_INVALID_EDGE.code) {
throw Object.assign(
@ -752,10 +789,12 @@ router.post('/:graph/edge/:collection', function (req, res) {
}
throw e;
}
setResponse(res, 'edge', meta, ACCEPTED);
setResponse(res, 'edge', meta, waitForSync ? CREATED : ACCEPTED, false, returnNew);
})
.pathParam('graph', graphName)
.pathParam('collection', edgeCollectionName)
.queryParam('waitForSync', waitForSyncFlag)
.queryParam('returnNew', returnNewFlag)
.body(joi.object().required(), 'The edge to be stored. Has to contain _from and _to attributes.')
.error('bad request', 'The edge is invalid.')
.error('not found', 'Graph or collection not found.')
@ -793,6 +832,8 @@ router.get('/:graph/edge/:collection/:key', function (req, res) {
router.put('/:graph/edge/:collection/:key', function (req, res) {
const waitForSync = Boolean(req.queryParams.waitForSync);
const returnOld = Boolean(req.queryParams.returnOld);
const returnNew = Boolean(req.queryParams.returnNew);
const name = req.pathParams.graph;
const collection = req.pathParams.collection;
const key = req.pathParams.key;
@ -812,13 +853,15 @@ router.put('/:graph/edge/:collection/:key', function (req, res) {
throw e;
}
matchVertexRevision(req, doc._rev);
const meta = g[collection].replace(id, req.body, {waitForSync});
setResponse(res, 'edge', meta, waitForSync ? OK : ACCEPTED);
const meta = g[collection].replace(id, req.body, {waitForSync, returnOld, returnNew});
setResponse(res, 'edge', meta, waitForSync ? OK : ACCEPTED, returnOld, returnNew);
})
.pathParam('graph', graphName)
.pathParam('collection', edgeCollectionName)
.pathParam('key', edgeKey)
.queryParam('waitForSync', waitForSyncFlag)
.queryParam('returnOld', returnOldFlag)
.queryParam('returnNew', returnNewFlag)
.body(joi.any().required(), 'The document to be stored. _from and _to attributes are ignored')
.error('bad request', 'The edge is invalid.')
.error('not found', 'The edge does not exist.')
@ -830,6 +873,8 @@ router.put('/:graph/edge/:collection/:key', function (req, res) {
router.patch('/:graph/edge/:collection/:key', function (req, res) {
const waitForSync = Boolean(req.queryParams.waitForSync);
const returnOld = Boolean(req.queryParams.returnOld);
const returnNew = Boolean(req.queryParams.returnNew);
const keepNull = Boolean(req.queryParams.keepNull);
const name = req.pathParams.graph;
const collection = req.pathParams.collection;
@ -850,13 +895,15 @@ router.patch('/:graph/edge/:collection/:key', function (req, res) {
throw e;
}
matchVertexRevision(req, doc._rev);
const meta = g[collection].update(id, req.body, {waitForSync, keepNull});
setResponse(res, 'edge', meta, waitForSync ? OK : ACCEPTED);
const meta = g[collection].update(id, req.body, {waitForSync, keepNull, returnOld, returnNew});
setResponse(res, 'edge', meta, waitForSync ? OK : ACCEPTED, returnOld, returnNew);
})
.pathParam('graph', graphName)
.pathParam('collection', edgeCollectionName)
.pathParam('key', edgeKey)
.queryParam('waitForSync', waitForSyncFlag)
.queryParam('returnOld', returnOldFlag)
.queryParam('returnNew', returnNewFlag)
.queryParam('keepNull', keepNullFlag)
.body(joi.any().required(), 'The values that should be modified. _from and _to attributes are ignored')
.error('bad request', 'The edge is invalid.')
@ -869,6 +916,7 @@ router.patch('/:graph/edge/:collection/:key', function (req, res) {
router.delete('/:graph/edge/:collection/:key', function (req, res) {
const waitForSync = Boolean(req.queryParams.waitForSync);
const returnOld = Boolean(req.queryParams.returnOld);
const name = req.pathParams.graph;
const collection = req.pathParams.collection;
const key = req.pathParams.key;
@ -900,12 +948,17 @@ router.delete('/:graph/edge/:collection/:key', function (req, res) {
}
throw e;
}
setResponse(res, 'removed', didRemove, waitForSync ? OK : ACCEPTED);
let meta = { removed: didRemove };
if (returnOld) {
meta.old = doc;
}
setResponse(res, undefined, meta, waitForSync ? OK : ACCEPTED, returnOld, false);
})
.pathParam('graph', graphName)
.pathParam('collection', edgeCollectionName)
.pathParam('key', edgeKey)
.queryParam('waitForSync', waitForSyncFlag)
.queryParam('returnOld', returnOldFlag)
.error('not found', 'The edge does not exist.')
.summary('Delete an edge.')
.description('Deletes an edge with the given id, if it is contained within the graph.');

View File

@ -382,10 +382,16 @@ var bindEdgeCollections = function (self, edgeCollections) {
// save
var oldSave = wrap.insert;
wrap.save = wrap.insert = function (from, to, data) {
var options = {};
if (typeof from === 'object' && to === undefined) {
data = from;
from = data._from;
to = data._to;
} else if (typeof from === 'object' && typeof to === 'object' && data === undefined) {
data = from;
options = to;
from = data._from;
to = data._to;
} else if (typeof from === 'string' && typeof to === 'string' && typeof data === 'object') {
data._from = from;
data._to = to;
@ -420,7 +426,7 @@ var bindEdgeCollections = function (self, edgeCollections) {
}
}
);
return oldSave(data);
return oldSave(data, options);
};
// remove
@ -580,9 +586,7 @@ var checkRWPermission = function (c) {
let user = users.currentUser();
if (user) {
let p = users.permission(user, db._name(), c);
//print(`${user}: ${db._name()}/${c} = ${p}`);
if (p !== 'rw') {
//print(`Denied ${user} access to ${db._name()}/${c}`);
var err = new ArangoError();
err.errorNum = arangodb.errors.ERROR_FORBIDDEN.code;
err.errorMessage = arangodb.errors.ERROR_FORBIDDEN.message;
@ -601,7 +605,6 @@ var checkROPermission = function(c) {
let p = users.permission(user, db._name(), c);
var err = new ArangoError();
if (p === 'none') {
//print(`Denied ${user} access to ${db._name()}/${c}`);
err.errorNum = arangodb.errors.ERROR_FORBIDDEN.code;
err.errorMessage = arangodb.errors.ERROR_FORBIDDEN.message;
throw err;