1
0
Fork 0
arangodb/tests/js/client/load-balancing/load-balancing-async-auth-c...

328 lines
11 KiB
JavaScript

/* jshint globalstrict:true, strict:true, maxlen: 5000 */
/* global assertTrue, assertFalse, assertEqual, require*/
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2018 ArangoDB GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dan Larkin-York
/// @author Copyright 2018, ArangoDB GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
'use strict';
const jsunity = require("jsunity");
const base64Encode = require('internal').base64Encode;
const db = require("internal").db;
const request = require("@arangodb/request");
const url = require('url');
const userModule = require("@arangodb/users");
const _ = require("lodash");
function getCoordinators() {
const isCoordinator = (d) => (_.toLower(d.role) === 'coordinator');
const toEndpoint = (d) => (d.endpoint);
const endpointToURL = (endpoint) => {
if (endpoint.substr(0, 6) === 'ssl://') {
return 'https://' + endpoint.substr(6);
}
var pos = endpoint.indexOf('://');
if (pos === -1) {
return 'http://' + endpoint;
}
return 'http' + endpoint.substr(pos);
};
const instanceInfo = JSON.parse(require('internal').env.INSTANCEINFO);
return instanceInfo.arangods.filter(isCoordinator)
.map(toEndpoint)
.map(endpointToURL);
}
const servers = getCoordinators();
function AsyncAuthSuite () {
'use strict';
const cns = ["animals", "fruits"];
const keys = [
["ant", "bird", "cat", "dog"],
["apple", "banana", "coconut", "date"]
];
let cs = [];
let coordinators = [];
const users = [
{ username: 'alice', password: 'pass1' },
{ username: 'bob', password: 'pass2' },
];
const baseCursorUrl = `/_api/cursor`;
const baseJobUrl = `/_api/job`;
function sendRequest(auth, method, endpoint, headers, body, usePrimary) {
let res;
const i = usePrimary ? 0 : 1;
try {
const envelope = {
headers: Object.assign(headers, {
authorization:
`Basic ${base64Encode(auth.username + ':' + auth.password)}`
}),
json: true,
method,
url: `${coordinators[i]}${endpoint}`
};
if (method !== 'GET') {
envelope.body = body;
}
res = request(envelope);
} catch(err) {
console.error(`Exception processing ${method} ${endpoint}`, err.stack);
return {};
}
if (typeof res.body === "string") {
if (res.body === "") {
res.body = {};
} else {
res.body = JSON.parse(res.body);
}
}
return res;
}
return {
setUp: function() {
coordinators = getCoordinators();
if (coordinators.length < 2) {
throw new Error('Expecting at least two coordinators');
}
cs = [];
for (let i = 0; i < cns.length; i++) {
db._drop(cns[i]);
cs.push(db._create(cns[i]));
assertTrue(cs[i].name() === cns[i]);
for (let key in keys[i]) {
cs[i].save({ _key: key });
}
}
try {
userModule.remove(users[0].username);
userModule.remove(users[1].username);
} catch (err) {}
userModule.save(users[0].username, users[0].password);
userModule.save(users[1].username, users[1].password);
userModule.grantDatabase(users[0].username, '_system', 'ro');
userModule.grantDatabase(users[1].username, '_system', 'ro');
userModule.grantCollection(users[0].username, '_system', cns[0], 'ro');
userModule.grantCollection(users[1].username, '_system', cns[0], 'ro');
userModule.grantCollection(users[0].username, '_system', cns[1], 'ro');
userModule.grantCollection(users[1].username, '_system', cns[1], 'none');
require("internal").wait(2);
},
tearDown: function() {
const url = `${baseJobUrl}/all`;
const result = sendRequest(users[0], 'DELETE', url, {}, {}, true);
assertFalse(result === undefined || result === {});
assertEqual(result.status, 200);
db._drop(cns[0]);
db._drop(cns[1]);
userModule.remove(users[0].username);
userModule.remove(users[1].username);
cs = [];
coordinators = [];
},
testAsyncForwardingSameUserBasic: function() {
let url = baseCursorUrl;
const headers = {
"X-Arango-Async": "store"
};
const query = {
query: `FOR i IN 1..10 LET x = sleep(1.0) FILTER i == 5 RETURN 42`
};
let result = sendRequest(users[0], 'POST', url, headers, query, true);
assertFalse(result === undefined || result === {});
assertEqual(result.body, {});
assertEqual(result.status, 202);
assertFalse(result.headers["x-arango-async-id"] === undefined);
assertTrue(result.headers["x-arango-async-id"].match(/^\d+$/).length > 0);
const jobId = result.headers["x-arango-async-id"];
url = `${baseJobUrl}/${jobId}`;
result = sendRequest(users[0], 'PUT', url, {}, {}, false);
assertFalse(result === undefined || result === {});
assertEqual(result.status, 204);
assertEqual(result.headers["x-arango-async-id"], undefined);
require('internal').wait(11.0, false);
url = `${baseJobUrl}/${jobId}`;
result = sendRequest(users[0], 'PUT', url, {}, {}, false);
assertFalse(result === undefined || result === {});
assertFalse(result.body.error);
assertEqual(result.status, 201);
assertFalse(result.headers["x-arango-async-id"] === undefined);
assertEqual(result.body.result.length, 1);
assertEqual(result.body.result[0], 42);
assertFalse(result.body.hasMore);
},
testAsyncForwardingSameUserDelete: function() {
let url = baseCursorUrl;
const headers = {
"X-Arango-Async": "store"
};
const query = {
query: `FOR i IN 1..10 LET x = sleep(1.0) FILTER i == 5 RETURN 42`
};
let result = sendRequest(users[0], 'POST', url, headers, query, true);
assertFalse(result === undefined || result === {});
assertEqual(result.body, {});
assertEqual(result.status, 202);
assertFalse(result.headers["x-arango-async-id"] === undefined);
assertTrue(result.headers["x-arango-async-id"].match(/^\d+$/).length > 0);
const jobId = result.headers["x-arango-async-id"];
url = `${baseJobUrl}/${jobId}`;
result = sendRequest(users[0], 'PUT', url, {}, {}, false);
assertFalse(result === undefined || result === {});
assertEqual(result.status, 204);
assertEqual(result.headers["x-arango-async-id"], undefined);
require('internal').wait(11.0, false);
url = `${baseJobUrl}/${jobId}`;
result = sendRequest(users[0], 'DELETE', url, {}, {}, false);
assertFalse(result === undefined || result === {});
assertFalse(result.body.error);
assertEqual(result.status, 200);
},
testAsyncForwardingSameUserCancel: function() {
let url = baseCursorUrl;
const headers = {
"X-Arango-Async": "store"
};
const query = {
query: `FOR i IN 1..10 LET x = sleep(1.0) FILTER i == 5 RETURN 42`
};
let result = sendRequest(users[0], 'POST', url, headers, query, true);
assertFalse(result === undefined || result === {});
assertEqual(result.body, {});
assertEqual(result.status, 202);
assertFalse(result.headers["x-arango-async-id"] === undefined);
assertTrue(result.headers["x-arango-async-id"].match(/^\d+$/).length > 0);
const jobId = result.headers["x-arango-async-id"];
url = `${baseJobUrl}/${jobId}`;
result = sendRequest(users[0], 'PUT', url, {}, {}, false);
url = `${baseJobUrl}/${jobId}/cancel`;
result = sendRequest(users[0], 'PUT', url, {}, {}, false);
assertFalse(result === undefined || result === {});
assertFalse(result.body.error);
assertEqual(result.status, 200);
},
testAsyncForwardingDifferentUserBasic: function() {
let url = baseCursorUrl;
const headers = {
"X-Arango-Async": "store"
};
const query = {
query: `FOR i IN 1..10 LET x = sleep(1.0) FILTER i == 5 RETURN 42`
};
let result = sendRequest(users[0], 'POST', url, headers, query, true);
assertFalse(result === undefined || result === {});
assertEqual(result.body, {});
assertEqual(result.status, 202);
assertFalse(result.headers["x-arango-async-id"] === undefined);
assertTrue(result.headers["x-arango-async-id"].match(/^\d+$/).length > 0);
const jobId = result.headers["x-arango-async-id"];
url = `${baseJobUrl}/${jobId}`;
result = sendRequest(users[1], 'PUT', url, {}, {}, false);
assertFalse(result === undefined || result === {});
assertEqual(result.status, 404);
assertEqual(result.headers["x-arango-async-id"], undefined);
require('internal').wait(11.0, false);
url = `${baseJobUrl}/${jobId}`;
result = sendRequest(users[1], 'PUT', url, {}, {}, false);
assertFalse(result === undefined || result === {});
assertEqual(result.status, 404);
},
testAsyncForwardingDifferentUserDelete: function() {
let url = baseCursorUrl;
const headers = {
"X-Arango-Async": "store"
};
const query = {
query: `FOR i IN 1..10 LET x = sleep(1.0) FILTER i == 5 RETURN 42`
};
let result = sendRequest(users[0], 'POST', url, headers, query, true);
assertFalse(result === undefined || result === {});
assertEqual(result.body, {});
assertEqual(result.status, 202);
assertFalse(result.headers["x-arango-async-id"] === undefined);
assertTrue(result.headers["x-arango-async-id"].match(/^\d+$/).length > 0);
const jobId = result.headers["x-arango-async-id"];
url = `${baseJobUrl}/${jobId}`;
result = sendRequest(users[1], 'PUT', url, {}, {}, false);
assertFalse(result === undefined || result === {});
assertEqual(result.status, 404);
assertEqual(result.headers["x-arango-async-id"], undefined);
url = `${baseJobUrl}/${jobId}`;
result = sendRequest(users[1], 'DELETE', url, {}, {}, false);
assertFalse(result === undefined || result === {});
assertEqual(result.status, 404);
},
};
}
jsunity.run(AsyncAuthSuite);
return jsunity.done();