diff --git a/bindings/node.js/client.cc b/bindings/node.js/client.cc index 687d0eb0..37d09b32 100644 --- a/bindings/node.js/client.cc +++ b/bindings/node.js/client.cc @@ -182,6 +182,17 @@ class Operation bool convert_maxmin(v8::Handle& _maxmin, int* maximize); + // 20 Sept 2015 - William Whitacre + // Patch against 1.8.1: Enable macaroon authorization. + + // Convert a v8 array of strings to a character pointer array. + bool convert_auth_context(v8::Handle &_value, + const char ***p_auth, size_t *p_auth_sz); + + // Set and clear the auth context using the hyperdex_client API. + bool set_auth_context(v8::Handle &_value); + bool clear_auth_context(); + bool build_string(const char* value, size_t value_sz, v8::Local& retval, v8::Local& error); @@ -275,6 +286,7 @@ class Operation uint64_t count; bool finished; void (Operation::*encode_return)(); + const char **m_auth; private: void inc() { ++m_ref; } @@ -845,6 +857,7 @@ Operation :: Operation(v8::Handle& c1, HyperDexClient* c2) , count(0) , finished(false) , encode_return() + , m_auth(NULL) , m_ref(0) , m_arena(hyperdex_ds_arena_create()) , m_client() @@ -871,6 +884,11 @@ Operation :: ~Operation() throw () hyperdex_client_destroy_attrs(attrs, attrs_sz); } + if (m_auth) + { + free((void *)m_auth); + } + if (description) { free((void*)description); @@ -1662,6 +1680,95 @@ Operation :: convert_maxmin(v8::Handle& _maxmin, return true; } +// 20 Sept 2015 - William Whitacre +// Patch against 1.8.1: Enable macaroon authorization. +bool +Operation :: convert_auth_context(v8::Handle &_value, + const char ***p_auth, size_t *p_auth_sz) +{ + // Make sure this is an array we've been passed. + if (!_value->IsArray()) + { + this->callback_error_message("auth must be specified as an array"); + return false; + } + + // Reference it as an array. + v8::Local arr = + v8::Local::New(_value.As()); + + // Allocate the pointer array for storing the authorization chain. + const size_t auth_sz = arr->Length(); + const char **auth = reinterpret_cast(malloc(auth_sz * sizeof(const char *))); + + // Loop through the array elements. + for (size_t i = 0; i < auth_sz; ++i) + { + // Retrieve array element at index i. + v8::Local _M = arr->Get(i); + + // Make sure it's actually a string and use the convert_cstring member + // function to copy the string. + if (_M.IsEmpty() || + !(_M->IsString() && this->convert_cstring(_M, &auth[i]))) + { + this->callback_error_message("auth must be an array of strings"); + return false; + } + } + + // Copy the resulting pointers to the return arguments. + *p_auth_sz = auth_sz; + *p_auth = auth; + + // Everything worked ok. + return true; +} + +bool +Operation :: set_auth_context(v8::Handle &_value) +{ + // Clear the authorization context if it's already been set (wierd). + this->clear_auth_context(); + size_t auth_sz; + + // Convert the authorization context object to an array of character + // pointers. + if (this->convert_auth_context(_value, &this->m_auth, &auth_sz)) + { + // Call hyperdex client to set the authorization context. + hyperdex_client_set_auth_context( + this->client->client(), + this->m_auth, auth_sz + ); + return true; + } + else + { + // Something went wrong during conversion! + return false; + } +} + +bool +Operation :: clear_auth_context() +{ + // Make sure the authorization context has been set. + if (this->m_auth != NULL) + { + // Call hyperdex client to clear the authorization context. + hyperdex_client_clear_auth_context(this->client->client()); + + // Free the array. + free((void *)this->m_auth); + this->m_auth = NULL; + } + + // this->m_auth is always null at this point, and if an array was there + // it was freed. + return true; +} + bool Operation :: build_string(const char* value, size_t value_sz, v8::Local& retval, diff --git a/bindings/node.js/client.definitions.cc b/bindings/node.js/client.definitions.cc index 5f1dabc3..92dd1e60 100644 --- a/bindings/node.js/client.definitions.cc +++ b/bindings/node.js/client.definitions.cc @@ -35,7 +35,10 @@ HyperDexClient :: asynccall__spacename_key__status_attributes(int64_t (*f)(struc v8::Local client_obj = args.This(); HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); e::intrusive_ptr op(new Operation(client_obj, client)); - v8::Local func = args[2].As(); + const size_t base_args_sz = 2; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); if (func.IsEmpty() || !func->IsFunction()) { @@ -44,6 +47,7 @@ HyperDexClient :: asynccall__spacename_key__status_attributes(int64_t (*f)(struc } if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char* in_space; v8::Local spacename = args[0]; if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); @@ -51,8 +55,15 @@ HyperDexClient :: asynccall__spacename_key__status_attributes(int64_t (*f)(struc size_t in_key_sz; v8::Local key = args[1]; if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_key, in_key_sz, &op->status, &op->attrs, &op->attrs_sz); + if (bDoAuth) op->clear_auth_context(); if (op->reqid < 0) { op->callback_error_from_status(); @@ -71,7 +82,10 @@ HyperDexClient :: asynccall__spacename_key_attributenames__status_attributes(int v8::Local client_obj = args.This(); HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); e::intrusive_ptr op(new Operation(client_obj, client)); - v8::Local func = args[3].As(); + const size_t base_args_sz = 3; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); if (func.IsEmpty() || !func->IsFunction()) { @@ -80,6 +94,7 @@ HyperDexClient :: asynccall__spacename_key_attributenames__status_attributes(int } if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char* in_space; v8::Local spacename = args[0]; if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); @@ -91,8 +106,15 @@ HyperDexClient :: asynccall__spacename_key_attributenames__status_attributes(int size_t in_attrnames_sz; v8::Local attributenames = args[2]; if (!op->convert_attributenames(attributenames, &in_attrnames, &in_attrnames_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_attrnames, in_attrnames_sz, &op->status, &op->attrs, &op->attrs_sz); + if (bDoAuth) op->clear_auth_context(); if (op->reqid < 0) { op->callback_error_from_status(); @@ -111,7 +133,10 @@ HyperDexClient :: asynccall__spacename_key_attributes__status(int64_t (*f)(struc v8::Local client_obj = args.This(); HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); e::intrusive_ptr op(new Operation(client_obj, client)); - v8::Local func = args[3].As(); + const size_t base_args_sz = 3; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); if (func.IsEmpty() || !func->IsFunction()) { @@ -120,6 +145,7 @@ HyperDexClient :: asynccall__spacename_key_attributes__status(int64_t (*f)(struc } if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char* in_space; v8::Local spacename = args[0]; if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); @@ -131,8 +157,15 @@ HyperDexClient :: asynccall__spacename_key_attributes__status(int64_t (*f)(struc size_t in_attrs_sz; v8::Local attributes = args[2]; if (!op->convert_attributes(attributes, &in_attrs, &in_attrs_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_attrs, in_attrs_sz, &op->status); + if (bDoAuth) op->clear_auth_context(); if (op->reqid < 0) { op->callback_error_from_status(); @@ -151,7 +184,10 @@ HyperDexClient :: asynccall__spacename_key_predicates_attributes__status(int64_t v8::Local client_obj = args.This(); HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); e::intrusive_ptr op(new Operation(client_obj, client)); - v8::Local func = args[4].As(); + const size_t base_args_sz = 4; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); if (func.IsEmpty() || !func->IsFunction()) { @@ -160,6 +196,7 @@ HyperDexClient :: asynccall__spacename_key_predicates_attributes__status(int64_t } if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char* in_space; v8::Local spacename = args[0]; if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); @@ -175,8 +212,15 @@ HyperDexClient :: asynccall__spacename_key_predicates_attributes__status(int64_t size_t in_attrs_sz; v8::Local attributes = args[3]; if (!op->convert_attributes(attributes, &in_attrs, &in_attrs_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_checks, in_checks_sz, in_attrs, in_attrs_sz, &op->status); + if (bDoAuth) op->clear_auth_context(); if (op->reqid < 0) { op->callback_error_from_status(); @@ -195,7 +239,10 @@ HyperDexClient :: asynccall__spacename_predicates_attributes__status_count(int64 v8::Local client_obj = args.This(); HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); e::intrusive_ptr op(new Operation(client_obj, client)); - v8::Local func = args[3].As(); + const size_t base_args_sz = 3; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); if (func.IsEmpty() || !func->IsFunction()) { @@ -204,6 +251,7 @@ HyperDexClient :: asynccall__spacename_predicates_attributes__status_count(int64 } if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char* in_space; v8::Local spacename = args[0]; if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); @@ -215,8 +263,15 @@ HyperDexClient :: asynccall__spacename_predicates_attributes__status_count(int64 size_t in_attrs_sz; v8::Local attributes = args[2]; if (!op->convert_attributes(attributes, &in_attrs, &in_attrs_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_checks, in_checks_sz, in_attrs, in_attrs_sz, &op->status, &op->count); + if (bDoAuth) op->clear_auth_context(); if (op->reqid < 0) { op->callback_error_from_status(); @@ -235,7 +290,10 @@ HyperDexClient :: asynccall__spacename_key__status(int64_t (*f)(struct hyperdex_ v8::Local client_obj = args.This(); HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); e::intrusive_ptr op(new Operation(client_obj, client)); - v8::Local func = args[2].As(); + const size_t base_args_sz = 2; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); if (func.IsEmpty() || !func->IsFunction()) { @@ -244,6 +302,7 @@ HyperDexClient :: asynccall__spacename_key__status(int64_t (*f)(struct hyperdex_ } if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char* in_space; v8::Local spacename = args[0]; if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); @@ -251,8 +310,15 @@ HyperDexClient :: asynccall__spacename_key__status(int64_t (*f)(struct hyperdex_ size_t in_key_sz; v8::Local key = args[1]; if (!op->convert_key(key, &in_key, &in_key_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_key, in_key_sz, &op->status); + if (bDoAuth) op->clear_auth_context(); if (op->reqid < 0) { op->callback_error_from_status(); @@ -271,7 +337,10 @@ HyperDexClient :: asynccall__spacename_key_predicates__status(int64_t (*f)(struc v8::Local client_obj = args.This(); HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); e::intrusive_ptr op(new Operation(client_obj, client)); - v8::Local func = args[3].As(); + const size_t base_args_sz = 3; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); if (func.IsEmpty() || !func->IsFunction()) { @@ -280,6 +349,7 @@ HyperDexClient :: asynccall__spacename_key_predicates__status(int64_t (*f)(struc } if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char* in_space; v8::Local spacename = args[0]; if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); @@ -291,8 +361,15 @@ HyperDexClient :: asynccall__spacename_key_predicates__status(int64_t (*f)(struc size_t in_checks_sz; v8::Local predicates = args[2]; if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_checks, in_checks_sz, &op->status); + if (bDoAuth) op->clear_auth_context(); if (op->reqid < 0) { op->callback_error_from_status(); @@ -311,7 +388,10 @@ HyperDexClient :: asynccall__spacename_predicates__status_count(int64_t (*f)(str v8::Local client_obj = args.This(); HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); e::intrusive_ptr op(new Operation(client_obj, client)); - v8::Local func = args[2].As(); + const size_t base_args_sz = 2; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); if (func.IsEmpty() || !func->IsFunction()) { @@ -320,6 +400,7 @@ HyperDexClient :: asynccall__spacename_predicates__status_count(int64_t (*f)(str } if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char* in_space; v8::Local spacename = args[0]; if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); @@ -327,8 +408,15 @@ HyperDexClient :: asynccall__spacename_predicates__status_count(int64_t (*f)(str size_t in_checks_sz; v8::Local predicates = args[1]; if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_checks, in_checks_sz, &op->status, &op->count); + if (bDoAuth) op->clear_auth_context(); if (op->reqid < 0) { op->callback_error_from_status(); @@ -347,7 +435,10 @@ HyperDexClient :: asynccall__spacename_key_mapattributes__status(int64_t (*f)(st v8::Local client_obj = args.This(); HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); e::intrusive_ptr op(new Operation(client_obj, client)); - v8::Local func = args[3].As(); + const size_t base_args_sz = 3; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); if (func.IsEmpty() || !func->IsFunction()) { @@ -356,6 +447,7 @@ HyperDexClient :: asynccall__spacename_key_mapattributes__status(int64_t (*f)(st } if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char* in_space; v8::Local spacename = args[0]; if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); @@ -367,8 +459,15 @@ HyperDexClient :: asynccall__spacename_key_mapattributes__status(int64_t (*f)(st size_t in_mapattrs_sz; v8::Local mapattributes = args[2]; if (!op->convert_mapattributes(mapattributes, &in_mapattrs, &in_mapattrs_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_mapattrs, in_mapattrs_sz, &op->status); + if (bDoAuth) op->clear_auth_context(); if (op->reqid < 0) { op->callback_error_from_status(); @@ -387,7 +486,10 @@ HyperDexClient :: asynccall__spacename_key_predicates_mapattributes__status(int6 v8::Local client_obj = args.This(); HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); e::intrusive_ptr op(new Operation(client_obj, client)); - v8::Local func = args[4].As(); + const size_t base_args_sz = 4; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); if (func.IsEmpty() || !func->IsFunction()) { @@ -396,6 +498,7 @@ HyperDexClient :: asynccall__spacename_key_predicates_mapattributes__status(int6 } if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char* in_space; v8::Local spacename = args[0]; if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); @@ -411,8 +514,15 @@ HyperDexClient :: asynccall__spacename_key_predicates_mapattributes__status(int6 size_t in_mapattrs_sz; v8::Local mapattributes = args[3]; if (!op->convert_mapattributes(mapattributes, &in_mapattrs, &in_mapattrs_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_key, in_key_sz, in_checks, in_checks_sz, in_mapattrs, in_mapattrs_sz, &op->status); + if (bDoAuth) op->clear_auth_context(); if (op->reqid < 0) { op->callback_error_from_status(); @@ -431,7 +541,10 @@ HyperDexClient :: asynccall__spacename_predicates_mapattributes__status_count(in v8::Local client_obj = args.This(); HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); e::intrusive_ptr op(new Operation(client_obj, client)); - v8::Local func = args[3].As(); + const size_t base_args_sz = 3; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); if (func.IsEmpty() || !func->IsFunction()) { @@ -440,6 +553,7 @@ HyperDexClient :: asynccall__spacename_predicates_mapattributes__status_count(in } if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char* in_space; v8::Local spacename = args[0]; if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); @@ -451,8 +565,15 @@ HyperDexClient :: asynccall__spacename_predicates_mapattributes__status_count(in size_t in_mapattrs_sz; v8::Local mapattributes = args[2]; if (!op->convert_mapattributes(mapattributes, &in_mapattrs, &in_mapattrs_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_checks, in_checks_sz, in_mapattrs, in_mapattrs_sz, &op->status, &op->count); + if (bDoAuth) op->clear_auth_context(); if (op->reqid < 0) { op->callback_error_from_status(); @@ -515,7 +636,10 @@ HyperDexClient :: asynccall__spacename_predicates__status_description(int64_t (* v8::Local client_obj = args.This(); HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj); e::intrusive_ptr op(new Operation(client_obj, client)); - v8::Local func = args[2].As(); + const size_t base_args_sz = 2; + const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1); + const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz; + v8::Local func = args[i_Func].As(); if (func.IsEmpty() || !func->IsFunction()) { @@ -524,6 +648,7 @@ HyperDexClient :: asynccall__spacename_predicates__status_description(int64_t (* } if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); } + const char* in_space; v8::Local spacename = args[0]; if (!op->convert_spacename(spacename, &in_space)) return scope.Close(v8::Undefined()); @@ -531,8 +656,15 @@ HyperDexClient :: asynccall__spacename_predicates__status_description(int64_t (* size_t in_checks_sz; v8::Local predicates = args[1]; if (!op->convert_predicates(predicates, &in_checks, &in_checks_sz)) return scope.Close(v8::Undefined()); + if (bDoAuth) + { + v8::Handle M = args[base_args_sz]; + if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); } + } + op->reqid = f(client->client(), in_space, in_checks, in_checks_sz, &op->status, &op->description); + if (bDoAuth) op->clear_auth_context(); if (op->reqid < 0) { op->callback_error_from_status(); diff --git a/bindings/node.js/package.json b/bindings/node.js/package.json index 50c1e2f9..311ece5c 100644 --- a/bindings/node.js/package.json +++ b/bindings/node.js/package.json @@ -1 +1,16 @@ -{"name": "hyperdex-client", "license": "BSD-3-Clause", "bugs": {"url": "https://github.com/rescrv/HyperDex/issues", "email": "support@hyperdex.org"}, "version": "0.0.3", "homepage": "http://hyperdex.org", "description": "Client bindings for HyperDex"} +{ + "name": "node-hyperdex-test", + "version": "0.0.0", + "description": "testing patch for node.js hyperdex-client authorization support", + "main": "test-patch.js", + "dependencies": { + "macaroons.js": "^0.3.5", + "when": "^3.7.3" + }, + "devDependencies": {}, + "scripts": { + "test": "node test-patch.js" + }, + "author": "NuMaya LLC.", + "license": "" +} diff --git a/bindings/nodejs.py b/bindings/nodejs.py index 832b2cb8..2d3c2e83 100644 --- a/bindings/nodejs.py +++ b/bindings/nodejs.py @@ -42,7 +42,7 @@ def generate_worker_declarations(xs, lib): continue if x.form is bindings.MicrotransactionCall: continue #TODO support microtransactions in NodeJS - + assert x.form in (bindings.AsyncCall, bindings.Iterator) fptr = bindings.c.generate_func_ptr(x, lib) yield 'static v8::Handle {0}({1}, const v8::Arguments& args);'.format(call, fptr) @@ -53,6 +53,8 @@ def generate_declaration(x): func = 'static v8::Handle {0}(const v8::Arguments& args);' return func.format(x.name) +# 20 Sept 2015 - William Whitacre +# Patch against 1.8.1: Enable macaroon authorization. def generate_worker_definitions(xs, lib): calls = set([]) for x in xs: @@ -70,14 +72,21 @@ def generate_worker_definitions(xs, lib): func += ' v8::Local client_obj = args.This();\n' func += ' HyperDexClient* client = node::ObjectWrap::Unwrap(client_obj);\n' func += ' e::intrusive_ptr op(new Operation(client_obj, client));\n' + wrap_auth_context, arg_count = False, len(x.args_in) if x.form == bindings.AsyncCall: - func += ' v8::Local func = args[{0}].As();\n'.format(len(x.args_in)) + func += ' const size_t base_args_sz = {0};\n'.format(arg_count) + func += ' const bool bDoAuth = ((size_t)args.Length() > base_args_sz + 1);\n' + func += ' const size_t i_Func = bDoAuth ? base_args_sz + 1 : base_args_sz;\n' + + func += ' v8::Local func = args[i_Func].As();\n' func += '\n if (func.IsEmpty() || !func->IsFunction())\n' func += ' {\n' func += ' v8::ThrowException(v8::String::New("Callback must be a function"));\n' func += ' return scope.Close(v8::Undefined());\n' func += ' }\n\n' - func += ' if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); }\n' + func += ' if (!op->set_callback(func)) { return scope.Close(v8::Undefined()); }\n\n' + + wrap_auth_context = True if x.form == bindings.Iterator: func += ' v8::Local func = args[{0}].As();\n'.format(len(x.args_in)) func += '\n if (func.IsEmpty() || !func->IsFunction())\n' @@ -92,14 +101,27 @@ def generate_worker_definitions(xs, lib): func += ' return scope.Close(v8::Undefined());\n' func += ' }\n\n' func += ' if (!op->set_callback(func, done)) { return scope.Close(v8::Undefined()); }\n' + + wrap_auth_context = False + for idx, arg in enumerate(x.args_in): for p, n in arg.args: func += ' ' + p + ' in_' + n + ';\n' args = ', '.join(['&in_' + n for p, n in arg.args]) func += ' v8::Local {0} = args[{1}];\n'.format(arg.__name__.lower(), idx) func += ' if (!op->convert_{0}({0}, {1})) return scope.Close(v8::Undefined());\n'.format(arg.__name__.lower(), args) + + if wrap_auth_context: + func += ' if (bDoAuth)\n {\n' + func += ' v8::Handle M = args[base_args_sz];\n' + func += ' if (!op->set_auth_context(M)) { return scope.Close(v8::Undefined()); }\n }\n\n' + func += ' op->reqid = f(client->client(), {0}, {1});\n\n'.format(', '.join(['in_' + n for p, n in sum([list(a.args) for a in x.args_in], [])]), ', '.join(['&op->' + n for p, n in sum([list(a.args) for a in x.args_out], [])])) + + if wrap_auth_context: + func += ' if (bDoAuth) op->clear_auth_context();\n' + func += ' if (op->reqid < 0)\n {\n' func += ' op->callback_error_from_status();\n' func += ' return scope.Close(v8::Undefined());\n'