From 16e12ca728c58651be57a660dec8734762578189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ante=20Pu=C5=A1i=C4=87?= Date: Mon, 20 May 2024 16:13:05 +0200 Subject: [PATCH 01/10] Add the schema and credentials parameters --- include/mgclient.h | 4 ++++ mgclient_cpp/include/mgclient.hpp | 11 +++++++---- src/mgclient.c | 22 ++++++++++++++++++---- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/include/mgclient.h b/include/mgclient.h index b916a6c..b1de875 100644 --- a/include/mgclient.h +++ b/include/mgclient.h @@ -1233,10 +1233,14 @@ MGCLIENT_EXPORT void mg_session_params_set_host(mg_session_params *, const char *host); MGCLIENT_EXPORT void mg_session_params_set_port(mg_session_params *, uint16_t port); +MGCLIENT_EXPORT void mg_session_params_set_scheme(mg_session_params *, + const char *scheme); MGCLIENT_EXPORT void mg_session_params_set_username(mg_session_params *, const char *username); MGCLIENT_EXPORT void mg_session_params_set_password(mg_session_params *, const char *password); +MGCLIENT_EXPORT void mg_session_params_set_credentials(mg_session_params *, + const char *credentials); MGCLIENT_EXPORT void mg_session_params_set_user_agent(mg_session_params *, const char *user_agent); MGCLIENT_EXPORT void mg_session_params_set_sslmode(mg_session_params *, diff --git a/mgclient_cpp/include/mgclient.hpp b/mgclient_cpp/include/mgclient.hpp index 241fee6..a4d155e 100644 --- a/mgclient_cpp/include/mgclient.hpp +++ b/mgclient_cpp/include/mgclient.hpp @@ -57,8 +57,10 @@ class Client { struct Params { std::string host = "127.0.0.1"; uint16_t port = 7687; + std::string scheme = "basic"; std::string username = ""; std::string password = ""; + std::string credentials = ""; bool use_ssl = false; std::string user_agent = "mgclient++/" + std::string(mg_client_version()); }; @@ -150,10 +152,14 @@ inline std::unique_ptr Client::Connect(const Client::Params ¶ms) { } mg_session_params_set_host(mg_params, params.host.c_str()); mg_session_params_set_port(mg_params, params.port); + mg_session_params_set_scheme(mg_params, params.scheme.c_str()); if (!params.username.empty()) { mg_session_params_set_username(mg_params, params.username.c_str()); mg_session_params_set_password(mg_params, params.password.c_str()); } + if (!params.credentials.empty()) { + mg_session_params_set_credentials(mg_params, params.credentials.c_str()); + } mg_session_params_set_user_agent(mg_params, params.user_agent.c_str()); mg_session_params_set_sslmode( mg_params, params.use_ssl ? MG_SSLMODE_REQUIRE : MG_SSLMODE_DISABLE); @@ -255,10 +261,7 @@ inline std::optional> Client::FetchOne() { return values; } -inline void Client::DiscardAll() { - while (FetchOne()) - ; -} +inline void Client::DiscardAll() { while (FetchOne()); } inline std::optional>> Client::FetchAll() { std::vector> data; diff --git a/src/mgclient.c b/src/mgclient.c index df661f7..b6d5231 100644 --- a/src/mgclient.c +++ b/src/mgclient.c @@ -67,8 +67,10 @@ typedef struct mg_session_params { const char *address; const char *host; uint16_t port; + const char *scheme; const char *username; const char *password; + const char *credentials; const char *user_agent; enum mg_sslmode sslmode; const char *sslcert; @@ -118,6 +120,11 @@ void mg_session_params_set_port(mg_session_params *params, uint16_t port) { params->port = port; } +void mg_session_params_set_scheme(mg_session_params *params, + const char *scheme) { + params->scheme = scheme; +} + void mg_session_params_set_username(mg_session_params *params, const char *username) { params->username = username; @@ -128,6 +135,11 @@ void mg_session_params_set_password(mg_session_params *params, params->password = password; } +void mg_session_params_set_credentials(mg_session_params *params, + const char *credentials) { + params->credentials = credentials; +} + void mg_session_params_set_user_agent(mg_session_params *params, const char *user_agent) { params->user_agent = user_agent; @@ -364,8 +376,9 @@ int mg_bolt_init_v1(mg_session *session, const mg_session_params *params) { return status; } -static mg_map *build_hello_extra(const char *user_agent, const char *username, - const char *password) { +static mg_map *build_hello_extra(const char *user_agent, const char *scheme, + const char *username, const char *password, + const char *credentials) { mg_map *extra = mg_map_make_empty(4); if (!extra) { return NULL; @@ -379,7 +392,7 @@ static mg_map *build_hello_extra(const char *user_agent, const char *username, } } - assert((username && password) || (!username && !password)); + // TODO: support custom schemas if (username) { mg_value *scheme = mg_value_make_string("basic"); if (!scheme || mg_map_insert_unsafe(extra, "scheme", scheme) != 0) { @@ -412,7 +425,8 @@ static mg_map *build_hello_extra(const char *user_agent, const char *username, int mg_bolt_init_v4(mg_session *session, const mg_session_params *params) { mg_map *extra = - build_hello_extra(params->user_agent, params->username, params->password); + build_hello_extra(params->user_agent, params->scheme, params->username, + params->password, params->credentials); if (!extra) { return MG_ERROR_OOM; } From 0cc6927939cdd21e422dc4df4652bc84c4eeb636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ante=20Pu=C5=A1i=C4=87?= Date: Wed, 29 May 2024 15:18:19 +0200 Subject: [PATCH 02/10] Make custom auth logic simpler & conform to Bolt message requirements --- include/mgclient.h | 2 -- mgclient_cpp/include/mgclient.hpp | 6 ++-- src/mgclient.c | 46 +++++++++++++++++-------------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/include/mgclient.h b/include/mgclient.h index b1de875..51b24b0 100644 --- a/include/mgclient.h +++ b/include/mgclient.h @@ -1239,8 +1239,6 @@ MGCLIENT_EXPORT void mg_session_params_set_username(mg_session_params *, const char *username); MGCLIENT_EXPORT void mg_session_params_set_password(mg_session_params *, const char *password); -MGCLIENT_EXPORT void mg_session_params_set_credentials(mg_session_params *, - const char *credentials); MGCLIENT_EXPORT void mg_session_params_set_user_agent(mg_session_params *, const char *user_agent); MGCLIENT_EXPORT void mg_session_params_set_sslmode(mg_session_params *, diff --git a/mgclient_cpp/include/mgclient.hpp b/mgclient_cpp/include/mgclient.hpp index a4d155e..92f6ceb 100644 --- a/mgclient_cpp/include/mgclient.hpp +++ b/mgclient_cpp/include/mgclient.hpp @@ -60,7 +60,6 @@ class Client { std::string scheme = "basic"; std::string username = ""; std::string password = ""; - std::string credentials = ""; bool use_ssl = false; std::string user_agent = "mgclient++/" + std::string(mg_client_version()); }; @@ -155,10 +154,9 @@ inline std::unique_ptr Client::Connect(const Client::Params ¶ms) { mg_session_params_set_scheme(mg_params, params.scheme.c_str()); if (!params.username.empty()) { mg_session_params_set_username(mg_params, params.username.c_str()); - mg_session_params_set_password(mg_params, params.password.c_str()); } - if (!params.credentials.empty()) { - mg_session_params_set_credentials(mg_params, params.credentials.c_str()); + if (!params.password.empty()) { + mg_session_params_set_password(mg_params, params.password.c_str()); } mg_session_params_set_user_agent(mg_params, params.user_agent.c_str()); mg_session_params_set_sslmode( diff --git a/src/mgclient.c b/src/mgclient.c index b6d5231..f2f9f90 100644 --- a/src/mgclient.c +++ b/src/mgclient.c @@ -70,7 +70,6 @@ typedef struct mg_session_params { const char *scheme; const char *username; const char *password; - const char *credentials; const char *user_agent; enum mg_sslmode sslmode; const char *sslcert; @@ -135,11 +134,6 @@ void mg_session_params_set_password(mg_session_params *params, params->password = password; } -void mg_session_params_set_credentials(mg_session_params *params, - const char *credentials) { - params->credentials = credentials; -} - void mg_session_params_set_user_agent(mg_session_params *params, const char *user_agent) { params->user_agent = user_agent; @@ -377,8 +371,7 @@ int mg_bolt_init_v1(mg_session *session, const mg_session_params *params) { } static mg_map *build_hello_extra(const char *user_agent, const char *scheme, - const char *username, const char *password, - const char *credentials) { + const char *username, const char *password) { mg_map *extra = mg_map_make_empty(4); if (!extra) { return NULL; @@ -392,41 +385,52 @@ static mg_map *build_hello_extra(const char *user_agent, const char *scheme, } } - // TODO: support custom schemas - if (username) { - mg_value *scheme = mg_value_make_string("basic"); - if (!scheme || mg_map_insert_unsafe(extra, "scheme", scheme) != 0) { + // The "basic" scheme requires a username and a password in the HELLO message. + // Other schemes (save for "kerberos", which is not supported by Memgraph) do + // not have such requirements: + // https://neo4j.com/docs/bolt/current/bolt/message/#messages-hello + // https://neo4j.com/docs/bolt/current/bolt/message/#messages-logon + if (scheme && strcmp(scheme, "basic")) { + assert(username && password); + } + + if (!username && !password) { + mg_value *scheme_ = mg_value_make_string("none"); + if (!scheme_ || mg_map_insert_unsafe(extra, "scheme", scheme_) != 0) { goto cleanup; } + return extra; + } + mg_value *scheme_ = mg_value_make_string(scheme ? scheme : "basic"); + if (!scheme_ || mg_map_insert_unsafe(extra, "scheme", scheme_) != 0) { + goto cleanup; + } + + if (username) { mg_value *principal = mg_value_make_string(username); if (!principal || mg_map_insert_unsafe(extra, "principal", principal)) { goto cleanup; } + } + if (password) { mg_value *credentials = mg_value_make_string(password); if (!credentials || mg_map_insert_unsafe(extra, "credentials", credentials)) { goto cleanup; } - } else { - mg_value *scheme = mg_value_make_string("none"); - if (!scheme || mg_map_insert_unsafe(extra, "scheme", scheme) != 0) { - goto cleanup; - } } return extra; - cleanup: mg_map_destroy(extra); return NULL; } int mg_bolt_init_v4(mg_session *session, const mg_session_params *params) { - mg_map *extra = - build_hello_extra(params->user_agent, params->scheme, params->username, - params->password, params->credentials); + mg_map *extra = build_hello_extra(params->user_agent, params->scheme, + params->username, params->password); if (!extra) { return MG_ERROR_OOM; } From 192c9ed1c25a2f40a6d078a4f7c0ed13e1d63789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ante=20Pu=C5=A1i=C4=87?= Date: Mon, 10 Jun 2024 17:47:52 +0200 Subject: [PATCH 03/10] Fix clang-tidy and build error --- mgclient_cpp/include/mgclient.hpp | 4 +++- tests/integration/basic_cpp.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mgclient_cpp/include/mgclient.hpp b/mgclient_cpp/include/mgclient.hpp index 92f6ceb..363a0f1 100644 --- a/mgclient_cpp/include/mgclient.hpp +++ b/mgclient_cpp/include/mgclient.hpp @@ -259,7 +259,9 @@ inline std::optional> Client::FetchOne() { return values; } -inline void Client::DiscardAll() { while (FetchOne()); } +inline void Client::DiscardAll() { + while (FetchOne()); +} inline std::optional>> Client::FetchAll() { std::vector> data; diff --git a/tests/integration/basic_cpp.cpp b/tests/integration/basic_cpp.cpp index b5ff5a8..adc9264 100644 --- a/tests/integration/basic_cpp.cpp +++ b/tests/integration/basic_cpp.cpp @@ -35,7 +35,7 @@ class MemgraphConnection : public ::testing::Test { client = mg::Client::Connect( {GetEnvOrDefault("MEMGRAPH_HOST", "127.0.0.1"), - GetEnvOrDefault("MEMGRAPH_PORT", 7687), "", "", + GetEnvOrDefault("MEMGRAPH_PORT", 7687), "basic", "", "", GetEnvOrDefault("MEMGRAPH_SSLMODE", false), ""}); ASSERT_TRUE(client); From 96aec590741d3b997876ce427be0a358334e439d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ante=20Pu=C5=A1i=C4=87?= Date: Mon, 10 Jun 2024 17:53:55 +0200 Subject: [PATCH 04/10] Comply with clang-tidy --- mgclient_cpp/include/mgclient.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mgclient_cpp/include/mgclient.hpp b/mgclient_cpp/include/mgclient.hpp index 363a0f1..e02cb53 100644 --- a/mgclient_cpp/include/mgclient.hpp +++ b/mgclient_cpp/include/mgclient.hpp @@ -260,7 +260,8 @@ inline std::optional> Client::FetchOne() { } inline void Client::DiscardAll() { - while (FetchOne()); + while (FetchOne()) + ; } inline std::optional>> Client::FetchAll() { From 6d2a046a7f473a5f522a0547d2d73cf283ae539f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ante=20Pu=C5=A1i=C4=87?= Date: Mon, 10 Jun 2024 17:56:41 +0200 Subject: [PATCH 05/10] Remove whitespace --- mgclient_cpp/include/mgclient.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mgclient_cpp/include/mgclient.hpp b/mgclient_cpp/include/mgclient.hpp index e02cb53..fef710b 100644 --- a/mgclient_cpp/include/mgclient.hpp +++ b/mgclient_cpp/include/mgclient.hpp @@ -259,7 +259,7 @@ inline std::optional> Client::FetchOne() { return values; } -inline void Client::DiscardAll() { +inline void Client::DiscardAll() { while (FetchOne()) ; } From 55de52ea73633a2f1aaa67de3a570edafe42f7b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ante=20Pu=C5=A1i=C4=87?= Date: Tue, 18 Jun 2024 19:21:21 +0200 Subject: [PATCH 06/10] Fix logic --- src/mgclient.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mgclient.c b/src/mgclient.c index f2f9f90..16db7d0 100644 --- a/src/mgclient.c +++ b/src/mgclient.c @@ -390,7 +390,7 @@ static mg_map *build_hello_extra(const char *user_agent, const char *scheme, // not have such requirements: // https://neo4j.com/docs/bolt/current/bolt/message/#messages-hello // https://neo4j.com/docs/bolt/current/bolt/message/#messages-logon - if (scheme && strcmp(scheme, "basic")) { + if (scheme && strcmp(scheme, "basic") == 0) { assert(username && password); } From adeaa28ca715d3303655c48e78b37b2e5f4f4acc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ante=20Pu=C5=A1i=C4=87?= Date: Tue, 18 Jun 2024 19:21:42 +0200 Subject: [PATCH 07/10] Clarify comment --- src/mgclient.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mgclient.c b/src/mgclient.c index 16db7d0..013345c 100644 --- a/src/mgclient.c +++ b/src/mgclient.c @@ -385,9 +385,9 @@ static mg_map *build_hello_extra(const char *user_agent, const char *scheme, } } - // The "basic" scheme requires a username and a password in the HELLO message. - // Other schemes (save for "kerberos", which is not supported by Memgraph) do - // not have such requirements: + // The "basic" scheme requires a username and a password/credential within the + // HELLO message. Other schemes (save for "kerberos", which is not supported + // by Memgraph) do not have such requirements: // https://neo4j.com/docs/bolt/current/bolt/message/#messages-hello // https://neo4j.com/docs/bolt/current/bolt/message/#messages-logon if (scheme && strcmp(scheme, "basic") == 0) { From 263a84f19d2cb3b169dbf0b3fcd2a9f98d82f2d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ante=20Pu=C5=A1i=C4=87?= Date: Tue, 18 Jun 2024 19:21:58 +0200 Subject: [PATCH 08/10] Add test while avoiding code repetition --- tests/client.cpp | 204 ++++++++++++++++++----------------------------- 1 file changed, 77 insertions(+), 127 deletions(-) diff --git a/tests/client.cpp b/tests/client.cpp index 59c3839..6744f46 100644 --- a/tests/client.cpp +++ b/tests/client.cpp @@ -508,76 +508,73 @@ TEST_F(ConnectTest, Success) { ASSERT_MEMORY_OK(); } -TEST_F(ConnectTest, Success_v4) { - RunServer([](int sockfd) { - // Perform handshake. - { - char handshake[20]; - ASSERT_EQ(RecvData(sockfd, handshake, 20), 0); - ASSERT_EQ(std::string(handshake, 4), "\x60\x60\xB0\x17"s); - ASSERT_EQ(std::string(handshake + 4, 4), "\x00\x00\x01\x04"s); - ASSERT_EQ(std::string(handshake + 8, 4), "\x00\x00\x00\x01"s); - ASSERT_EQ(std::string(handshake + 12, 4), "\x00\x00\x00\x00"s); - ASSERT_EQ(std::string(handshake + 16, 4), "\x00\x00\x00\x00"s); +auto run_v4_server_success = [](int sockfd) { + // Perform handshake. + { + char handshake[20]; + ASSERT_EQ(RecvData(sockfd, handshake, 20), 0); + ASSERT_EQ(std::string(handshake, 4), "\x60\x60\xB0\x17"s); + ASSERT_EQ(std::string(handshake + 4, 4), "\x00\x00\x01\x04"s); + ASSERT_EQ(std::string(handshake + 8, 4), "\x00\x00\x00\x01"s); + ASSERT_EQ(std::string(handshake + 12, 4), "\x00\x00\x00\x00"s); + ASSERT_EQ(std::string(handshake + 16, 4), "\x00\x00\x00\x00"s); - uint32_t version = htobe32(0x0104); - ASSERT_EQ(SendData(sockfd, (char *)&version, 4), 0); - } + uint32_t version = htobe32(1); + ASSERT_EQ(SendData(sockfd, (char *)&version, 4), 0); + } - mg_session *session = mg_session_init(&mg_system_allocator); - ASSERT_TRUE(session); - session->version = 4; - mg_raw_transport_init(sockfd, (mg_raw_transport **)&session->transport, - &mg_system_allocator); + mg_session *session = mg_session_init(&mg_system_allocator); + ASSERT_TRUE(session); + session->version = 1; + mg_raw_transport_init(sockfd, (mg_raw_transport **)&session->transport, + &mg_system_allocator); - // Read HELLO message. + // Read INIT message. + { + mg_message *message; + ASSERT_EQ(mg_session_receive_message(session), 0); + ASSERT_EQ(mg_session_read_bolt_message(session, &message), 0); + ASSERT_EQ(message->type, MG_MESSAGE_TYPE_INIT); + + mg_message_init *msg_init = message->init_v; + EXPECT_EQ( + std::string(msg_init->client_name->data, msg_init->client_name->size), + MG_USER_AGENT); { - mg_message *message; - ASSERT_EQ(mg_session_receive_message(session), 0); - ASSERT_EQ(mg_session_read_bolt_message(session, &message), 0); - ASSERT_EQ(message->type, MG_MESSAGE_TYPE_HELLO); - - mg_message_hello *msg_hello = message->hello_v; - { - ASSERT_EQ(mg_map_size(msg_hello->extra), 4u); - - const mg_value *user_agent_val = - mg_map_at(msg_hello->extra, "user_agent"); - ASSERT_TRUE(user_agent_val); - ASSERT_EQ(mg_value_get_type(user_agent_val), MG_VALUE_TYPE_STRING); - const mg_string *user_agent = mg_value_string(user_agent_val); - ASSERT_EQ(std::string(user_agent->data, user_agent->size), - MG_USER_AGENT); - - const mg_value *scheme_val = mg_map_at(msg_hello->extra, "scheme"); - ASSERT_TRUE(scheme_val); - ASSERT_EQ(mg_value_get_type(scheme_val), MG_VALUE_TYPE_STRING); - const mg_string *scheme = mg_value_string(scheme_val); - ASSERT_EQ(std::string(scheme->data, scheme->size), "basic"); - - const mg_value *principal_val = - mg_map_at(msg_hello->extra, "principal"); - ASSERT_TRUE(principal_val); - ASSERT_EQ(mg_value_get_type(principal_val), MG_VALUE_TYPE_STRING); - const mg_string *principal = mg_value_string(principal_val); - ASSERT_EQ(std::string(principal->data, principal->size), "user"); + ASSERT_EQ(mg_map_size(msg_init->auth_token), 3u); + + const mg_value *scheme_val = mg_map_at(msg_init->auth_token, "scheme"); + ASSERT_TRUE(scheme_val); + ASSERT_EQ(mg_value_get_type(scheme_val), MG_VALUE_TYPE_STRING); + const mg_string *scheme = mg_value_string(scheme_val); + ASSERT_EQ(std::string(scheme->data, scheme->size), "basic"); + + const mg_value *principal_val = + mg_map_at(msg_init->auth_token, "principal"); + ASSERT_TRUE(principal_val); + ASSERT_EQ(mg_value_get_type(principal_val), MG_VALUE_TYPE_STRING); + const mg_string *principal = mg_value_string(principal_val); + ASSERT_EQ(std::string(principal->data, principal->size), "user"); + + const mg_value *credentials_val = + mg_map_at(msg_init->auth_token, "credentials"); + ASSERT_TRUE(credentials_val); + ASSERT_EQ(mg_value_get_type(credentials_val), MG_VALUE_TYPE_STRING); + const mg_string *credentials = mg_value_string(credentials_val); + ASSERT_EQ(std::string(credentials->data, credentials->size), "pass"); + } + + mg_message_destroy_ca(message, session->decoder_allocator); + } - const mg_value *credentials_val = - mg_map_at(msg_hello->extra, "credentials"); - ASSERT_TRUE(credentials_val); - ASSERT_EQ(mg_value_get_type(credentials_val), MG_VALUE_TYPE_STRING); - const mg_string *credentials = mg_value_string(credentials_val); - ASSERT_EQ(std::string(credentials->data, credentials->size), "pass"); - } + // Send SUCCESS message. + ASSERT_EQ(mg_session_send_success_message(session, &mg_empty_map), 0); - mg_message_destroy_ca(message, session->decoder_allocator); - } - - // Send SUCCESS message. - ASSERT_EQ(mg_session_send_success_message(session, &mg_empty_map), 0); + mg_session_destroy(session); +}; - mg_session_destroy(session); - }); +TEST_F(ConnectTest, Success_v4) { + RunServer(run_v4_server_success); mg_session_params *params = mg_session_params_make(); mg_session_params_set_host(params, "127.0.0.1"); mg_session_params_set_port(params, port); @@ -592,70 +589,7 @@ TEST_F(ConnectTest, Success_v4) { } TEST_F(ConnectTest, SuccessWithSSL) { - RunServer([](int sockfd) { - // Perform handshake. - { - char handshake[20]; - ASSERT_EQ(RecvData(sockfd, handshake, 20), 0); - ASSERT_EQ(std::string(handshake, 4), "\x60\x60\xB0\x17"s); - ASSERT_EQ(std::string(handshake + 4, 4), "\x00\x00\x01\x04"s); - ASSERT_EQ(std::string(handshake + 8, 4), "\x00\x00\x00\x01"s); - ASSERT_EQ(std::string(handshake + 12, 4), "\x00\x00\x00\x00"s); - ASSERT_EQ(std::string(handshake + 16, 4), "\x00\x00\x00\x00"s); - - uint32_t version = htobe32(1); - ASSERT_EQ(SendData(sockfd, (char *)&version, 4), 0); - } - - mg_session *session = mg_session_init(&mg_system_allocator); - ASSERT_TRUE(session); - session->version = 1; - mg_raw_transport_init(sockfd, (mg_raw_transport **)&session->transport, - &mg_system_allocator); - - // Read INIT message. - { - mg_message *message; - ASSERT_EQ(mg_session_receive_message(session), 0); - ASSERT_EQ(mg_session_read_bolt_message(session, &message), 0); - ASSERT_EQ(message->type, MG_MESSAGE_TYPE_INIT); - - mg_message_init *msg_init = message->init_v; - EXPECT_EQ( - std::string(msg_init->client_name->data, msg_init->client_name->size), - MG_USER_AGENT); - { - ASSERT_EQ(mg_map_size(msg_init->auth_token), 3u); - - const mg_value *scheme_val = mg_map_at(msg_init->auth_token, "scheme"); - ASSERT_TRUE(scheme_val); - ASSERT_EQ(mg_value_get_type(scheme_val), MG_VALUE_TYPE_STRING); - const mg_string *scheme = mg_value_string(scheme_val); - ASSERT_EQ(std::string(scheme->data, scheme->size), "basic"); - - const mg_value *principal_val = - mg_map_at(msg_init->auth_token, "principal"); - ASSERT_TRUE(principal_val); - ASSERT_EQ(mg_value_get_type(principal_val), MG_VALUE_TYPE_STRING); - const mg_string *principal = mg_value_string(principal_val); - ASSERT_EQ(std::string(principal->data, principal->size), "user"); - - const mg_value *credentials_val = - mg_map_at(msg_init->auth_token, "credentials"); - ASSERT_TRUE(credentials_val); - ASSERT_EQ(mg_value_get_type(credentials_val), MG_VALUE_TYPE_STRING); - const mg_string *credentials = mg_value_string(credentials_val); - ASSERT_EQ(std::string(credentials->data, credentials->size), "pass"); - } - - mg_message_destroy_ca(message, session->decoder_allocator); - } - - // Send SUCCESS message. - ASSERT_EQ(mg_session_send_success_message(session, &mg_empty_map), 0); - - mg_session_destroy(session); - }); + RunServer(run_v4_server_success); mg_secure_transport_init_called = 0; trust_callback_ok = 0; @@ -681,6 +615,22 @@ TEST_F(ConnectTest, SuccessWithSSL) { ASSERT_MEMORY_OK(); } +TEST_F(ConnectTest, CustomScheme) { + RunServer(run_v4_server_success); + mg_session_params *params = mg_session_params_make(); + mg_session_params_set_host(params, "127.0.0.1"); + mg_session_params_set_port(params, port); + mg_session_params_set_scheme(params, "custom_scheme"); + mg_session_params_set_username(params, "user"); + mg_session_params_set_password(params, "pass"); + mg_session *session; + ASSERT_EQ(mg_connect_ca(params, &session, (mg_allocator *)&allocator), 0); + EXPECT_EQ(mg_session_status(session), MG_SESSION_READY); + mg_session_params_destroy(params); + mg_session_destroy(session); + ASSERT_MEMORY_OK(); +} + class RunTest : public ::testing::Test { protected: virtual void SetUp() override { From d7561ade22ebf666900753d3087dab161db28e1d Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Fri, 30 Aug 2024 20:05:19 +0200 Subject: [PATCH 09/10] A few fixes WIP --- mgclient_cpp/include/mgclient.hpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/mgclient_cpp/include/mgclient.hpp b/mgclient_cpp/include/mgclient.hpp index fef710b..4b0a79b 100644 --- a/mgclient_cpp/include/mgclient.hpp +++ b/mgclient_cpp/include/mgclient.hpp @@ -57,7 +57,7 @@ class Client { struct Params { std::string host = "127.0.0.1"; uint16_t port = 7687; - std::string scheme = "basic"; + std::string scheme = "none"; std::string username = ""; std::string password = ""; bool use_ssl = false; @@ -149,16 +149,24 @@ inline std::unique_ptr Client::Connect(const Client::Params ¶ms) { if (!mg_params) { return nullptr; } - mg_session_params_set_host(mg_params, params.host.c_str()); - mg_session_params_set_port(mg_params, params.port); - mg_session_params_set_scheme(mg_params, params.scheme.c_str()); + if (!params.host.empty()) { + mg_session_params_set_host(mg_params, params.host.c_str()); + } + if (params.port != 0) { + mg_session_params_set_port(mg_params, params.port); + } + if (!params.scheme.empty()) { + mg_session_params_set_scheme(mg_params, params.scheme.c_str()); + } if (!params.username.empty()) { mg_session_params_set_username(mg_params, params.username.c_str()); } if (!params.password.empty()) { mg_session_params_set_password(mg_params, params.password.c_str()); } - mg_session_params_set_user_agent(mg_params, params.user_agent.c_str()); + if (!params.user_agent.empty()) { + mg_session_params_set_user_agent(mg_params, params.user_agent.c_str()); + } mg_session_params_set_sslmode( mg_params, params.use_ssl ? MG_SSLMODE_REQUIRE : MG_SSLMODE_DISABLE); From 6616b4ed46afdd1029b3abb78c9cac4b613498fb Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Fri, 30 Aug 2024 20:59:03 +0200 Subject: [PATCH 10/10] A few more changes --- src/mgclient.c | 3 ++- tests/client.cpp | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mgclient.c b/src/mgclient.c index f092965..c346d91 100644 --- a/src/mgclient.c +++ b/src/mgclient.c @@ -390,6 +390,7 @@ static mg_map *build_hello_extra(const char *user_agent, const char *scheme, // by Memgraph) do not have such requirements: // https://neo4j.com/docs/bolt/current/bolt/message/#messages-hello // https://neo4j.com/docs/bolt/current/bolt/message/#messages-logon + // NOTE: HELLO message does NOT contain schema after Bolt 5.0. if (scheme && strcmp(scheme, "basic") == 0) { assert(username && password); } @@ -402,7 +403,7 @@ static mg_map *build_hello_extra(const char *user_agent, const char *scheme, return extra; } - mg_value *scheme_ = mg_value_make_string(scheme ? scheme : "basic"); + mg_value *scheme_ = mg_value_make_string(scheme ? scheme : "none"); // NOTE: Makes none default. if (!scheme_ || mg_map_insert_unsafe(extra, "scheme", scheme_) != 0) { goto cleanup; } diff --git a/tests/client.cpp b/tests/client.cpp index 6744f46..4f48046 100644 --- a/tests/client.cpp +++ b/tests/client.cpp @@ -19,7 +19,6 @@ #include #include "mgclient.h" -#include "mgcommon.h" #include "mgsession.h" #include "mgsocket.h"