1
0
Fork 0

use defer release

This commit is contained in:
Frank Celler 2016-06-10 14:01:28 +02:00
parent 5cb1d86d58
commit fa9501cc0c
10 changed files with 397 additions and 295 deletions

View File

@ -54,7 +54,7 @@ CheckVersionFeature::CheckVersionFeature(
void CheckVersionFeature::collectOptions(
std::shared_ptr<ProgramOptions> options) {
options->addSection("database", "Configure the database");
options->addOldOption("check-version", "database.check-version");
options->addHiddenOption("--database.check-version",
@ -70,15 +70,18 @@ void CheckVersionFeature::validateOptions(
ApplicationServer::forceDisableFeatures(_nonServerFeatures);
LoggerFeature* logger = ApplicationServer::getFeature<LoggerFeature>("Logger");
LoggerFeature* logger =
ApplicationServer::getFeature<LoggerFeature>("Logger");
logger->disableThreaded();
DatabaseFeature* database = ApplicationServer::getFeature<DatabaseFeature>("Database");
DatabaseFeature* database =
ApplicationServer::getFeature<DatabaseFeature>("Database");
database->disableReplicationApplier();
database->disableCompactor();
database->enableCheckVersion();
V8DealerFeature* v8dealer = ApplicationServer::getFeature<V8DealerFeature>("V8Dealer");
V8DealerFeature* v8dealer =
ApplicationServer::getFeature<V8DealerFeature>("V8Dealer");
v8dealer->setNumberContexts(1);
}
@ -116,6 +119,8 @@ void CheckVersionFeature::checkVersion() {
FATAL_ERROR_EXIT();
}
TRI_DEFER(V8DealerFeature::DEALER->exitContext(context));
{
v8::HandleScope scope(context->_isolate);
auto localContext =
@ -136,7 +141,8 @@ void CheckVersionFeature::checkVersion() {
for (auto& p : theLists->_databases) {
TRI_vocbase_t* vocbase = p.second;
// special check script to be run just once in first thread (not in all)
// special check script to be run just once in first thread (not in
// all)
// but for all databases
int status = TRI_CheckDatabaseVersion(vocbase, localContext);
@ -144,8 +150,9 @@ void CheckVersionFeature::checkVersion() {
LOG(DEBUG) << "version check return status " << status;
if (status < 0) {
LOG(FATAL) << "Database version check failed for '" << vocbase->_name
<< "'. Please inspect the logs for any errors";
LOG(FATAL) << "Database version check failed for '"
<< vocbase->_name
<< "'. Please inspect the logs for any errors";
FATAL_ERROR_EXIT();
} else if (status == 3) {
*_result = 3;
@ -155,11 +162,11 @@ void CheckVersionFeature::checkVersion() {
}
}
// issue #391: when invoked with --database.auto-upgrade, the server will not always shut
// issue #391: when invoked with --database.auto-upgrade, the server will
// not always shut
// down
localContext->Exit();
}
V8DealerFeature::DEALER->exitContext(context);
}
if (*_result == 1) {

View File

@ -63,6 +63,13 @@ void ConsoleThread::run() {
// enter V8 context
_context = V8DealerFeature::DEALER->enterContext(_vocbase, true);
if (_context != nullptr) {
LOG(FATAL) << "cannot acquire V8 context";
FATAL_ERROR_EXIT();
}
TRI_DEFER(V8DealerFeature::DEALER->exitContext(_context));
// work
try {
inner();
@ -71,14 +78,11 @@ void ConsoleThread::run() {
LOG(ERR) << error;
}
} catch (...) {
V8DealerFeature::DEALER->exitContext(_context);
_applicationServer->beginShutdown();
throw;
}
// exit context
V8DealerFeature::DEALER->exitContext(_context);
_applicationServer->beginShutdown();
}

View File

@ -71,6 +71,14 @@ int ScriptFeature::runScript(std::vector<std::string> const& scripts) {
auto database = ApplicationServer::getFeature<DatabaseFeature>("Database");
V8Context* context =
V8DealerFeature::DEALER->enterContext(database->vocbase(), true);
if (context != nullptr) {
LOG(FATAL) << "cannot acquire V8 context";
FATAL_ERROR_EXIT();
}
TRI_DEFER(V8DealerFeature::DEALER->exitContext(context));
auto isolate = context->_isolate;
{
@ -145,7 +153,5 @@ int ScriptFeature::runScript(std::vector<std::string> const& scripts) {
localContext->Exit();
}
V8DealerFeature::DEALER->exitContext(context);
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@ -65,6 +65,13 @@ int UnitTestsFeature::runUnitTests(std::vector<std::string> const& unitTests) {
V8Context* context =
V8DealerFeature::DEALER->enterContext(database->vocbase(), true);
if (context != nullptr) {
LOG(FATAL) << "cannot acquire V8 context";
FATAL_ERROR_EXIT();
}
TRI_DEFER(V8DealerFeature::DEALER->exitContext(context));
auto isolate = context->_isolate;
bool ok = false;
@ -111,7 +118,5 @@ int UnitTestsFeature::runUnitTests(std::vector<std::string> const& unitTests) {
localContext->Exit();
}
V8DealerFeature::DEALER->exitContext(context);
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@ -132,6 +132,8 @@ void UpgradeFeature::changeAdminPassword(std::string const& defaultPassword) {
FATAL_ERROR_EXIT();
}
TRI_DEFER(V8DealerFeature::DEALER->exitContext(context));
{
v8::HandleScope scope(context->_isolate);
auto localContext =
@ -166,8 +168,6 @@ void UpgradeFeature::changeAdminPassword(std::string const& defaultPassword) {
// failure when we delete the context locker below
localContext->Exit();
}
V8DealerFeature::DEALER->exitContext(context);
}
// and return from the context
@ -190,6 +190,8 @@ void UpgradeFeature::upgradeDatabase(std::string const& defaultPassword) {
FATAL_ERROR_EXIT();
}
TRI_DEFER(V8DealerFeature::DEALER->exitContext(context));
{
v8::HandleScope scope(context->_isolate);
auto localContext =
@ -253,13 +255,9 @@ void UpgradeFeature::upgradeDatabase(std::string const& defaultPassword) {
}
// finally leave the context. otherwise v8 will crash with assertion
// failure
// when we delete
// the context locker below
// failure when we delete the context locker below
localContext->Exit();
}
V8DealerFeature::DEALER->exitContext(context);
}
if (_upgrade) {

View File

@ -181,7 +181,7 @@ void V8DealerFeature::start() {
// try to guess a suitable number of contexts
if (0 == _nrContexts && 0 == _forceNrContexts) {
DispatcherFeature* dispatcher =
DispatcherFeature* dispatcher =
ApplicationServer::getFeature<DispatcherFeature>("Dispatcher");
_nrContexts = dispatcher->concurrency();
@ -216,7 +216,7 @@ void V8DealerFeature::start() {
applyContextUpdates();
DatabaseFeature* database =
DatabaseFeature* database =
ApplicationServer::getFeature<DatabaseFeature>("Database");
loadJavascript(database->vocbase(), "server/initialize.js");
@ -262,10 +262,12 @@ void V8DealerFeature::collectGarbage() {
bool preferFree = false;
// the time we'll wait for a signal
uint64_t const regularWaitTime = static_cast<uint64_t>(_gcFrequency * 1000.0 * 1000.0);
uint64_t const regularWaitTime =
static_cast<uint64_t>(_gcFrequency * 1000.0 * 1000.0);
// the time we'll wait for a signal when the previous wait timed out
uint64_t const reducedWaitTime = static_cast<uint64_t>(_gcFrequency * 1000.0 * 200.0);
uint64_t const reducedWaitTime =
static_cast<uint64_t>(_gcFrequency * 1000.0 * 200.0);
while (_stopping == 0) {
V8Context* context = nullptr;
@ -483,8 +485,8 @@ V8Context* V8DealerFeature::enterContext(TRI_vocbase_t* vocbase,
_freeContexts.push_back(context);
_dirtyContexts.pop_back();
break;
}
}
auto currentThread = arangodb::rest::DispatcherThread::current();
if (currentThread != nullptr) {
@ -682,8 +684,8 @@ void V8DealerFeature::applyContextUpdates() {
vocbase = DatabaseFeature::DATABASE->vocbase();
}
V8Context* context =
V8DealerFeature::DEALER->enterContext(vocbase, true, static_cast<ssize_t>(i));
V8Context* context = V8DealerFeature::DEALER->enterContext(
vocbase, true, static_cast<ssize_t>(i));
if (context == nullptr) {
LOG(FATAL) << "could not updated V8 context #" << i;
@ -703,7 +705,7 @@ void V8DealerFeature::applyContextUpdates() {
localContext->Exit();
}
V8DealerFeature::DEALER->exitContext(context);
LOG(TRACE) << "updated V8 context #" << i;
@ -851,8 +853,9 @@ V8Context* V8DealerFeature::pickFreeContextForGc() {
void V8DealerFeature::initializeContext(size_t i) {
CONDITION_LOCKER(guard, _contextCondition);
V8PlatformFeature* v8platform =
application_features::ApplicationServer::getFeature<V8PlatformFeature>("V8Platform");
V8PlatformFeature* v8platform =
application_features::ApplicationServer::getFeature<V8PlatformFeature>(
"V8Platform");
TRI_ASSERT(v8platform != nullptr);
v8::Isolate::CreateParams createParams;
@ -963,7 +966,8 @@ void V8DealerFeature::initializeContext(size_t i) {
void V8DealerFeature::loadJavascriptFiles(TRI_vocbase_t* vocbase,
std::string const& file, size_t i) {
V8Context* context = V8DealerFeature::DEALER->enterContext(vocbase, true, static_cast<ssize_t>(i));
V8Context* context = V8DealerFeature::DEALER->enterContext(
vocbase, true, static_cast<ssize_t>(i));
if (context == nullptr) {
LOG(FATAL) << "could not load JavaScript files in context #" << i;
@ -979,7 +983,8 @@ void V8DealerFeature::loadJavascriptFiles(TRI_vocbase_t* vocbase,
{
v8::Context::Scope contextScope(localContext);
switch (_startupLoader.loadScript(context->_isolate, localContext, file)) {
switch (
_startupLoader.loadScript(context->_isolate, localContext, file)) {
case JSLoader::eSuccess:
LOG(TRACE) << "loaded JavaScript file '" << file << "'";
break;
@ -989,7 +994,7 @@ void V8DealerFeature::loadJavascriptFiles(TRI_vocbase_t* vocbase,
break;
case JSLoader::eFailExecute:
LOG(FATAL) << "error during execution of JavaScript file '" << file
<< "'";
<< "'";
FATAL_ERROR_EXIT();
break;
}

View File

@ -75,6 +75,8 @@ void V8Job::work() {
return;
}
TRI_DEFER(V8DealerFeature::DEALER->exitContext(context));
// now execute the function within this context
{
auto isolate = context->_isolate;
@ -131,8 +133,6 @@ void V8Job::work() {
}
}
}
V8DealerFeature::DEALER->exitContext(context);
}
bool V8Job::cancel() {

View File

@ -71,6 +71,8 @@ void V8QueueJob::work() {
return;
}
TRI_DEFER(V8DealerFeature::DEALER->exitContext(context));
// now execute the function within this context
{
auto isolate = context->_isolate;
@ -118,8 +120,6 @@ void V8QueueJob::work() {
}
}
}
V8DealerFeature::DEALER->exitContext(context);
}
bool V8QueueJob::cancel() {

View File

@ -89,7 +89,8 @@ class v8_action_t : public TRI_action_t {
TRI_action_result_t result;
// allow use datase execution in rest calls
bool allowUseDatabaseInRestActions = ActionFeature::ACTION->allowUseDatabase();
bool allowUseDatabaseInRestActions =
ActionFeature::ACTION->allowUseDatabase();
if (_allowUseDatabase) {
allowUseDatabaseInRestActions = true;
@ -114,6 +115,8 @@ class v8_action_t : public TRI_action_t {
return result;
}
TRI_DEFER(V8DealerFeature::DEALER->exitContext(context));
// locate the callback
READ_LOCKER(readLocker, _callbacksLock);
@ -124,8 +127,6 @@ class v8_action_t : public TRI_action_t {
LOG(WARN) << "no callback function for JavaScript action '" << _url
<< "'";
V8DealerFeature::DEALER->exitContext(context);
result.isValid = true;
result.response =
new HttpResponse(GeneralResponse::ResponseCode::NOT_FOUND);
@ -139,9 +140,6 @@ class v8_action_t : public TRI_action_t {
if (*data != 0) {
result.canceled = true;
V8DealerFeature::DEALER->exitContext(context);
return result;
}
@ -163,7 +161,6 @@ class v8_action_t : public TRI_action_t {
*data = 0;
}
}
V8DealerFeature::DEALER->exitContext(context);
return result;
}
@ -547,12 +544,14 @@ static HttpResponse* ResponseV8ToCpp(v8::Isolate* isolate,
// base64-encode the result
out = StringUtils::encodeBase64(out);
// set the correct content-encoding header
response->setHeaderNC(StaticStrings::ContentEncoding, StaticStrings::Base64);
response->setHeaderNC(StaticStrings::ContentEncoding,
StaticStrings::Base64);
} else if (name == "base64decode") {
// base64-decode the result
out = StringUtils::decodeBase64(out);
// set the correct content-encoding header
response->setHeaderNC(StaticStrings::ContentEncoding, StaticStrings::Binary);
response->setHeaderNC(StaticStrings::ContentEncoding,
StaticStrings::Binary);
}
}
@ -726,7 +725,8 @@ static TRI_action_result_t ExecuteActionVocbase(
else if (tryCatch.HasCaught()) {
if (tryCatch.CanContinue()) {
HttpResponse* response = new HttpResponse(GeneralResponse::ResponseCode::SERVER_ERROR);
HttpResponse* response =
new HttpResponse(GeneralResponse::ResponseCode::SERVER_ERROR);
response->body().appendText(TRI_StringifyV8Exception(isolate, &tryCatch));
result.response = response;
@ -738,8 +738,7 @@ static TRI_action_result_t ExecuteActionVocbase(
}
else {
result.response =
ResponseV8ToCpp(isolate, v8g, res);
result.response = ResponseV8ToCpp(isolate, v8g, res);
}
return result;
@ -1173,7 +1172,8 @@ static bool clusterSendToAllServers(
DBServers = ci->getCurrentDBServers();
for (auto const& sid : DBServers) {
auto headers = std::make_unique<std::unordered_map<std::string, std::string>>();
auto headers =
std::make_unique<std::unordered_map<std::string, std::string>>();
cc->asyncRequest("", coordTransactionID, "server:" + sid, method, url,
reqBodyString, headers, nullptr, 3600.0);
}

View File

@ -28,108 +28,154 @@ const actions = require("@arangodb/actions");
const users = require("@arangodb/users");
const db = require("@arangodb").db;
function get_api_user(req, res) {
if (req.suffix.length === 0) {
actions.resultOk(req, res, actions.HTTP_OK, {
result: users.all()
});
return;
// check if user is an administrator (aka member of _system)
function needSystemUser(req, res) {
const user = req.user;
// authentication disabled
if (user === null) {
return true;
}
var user = decodeURIComponent(req.suffix[0]);
const allowed = users.permission(user, "_system") === 'rw' ||
users.permission(user, "*") === 'rw';
try {
actions.resultOk(req, res, actions.HTTP_OK, users.document(user));
} catch (err) {
if (err.errorNum === arangodb.errors.ERROR_USER_NOT_FOUND.code) {
actions.resultNotFound(req, res, arangodb.errors.ERROR_USER_NOT_FOUND.code);
} else {
throw err;
}
if (!allowed) {
actions.resultError(req, res, actions.HTTP_FORBIDDEN,
String("you need administrator privileges"));
}
return allowed;
}
// check if user is asking infos for itself (or is an administrator)
function needMyself(req, res, username) {
const user = req.user;
// authentication disabled
if (user === null) {
return true;
}
let allowed = (user === username);
if (!allowed) {
allowed = users.permission(username, "_system") === 'rw' ||
users.permission(username, "*") === 'rw';
}
if (!allowed) {
actions.resultError(req, res, actions.HTTP_FORBIDDEN,
String("you cannot access other users"));
}
return allowed;
}
// handle exception
function handleException(req, res, err) {
if (err.errorNum === arangodb.errors.ERROR_USER_NOT_FOUND.code) {
actions.resultNotFound(req, res, arangodb.errors.ERROR_USER_NOT_FOUND.code);
} else {
throw err;
}
}
function get_api_permission(req, res, key) {
var user = decodeURIComponent(req.suffix[0]);
// GET /_api/user | GET /_api/user/<username>
function get_api_user(req, res) {
if (req.suffix.length === 0) {
if (needSystemUser(req, res)) {
actions.resultOk(req, res, actions.HTTP_OK, {
result: users.all()
});
}
var oldDbname = db._name();
return;
}
const user = decodeURIComponent(req.suffix[0]);
try {
var doc;
if (key !== null && key !== undefined) {
doc = users.permission(user, key);
if (needMyself(req, res, user)) {
actions.resultOk(req, res, actions.HTTP_OK, users.document(user));
}
doc = users.permission(user);
actions.resultOk(req, res, actions.HTTP_OK, { result: doc });
} catch (err) {
if (err.errorNum === arangodb.errors.ERROR_USER_NOT_FOUND.code) {
actions.resultNotFound(req, res, arangodb.errors.ERROR_USER_NOT_FOUND.code);
handleException(req, res, err);
}
}
// GET /_api/user/<username>/database | GET /_api/user/<username>/database/<dbname>
function get_api_database(req, res, key) {
const user = decodeURIComponent(req.suffix[0]);
try {
if (needMyself(req, res, user)) {
actions.resultOk(req, res, actions.HTTP_OK, {
result: users.permission(user, key)
});
}
} catch (err) {
handleException(req, res, err);
}
}
// GET /_api/user/<username>/config | GET /_api/user/<username>/config/<key>
function get_api_config(req, res, key) {
const user = decodeURIComponent(req.suffix[0]);
try {
if (needMyself(req, res, user)) {
actions.resultOk(req, res, actions.HTTP_OK, {
result: users.configData(user, key)
});
}
} catch (err) {
handleException(req, res, err);
}
}
// GET /_api/user/...
function get_api_user_request(req, res) {
const oldDbname = db._name();
db._useDatabase("_system");
try {
if (req.suffix.length === 0) {
get_api_user(req, res);
} else if (req.suffix.length === 1) {
get_api_user(req, res);
} else if (req.suffix.length === 2) {
if (req.suffix[1] === "config") {
get_api_config(req, res, null);
} else if (req.suffix[1] === "database") {
get_api_database(req, res, null);
} else {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
} else if (req.suffix.length === 3) {
if (req.suffix[1] === "config") {
get_api_config(req, res, req.suffix[2]);
} else {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
} else {
throw err;
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
} finally {
db._useDatabase(oldDbname);
}
}
function get_api_config(req, res, key) {
var user = decodeURIComponent(req.suffix[0]);
if (user !== req.user) {
actions.resultBad(req, res, arangodb.errors.ERROR_HTTP_UNAUTHORIZED.code);
} else {
var oldDbname = db._name();
try {
var doc = users.configData(user, key);
actions.resultOk(req, res, actions.HTTP_OK, { result: doc });
} catch (err) {
if (err.errorNum === arangodb.errors.ERROR_USER_NOT_FOUND.code) {
actions.resultNotFound(req, res, arangodb.errors.ERROR_USER_NOT_FOUND.code);
} else {
throw err;
}
} finally {
db._useDatabase(oldDbname);
}
}
}
function get_api_user_or_config(req, res) {
if (req.suffix.length === 0) {
get_api_user(req, res);
} else if (req.suffix.length === 1) {
get_api_user(req, res);
} else if (req.suffix.length === 2) {
if (req.suffix[1] === "config") {
get_api_config(req, res, null);
} else if (req.suffix[1] === "permission") {
get_api_permission(req, res, null);
}
else {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
} else if (req.suffix.length === 3) {
if (req.suffix[1] === "config") {
get_api_config(req, res, req.suffix[2]);
} else {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
} else {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
}
// POST /_api/user | POST /_api/user/<username>
function post_api_user(req, res) {
var json = actions.getJsonBody(req, res, actions.HTTP_BAD);
const json = actions.getJsonBody(req, res, actions.HTTP_BAD);
if (json === undefined) {
return;
}
// validate if a combination or username / password is valid
if (req.suffix.length === 1) {
// validate if a combination or username / password is valid
const user = decodeURIComponent(req.suffix[0]);
const result = users.isValid(user, json.passwd);
@ -143,57 +189,79 @@ function post_api_user(req, res) {
return;
}
if (req.suffix.length !== 0) {
// unexpected URL
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
return;
}
if (needSystemUser(req, res)) {
const user = json.user;
const doc = users.save(user, json.passwd, json.active, json.extra,
json.changePassword);
const user = json.user;
const doc = users.save(user, json.passwd, json.active, json.extra, json.changePassword);
if (json.passwordToken) {
users.setPasswordToken(user, json.passwordToken);
}
if (json.passwordToken) {
users.setPasswordToken(user, json.passwordToken);
}
users.reload();
actions.resultOk(req, res, actions.HTTP_CREATED, doc);
}
function put_api_user(req, res) {
var user = decodeURIComponent(req.suffix[0]);
var json = actions.getJsonBody(req, res, actions.HTTP_BAD);
if (json === undefined) {
return;
}
try {
var doc = users.replace(user, json.passwd, json.active, json.extra, json.changePassword);
users.reload();
actions.resultOk(req, res, actions.HTTP_OK, doc);
} catch (err) {
if (err.errorNum === arangodb.errors.ERROR_USER_NOT_FOUND.code) {
actions.resultNotFound(req, res, arangodb.errors.ERROR_USER_NOT_FOUND.code);
} else {
throw err;
}
actions.resultOk(req, res, actions.HTTP_CREATED, doc);
}
}
function put_api_permission(req, res) {
var user = decodeURIComponent(req.suffix[0]);
var dbname = decodeURIComponent(req.suffix[2]);
var json = actions.getJsonBody(req, res, actions.HTTP_BAD);
// POST /_api/user/...
function post_api_user_request(req, res) {
const oldDbname = db._name();
db._useDatabase("_system");
try {
if (req.suffix.length < 2) {
post_api_user(req, res);
} else {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
} finally {
db._useDatabase(oldDbname);
}
}
// PUT /_api/user/<username>
function put_api_user(req, res) {
const user = decodeURIComponent(req.suffix[0]);
const json = actions.getJsonBody(req, res, actions.HTTP_BAD);
if (json === undefined) {
return;
}
try {
var doc;
const isActive = users.document(user).active;
if (isActive) {
if (needMyself(req, res, user)) {
actions.resultOk(req, res, actions.HTTP_OK,
users.replace(user, json.passwd, json.active, json.extra));
}
} else {
if (needSystemUser(req, res, user)) {
actions.resultOk(req, res, actions.HTTP_OK,
users.replace(user, json.passwd, json.active, json.extra));
}
}
users.reload();
} catch (err) {
handleException(req, res, err);
}
}
// PUT /_api/user/<username>/database/<dbname>
function put_api_permission(req, res) {
const user = decodeURIComponent(req.suffix[0]);
const dbname = decodeURIComponent(req.suffix[2]);
const json = actions.getJsonBody(req, res, actions.HTTP_BAD);
if (json === undefined) {
return;
}
try {
let doc;
if (json.grant === "rw" || json.grant === "ro") {
doc = users.grantDatabase(user, dbname, json.grant);
@ -205,112 +273,121 @@ function put_api_permission(req, res) {
actions.resultOk(req, res, actions.HTTP_OK, doc);
} catch (err) {
if (err.errorNum === arangodb.errors.ERROR_USER_NOT_FOUND.code) {
actions.resultNotFound(req, res, arangodb.errors.ERROR_USER_NOT_FOUND.code);
} else {
throw err;
}
handleException(req, res, err);
}
}
// PUT /_api/user/<username>/config/<key>
function put_api_config(req, res) {
var user = decodeURIComponent(req.suffix[0]);
if (user !== req.user) {
actions.resultBad(req, res, arangodb.errors.ERROR_HTTP_UNAUTHORIZED.code);
} else {
var oldDbname = db._name();
try {
db._useDatabase("_system");
var key = decodeURIComponent(req.suffix[2]);
var json = actions.getJsonBody(req, res, actions.HTTP_BAD);
if (json === undefined) {
return;
}
try {
users.updateConfigData(user, key, json.value);
actions.resultOk(req, res, actions.HTTP_OK, {});
} catch (err) {
if (err.errorNum === arangodb.errors.ERROR_USER_NOT_FOUND.code) {
actions.resultNotFound(req, res, arangodb.errors.ERROR_USER_NOT_FOUND.code);
} else {
throw err;
}
}
} finally {
db._useDatabase(oldDbname);
}
}
}
function put_api_user_or_permission(req, res) {
if (req.suffix.length === 1) {
put_api_user(req, res);
} else if (req.suffix.length === 3) {
if (req.suffix[1] === "database") {
put_api_permission(req, res);
} else if (req.suffix[1] === "config") {
put_api_config(req, res);
} else {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
} else {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
}
function patch_api_user(req, res) {
if (req.suffix.length !== 1) {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
return;
}
var user = decodeURIComponent(req.suffix[0]);
var json = actions.getJsonBody(req, res, actions.HTTP_BAD);
const user = decodeURIComponent(req.suffix[0]);
const key = decodeURIComponent(req.suffix[2]);
const json = actions.getJsonBody(req, res, actions.HTTP_BAD);
if (json === undefined) {
return;
}
try {
var doc = users.update(user, json.passwd, json.active, json.extra, json.changePassword);
users.reload();
if (needMyself(req, res, user)) {
users.updateConfigData(user, key, json.value);
actions.resultOk(req, res, actions.HTTP_OK, doc);
} catch (err) {
if (err.errorNum === arangodb.errors.ERROR_USER_NOT_FOUND.code) {
actions.resultNotFound(req, res, arangodb.errors.ERROR_USER_NOT_FOUND.code);
} else {
throw err;
actions.resultOk(req, res, actions.HTTP_OK, {});
}
} catch (err) {
handleException(req, res, err);
}
}
function delete_api_user(req, res) {
var user = decodeURIComponent(req.suffix[0]);
// PUT /_api/user/...
function put_api_user_request(req, res) {
const oldDbname = db._name();
db._useDatabase("_system");
try {
users.remove(user);
users.reload();
actions.resultOk(req, res, actions.HTTP_ACCEPTED, {});
} catch (err) {
if (err.errorNum === arangodb.errors.ERROR_USER_NOT_FOUND.code) {
actions.resultNotFound(req, res, arangodb.errors.ERROR_USER_NOT_FOUND.code);
if (req.suffix.length === 1) {
put_api_user(req, res);
} else if (req.suffix.length === 3) {
if (req.suffix[1] === "database") {
put_api_permission(req, res);
} else if (req.suffix[1] === "config") {
put_api_config(req, res);
} else {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
} else {
throw err;
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
} finally {
db._useDatabase(oldDbname);
}
}
// PATCH /_api/user/<username>
function patch_api_user(req, res) {
const user = decodeURIComponent(req.suffix[0]);
const json = actions.getJsonBody(req, res, actions.HTTP_BAD);
if (json === undefined) {
return;
}
try {
const isActive = users.document(user).active;
if (isActive) {
if (needMyself(req, res, user)) {
actions.resultOk(req, res, actions.HTTP_OK,
users.update(user, json.passwd, json.active, json.extra));
}
} else {
if (needSystemUser(req, res, user)) {
actions.resultOk(req, res, actions.HTTP_OK,
users.update(user, json.passwd, json.active, json.extra));
}
}
users.reload();
} catch (err) {
handleException(req, res, err);
}
}
// PATCH /_api/user/...
function patch_api_user_request(req, res) {
const oldDbname = db._name();
db._useDatabase("_system");
try {
if (req.suffix.length === 1) {
patch_api_user(req, res);
} else {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
} finally {
db._useDatabase(oldDbname);
}
}
// DELETE /_api/user/<username>
function delete_api_user(req, res) {
const user = decodeURIComponent(req.suffix[0]);
try {
if (needSystemUser(req, res)) {
users.remove(user);
users.reload();
actions.resultOk(req, res, actions.HTTP_ACCEPTED, {});
}
} catch (err) {
handleException(req, res, err);
}
}
// DELETE /_api/user/<username>/database/<dbname>
function delete_api_permission(req, res) {
var user = decodeURIComponent(req.suffix[0]);
var dbname = decodeURIComponent(req.suffix[2]);
const user = decodeURIComponent(req.suffix[0]);
const dbname = decodeURIComponent(req.suffix[2]);
try {
users.revokeDatabase(user, dbname);
@ -318,60 +395,60 @@ function delete_api_permission(req, res) {
actions.resultOk(req, res, actions.HTTP_ACCEPTED, {});
} catch (err) {
if (err.errorNum === arangodb.errors.ERROR_USER_NOT_FOUND.code) {
actions.resultNotFound(req, res, arangodb.errors.ERROR_USER_NOT_FOUND.code);
} else {
throw err;
}
handleException(req, res, err);
}
}
// DELETE /_api/user/<username>/config/<key>
function delete_api_config(req, res, key) {
var user = decodeURIComponent(req.suffix[0]);
const user = decodeURIComponent(req.suffix[0]);
if (user !== req.user) {
actions.resultBad(req, res, arangodb.errors.ERROR_HTTP_UNAUTHORIZED.code);
} else {
var oldDbname = db._name();
try {
try {
if (needMyself(req, res, user)) {
users.updateConfigData(user, key);
actions.resultOk(req, res, actions.HTTP_ACCEPTED, {});
} catch (err) {
if (err.errorNum === arangodb.errors.ERROR_USER_NOT_FOUND.code) {
actions.resultNotFound(req, res, arangodb.errors.ERROR_USER_NOT_FOUND.code);
}
} catch (err) {
handleException(req, res, err);
}
}
// DELETE /_api/user/...
function delete_api_user_request(req, res) {
const oldDbname = db._name();
db._useDatabase("_system");
try {
if (req.suffix.length === 1) {
if (req.suffix.length === 1) {
delete_api_user(req, res);
} else if (req.suffix.length === 2) {
if (req.suffix[1] === "config") {
delete_api_config(req, res, null);
} else {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
} else if (req.suffix.length === 3) {
if (req.suffix[1] === "database") {
delete_api_permission(req, res);
} else if (req.suffix[1] === "config") {
delete_api_config(req, res, req.suffix[2]);
} else {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
} else {
throw err;
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
} finally {
db._useDatabase(oldDbname);
}
}
}
function delete_api_user_or_permission(req, res) {
if (req.suffix.length === 1) {
delete_api_user(req, res);
} else if (req.suffix.length === 2) {
if (req.suffix[1] === "config") {
delete_api_config(req, res, null);
} else {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
} else if (req.suffix.length === 3) {
if (req.suffix[1] === "database") {
delete_api_permission(req, res);
} else if (req.suffix[1] === "config") {
delete_api_config(req, res, req.suffix[2]);
} else {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
}
} else {
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER);
} finally {
db._useDatabase(oldDbname);
}
}
// all api calls
actions.defineHttp({
url: "_api/user",
allowUseDatabase: true,
@ -380,23 +457,23 @@ actions.defineHttp({
try {
switch (req.requestType) {
case actions.GET:
get_api_user_or_config(req, res);
get_api_user_request(req, res);
break;
case actions.POST:
post_api_user(req, res);
post_api_user_request(req, res);
break;
case actions.PUT:
put_api_user_or_permission(req, res);
put_api_user_request(req, res);
break;
case actions.PATCH:
patch_api_user(req, res);
patch_api_user_request(req, res);
break;
case actions.DELETE:
delete_api_user_or_permission(req, res);
delete_api_user_request(req, res);
break;
default: