diff --git a/arangod/Aql/AstHelper.h b/arangod/Aql/AstHelper.h index 2f33d2371a..8e0a758be3 100644 --- a/arangod/Aql/AstHelper.h +++ b/arangod/Aql/AstHelper.h @@ -84,7 +84,6 @@ bool accessesSearchVariableViaReference(AstNode const* current, Variable const* bool isTargetVariable(AstNode const* node, SmallVector& searchVariables, bool& isSafeForOptimization) { TRI_ASSERT(!searchVariables.empty()); - TRI_ASSERT(node->type == NODE_TYPE_INDEXED_ACCESS || node->type == NODE_TYPE_EXPANSION); // given and expression like g3[0].`g2`[0].`g1`[0].`item1`.`_id` // this loop resolves subtrees of the form: .`g2`[0].`g1`[0] diff --git a/arangod/VocBase/Methods/Databases.cpp b/arangod/VocBase/Methods/Databases.cpp index 0ffcce262c..03987ecf9d 100644 --- a/arangod/VocBase/Methods/Databases.cpp +++ b/arangod/VocBase/Methods/Databases.cpp @@ -251,8 +251,10 @@ arangodb::Result Databases::info(TRI_vocbase_t* vocbase, VPackBuilder& result) { // Grant permissions on newly created database to current user // to be able to run the upgrade script -arangodb::Result Databases::grantCurrentUser(CreateDatabaseInfo const& info) { +arangodb::Result Databases::grantCurrentUser(CreateDatabaseInfo const& info, int64_t timeout) { auth::UserManager* um = AuthenticationFeature::instance()->userManager(); + + Result res; if (um != nullptr) { ExecContext const* exec = ExecContext::CURRENT; @@ -261,21 +263,34 @@ arangodb::Result Databases::grantCurrentUser(CreateDatabaseInfo const& info) { // called us, or when authentication is off), granting rights // will fail. We hence ignore it here, but issue a warning below if (!exec->isAdminUser()) { - return um->updateUser(exec->user(), [&](auth::User& entry) { - entry.grantDatabase(info.getName(), auth::Level::RW); - entry.grantCollection(info.getName(), "*", auth::Level::RW); - return TRI_ERROR_NO_ERROR; - }); + auto const endTime = std::chrono::steady_clock::now() + std::chrono::seconds(timeout); + while (true) { + res = um->updateUser(exec->user(), [&](auth::User& entry) { + entry.grantDatabase(info.getName(), auth::Level::RW); + entry.grantCollection(info.getName(), "*", auth::Level::RW); + return TRI_ERROR_NO_ERROR; + }); + if (res.ok() || + !res.is(TRI_ERROR_ARANGO_CONFLICT) || + std::chrono::steady_clock::now() > endTime) { + break; + } + + if (application_features::ApplicationServer::isStopping()) { + res.reset(TRI_ERROR_SHUTTING_DOWN); + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } } else { LOG_TOPIC("2a4dd", DEBUG, Logger::FIXME) << "current ExecContext's user() is empty." << "Database will be created without any user having permissions"; - return Result(); } } } - return Result(); + return res; } // Create database on cluster; @@ -311,7 +326,7 @@ Result Databases::createCoordinator(CreateDatabaseInfo const& info) { } }); - res = grantCurrentUser(info); + res = grantCurrentUser(info, 5); if (!res.ok()) { return res; } @@ -366,7 +381,7 @@ Result Databases::createOther(CreateDatabaseInfo const& info) { TRI_DEFER(vocbase->release()); - Result res = grantCurrentUser(info); + Result res = grantCurrentUser(info, 10); if (!res.ok()) { return res; } diff --git a/arangod/VocBase/Methods/Databases.h b/arangod/VocBase/Methods/Databases.h index 7ef44fd371..2e5c97a40b 100644 --- a/arangod/VocBase/Methods/Databases.h +++ b/arangod/VocBase/Methods/Databases.h @@ -73,7 +73,8 @@ struct Databases { static arangodb::Result drop(TRI_vocbase_t* systemVocbase, std::string const& dbName); private: - static arangodb::Result grantCurrentUser(CreateDatabaseInfo const& info); + /// @brief will retry for at most seconds + static arangodb::Result grantCurrentUser(CreateDatabaseInfo const& info, int64_t timeout); static arangodb::Result createCoordinator(CreateDatabaseInfo const& info); static arangodb::Result createOther(CreateDatabaseInfo const& info); };