1
0
Fork 0

added CURRENT_USER function for AQL

This commit is contained in:
Jan Steemann 2014-05-02 12:00:39 +02:00
parent f3d2e28379
commit 02a532a122
10 changed files with 162 additions and 7 deletions

View File

@ -1,6 +1,13 @@
v2.1.0 (XXXX-XX-XX)
-------------------
* added AQL CURRENT_USER() function
This function returns the current user from an AQL query. The current user is the
username that was specified in the `Authorization` HTTP header of the request. If
authentication is turned off or the query was executed outside a request context,
the function will return `null`.
* fixed issue #796: Searching with newline chars broken?
fixed slightly different handling of backslash escape characters in a few

View File

@ -1751,6 +1751,11 @@ function categories:
- @FN{COLLECTIONS()}: Returns a list of collections. Each collection is returned as a document
with attributes `name` and `_id`
- @FN{CURRENT_USER()}: Returns the name of the current user. The current user is the user
account name that was specified in the `Authorization` HTTP header of the request. It will
only be populated if authentication on the server is turned on, and if the query was executed
inside a request context. Otherwise, the return value of this function will be `null`.
- @FN{DOCUMENT(@FA{collection}, @FA{id})}: Returns the document which is uniquely identified by
the @FA{id}. ArangoDB will try to find the document using the `_id` value of the document
in the specified collection. If there is a mismatch between the @FA{collection} passed and

View File

@ -719,6 +719,7 @@ TRI_associative_pointer_t* TRI_CreateFunctionsAql (void) {
REGISTER_FUNCTION("FIRST_DOCUMENT", "FIRST_DOCUMENT", true, false, ".|+", NULL);
REGISTER_FUNCTION("PARSE_IDENTIFIER", "PARSE_IDENTIFIER", true, false, ".", NULL);
REGISTER_FUNCTION("SKIPLIST", "SKIPLIST_QUERY", false, false, "h,a|n,n", NULL);
REGISTER_FUNCTION("CURRENT_USER", "CURRENT_USER", false, false, "", NULL);
if (! result) {
TRI_FreeFunctionsAql(functions);

View File

@ -668,12 +668,12 @@ static TRI_action_result_t ExecuteActionVocbase (TRI_vocbase_t* vocbase,
v8::Handle<v8::Function> callback,
HttpRequest* request) {
TRI_action_result_t result;
TRI_v8_global_t const* v8g;
TRI_v8_global_t* v8g;
v8::HandleScope scope;
v8::TryCatch tryCatch;
v8g = (TRI_v8_global_t const*) isolate->GetData();
v8g = static_cast<TRI_v8_global_t*>(isolate->GetData());
v8::Handle<v8::Object> req = RequestCppToV8(v8g, request);
@ -698,12 +698,22 @@ static TRI_action_result_t ExecuteActionVocbase (TRI_vocbase_t* vocbase,
// copy full path
req->Set(v8g->PathKey, v8::String::New(path.c_str(), (int) path.size()));
// execute the callback
// create the response object
v8::Handle<v8::Object> res = v8::Object::New();
// register request & response in the context
v8g->_currentRequest = req;
v8g->_currentResponse = res;
// execute the callback
v8::Handle<v8::Value> args[2] = { req, res };
callback->Call(callback, 2, args);
// invalidate request / response objects
v8g->_currentRequest = v8::Undefined();
v8g->_currentResponse = v8::Undefined();
// convert the result
result.isValid = true;
@ -859,6 +869,40 @@ static v8::Handle<v8::Value> JS_ExecuteGlobalContextFunction (v8::Arguments cons
return scope.Close(v8::Undefined());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get the current request
///
/// @FUN{internal.getCurrentRequest()}
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_GetCurrentRequest (v8::Arguments const& argv) {
v8::HandleScope scope;
if (argv.Length() != 0) {
TRI_V8_EXCEPTION_USAGE(scope, "getCurrentRequest()");
}
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
return scope.Close(v8g->_currentRequest);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get the current response
///
/// @FUN{internal.getCurrentRequest()}
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_GetCurrentResponse (v8::Arguments const& argv) {
v8::HandleScope scope;
if (argv.Length() != 0) {
TRI_V8_EXCEPTION_USAGE(scope, "getCurrentResponse()");
}
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
return scope.Close(v8g->_currentResponse);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief function to test sharding
///
@ -884,8 +928,7 @@ class CallbackTest : public ClusterCommCallback {
static v8::Handle<v8::Value> JS_ClusterTest (v8::Arguments const& argv) {
v8::HandleScope scope;
TRI_v8_global_t* v8g = (TRI_v8_global_t*)
v8::Isolate::GetCurrent()->GetData();
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
if (argv.Length() != 9) {
TRI_V8_EXCEPTION_USAGE(scope,
@ -1275,6 +1318,8 @@ void TRI_InitV8Actions (v8::Handle<v8::Context> context,
TRI_AddGlobalFunctionVocbase(context, "SYS_DEFINE_ACTION", JS_DefineAction);
TRI_AddGlobalFunctionVocbase(context, "SYS_EXECUTE_GLOBAL_CONTEXT_FUNCTION", JS_ExecuteGlobalContextFunction);
TRI_AddGlobalFunctionVocbase(context, "SYS_GET_CURRENT_REQUEST", JS_GetCurrentRequest);
TRI_AddGlobalFunctionVocbase(context, "SYS_GET_CURRENT_RESPONSE", JS_GetCurrentResponse);
#ifdef TRI_ENABLE_CLUSTER
TRI_AddGlobalFunctionVocbase(context, "SYS_CLUSTER_TEST", JS_ClusterTest, true);

View File

@ -7,7 +7,8 @@
REPLICATION_SYNCHRONISE, REPLICATION_SERVER_ID, CONFIGURE_ENDPOINT, REMOVE_ENDPOINT, LIST_ENDPOINTS,
SYS_BASE64DECODE, SYS_BASE64ENCODE, SYS_DEBUG_SEGFAULT,
SYS_DEBUG_CAN_USE_FAILAT, SYS_DEBUG_SET_FAILAT, SYS_DEBUG_REMOVE_FAILAT, SYS_DEBUG_CLEAR_FAILAT,
SYS_DOWNLOAD, SYS_EXECUTE, SYS_LOAD, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STATISTICS,
SYS_DOWNLOAD, SYS_EXECUTE, SYS_GET_CURRENT_REQUEST, SYS_GET_CURRENT_RESPONSE,
SYS_LOAD, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STATISTICS,
SYS_RAND, SYS_SERVER_STATISTICS, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER,
SYS_SHA256, SYS_SLEEP, SYS_WAIT, SYS_PARSE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, SYS_LOG,
SYS_GEN_RANDOM_NUMBERS, SYS_GEN_RANDOM_ALPHA_NUMBERS, SYS_GEN_RANDOM_SALT, SYS_CREATE_NONCE,
@ -481,6 +482,24 @@
delete SYS_EXECUTE;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief getCurrentRequest
////////////////////////////////////////////////////////////////////////////////
if (typeof SYS_GET_CURRENT_REQUEST !== "undefined") {
exports.getCurrentRequest = SYS_GET_CURRENT_REQUEST;
delete SYS_GET_CURRENT_REQUEST;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief getCurrentResponse
////////////////////////////////////////////////////////////////////////////////
if (typeof SYS_GET_CURRENT_RESPONSE !== "undefined") {
exports.getCurrentResponse = SYS_GET_CURRENT_RESPONSE;
delete SYS_GET_CURRENT_RESPONSE;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief extend
////////////////////////////////////////////////////////////////////////////////

View File

@ -7,7 +7,8 @@
REPLICATION_SYNCHRONISE, REPLICATION_SERVER_ID, CONFIGURE_ENDPOINT, REMOVE_ENDPOINT, LIST_ENDPOINTS,
SYS_BASE64DECODE, SYS_BASE64ENCODE, SYS_DEBUG_SEGFAULT,
SYS_DEBUG_CAN_USE_FAILAT, SYS_DEBUG_SET_FAILAT, SYS_DEBUG_REMOVE_FAILAT, SYS_DEBUG_CLEAR_FAILAT,
SYS_DOWNLOAD, SYS_EXECUTE, SYS_LOAD, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STATISTICS,
SYS_DOWNLOAD, SYS_EXECUTE, SYS_GET_CURRENT_REQUEST, SYS_GET_CURRENT_RESPONSE,
SYS_LOAD, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STATISTICS,
SYS_RAND, SYS_SERVER_STATISTICS, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER,
SYS_SHA256, SYS_SLEEP, SYS_WAIT, SYS_PARSE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, SYS_LOG,
SYS_GEN_RANDOM_NUMBERS, SYS_GEN_RANDOM_ALPHA_NUMBERS, SYS_GEN_RANDOM_SALT, SYS_CREATE_NONCE,
@ -481,6 +482,24 @@
delete SYS_EXECUTE;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief getCurrentRequest
////////////////////////////////////////////////////////////////////////////////
if (typeof SYS_GET_CURRENT_REQUEST !== "undefined") {
exports.getCurrentRequest = SYS_GET_CURRENT_REQUEST;
delete SYS_GET_CURRENT_REQUEST;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief getCurrentResponse
////////////////////////////////////////////////////////////////////////////////
if (typeof SYS_GET_CURRENT_RESPONSE !== "undefined") {
exports.getCurrentResponse = SYS_GET_CURRENT_RESPONSE;
delete SYS_GET_CURRENT_RESPONSE;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief extend
////////////////////////////////////////////////////////////////////////////////

View File

@ -3678,6 +3678,24 @@ function SLEEP (duration) {
INTERNAL.sleep(duration);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the current user
/// note: this might be null if the query is not executed in a context that
/// has a user
////////////////////////////////////////////////////////////////////////////////
function CURRENT_USER () {
"use strict";
var req = INTERNAL.getCurrentRequest();
if (typeof req === 'object') {
return req.user;
}
return null;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief always fail
///
@ -4368,6 +4386,7 @@ exports.MERGE_RECURSIVE = MERGE_RECURSIVE;
exports.MATCHES = MATCHES;
exports.PASSTHRU = PASSTHRU;
exports.SLEEP = SLEEP;
exports.CURRENT_USER = CURRENT_USER;
exports.FAIL = FAIL;
exports.reload = reloadUserFunctions;

View File

@ -3753,6 +3753,32 @@ function ahuacatlFunctionsTestSuite () {
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN STDDEV_POPULATION({ })");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test current user function
////////////////////////////////////////////////////////////////////////////////
testCurrentUser : function () {
var actual = getQueryResults("RETURN CURRENT_USER()");
// there is no current user in the non-request context
assertEqual([ null ], actual);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test sleep function
////////////////////////////////////////////////////////////////////////////////
testSleep : function () {
var start = require("internal").time();
var actual = getQueryResults("LET a = SLEEP(2) RETURN 1");
var diff = Math.round(require("internal").time() - start, 1);
assertEqual([ 1 ], actual);
// allow some tolerance for the time diff
assertTrue(diff >= 1.5 && diff <= 2.5);
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test non-existing functions
////////////////////////////////////////////////////////////////////////////////

View File

@ -133,6 +133,8 @@ TRI_v8_global_s::TRI_v8_global_s (v8::Isolate* isolate)
_RevKey(),
_ToKey(),
_currentRequest(0),
_currentResponse(0),
_currentTransaction(0),
_server(0),
_vocbase(0),

View File

@ -730,6 +730,18 @@ typedef struct TRI_v8_global_s {
// --SECTION-- DATABASE
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief currently request object (might be invalid!)
////////////////////////////////////////////////////////////////////////////////
v8::Handle<v8::Value> _currentRequest;
////////////////////////////////////////////////////////////////////////////////
/// @brief currently response object (might be invalid!)
////////////////////////////////////////////////////////////////////////////////
v8::Handle<v8::Value> _currentResponse;
////////////////////////////////////////////////////////////////////////////////
/// @brief currently running transaction
////////////////////////////////////////////////////////////////////////////////