From adb948d1a52963ae3588fe845c6cc6051cb876e2 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 21 Aug 2020 13:05:31 +0000 Subject: [PATCH 001/293] adding error transaction api endpoint, only empty function --- src/Controller/JsonRequestHandlerController.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Controller/JsonRequestHandlerController.php b/src/Controller/JsonRequestHandlerController.php index 89d07a93f..d97f27373 100644 --- a/src/Controller/JsonRequestHandlerController.php +++ b/src/Controller/JsonRequestHandlerController.php @@ -58,11 +58,20 @@ class JsonRequestHandlerController extends AppController { case 'checkUser': return $this->checkUser($jsonData->email, $jsonData->last_name); case 'getUsers' : return $this->getUsers($jsonData->page, $jsonData->limit); case 'getUserBalance': return $this->getUserBalance($jsonData->email, $jsonData->last_name); + case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionSha256, $jsonData->error, $jsonData->errorMessage); } return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for post', 'details' => $method]); } return $this->returnJson(['state' => 'error', 'msg' => 'no post or get']); } + + //! \param $transactionCreated creation of transaction in timestamp in seconds + //! \param $transactionBodyBase64Sha256 sha256 hash from transaction body serialized and converted to base64 + //! \param $error short error name in user language + //! \param $errorDetails more detailed error message in user language + private function errorInTransaction($transactionCreated, $transactionBodyBase64Sha256, $error, $errorDetails) { + + } private function putTransaction($transactionBase64) { $transaction = new Transaction($transactionBase64); From 28ab6f3810da9823a1d36d6be2a901561cda10c6 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 21 Aug 2020 13:16:58 +0000 Subject: [PATCH 002/293] change to blake2 --- src/Controller/JsonRequestHandlerController.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Controller/JsonRequestHandlerController.php b/src/Controller/JsonRequestHandlerController.php index d97f27373..af93d2190 100644 --- a/src/Controller/JsonRequestHandlerController.php +++ b/src/Controller/JsonRequestHandlerController.php @@ -58,7 +58,7 @@ class JsonRequestHandlerController extends AppController { case 'checkUser': return $this->checkUser($jsonData->email, $jsonData->last_name); case 'getUsers' : return $this->getUsers($jsonData->page, $jsonData->limit); case 'getUserBalance': return $this->getUserBalance($jsonData->email, $jsonData->last_name); - case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionSha256, $jsonData->error, $jsonData->errorMessage); + case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionGenericHash, $jsonData->error, $jsonData->errorMessage); } return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for post', 'details' => $method]); } @@ -66,10 +66,11 @@ class JsonRequestHandlerController extends AppController { } //! \param $transactionCreated creation of transaction in timestamp in seconds - //! \param $transactionBodyBase64Sha256 sha256 hash from transaction body serialized and converted to base64 + //! \param $transactionBodyBase64Sha256 generic hash from transaction body serialized and converted to base64 + //! using sodium_crypto_generichash to calculate //! \param $error short error name in user language //! \param $errorDetails more detailed error message in user language - private function errorInTransaction($transactionCreated, $transactionBodyBase64Sha256, $error, $errorDetails) { + private function errorInTransaction($transactionCreated, $transactionBodyBase64GenericHash, $error, $errorDetails) { } From 1206b6105db626d91b45d4d4b3d85eaf9e0eb249 Mon Sep 17 00:00:00 2001 From: einhornimmond - MarkX Date: Mon, 24 Aug 2020 18:24:48 +0200 Subject: [PATCH 003/293] include grpc manuell in cmake project, debug windows, other configurations are to come --- .gitmodules | 3 +++ CMakeLists.txt | 6 ++++++ README | 7 +++++++ compile_proto.sh | 5 +++-- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 2f85c0ab3..94115f227 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "dependencies/spirit-po"] path = dependencies/spirit-po url = https://github.com/cbeck88/spirit-po.git +[submodule "dependencies/grpc"] + path = dependencies/grpc + url = https://github.com/grpc/grpc.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f4e05b75..e544d1bac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ include_directories( "dependencies/mariadb-connector-c/include" "dependencies/mariadb-connector-c/build/include" "dependencies/spirit-po/include" + "dependencies/grpc/include" "src/cpp/proto" #"dependencies/mariadb-connector-c/build/include" #"dependencies/mariadb-connector-c/include" @@ -91,6 +92,10 @@ find_library(MYSQL_LIBRARIES mariadbclient.lib PATHS "dependencies/mariadb-conne #find_library(MYSQL_LIBRARIES_DEBUG mariadbclient.lib PATHS "import/mariadb/lib/debug") find_library(COMPILED_MARIADB_CLIENT_DEBUG mariadbclient PATHS "dependencies/mariadb-connector-c/build/libmariadb/Debug" REQUIRED) find_library(IROHA_ED25519 ed25519 PATHS "dependencies/iroha-ed25519/build/Debug" REQUIRED) +set(GRPC_PATH "dependencies/grpc/_build/Debug") +find_library(GRPC_PLUSPLUS grpc++ PATHS ${GRPC_PATH} REQUIRED) +find_library(GRPC_REFLECTION grpc++_reflection PATHS ${GRPC_PATH} REQUIRED) +set(GRPC_LIBS ${GRPC_PLUSPLUS} ${GRPC_REFLECTION}) set(MYSQL_INCLUDE_DIR "dependencies/mariadb-connector-c/include") #set(POCO_DEBUG_PATH "I:/FremdCode/C++/poco/win64/lib/Debug") @@ -139,6 +144,7 @@ target_link_libraries(Gradido_LoginServer ${CONAN_LIBS} ${IROHA_ED25519}) if(WIN32) TARGET_LINK_LIBRARIES(Gradido_LoginServer optimized ${MYSQL_LIBRARIES} Shlwapi) TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${COMPILED_MARIADB_CLIENT_DEBUG} Shlwapi) +TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${GRPC_LIBS}) else(WIN32) target_link_libraries(Gradido_LoginServer libmariadb protoc protobuf -pthread) endif(WIN32) diff --git a/README b/README index f6ca48a88..89783a878 100644 --- a/README +++ b/README @@ -20,6 +20,13 @@ cmake -DWITH_SSL=OFF .. cd ../../../ +cd dependencies/grpc +mkdir _build +cd _build +cmake .. +make +cd ../../../ + # get more dependencies with conan (need conan from https://conan.io/) mkdir build && cd build conan remote add inexor https://api.bintray.com/conan/inexorgame/inexor-conan diff --git a/compile_proto.sh b/compile_proto.sh index 16e3f975f..7e823733d 100755 --- a/compile_proto.sh +++ b/compile_proto.sh @@ -6,12 +6,13 @@ if [ ! -d "./src/cpp/proto/gradido" ] ; then mkdir ./src/cpp/proto/gradido fi -protoc --cpp_out=./src/cpp/proto --proto_path=./src/proto ./src/proto/gradido/*.proto +./protoc --cpp_out=./src/cpp/proto --proto_path=./src/proto ./src/proto/gradido/*.proto if [ ! -d "./src/cpp/proto/hedera" ] ; then mkdir ./src/cpp/proto/hedera fi -protoc --cpp_out=./src/cpp/proto/hedera --proto_path=./src/proto/hedera/hedera-protobuf/src/main/proto ./src/proto/hedera/hedera-protobuf/src/main/proto/*.proto +./protoc --plugin=protoc-gen-grpc=./grpc_cpp_plugin.exe --cpp_out=./src/cpp/proto/hedera --grpc_out=./src/cpp/proto/hedera --proto_path=./src/proto/hedera/hedera-protobuf/src/main/proto ./src/proto/hedera/hedera-protobuf/src/main/proto/*.proto + From d0b105b9e5cf8636c1cf62d0f66109eecdbd0007 Mon Sep 17 00:00:00 2001 From: einhornimmond - MarkX Date: Tue, 25 Aug 2020 11:26:14 +0200 Subject: [PATCH 004/293] add empty files for hedera proto wrappers --- CMakeLists.txt | 4 +++- dependencies/grpc | 1 + src/cpp/model/hedera/ConsensusCreateTopic.cpp | 0 src/cpp/model/hedera/ConsensusCreateTopic.h | 0 src/cpp/model/hedera/ConsensusGetTopicInfoResponse.cpp | 0 src/cpp/model/hedera/ConsensusGetTopicInfoResponse.h | 0 src/cpp/model/hedera/ConsensusSubmitMessage.cpp | 0 src/cpp/model/hedera/ConsensusSubmitMessage.h | 0 src/cpp/model/hedera/Query.cpp | 0 src/cpp/model/hedera/Query.h | 0 src/cpp/model/hedera/QueryHeader.cpp | 0 src/cpp/model/hedera/QueryHeader.h | 0 src/cpp/model/hedera/Response.cpp | 0 src/cpp/model/hedera/Response.h | 0 src/cpp/model/hedera/ResponseHeader.cpp | 0 src/cpp/model/hedera/ResponseHeader.h | 0 src/cpp/model/hedera/Transaction.cpp | 0 src/cpp/model/hedera/Transaction.h | 0 src/cpp/model/hedera/TransactionBody.cpp | 0 src/cpp/model/hedera/TransactionBody.h | 0 20 files changed, 4 insertions(+), 1 deletion(-) create mode 160000 dependencies/grpc create mode 100644 src/cpp/model/hedera/ConsensusCreateTopic.cpp create mode 100644 src/cpp/model/hedera/ConsensusCreateTopic.h create mode 100644 src/cpp/model/hedera/ConsensusGetTopicInfoResponse.cpp create mode 100644 src/cpp/model/hedera/ConsensusGetTopicInfoResponse.h create mode 100644 src/cpp/model/hedera/ConsensusSubmitMessage.cpp create mode 100644 src/cpp/model/hedera/ConsensusSubmitMessage.h create mode 100644 src/cpp/model/hedera/Query.cpp create mode 100644 src/cpp/model/hedera/Query.h create mode 100644 src/cpp/model/hedera/QueryHeader.cpp create mode 100644 src/cpp/model/hedera/QueryHeader.h create mode 100644 src/cpp/model/hedera/Response.cpp create mode 100644 src/cpp/model/hedera/Response.h create mode 100644 src/cpp/model/hedera/ResponseHeader.cpp create mode 100644 src/cpp/model/hedera/ResponseHeader.h create mode 100644 src/cpp/model/hedera/Transaction.cpp create mode 100644 src/cpp/model/hedera/Transaction.h create mode 100644 src/cpp/model/hedera/TransactionBody.cpp create mode 100644 src/cpp/model/hedera/TransactionBody.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e544d1bac..b16d3bb4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ FILE(GLOB LIB_SRC "src/cpp/lib/*.h" "src/cpp/lib/*.cpp") FILE(GLOB MODEL "src/cpp/model/*.h" "src/cpp/model/*.cpp") FILE(GLOB MODEL_TABLE "src/cpp/model/table/*.h" "src/cpp/model/table/*.cpp") FILE(GLOB MODEL_EMAIL "src/cpp/model/email/*.h" "src/cpp/model/email/*.cpp") +FILE(GLOB MODEL_HEDERA "src/cpp/model/hedera/*.h" "src/cpp/model/hedera/*.cpp") FILE(GLOB CRYPTO "src/cpp/Crypto/*.h" "src/cpp/Crypto/*.cpp") FILE(GLOB MAIN "src/cpp/*.cpp" "src/cpp/*.c" "src/cpp/*.h") FILE(GLOB MYSQL "src/cpp/MySQL/*.cpp" "src/cpp/MySQL/*.h" "src/cpp/MySQL/Poco/*.h") @@ -44,7 +45,7 @@ FILE(GLOB TEST_CONTROLLER "src/cpp/test/controller/*.cpp" "src/cpp/test/controll SET(LOCAL_SRCS ${CONTROLLER} ${TINF} ${MAIN} ${HTTPInterface} - ${JSONInterface} ${CRYPTO} ${MODEL} ${MODEL_TABLE} ${MODEL_EMAIL} + ${JSONInterface} ${CRYPTO} ${MODEL} ${MODEL_TABLE} ${MODEL_EMAIL} ${MODEL_HEDERA} ${SINGLETON_MANAGER} ${LIB_SRC} ${MYSQL} ${TASKS} ${PROTO_GRADIDO} ${PROTO_HEDERA} ) @@ -63,6 +64,7 @@ source_group("Crypto" FILES ${CRYPTO}) source_group("tasks" FILES ${TASKS}) source_group("model\\table" FILES ${MODEL_TABLE}) source_group("model\\email" FILES ${MODEL_EMAIL}) +source_group("model\\hedera" FILES ${MODEL_HEDERA}) source_group("model" FILES ${MODEL}) source_group("mysql" FILES ${MYSQL}) source_group("SingletonManager" FILES ${SINGLETON_MANAGER}) diff --git a/dependencies/grpc b/dependencies/grpc new file mode 160000 index 000000000..f57a0619b --- /dev/null +++ b/dependencies/grpc @@ -0,0 +1 @@ +Subproject commit f57a0619bc5697ea98c2d5b2c983c7024f43a5db diff --git a/src/cpp/model/hedera/ConsensusCreateTopic.cpp b/src/cpp/model/hedera/ConsensusCreateTopic.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/ConsensusCreateTopic.h b/src/cpp/model/hedera/ConsensusCreateTopic.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/ConsensusGetTopicInfoResponse.cpp b/src/cpp/model/hedera/ConsensusGetTopicInfoResponse.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/ConsensusGetTopicInfoResponse.h b/src/cpp/model/hedera/ConsensusGetTopicInfoResponse.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/ConsensusSubmitMessage.cpp b/src/cpp/model/hedera/ConsensusSubmitMessage.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/ConsensusSubmitMessage.h b/src/cpp/model/hedera/ConsensusSubmitMessage.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/Query.cpp b/src/cpp/model/hedera/Query.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/Query.h b/src/cpp/model/hedera/Query.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/QueryHeader.cpp b/src/cpp/model/hedera/QueryHeader.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/QueryHeader.h b/src/cpp/model/hedera/QueryHeader.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/Response.cpp b/src/cpp/model/hedera/Response.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/Response.h b/src/cpp/model/hedera/Response.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/ResponseHeader.cpp b/src/cpp/model/hedera/ResponseHeader.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/ResponseHeader.h b/src/cpp/model/hedera/ResponseHeader.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/Transaction.cpp b/src/cpp/model/hedera/Transaction.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/Transaction.h b/src/cpp/model/hedera/Transaction.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/TransactionBody.cpp b/src/cpp/model/hedera/TransactionBody.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/TransactionBody.h b/src/cpp/model/hedera/TransactionBody.h new file mode 100644 index 000000000..e69de29bb From 8549c8821c201fcce2d0597b00a7cd527d226763 Mon Sep 17 00:00:00 2001 From: einhornimmond - MarkX Date: Tue, 25 Aug 2020 12:10:02 +0200 Subject: [PATCH 005/293] add nearly empty hedera topic management page, and additional wrapper for hedera proto --- src/cpp/model/hedera/ConsensusDeleteTopic.cpp | 0 src/cpp/model/hedera/ConsensusDeleteTopic.h | 0 src/cpp/model/hedera/ConsensusUpdateTopic.cpp | 0 src/cpp/model/hedera/ConsensusUpdateTopic.h | 0 src/cpsp/adminHederaTopic.cpsp | 21 +++++++++++++++++++ 5 files changed, 21 insertions(+) create mode 100644 src/cpp/model/hedera/ConsensusDeleteTopic.cpp create mode 100644 src/cpp/model/hedera/ConsensusDeleteTopic.h create mode 100644 src/cpp/model/hedera/ConsensusUpdateTopic.cpp create mode 100644 src/cpp/model/hedera/ConsensusUpdateTopic.h create mode 100644 src/cpsp/adminHederaTopic.cpsp diff --git a/src/cpp/model/hedera/ConsensusDeleteTopic.cpp b/src/cpp/model/hedera/ConsensusDeleteTopic.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/ConsensusDeleteTopic.h b/src/cpp/model/hedera/ConsensusDeleteTopic.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/ConsensusUpdateTopic.cpp b/src/cpp/model/hedera/ConsensusUpdateTopic.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/ConsensusUpdateTopic.h b/src/cpp/model/hedera/ConsensusUpdateTopic.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpsp/adminHederaTopic.cpsp b/src/cpsp/adminHederaTopic.cpsp new file mode 100644 index 000000000..bc1fcf36e --- /dev/null +++ b/src/cpsp/adminHederaTopic.cpsp @@ -0,0 +1,21 @@ +<%@ page class="AdminHederaTopic" %> +<%@ page form="true" %> +<%@ page compressed="true" %> +<%@ page baseClass="SessionHTTPRequestHandler" %> +<%@ page ctorArg="Session*" %> +<%@ header include="SessionHTTPRequestHandler.h" %> +<%! + + +%> +<%% + const char* pageName = "Admin Hedera Topic"; + + +%><%@ include file="header_old.cpsp" %> +
+

Admin Hedera Topic

+ <%= getErrorsHtml() %> + +
+<%@ include file="footer.cpsp" %> From 0c3e69b045d97ba56134a756969083ccf0ec3662 Mon Sep 17 00:00:00 2001 From: einhornimmond - MarkX Date: Tue, 25 Aug 2020 12:59:34 +0200 Subject: [PATCH 006/293] add new tables and model/table empty files for them --- skeema/gradido_login/crypto_keys.sql | 7 +++++++ skeema/gradido_login/groups.sql | 7 +++++++ skeema/gradido_login/hedera_accounts.sql | 9 +++++++++ skeema/gradido_login/hedera_ids.sql | 7 +++++++ skeema/gradido_login/hedera_topics.sql | 13 +++++++++++++ src/cpp/model/table/CryptoKeys.cpp | 0 src/cpp/model/table/CryptoKeys.h | 0 src/cpp/model/table/Groups.cpp | 0 src/cpp/model/table/Groups.h | 0 src/cpp/model/table/HederaAccounts.cpp | 0 src/cpp/model/table/HederaAccounts.h | 0 src/cpp/model/table/HederaIds.cpp | 0 src/cpp/model/table/HederaIds.h | 0 src/cpp/model/table/HederaTopics.cpp | 0 src/cpp/model/table/HederaTopics.h | 0 15 files changed, 43 insertions(+) create mode 100644 skeema/gradido_login/crypto_keys.sql create mode 100644 skeema/gradido_login/groups.sql create mode 100644 skeema/gradido_login/hedera_accounts.sql create mode 100644 skeema/gradido_login/hedera_ids.sql create mode 100644 skeema/gradido_login/hedera_topics.sql create mode 100644 src/cpp/model/table/CryptoKeys.cpp create mode 100644 src/cpp/model/table/CryptoKeys.h create mode 100644 src/cpp/model/table/Groups.cpp create mode 100644 src/cpp/model/table/Groups.h create mode 100644 src/cpp/model/table/HederaAccounts.cpp create mode 100644 src/cpp/model/table/HederaAccounts.h create mode 100644 src/cpp/model/table/HederaIds.cpp create mode 100644 src/cpp/model/table/HederaIds.h create mode 100644 src/cpp/model/table/HederaTopics.cpp create mode 100644 src/cpp/model/table/HederaTopics.h diff --git a/skeema/gradido_login/crypto_keys.sql b/skeema/gradido_login/crypto_keys.sql new file mode 100644 index 000000000..971c56a7b --- /dev/null +++ b/skeema/gradido_login/crypto_keys.sql @@ -0,0 +1,7 @@ +CREATE TABLE `crypto_keys` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `private_key` VARBINARY(64) NOT NULL, + `public_key` BINARY(32) NOT NULL, + `crypto_key_type_id` INT NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/skeema/gradido_login/groups.sql b/skeema/gradido_login/groups.sql new file mode 100644 index 000000000..c3d0bc787 --- /dev/null +++ b/skeema/gradido_login/groups.sql @@ -0,0 +1,7 @@ +CREATE TABLE `groups` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `alias` VARCHAR(255) NOT NULL, + `name` VARCHAR(255) NOT NULL, + `description` TEXT NULL DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/skeema/gradido_login/hedera_accounts.sql b/skeema/gradido_login/hedera_accounts.sql new file mode 100644 index 000000000..fc2ad9735 --- /dev/null +++ b/skeema/gradido_login/hedera_accounts.sql @@ -0,0 +1,9 @@ +CREATE TABLE `hedera_accounts` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `user_id` INT UNSIGNED NOT NULL, + `account_hedera_id` INT UNSIGNED NOT NULL, + `account_key_id` INT UNSIGNED NOT NULL, + `balance` BIGINT UNSIGNED NOT NULL DEFAULT '0', + `updated` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/skeema/gradido_login/hedera_ids.sql b/skeema/gradido_login/hedera_ids.sql new file mode 100644 index 000000000..624a02207 --- /dev/null +++ b/skeema/gradido_login/hedera_ids.sql @@ -0,0 +1,7 @@ +CREATE TABLE `hedera_ids` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `shardNum` BIGINT NOT NULL DEFAULT '0', + `realmNum` BIGINT NOT NULL DEFAULT '0', + `num` BIGINT NOT NULL, + PRIMARY KEY (`id`) +) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/skeema/gradido_login/hedera_topics.sql b/skeema/gradido_login/hedera_topics.sql new file mode 100644 index 000000000..c1fa90f2b --- /dev/null +++ b/skeema/gradido_login/hedera_topics.sql @@ -0,0 +1,13 @@ +CREATE TABLE `hedera_topics` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `topic_hedera_id` INT UNSIGNED NOT NULL, + `auto_renew_account_hedera_id` INT UNSIGNED NULL, + `auto_renew_period` INT UNSIGNED NOT NULL DEFAULT '0', + `group_id` INT UNSIGNED NOT NULL, + `admin_key_id` INT UNSIGNED NULL, + `submit_key_id` INT UNSIGNED NULL, + `current_timeout` BIGINT UNSIGNED NOT NULL DEFAULT '0', + `sequence_number` BIGINT UNSIGNED NULL DEFAULT '0', + `updated` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/src/cpp/model/table/CryptoKeys.cpp b/src/cpp/model/table/CryptoKeys.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/table/CryptoKeys.h b/src/cpp/model/table/CryptoKeys.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/table/Groups.cpp b/src/cpp/model/table/Groups.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/table/Groups.h b/src/cpp/model/table/Groups.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/table/HederaAccounts.cpp b/src/cpp/model/table/HederaAccounts.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/table/HederaAccounts.h b/src/cpp/model/table/HederaAccounts.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/table/HederaIds.cpp b/src/cpp/model/table/HederaIds.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/table/HederaIds.h b/src/cpp/model/table/HederaIds.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/table/HederaTopics.cpp b/src/cpp/model/table/HederaTopics.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/table/HederaTopics.h b/src/cpp/model/table/HederaTopics.h new file mode 100644 index 000000000..e69de29bb From 5d3fbcfdfa9a1ab1e819d5234272021402e153e0 Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 25 Aug 2020 16:17:28 +0200 Subject: [PATCH 007/293] rename AuthenticatedEncryption to SecretKeyCryptography --- src/cpp/Crypto/KeyPairEd25519.cpp | 4 ++-- src/cpp/Crypto/KeyPairEd25519.h | 4 ++-- ...dEncryption.cpp => SecretKeyCryptography.cpp} | 16 ++++++++-------- ...catedEncryption.h => SecretKeyCryptography.h} | 14 +++++++------- src/cpp/controller/User.cpp | 10 +++++----- src/cpp/controller/User.h | 6 +++--- .../AuthenticatedEncryptionCreateKeyTask.cpp | 4 ++-- .../test/crypto/TestAuthenticatedEncryption.cpp | 10 +++++----- 8 files changed, 34 insertions(+), 34 deletions(-) rename src/cpp/Crypto/{AuthenticatedEncryption.cpp => SecretKeyCryptography.cpp} (86%) rename src/cpp/Crypto/{AuthenticatedEncryption.h => SecretKeyCryptography.h} (85%) diff --git a/src/cpp/Crypto/KeyPairEd25519.cpp b/src/cpp/Crypto/KeyPairEd25519.cpp index ee8cabfa0..392bf5e8e 100644 --- a/src/cpp/Crypto/KeyPairEd25519.cpp +++ b/src/cpp/Crypto/KeyPairEd25519.cpp @@ -151,13 +151,13 @@ MemoryBin* KeyPairEd25519::sign(const unsigned char* message, size_t messageSize } -MemoryBin* KeyPairEd25519::getCryptedPrivKey(const Poco::AutoPtr password) const +MemoryBin* KeyPairEd25519::getCryptedPrivKey(const Poco::AutoPtr password) const { if (password.isNull()) return nullptr; if (!mSodiumSecret) return nullptr; MemoryBin* encryptedKey = nullptr; - if (AuthenticatedEncryption::AUTH_ENCRYPT_OK == password->encrypt(mSodiumSecret, &encryptedKey)) { + if (SecretKeyCryptography::AUTH_ENCRYPT_OK == password->encrypt(mSodiumSecret, &encryptedKey)) { return encryptedKey; } else { diff --git a/src/cpp/Crypto/KeyPairEd25519.h b/src/cpp/Crypto/KeyPairEd25519.h index 7b3f11d4b..75a1ce9f1 100644 --- a/src/cpp/Crypto/KeyPairEd25519.h +++ b/src/cpp/Crypto/KeyPairEd25519.h @@ -13,7 +13,7 @@ #include "sodium.h" -#include "AuthenticatedEncryption.h" +#include "SecretKeyCryptography.h" #include "Passphrase.h" class KeyPairEd25519 : public IKeyPair @@ -63,7 +63,7 @@ public: inline bool hasPrivateKey() const { return mSodiumSecret != nullptr; } //! \brief only way to get a private key.. encrypted - MemoryBin* getCryptedPrivKey(const Poco::AutoPtr password) const; + MemoryBin* getCryptedPrivKey(const Poco::AutoPtr password) const; protected: diff --git a/src/cpp/Crypto/AuthenticatedEncryption.cpp b/src/cpp/Crypto/SecretKeyCryptography.cpp similarity index 86% rename from src/cpp/Crypto/AuthenticatedEncryption.cpp rename to src/cpp/Crypto/SecretKeyCryptography.cpp index 421537a66..0685ecaff 100644 --- a/src/cpp/Crypto/AuthenticatedEncryption.cpp +++ b/src/cpp/Crypto/SecretKeyCryptography.cpp @@ -1,22 +1,22 @@ -#include "AuthenticatedEncryption.h" +#include "SecretKeyCryptography.h" #include "sodium.h" #include "../ServerConfig.h" #include #include "../lib/Profiler.h" -AuthenticatedEncryption::AuthenticatedEncryption() +SecretKeyCryptography::SecretKeyCryptography() : mOpsLimit(10), mMemLimit(33554432), mAlgo(2), mEncryptionKey(nullptr), mEncryptionKeyHash(0) { } -AuthenticatedEncryption::AuthenticatedEncryption(unsigned long long opslimit, size_t memlimit, int algo) +SecretKeyCryptography::SecretKeyCryptography(unsigned long long opslimit, size_t memlimit, int algo) : mOpsLimit(opslimit), mMemLimit(memlimit), mAlgo(algo), mEncryptionKey(nullptr), mEncryptionKeyHash(0) { } -AuthenticatedEncryption::~AuthenticatedEncryption() +SecretKeyCryptography::~SecretKeyCryptography() { if (mEncryptionKey) { MemoryManager::getInstance()->releaseMemory(mEncryptionKey); @@ -24,7 +24,7 @@ AuthenticatedEncryption::~AuthenticatedEncryption() } } -AuthenticatedEncryption::ResultType AuthenticatedEncryption::createKey(const std::string& salt_parameter, const std::string& passwd) +SecretKeyCryptography::ResultType SecretKeyCryptography::createKey(const std::string& salt_parameter, const std::string& passwd) { assert(crypto_hash_sha512_BYTES >= crypto_pwhash_SALTBYTES); @@ -79,7 +79,7 @@ AuthenticatedEncryption::ResultType AuthenticatedEncryption::createKey(const std return AUTH_ENCRYPT_OK; } -AuthenticatedEncryption::ResultType AuthenticatedEncryption::encrypt(const MemoryBin* message, MemoryBin** encryptedMessage) const +SecretKeyCryptography::ResultType SecretKeyCryptography::encrypt(const MemoryBin* message, MemoryBin** encryptedMessage) const { assert(message && encryptedMessage); std::shared_lock _lock(mWorkingMutex); @@ -111,7 +111,7 @@ AuthenticatedEncryption::ResultType AuthenticatedEncryption::encrypt(const Memor return AUTH_ENCRYPT_OK; } -AuthenticatedEncryption::ResultType AuthenticatedEncryption::decrypt(const unsigned char* encryptedMessage, size_t encryptedMessageSize, MemoryBin** message) const +SecretKeyCryptography::ResultType SecretKeyCryptography::decrypt(const unsigned char* encryptedMessage, size_t encryptedMessageSize, MemoryBin** message) const { assert(message); std::shared_lock _lock(mWorkingMutex); @@ -139,7 +139,7 @@ AuthenticatedEncryption::ResultType AuthenticatedEncryption::decrypt(const unsig return AUTH_DECRYPT_OK; } -const char* AuthenticatedEncryption::getErrorMessage(ResultType type) +const char* SecretKeyCryptography::getErrorMessage(ResultType type) { switch (type) { case AUTH_ENCRYPT_OK: return "everything is ok"; diff --git a/src/cpp/Crypto/AuthenticatedEncryption.h b/src/cpp/Crypto/SecretKeyCryptography.h similarity index 85% rename from src/cpp/Crypto/AuthenticatedEncryption.h rename to src/cpp/Crypto/SecretKeyCryptography.h index a19e0f856..0a0a16072 100644 --- a/src/cpp/Crypto/AuthenticatedEncryption.h +++ b/src/cpp/Crypto/SecretKeyCryptography.h @@ -17,13 +17,13 @@ * * \date: 07-06-2020 * - * \brief: Wrapper Class for make using libsodium authenticated encryption easy, used for encrypt private keys for user + * \brief: Wrapper Class for make using libsodium secret key encryption easy, used for encrypt private keys for user with pwhash * */ typedef Poco::UInt64 KeyHashed; -class AuthenticatedEncryption : public AutoPtrContainer +class SecretKeyCryptography : public AutoPtrContainer { public: @@ -37,20 +37,20 @@ public: }; //! \brief init with default algorithms parameter - AuthenticatedEncryption(); + SecretKeyCryptography(); //! \brief init with custom algorithms parameter //! //! details see in libsodium crypto_pwhash - AuthenticatedEncryption(unsigned long long opslimit, size_t memlimit, int algo); + SecretKeyCryptography(unsigned long long opslimit, size_t memlimit, int algo); - ~AuthenticatedEncryption(); + ~SecretKeyCryptography(); inline KeyHashed getKeyHashed() const { std::shared_lock _lock(mWorkingMutex); return mEncryptionKeyHash; } - inline bool operator == (const Poco::AutoPtr& b) const { + inline bool operator == (const Poco::AutoPtr& b) const { return isTheSame(b); } - inline bool isTheSame(const Poco::AutoPtr& b) const { + inline bool isTheSame(const Poco::AutoPtr& b) const { std::shared_lock _lock(mWorkingMutex); if (b.isNull()) return false; return mEncryptionKeyHash == b->getKeyHashed(); diff --git a/src/cpp/controller/User.cpp b/src/cpp/controller/User.cpp index 19c9df5a9..605f11087 100644 --- a/src/cpp/controller/User.cpp +++ b/src/cpp/controller/User.cpp @@ -144,7 +144,7 @@ namespace controller { return -3; } observer->addTask(email_hash, TASK_OBSERVER_PASSWORD_CREATION); - Poco::AutoPtr authenticated_encryption(new AuthenticatedEncryption); + Poco::AutoPtr authenticated_encryption(new SecretKeyCryptography); assert(!authenticated_encryption.isNull() && model); authenticated_encryption->createKey(model->getEmail(), password); @@ -163,7 +163,7 @@ namespace controller { } else { - if (AuthenticatedEncryption::AUTH_DECRYPT_OK == authenticated_encryption->decrypt(model->getPrivateKeyEncrypted(), &clear_private_key)) { + if (SecretKeyCryptography::AUTH_DECRYPT_OK == authenticated_encryption->decrypt(model->getPrivateKeyEncrypted(), &clear_private_key)) { if (mGradidoKeyPair) { if (mGradidoKeyPair->isTheSame(clear_private_key) == 0) { mCanDecryptPrivateKey = true; @@ -225,7 +225,7 @@ namespace controller { auto email_hash = observer->makeHash(model->getEmail()); observer->addTask(email_hash, TASK_OBSERVER_PASSWORD_CREATION); - Poco::AutoPtr authenticated_encryption(new AuthenticatedEncryption); + Poco::AutoPtr authenticated_encryption(new SecretKeyCryptography); assert(!authenticated_encryption.isNull() && model); authenticated_encryption->createKey(model->getEmail(), password); @@ -234,7 +234,7 @@ namespace controller { } - int User::setNewPassword(Poco::AutoPtr passwd) + int User::setNewPassword(Poco::AutoPtr passwd) { std::unique_lock _lock(mSharedMutex); auto model = getModel(); @@ -249,7 +249,7 @@ namespace controller { if ((!mGradidoKeyPair || !mGradidoKeyPair->hasPrivateKey()) && model->hasPrivateKeyEncrypted()) { //if (!mGradidoKeyPair) mGradidoKeyPair = new KeyPairEd25519; MemoryBin* clear_private_key = nullptr; - if (AuthenticatedEncryption::AUTH_DECRYPT_OK == mPassword->decrypt(model->getPrivateKeyEncrypted(), &clear_private_key)) { + if (SecretKeyCryptography::AUTH_DECRYPT_OK == mPassword->decrypt(model->getPrivateKeyEncrypted(), &clear_private_key)) { if (mGradidoKeyPair && mGradidoKeyPair->isTheSame(clear_private_key) != 0) { delete mGradidoKeyPair; diff --git a/src/cpp/controller/User.h b/src/cpp/controller/User.h index e251beb19..a42678739 100644 --- a/src/cpp/controller/User.h +++ b/src/cpp/controller/User.h @@ -81,7 +81,7 @@ namespace controller { //! \return 1 = password changed, private key re-encrypted and saved into db //! \return 2 = password changed, only hash stored in db, couldn't load private key for re-encryption //! \return -1 = stored pubkey and private key didn't match - int setNewPassword(Poco::AutoPtr passwd); + int setNewPassword(Poco::AutoPtr passwd); //! \brief set authenticated encryption and save hash in db, also re encrypt private key if exist @@ -93,7 +93,7 @@ namespace controller { int setNewPassword(const std::string& password); //! \brief return AuthenticatedEncryption Auto Pointer - inline const Poco::AutoPtr getPassword() { + inline const Poco::AutoPtr getPassword() { std::shared_lock _lock(mSharedMutex); return mPassword; } @@ -129,7 +129,7 @@ namespace controller { std::string mPublicHex; - Poco::AutoPtr mPassword; + Poco::AutoPtr mPassword; KeyPairEd25519* mGradidoKeyPair; bool mCanDecryptPrivateKey; diff --git a/src/cpp/tasks/AuthenticatedEncryptionCreateKeyTask.cpp b/src/cpp/tasks/AuthenticatedEncryptionCreateKeyTask.cpp index a43b6223e..9cc2338a1 100644 --- a/src/cpp/tasks/AuthenticatedEncryptionCreateKeyTask.cpp +++ b/src/cpp/tasks/AuthenticatedEncryptionCreateKeyTask.cpp @@ -22,9 +22,9 @@ int AuthenticatedEncryptionCreateKeyTask::run() { auto em = ErrorManager::getInstance(); const static char* function_name = "AuthenticatedEncryptionCreateKeyTask::run"; - auto authenticated_encryption = new AuthenticatedEncryption; + auto authenticated_encryption = new SecretKeyCryptography; Profiler timeUsed; - if (AuthenticatedEncryption::AUTH_ENCRYPT_OK != authenticated_encryption->createKey(mUser->getModel()->getEmail(), mPassword)) { + if (SecretKeyCryptography::AUTH_ENCRYPT_OK != authenticated_encryption->createKey(mUser->getModel()->getEmail(), mPassword)) { em->addError(new Error(function_name, "error creating key")); em->addError(new ParamError(function_name, "for email", mUser->getModel()->getEmail())); em->addError(new ParamError(function_name, "strerror: ", strerror(errno))); diff --git a/src/cpp/test/crypto/TestAuthenticatedEncryption.cpp b/src/cpp/test/crypto/TestAuthenticatedEncryption.cpp index 93c19bc9b..e863e773d 100644 --- a/src/cpp/test/crypto/TestAuthenticatedEncryption.cpp +++ b/src/cpp/test/crypto/TestAuthenticatedEncryption.cpp @@ -1,6 +1,6 @@ #include "TestAuthenticatedEncryption.h" -#include "../../Crypto/AuthenticatedEncryption.h" +#include "../../Crypto/SecretKeyCryptography.h" #include "../../lib/Profiler.h" #include "../../lib/DataTypeConverter.h" @@ -12,12 +12,12 @@ void TestAuthenticatedEncryption::SetUp() } TEST_F(TestAuthenticatedEncryption, encryptDecryptTest) { - AuthenticatedEncryption authenticated_encryption; + SecretKeyCryptography authenticated_encryption; EXPECT_FALSE(authenticated_encryption.hasKey()); EXPECT_EQ(authenticated_encryption.getKeyHashed(), 0); Profiler time_used; - EXPECT_EQ(authenticated_encryption.createKey("dariofrodo@gmx.de", "r3an7d_spassw"), AuthenticatedEncryption::AUTH_ENCRYPT_OK); + EXPECT_EQ(authenticated_encryption.createKey("dariofrodo@gmx.de", "r3an7d_spassw"), SecretKeyCryptography::AUTH_ENCRYPT_OK); printf("create key duration: %s\n", time_used.string().data()); EXPECT_TRUE(authenticated_encryption.hasKey()); @@ -29,12 +29,12 @@ TEST_F(TestAuthenticatedEncryption, encryptDecryptTest) { memcpy(*test_message_bin, test_message.data(), test_message.size()); time_used.reset(); - EXPECT_EQ(authenticated_encryption.encrypt(test_message_bin, &encrypted_message), AuthenticatedEncryption::AUTH_ENCRYPT_OK); + EXPECT_EQ(authenticated_encryption.encrypt(test_message_bin, &encrypted_message), SecretKeyCryptography::AUTH_ENCRYPT_OK); printf("encrypt message duration: %s\n", time_used.string().data()); MemoryBin* decrypted_message = nullptr; time_used.reset(); - EXPECT_EQ(authenticated_encryption.decrypt(encrypted_message, &decrypted_message), AuthenticatedEncryption::AUTH_DECRYPT_OK); + EXPECT_EQ(authenticated_encryption.decrypt(encrypted_message, &decrypted_message), SecretKeyCryptography::AUTH_DECRYPT_OK); printf("decrypt message duration: %s\n", time_used.string().data()); EXPECT_EQ(std::string((const char*)*decrypted_message, decrypted_message->size()), test_message); From 67c8069eb6b009994eb351d3f25f2776b994c015 Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 25 Aug 2020 16:18:38 +0200 Subject: [PATCH 008/293] add binToHex with Poco::Nullable for easy use with public keys --- src/cpp/lib/DataTypeConverter.cpp | 10 ++++++++++ src/cpp/lib/DataTypeConverter.h | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/cpp/lib/DataTypeConverter.cpp b/src/cpp/lib/DataTypeConverter.cpp index c3275ba49..a97cb8d0e 100644 --- a/src/cpp/lib/DataTypeConverter.cpp +++ b/src/cpp/lib/DataTypeConverter.cpp @@ -176,6 +176,16 @@ namespace DataTypeConverter return hexString; } + std::string binToHex(const Poco::Nullable& nullableBin) + { + if (nullableBin.isNull()) { + return "0x0"; + } + else { + return binToHex(nullableBin.value().content().data(), nullableBin.value().content().size()); + } + } + std::string pubkeyToHex(const unsigned char* pubkey) { auto mm = MemoryManager::getInstance(); diff --git a/src/cpp/lib/DataTypeConverter.h b/src/cpp/lib/DataTypeConverter.h index e1a419a93..46a767d97 100644 --- a/src/cpp/lib/DataTypeConverter.h +++ b/src/cpp/lib/DataTypeConverter.h @@ -5,9 +5,10 @@ #include "../SingletonManager/MemoryManager.h" #include "Poco/Timespan.h" +#include "Poco/Nullable.h" +#include "Poco/Data/LOB.h" #include "../SingletonManager/LanguageManager.h" - namespace DataTypeConverter { enum NumberParseState @@ -26,7 +27,9 @@ namespace DataTypeConverter { std::string binToBase64(const MemoryBin* data); + std::string binToHex(const unsigned char* data, size_t size); + std::string binToHex(const Poco::Nullable& nullableBin); inline std::string binToHex(const MemoryBin* data) { return binToHex(data->data(), data->size());} //! \param pubkey pointer to array with crypto_sign_PUBLICKEYBYTES size From 5fd66d48e7c0db0d63aa8a9bf9472bf0699a45e4 Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 25 Aug 2020 17:13:49 +0200 Subject: [PATCH 009/293] update skeema files, fill in empty model table classes for new mysql tables --- skeema/gradido_login/crypto_keys.sql | 12 ++-- skeema/gradido_login/elopage_buys.sql | 8 +-- skeema/gradido_login/email_opt_in.sql | 8 +-- skeema/gradido_login/email_opt_in_types.sql | 2 +- skeema/gradido_login/groups.sql | 15 ++--- skeema/gradido_login/hedera_accounts.sql | 18 +++--- skeema/gradido_login/hedera_ids.sql | 14 ++--- skeema/gradido_login/hedera_topics.sql | 25 ++++---- skeema/gradido_login/roles.sql | 4 +- skeema/gradido_login/user_backups.sql | 2 +- skeema/gradido_login/user_roles.sql | 2 +- skeema/gradido_login/users.sql | 10 +-- src/cpp/model/table/CryptoKeys.cpp | 70 +++++++++++++++++++++ src/cpp/model/table/CryptoKeys.h | 43 +++++++++++++ src/cpp/model/table/Groups.cpp | 57 +++++++++++++++++ src/cpp/model/table/Groups.h | 35 +++++++++++ src/cpp/model/table/HederaAccounts.cpp | 63 +++++++++++++++++++ src/cpp/model/table/HederaAccounts.h | 36 +++++++++++ src/cpp/model/table/HederaIds.cpp | 58 +++++++++++++++++ src/cpp/model/table/HederaIds.h | 36 +++++++++++ src/cpp/model/table/HederaTopics.cpp | 69 ++++++++++++++++++++ src/cpp/model/table/HederaTopics.h | 41 ++++++++++++ 22 files changed, 570 insertions(+), 58 deletions(-) diff --git a/skeema/gradido_login/crypto_keys.sql b/skeema/gradido_login/crypto_keys.sql index 971c56a7b..43b511db2 100644 --- a/skeema/gradido_login/crypto_keys.sql +++ b/skeema/gradido_login/crypto_keys.sql @@ -1,7 +1,7 @@ CREATE TABLE `crypto_keys` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `private_key` VARBINARY(64) NOT NULL, - `public_key` BINARY(32) NOT NULL, - `crypto_key_type_id` INT NOT NULL DEFAULT '0', - PRIMARY KEY (`id`) -) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4; + `id` int unsigned NOT NULL AUTO_INCREMENT, + `private_key` varbinary(64) NOT NULL, + `public_key` binary(32) NOT NULL, + `crypto_key_type_id` int NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/skeema/gradido_login/elopage_buys.sql b/skeema/gradido_login/elopage_buys.sql index be3464846..0be79a34b 100644 --- a/skeema/gradido_login/elopage_buys.sql +++ b/skeema/gradido_login/elopage_buys.sql @@ -1,15 +1,15 @@ CREATE TABLE `elopage_buys` ( - `id` int UNSIGNED NOT NULL AUTO_INCREMENT, + `id` int unsigned NOT NULL AUTO_INCREMENT, `elopage_user_id` int NOT NULL, `affiliate_program_id` int NOT NULL, `publisher_id` int NOT NULL, `order_id` int NOT NULL, `product_id` int NOT NULL, `product_price` int NOT NULL, - `payer_email` varchar(255) COLLATE utf8_bin NOT NULL, - `publisher_email` varchar(255) COLLATE utf8_bin NOT NULL, + `payer_email` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, + `publisher_email` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, `payed` tinyint NOT NULL, `success_date` datetime NOT NULL, - `event` varchar(255) CHARACTER SET utf8mb4 NOT NULL, + `event` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/skeema/gradido_login/email_opt_in.sql b/skeema/gradido_login/email_opt_in.sql index 1589093e8..da4288475 100644 --- a/skeema/gradido_login/email_opt_in.sql +++ b/skeema/gradido_login/email_opt_in.sql @@ -1,11 +1,11 @@ CREATE TABLE `email_opt_in` ( - `id` int UNSIGNED NOT NULL AUTO_INCREMENT, + `id` int unsigned NOT NULL AUTO_INCREMENT, `user_id` int NOT NULL, `verification_code` bigint unsigned NOT NULL, `email_opt_in_type_id` int NOT NULL, - `created` datetime NOT NULL DEFAULT current_timestamp(), - `resend_count` int DEFAULT 0, - `updated` DATETIME on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `resend_count` int DEFAULT '0', + `updated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `verification_code` (`verification_code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/skeema/gradido_login/email_opt_in_types.sql b/skeema/gradido_login/email_opt_in_types.sql index f46275727..dbcd2d272 100644 --- a/skeema/gradido_login/email_opt_in_types.sql +++ b/skeema/gradido_login/email_opt_in_types.sql @@ -1,5 +1,5 @@ CREATE TABLE `email_opt_in_types` ( - `id` int UNSIGNED NOT NULL AUTO_INCREMENT, + `id` int unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `description` varchar(255) NOT NULL, PRIMARY KEY (`id`) diff --git a/skeema/gradido_login/groups.sql b/skeema/gradido_login/groups.sql index c3d0bc787..8c5e143bb 100644 --- a/skeema/gradido_login/groups.sql +++ b/skeema/gradido_login/groups.sql @@ -1,7 +1,8 @@ -CREATE TABLE `groups` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `alias` VARCHAR(255) NOT NULL, - `name` VARCHAR(255) NOT NULL, - `description` TEXT NULL DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file +CREATE TABLE `groups` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `alias` varchar(190) NOT NULL, + `name` varchar(255) NOT NULL, + `description` text, + PRIMARY KEY (`id`), + UNIQUE KEY `alias` (`alias`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/skeema/gradido_login/hedera_accounts.sql b/skeema/gradido_login/hedera_accounts.sql index fc2ad9735..23ffa33d1 100644 --- a/skeema/gradido_login/hedera_accounts.sql +++ b/skeema/gradido_login/hedera_accounts.sql @@ -1,9 +1,11 @@ CREATE TABLE `hedera_accounts` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `user_id` INT UNSIGNED NOT NULL, - `account_hedera_id` INT UNSIGNED NOT NULL, - `account_key_id` INT UNSIGNED NOT NULL, - `balance` BIGINT UNSIGNED NOT NULL DEFAULT '0', - `updated` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (`id`) -) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4; + `id` int unsigned NOT NULL AUTO_INCREMENT, + `user_id` int unsigned NOT NULL, + `account_hedera_id` int unsigned NOT NULL, + `account_key_id` int unsigned NOT NULL, + `balance` bigint unsigned NOT NULL DEFAULT '0', + `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `account_hedera_id` (`account_hedera_id`), + UNIQUE KEY `account_key_id` (`account_key_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/skeema/gradido_login/hedera_ids.sql b/skeema/gradido_login/hedera_ids.sql index 624a02207..b5fd26682 100644 --- a/skeema/gradido_login/hedera_ids.sql +++ b/skeema/gradido_login/hedera_ids.sql @@ -1,7 +1,7 @@ -CREATE TABLE `hedera_ids` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `shardNum` BIGINT NOT NULL DEFAULT '0', - `realmNum` BIGINT NOT NULL DEFAULT '0', - `num` BIGINT NOT NULL, - PRIMARY KEY (`id`) -) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file +CREATE TABLE `hedera_ids` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `shardNum` bigint NOT NULL DEFAULT '0', + `realmNum` bigint NOT NULL DEFAULT '0', + `num` bigint NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file diff --git a/skeema/gradido_login/hedera_topics.sql b/skeema/gradido_login/hedera_topics.sql index c1fa90f2b..6a58174c1 100644 --- a/skeema/gradido_login/hedera_topics.sql +++ b/skeema/gradido_login/hedera_topics.sql @@ -1,13 +1,14 @@ CREATE TABLE `hedera_topics` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `topic_hedera_id` INT UNSIGNED NOT NULL, - `auto_renew_account_hedera_id` INT UNSIGNED NULL, - `auto_renew_period` INT UNSIGNED NOT NULL DEFAULT '0', - `group_id` INT UNSIGNED NOT NULL, - `admin_key_id` INT UNSIGNED NULL, - `submit_key_id` INT UNSIGNED NULL, - `current_timeout` BIGINT UNSIGNED NOT NULL DEFAULT '0', - `sequence_number` BIGINT UNSIGNED NULL DEFAULT '0', - `updated` TIMESTAMP on update CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (`id`) -) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4; + `id` int unsigned NOT NULL AUTO_INCREMENT, + `topic_hedera_id` int unsigned NOT NULL, + `auto_renew_account_hedera_id` int unsigned DEFAULT NULL, + `auto_renew_period` int unsigned NOT NULL DEFAULT '0', + `group_id` int unsigned NOT NULL, + `admin_key_id` int unsigned DEFAULT NULL, + `submit_key_id` int unsigned DEFAULT NULL, + `current_timeout` timestamp NOT NULL DEFAULT '0', + `sequence_number` bigint unsigned DEFAULT '0', + `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `topic_hedera_id` (`topic_hedera_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/skeema/gradido_login/roles.sql b/skeema/gradido_login/roles.sql index b9d51dd11..c99223961 100644 --- a/skeema/gradido_login/roles.sql +++ b/skeema/gradido_login/roles.sql @@ -1,7 +1,7 @@ CREATE TABLE `roles` ( - `id` int UNSIGNED NOT NULL AUTO_INCREMENT, + `id` int unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `description` varchar(255) NOT NULL, - `flags` bigint NOT NULL DEFAULT 0, + `flags` bigint NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/skeema/gradido_login/user_backups.sql b/skeema/gradido_login/user_backups.sql index 699c9a2c6..7e3b7d85a 100644 --- a/skeema/gradido_login/user_backups.sql +++ b/skeema/gradido_login/user_backups.sql @@ -1,5 +1,5 @@ CREATE TABLE `user_backups` ( - `id` int UNSIGNED NOT NULL AUTO_INCREMENT, + `id` int unsigned NOT NULL AUTO_INCREMENT, `user_id` int NOT NULL, `passphrase` text NOT NULL, `mnemonic_type` int DEFAULT '-1', diff --git a/skeema/gradido_login/user_roles.sql b/skeema/gradido_login/user_roles.sql index ac9f0834c..a92154ce8 100644 --- a/skeema/gradido_login/user_roles.sql +++ b/skeema/gradido_login/user_roles.sql @@ -1,5 +1,5 @@ CREATE TABLE `user_roles` ( - `id` int UNSIGNED NOT NULL AUTO_INCREMENT, + `id` int unsigned NOT NULL AUTO_INCREMENT, `user_id` int NOT NULL, `role_id` int NOT NULL, PRIMARY KEY (`id`) diff --git a/skeema/gradido_login/users.sql b/skeema/gradido_login/users.sql index 172f34b56..e3c7deec5 100644 --- a/skeema/gradido_login/users.sql +++ b/skeema/gradido_login/users.sql @@ -1,16 +1,16 @@ CREATE TABLE `users` ( - `id` int UNSIGNED NOT NULL AUTO_INCREMENT, + `id` int unsigned NOT NULL AUTO_INCREMENT, `email` varchar(191) NOT NULL, `first_name` varchar(150) NOT NULL, `last_name` varchar(255) DEFAULT '', `password` bigint unsigned NOT NULL, `pubkey` binary(32) DEFAULT NULL, `privkey` binary(80) DEFAULT NULL, - `created` datetime NOT NULL DEFAULT current_timestamp(), - `email_checked` tinyint NOT NULL DEFAULT 0, - `passphrase_shown` tinyint NOT NULL DEFAULT 0, + `created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `email_checked` tinyint NOT NULL DEFAULT '0', + `passphrase_shown` tinyint NOT NULL DEFAULT '0', `language` varchar(4) NOT NULL DEFAULT 'de', - `disabled` BOOLEAN NULL DEFAULT FALSE, + `disabled` tinyint DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `email` (`email`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/src/cpp/model/table/CryptoKeys.cpp b/src/cpp/model/table/CryptoKeys.cpp index e69de29bb..e159f51cc 100644 --- a/src/cpp/model/table/CryptoKeys.cpp +++ b/src/cpp/model/table/CryptoKeys.cpp @@ -0,0 +1,70 @@ +#include "CryptoKeys.h" +#include "../../lib/DataTypeConverter.h" +using namespace Poco::Data::Keywords; + +namespace model { + namespace table { + CryptoKeys::CryptoKeys() + { + + } + + CryptoKeys::~CryptoKeys() + { + + } + + std::string CryptoKeys::toString() + { + assert(mKeyType < KEY_TYPE_COUNT && mKeyType >= 0); + std::stringstream ss; + ss << "Key Type: " << typeToString(static_cast(mKeyType)) << std::endl; + ss << "Public Key: " << DataTypeConverter::binToHex(mPublicKey); + return ss.str(); + } + + + const char* CryptoKeys::typeToString(KeyType type) + { + switch (type) { + case KEY_TYPE_ED25519_REF10: return "ed25519 ref10"; + case KEY_TYPE_SODIUM_ED25519: return "sodium ed22519"; + } + return ""; + } + + Poco::Data::Statement CryptoKeys::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) + { + Poco::Data::Statement select(session); + + select << "SELECT id, private_key, public_key, crypto_key_type_id FROM " << getTableName() + << " where " << fieldName << " = ?" + , into(mID), into(mPrivateKey), into(mPublicKey), into(mKeyType); + + return select; + } + + Poco::Data::Statement CryptoKeys::_loadIdFromDB(Poco::Data::Session session) + { + Poco::Data::Statement select(session); + lock(); + select << "SELECT id FROM " << getTableName() + << " where public_key = ?" + , into(mID), use(mPublicKey); + unlock(); + return select; + } + + + Poco::Data::Statement CryptoKeys::_insertIntoDB(Poco::Data::Session session) + { + Poco::Data::Statement insert(session); + lock(); + insert << "INSERT INTO " << getTableName() + << " (private_key, public_key, crypto_key_type_id) VALUES(?,?,?)" + , use(mPrivateKey), use(mPublicKey), use(mKeyType); + unlock(); + return insert; + } + } +} \ No newline at end of file diff --git a/src/cpp/model/table/CryptoKeys.h b/src/cpp/model/table/CryptoKeys.h index e69de29bb..15991c70b 100644 --- a/src/cpp/model/table/CryptoKeys.h +++ b/src/cpp/model/table/CryptoKeys.h @@ -0,0 +1,43 @@ +#ifndef GRADIDO_LOGIN_SERVER_MODEL_TABLE_CRYPTO_KEYS_INCLUDE +#define GRADIDO_LOGIN_SERVER_MODEL_TABLE_CRYPTO_KEYS_INCLUDE + +#include "ModelBase.h" +#include "Poco/Types.h" + +namespace model { + namespace table { + + enum KeyType { + KEY_TYPE_SODIUM_ED25519, + KEY_TYPE_ED25519_REF10, + KEY_TYPE_COUNT + }; + + class CryptoKeys : public ModelBase + { + public: + CryptoKeys(); + ~CryptoKeys(); + + // generic db operations + const char* getTableName() const { return "crypto_keys"; } + std::string toString(); + + + static const char* typeToString(KeyType type); + protected: + Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); + Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session); + Poco::Data::Statement _insertIntoDB(Poco::Data::Session session); + + Poco::Nullable mPrivateKey; + Poco::Nullable mPublicKey; + int mKeyType; + + }; + + } +} + + +#endif //GRADIDO_LOGIN_SERVER_MODEL_TABLE_CRYPTO_KEYS_INCLUDE \ No newline at end of file diff --git a/src/cpp/model/table/Groups.cpp b/src/cpp/model/table/Groups.cpp index e69de29bb..e99780783 100644 --- a/src/cpp/model/table/Groups.cpp +++ b/src/cpp/model/table/Groups.cpp @@ -0,0 +1,57 @@ +#include "Groups.h" + +using namespace Poco::Data::Keywords; + +namespace model { + namespace table { + Groups::Groups() + { + } + + Groups::~Groups() + { + + } + + std::string Groups::toString() + { + std::stringstream ss; + ss << "Alias: " << mAlias << std::endl; + ss << "Name: " << mName << std::endl; + ss << "Description:" << mDescription << std::endl; + return ss.str(); + } + + Poco::Data::Statement Groups::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) + { + Poco::Data::Statement select(session); + + select << "SELECT id, alias, name, description FROM " << getTableName() + << " where " << fieldName << " = ?" + , into(mID), into(mAlias), into(mName), into(mDescription); + + return select; + } + Poco::Data::Statement Groups::_loadIdFromDB(Poco::Data::Session session) + { + Poco::Data::Statement select(session); + lock(); + select << "SELECT id FROM " << getTableName() + << " where alias = ?" + , into(mID), use(mAlias); + unlock(); + return select; + + } + Poco::Data::Statement Groups::_insertIntoDB(Poco::Data::Session session) + { + Poco::Data::Statement insert(session); + lock(); + insert << "INSERT INTO " << getTableName() + << " (alias, name, description) VALUES(?,?,?)" + , use(mAlias), use(mName), use(mDescription); + unlock(); + return insert; + } + } +} \ No newline at end of file diff --git a/src/cpp/model/table/Groups.h b/src/cpp/model/table/Groups.h index e69de29bb..adc5789c0 100644 --- a/src/cpp/model/table/Groups.h +++ b/src/cpp/model/table/Groups.h @@ -0,0 +1,35 @@ +#ifndef GRADIDO_LOGIN_SERVER_MODEL_TABLE_GROUPS_INCLUDE +#define GRADIDO_LOGIN_SERVER_MODEL_TABLE_GROUPS_INCLUDE + +#include "ModelBase.h" + +namespace model { + namespace table { + + class Groups : public ModelBase + { + public: + Groups(); + ~Groups(); + + // generic db operations + const char* getTableName() const { return "groups"; } + std::string toString(); + + + protected: + Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); + Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session); + Poco::Data::Statement _insertIntoDB(Poco::Data::Session session); + + std::string mAlias; + std::string mName; + std::string mDescription; + + }; + + } +} + + +#endif //GRADIDO_LOGIN_SERVER_MODEL_TABLE_GROUPS_INCLUDE \ No newline at end of file diff --git a/src/cpp/model/table/HederaAccounts.cpp b/src/cpp/model/table/HederaAccounts.cpp index e69de29bb..3c019374d 100644 --- a/src/cpp/model/table/HederaAccounts.cpp +++ b/src/cpp/model/table/HederaAccounts.cpp @@ -0,0 +1,63 @@ +#include "HederaAccounts.h" + +using namespace Poco::Data::Keywords; + +namespace model { + namespace table { + + HederaAccounts::HederaAccounts() + { + + } + + HederaAccounts::~HederaAccounts() + { + + } + + std::string HederaAccounts::toString() + { + std::stringstream ss; + ss << "user id: " << std::to_string(mUserId) << std::endl; + ss << "account hedera id: " << std::to_string(mAccountHederaId) << std::endl; + ss << "account crypto key id: " << std::to_string(mAccountKeyId) << std::endl; + // balance in tinybars, 100,000,000 tinybar = 1 HashBar + ss << "account balance: " << std::to_string((double)(mBalance) * 100000000.0) << " HBAR" << std::endl; + ss << "last update: " << Poco::DateTimeFormatter::format(mUpdated, "%f.%m.%Y %H:%M:%S") << std::endl; + + return ss.str(); + } + + Poco::Data::Statement HederaAccounts::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) + { + Poco::Data::Statement select(session); + + select << "SELECT id, user_id, account_hedera_id, account_key_id, balance, updated FROM " << getTableName() + << " where " << fieldName << " = ?" + , into(mID), into(mUserId), into(mAccountHederaId), into(mAccountKeyId), into(mBalance), into(mUpdated); + + return select; + + } + Poco::Data::Statement HederaAccounts::_loadIdFromDB(Poco::Data::Session session) + { + Poco::Data::Statement select(session); + lock(); + select << "SELECT id FROM " << getTableName() + << " where account_hedera_id = ?" + , into(mID), use(mAccountHederaId); + unlock(); + return select; + } + Poco::Data::Statement HederaAccounts::_insertIntoDB(Poco::Data::Session session) + { + Poco::Data::Statement insert(session); + lock(); + insert << "INSERT INTO " << getTableName() + << " (user_id, account_hedera_id, account_key_id, balance) VALUES(?,?,?,?)" + , use(mUserId), use(mAccountHederaId), use(mAccountKeyId), use(mBalance); + unlock(); + return insert; + } + } +} \ No newline at end of file diff --git a/src/cpp/model/table/HederaAccounts.h b/src/cpp/model/table/HederaAccounts.h index e69de29bb..74b2063d4 100644 --- a/src/cpp/model/table/HederaAccounts.h +++ b/src/cpp/model/table/HederaAccounts.h @@ -0,0 +1,36 @@ +#ifndef GRADIDO_LOGIN_SERVER_MODEL_TABLE_HEDERA_ACCOUNTS_INCLUDE +#define GRADIDO_LOGIN_SERVER_MODEL_TABLE_HEDERA_ACCOUNTS_INCLUDE + +#include "ModelBase.h" + +namespace model { + namespace table { + + class HederaAccounts : public ModelBase + { + public: + HederaAccounts(); + ~HederaAccounts(); + + // generic db operations + const char* getTableName() const { return "hedera_accounts"; } + std::string toString(); + + + protected: + Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); + Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session); + Poco::Data::Statement _insertIntoDB(Poco::Data::Session session); + + int mUserId; + int mAccountHederaId; + int mAccountKeyId; + Poco::UInt64 mBalance; + Poco::DateTime mUpdated; + }; + + } +} + + +#endif //GRADIDO_LOGIN_SERVER_MODEL_TABLE_HEDERA_ACCOUNTS_INCLUDE \ No newline at end of file diff --git a/src/cpp/model/table/HederaIds.cpp b/src/cpp/model/table/HederaIds.cpp index e69de29bb..8eeed0e55 100644 --- a/src/cpp/model/table/HederaIds.cpp +++ b/src/cpp/model/table/HederaIds.cpp @@ -0,0 +1,58 @@ +#include "HederaIds.h" + +using namespace Poco::Data::Keywords; + +namespace model { + namespace table { + HederaIds::HederaIds() + { + + } + + HederaIds::~HederaIds() + { + + } + + std::string HederaIds::toString() + { + std::stringstream ss; + ss << "Shard Num: " << std::to_string(mShardNum) << std::endl; + ss << "Realm Num: " << std::to_string(mRealmNum) << std::endl; + ss << "Num: " << std::to_string(mNum) << std::endl; + return ss.str(); + } + + Poco::Data::Statement HederaIds::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) + { + + Poco::Data::Statement select(session); + + select << "SELECT id, shardNum, realmNum, num FROM " << getTableName() + << " where " << fieldName << " = ?" + , into(mID), into(mShardNum), into(mRealmNum), into(mNum); + + return select; + } + Poco::Data::Statement HederaIds::_loadIdFromDB(Poco::Data::Session session) + { + Poco::Data::Statement select(session); + lock(); + select << "SELECT id FROM " << getTableName() + << " where shardNum = ? AND realmNum = ? AND num = ?" + , into(mID), use(mShardNum), use(mRealmNum), use(mNum); + unlock(); + return select; + } + Poco::Data::Statement HederaIds::_insertIntoDB(Poco::Data::Session session) + { + Poco::Data::Statement insert(session); + lock(); + insert << "INSERT INTO " << getTableName() + << " (shardNum, realmNum, num) VALUES(?,?,?)" + , use(mShardNum), use(mRealmNum), use(mNum); + unlock(); + return insert; + } + } +} \ No newline at end of file diff --git a/src/cpp/model/table/HederaIds.h b/src/cpp/model/table/HederaIds.h index e69de29bb..eaa6612b8 100644 --- a/src/cpp/model/table/HederaIds.h +++ b/src/cpp/model/table/HederaIds.h @@ -0,0 +1,36 @@ +#ifndef GRADIDO_LOGIN_SERVER_MODEL_TABLE_HEDERA_IDS_INCLUDE +#define GRADIDO_LOGIN_SERVER_MODEL_TABLE_HEDERA_IDS_INCLUDE + +#include "ModelBase.h" +#include "Poco/Types.h" + +namespace model { + namespace table { + + class HederaIds : public ModelBase + { + public: + HederaIds(); + ~HederaIds(); + + // generic db operations + const char* getTableName() const { return "hedera_ids"; } + std::string toString(); + + + protected: + Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); + Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session); + Poco::Data::Statement _insertIntoDB(Poco::Data::Session session); + + Poco::UInt64 mShardNum; + Poco::UInt64 mRealmNum; + Poco::UInt64 mNum; + + }; + + } +} + + +#endif //GRADIDO_LOGIN_SERVER_MODEL_TABLE_HEDERA_IDS_INCLUDE \ No newline at end of file diff --git a/src/cpp/model/table/HederaTopics.cpp b/src/cpp/model/table/HederaTopics.cpp index e69de29bb..aeed1ea05 100644 --- a/src/cpp/model/table/HederaTopics.cpp +++ b/src/cpp/model/table/HederaTopics.cpp @@ -0,0 +1,69 @@ +#include "HederaTopics.h" + +using namespace Poco::Data::Keywords; + +namespace model { + namespace table { + HederaTopics::HederaTopics() + { + + } + + HederaTopics::~HederaTopics() + { + + } + + std::string HederaTopics::toString() + { + std::stringstream ss; + ss << "Topic Hedera id: " << std::to_string(mTopicHederaId) << std::endl; + ss << "Auto Renew Account Hedera id: " << std::to_string(mAutoRenewAccountHederaId) << std::endl; + ss << "Auto Renew Period: " << std::to_string(mAutoRenewPeriod) << " seconds" << std::endl; + ss << "Group id: " << std::to_string(mGroupId) << std::endl; + ss << "Admin Key id: " << std::to_string(mAdminKeyId) << std::endl; + ss << "Submit Key id: " << std::to_string(mSubmitKeyId) << std::endl; + ss << "Hedera Topic Tiemout: " << Poco::DateTimeFormatter::format(mCurrentTimeout, "%f.%m.%Y %H:%M:%S") << std::endl; + ss << "Hedera Topic Sequence Number: " << std::to_string(mSequenceNumber) << std::endl; + ss << "Updated: " << Poco::DateTimeFormatter::format(mUpdated, "%f.%m.%Y %H:%M:%S") << std::endl; + return ss.str(); + } + + Poco::Data::Statement HederaTopics::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) + { + Poco::Data::Statement select(session); + + select << "SELECT id, topic_hedera_id, auto_renew_account_hedera_id, auto_renew_period, " + << "group_id, admin_key_id, submit_key_id, current_timeout, sequence_number, updated FROM " << getTableName() + << " where " << fieldName << " = ?" + , into(mID), into(mTopicHederaId), into(mAutoRenewAccountHederaId), into(mAutoRenewPeriod) + , into(mGroupId), into(mAdminKeyId), into(mSubmitKeyId), into(mCurrentTimeout), into(mSequenceNumber), into(mUpdated); + + return select; + + } + Poco::Data::Statement HederaTopics::_loadIdFromDB(Poco::Data::Session session) + { + Poco::Data::Statement select(session); + lock(); + select << "SELECT id FROM " << getTableName() + << " where topic_hedera_id = ?" + , into(mID), use(mTopicHederaId); + unlock(); + return select; + } + Poco::Data::Statement HederaTopics::_insertIntoDB(Poco::Data::Session session) + { + Poco::Data::Statement insert(session); + lock(); + insert << "INSERT INTO " << getTableName() + << " (topic_hedera_id, auto_renew_account_hedera_id, auto_renew_period," + << " group_id, admin_key_id, submit_key_id, current_timeout, sequence_number) VALUES(?,?,?,?,?,?,?,?)" + , use(mTopicHederaId), use(mAutoRenewAccountHederaId), use(mAutoRenewPeriod) + , use(mGroupId), use(mAdminKeyId), use(mSubmitKeyId), use(mCurrentTimeout), use(mSequenceNumber), use(mUpdated); + unlock(); + return insert; + } + + } +} \ No newline at end of file diff --git a/src/cpp/model/table/HederaTopics.h b/src/cpp/model/table/HederaTopics.h index e69de29bb..4584026ab 100644 --- a/src/cpp/model/table/HederaTopics.h +++ b/src/cpp/model/table/HederaTopics.h @@ -0,0 +1,41 @@ +#ifndef GRADIDO_LOGIN_SERVER_MODEL_TABLE_HEDERA_TOPICS_INCLUDE +#define GRADIDO_LOGIN_SERVER_MODEL_TABLE_HEDERA_TOPICS_INCLUDE + +#include "ModelBase.h" + +namespace model { + namespace table { + + class HederaTopics : public ModelBase + { + public: + HederaTopics(); + ~HederaTopics(); + + // generic db operations + const char* getTableName() const { return "hedera_topics"; } + std::string toString(); + + + protected: + Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); + Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session); + Poco::Data::Statement _insertIntoDB(Poco::Data::Session session); + + Poco::UInt32 mTopicHederaId; + Poco::UInt32 mAutoRenewAccountHederaId; + // in seconds + Poco::UInt32 mAutoRenewPeriod; + Poco::UInt32 mGroupId; + Poco::UInt32 mAdminKeyId; + Poco::UInt32 mSubmitKeyId; + Poco::DateTime mCurrentTimeout; + Poco::UInt64 mSequenceNumber; + Poco::DateTime mUpdated; + }; + + } +} + + +#endif //GRADIDO_LOGIN_SERVER_MODEL_TABLE_HEDERA_TOPICS_INCLUDE \ No newline at end of file From db87207bc0767050d2e2ebcdc67fae84e2d99113 Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 25 Aug 2020 18:02:08 +0200 Subject: [PATCH 010/293] Rename table models to singular --- doc/.gitignore | 1 + .../HTTPInterface/AdminCheckUserBackup.cpp | 6 ++-- .../HTTPInterface/AdminUserPasswordReset.cpp | 8 +++--- .../HTTPInterface/RepairDefectPassphrase.cpp | 4 +-- src/cpp/HTTPInterface/ResetPassword.cpp | 2 +- src/cpp/controller/User.cpp | 4 +-- .../{UserBackups.cpp => UserBackup.cpp} | 28 +++++++++---------- .../{UserBackups.h => UserBackup.h} | 14 +++++----- src/cpp/model/Session.cpp | 8 +++--- src/cpp/model/User.cpp | 4 +-- .../table/{CryptoKeys.cpp => CryptoKey.cpp} | 16 +++++------ .../model/table/{CryptoKeys.h => CryptoKey.h} | 6 ++-- src/cpp/model/table/{Groups.cpp => Group.cpp} | 14 +++++----- src/cpp/model/table/{Groups.h => Group.h} | 6 ++-- .../{HederaAccounts.cpp => HederaAccount.cpp} | 25 ++++++++++++----- .../{HederaAccounts.h => HederaAccount.h} | 10 +++++-- .../table/{HederaIds.cpp => HederaId.cpp} | 14 +++++----- .../model/table/{HederaIds.h => HederaId.h} | 6 ++-- .../{HederaTopics.cpp => HederaTopic.cpp} | 14 +++++----- .../table/{HederaTopics.h => HederaTopic.h} | 6 ++-- src/cpp/model/table/User.cpp | 4 +-- src/cpp/model/table/User.h | 2 +- .../table/{UserBackups.cpp => UserBackup.cpp} | 24 ++++++++-------- .../table/{UserBackups.h => UserBackup.h} | 10 +++---- .../table/{UserRoles.cpp => UserRole.cpp} | 24 ++++++++-------- .../model/table/{UserRoles.h => UserRole.h} | 10 +++---- src/cpsp/adminCheckUserBackup.cpsp | 4 +-- src/cpsp/adminUserPasswordReset.cpsp | 2 +- src/cpsp/repairDefectPassphrase.cpsp | 2 +- 29 files changed, 147 insertions(+), 131 deletions(-) create mode 100644 doc/.gitignore rename src/cpp/controller/{UserBackups.cpp => UserBackup.cpp} (70%) rename src/cpp/controller/{UserBackups.h => UserBackup.h} (68%) rename src/cpp/model/table/{CryptoKeys.cpp => CryptoKey.cpp} (75%) rename src/cpp/model/table/{CryptoKeys.h => CryptoKey.h} (92%) rename src/cpp/model/table/{Groups.cpp => Group.cpp} (73%) rename src/cpp/model/table/{Groups.h => Group.h} (91%) rename src/cpp/model/table/{HederaAccounts.cpp => HederaAccount.cpp} (66%) rename src/cpp/model/table/{HederaAccounts.h => HederaAccount.h} (72%) rename src/cpp/model/table/{HederaIds.cpp => HederaId.cpp} (74%) rename src/cpp/model/table/{HederaIds.h => HederaId.h} (91%) rename src/cpp/model/table/{HederaTopics.cpp => HederaTopic.cpp} (84%) rename src/cpp/model/table/{HederaTopics.h => HederaTopic.h} (92%) rename src/cpp/model/table/{UserBackups.cpp => UserBackup.cpp} (78%) rename src/cpp/model/table/{UserBackups.h => UserBackup.h} (88%) rename src/cpp/model/table/{UserRoles.cpp => UserRole.cpp} (73%) rename src/cpp/model/table/{UserRoles.h => UserRole.h} (90%) diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 000000000..1936cc1d4 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1 @@ +html diff --git a/src/cpp/HTTPInterface/AdminCheckUserBackup.cpp b/src/cpp/HTTPInterface/AdminCheckUserBackup.cpp index 940d084bc..c2ebcd232 100644 --- a/src/cpp/HTTPInterface/AdminCheckUserBackup.cpp +++ b/src/cpp/HTTPInterface/AdminCheckUserBackup.cpp @@ -10,7 +10,7 @@ #include "../Crypto/KeyPair.h" #include "../SingletonManager/ConnectionManager.h" -#include "../controller/UserBackups.h" +#include "../controller/UserBackup.h" #include "Poco/Data/Binding.h" using namespace Poco::Data::Keywords; @@ -20,7 +20,7 @@ typedef Poco::Tuple, std::string> UserBack struct SListEntry { Poco::AutoPtr user; - std::vector> backups; + std::vector> backups; }; #line 1 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_old.cpsp" @@ -94,7 +94,7 @@ void AdminCheckUserBackup::handleRequest(Poco::Net::HTTPServerRequest& request, SListEntry entry; entry.user = controller::User::create(); entry.user->load(user_id); - entry.backups = controller::UserBackups::load(user_id); + entry.backups = controller::UserBackup::load(user_id); notMatchingEntrys.push_back(entry); diff --git a/src/cpp/HTTPInterface/AdminUserPasswordReset.cpp b/src/cpp/HTTPInterface/AdminUserPasswordReset.cpp index 42778fd45..71a2f1bb0 100644 --- a/src/cpp/HTTPInterface/AdminUserPasswordReset.cpp +++ b/src/cpp/HTTPInterface/AdminUserPasswordReset.cpp @@ -10,7 +10,7 @@ // includes #include "../controller/User.h" #include "../controller/EmailVerificationCode.h" -#include "../controller/UserBackups.h" +#include "../controller/UserBackup.h" enum PageState @@ -43,7 +43,7 @@ void AdminUserPasswordReset::handleRequest(Poco::Net::HTTPServerRequest& request PageState state = PAGE_ASK_EMAIL; Poco::AutoPtr user = controller::User::create(); Poco::AutoPtr code; - Poco::AutoPtr userBackup; + Poco::AutoPtr userBackup; bool validUser = false; std::string pageName = "Admin User Passwort Reset"; @@ -69,7 +69,7 @@ void AdminUserPasswordReset::handleRequest(Poco::Net::HTTPServerRequest& request } } - auto backups = controller::UserBackups::load(userId); + auto backups = controller::UserBackup::load(userId); auto userPubkey = user->getModel()->getPublicKey(); for(auto it = backups.begin(); it != backups.end(); it++) { auto keys = (*it)->getKeyPair(); @@ -235,7 +235,7 @@ void AdminUserPasswordReset::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "Bitte schreibe sie dir auf und packe sie gut weg.\n"; responseStream << "\n"; #line 105 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminUserPasswordReset.cpsp" - responseStream << ( controller::UserBackups::formatPassphrase(userBackup->getPassphrase(ServerConfig::Mnemonic_Types::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER)) ); + responseStream << ( controller::UserBackup::formatPassphrase(userBackup->getPassphrase(ServerConfig::Mnemonic_Types::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER)) ); responseStream << "\n"; responseStream << " \n"; responseStream << "\n"; diff --git a/src/cpp/HTTPInterface/RepairDefectPassphrase.cpp b/src/cpp/HTTPInterface/RepairDefectPassphrase.cpp index 3b8087c0c..77fd06514 100644 --- a/src/cpp/HTTPInterface/RepairDefectPassphrase.cpp +++ b/src/cpp/HTTPInterface/RepairDefectPassphrase.cpp @@ -13,7 +13,7 @@ #include "../Crypto/Passphrase.h" #include "../Crypto/KeyPairEd25519.h" #include "../lib/DataTypeConverter.h" -#include "../controller/UserBackups.h" +#include "../controller/UserBackup.h" #include "../tasks/SigningTransaction.h" #include "../ServerConfig.h" @@ -85,7 +85,7 @@ void RepairDefectPassphrase::handleRequest(Poco::Net::HTTPServerRequest& request else { mSession->setPassphrase(passphrase); - auto newPassphraseModel = controller::UserBackups::create( + auto newPassphraseModel = controller::UserBackup::create( user_model->getID(), passphrase->getString(), ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER_FIXED_CASES diff --git a/src/cpp/HTTPInterface/ResetPassword.cpp b/src/cpp/HTTPInterface/ResetPassword.cpp index 23d6b8331..7d1bbd28e 100644 --- a/src/cpp/HTTPInterface/ResetPassword.cpp +++ b/src/cpp/HTTPInterface/ResetPassword.cpp @@ -11,7 +11,7 @@ #include "../SingletonManager/SessionManager.h" #include "../SingletonManager/EmailManager.h" #include "../controller/User.h" -#include "../controller/UserBackups.h" +#include "../controller/UserBackup.h" enum PageState { PAGE_EMAIL_ASK, diff --git a/src/cpp/controller/User.cpp b/src/cpp/controller/User.cpp index 605f11087..f425da9e0 100644 --- a/src/cpp/controller/User.cpp +++ b/src/cpp/controller/User.cpp @@ -1,5 +1,5 @@ #include "User.h" -#include "UserBackups.h" +#include "UserBackup.h" #include "sodium.h" @@ -299,7 +299,7 @@ namespace controller { auto user_model = getModel(); if (user_model->getID() <= 0) return -2; - auto backups = UserBackups::load(user_model->getID()); + auto backups = UserBackup::load(user_model->getID()); if (backups.size() == 0) return -1; for (auto it = backups.begin(); it != backups.end(); it++) { auto user_backup = *it; diff --git a/src/cpp/controller/UserBackups.cpp b/src/cpp/controller/UserBackup.cpp similarity index 70% rename from src/cpp/controller/UserBackups.cpp rename to src/cpp/controller/UserBackup.cpp index bf7096442..9a152592f 100644 --- a/src/cpp/controller/UserBackups.cpp +++ b/src/cpp/controller/UserBackup.cpp @@ -1,14 +1,14 @@ -#include "UserBackups.h" +#include "UserBackup.h" #include "../Crypto/Passphrase.h" namespace controller { - UserBackups::UserBackups(model::table::UserBackups* dbModel) + UserBackup::UserBackup(model::table::UserBackup* dbModel) { mDBModel = dbModel; } - UserBackups::~UserBackups() + UserBackup::~UserBackup() { } @@ -17,20 +17,20 @@ namespace controller { // --------------- static members ----------------------------- - Poco::AutoPtr UserBackups::create(int user_id, const std::string& passphrase, ServerConfig::Mnemonic_Types type) + Poco::AutoPtr UserBackup::create(int user_id, const std::string& passphrase, ServerConfig::Mnemonic_Types type) { - auto db = new model::table::UserBackups(user_id, passphrase, type); - return Poco::AutoPtr(new UserBackups(db)); + auto db = new model::table::UserBackup(user_id, passphrase, type); + return Poco::AutoPtr(new UserBackup(db)); } - std::vector> UserBackups::load(int user_id) + std::vector> UserBackup::load(int user_id) { - auto db = new model::table::UserBackups(); + auto db = new model::table::UserBackup(); auto results = db->loadFromDB("user_id", user_id, 1); - std::vector> resultObjects; + std::vector> resultObjects; if (db->errorCount()) { db->sendErrorsAsEmail(); db->release(); @@ -41,14 +41,14 @@ namespace controller { return resultObjects; } for (auto it = results.begin(); it != results.end(); it++) { - resultObjects.push_back(new UserBackups(new model::table::UserBackups(*it))); + resultObjects.push_back(new UserBackup(new model::table::UserBackup(*it))); } return resultObjects; } - Poco::SharedPtr UserBackups::getKeyPair() + Poco::SharedPtr UserBackup::getKeyPair() { if (!mKeyPair.isNull()) { return mKeyPair; @@ -61,7 +61,7 @@ namespace controller { return mKeyPair; } - KeyPairEd25519* UserBackups::createGradidoKeyPair() + KeyPairEd25519* UserBackup::createGradidoKeyPair() { auto model = getModel(); auto mnemonicType = model->getMnemonicType(); @@ -71,7 +71,7 @@ namespace controller { return KeyPairEd25519::create(passphrase); } - std::string UserBackups::getPassphrase(ServerConfig::Mnemonic_Types type) + std::string UserBackup::getPassphrase(ServerConfig::Mnemonic_Types type) { if ((int)type < 0 || (int)type >= ServerConfig::Mnemonic_Types::MNEMONIC_MAX) { return ""; @@ -96,7 +96,7 @@ namespace controller { } - std::string UserBackups::formatPassphrase(std::string passphrase, int targetLinesCount/* = 5*/) + std::string UserBackup::formatPassphrase(std::string passphrase, int targetLinesCount/* = 5*/) { int count = passphrase.size(); int charPerLine = count / (targetLinesCount); diff --git a/src/cpp/controller/UserBackups.h b/src/cpp/controller/UserBackup.h similarity index 68% rename from src/cpp/controller/UserBackups.h rename to src/cpp/controller/UserBackup.h index c1cb08047..a21d1c3ab 100644 --- a/src/cpp/controller/UserBackups.h +++ b/src/cpp/controller/UserBackup.h @@ -1,7 +1,7 @@ #ifndef GRADIDO_LOGIN_SERVER_CONTROLLER_USER_BACKUPS_INCLUDE #define GRADIDO_LOGIN_SERVER_CONTROLLER_USER_BACKUPS_INCLUDE -#include "../model/table/UserBackups.h" +#include "../model/table/UserBackup.h" #include "../Crypto/KeyPair.h" #include "../Crypto/KeyPairEd25519.h" @@ -10,19 +10,19 @@ #include "TableControllerBase.h" namespace controller { - class UserBackups : public TableControllerBase + class UserBackup : public TableControllerBase { public: - ~UserBackups(); + ~UserBackup(); - static Poco::AutoPtr create(int user_id, const std::string& passphrase, ServerConfig::Mnemonic_Types type); + static Poco::AutoPtr create(int user_id, const std::string& passphrase, ServerConfig::Mnemonic_Types type); - static std::vector> load(int user_id); + static std::vector> load(int user_id); inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } - inline Poco::AutoPtr getModel() { return _getModel(); } + inline Poco::AutoPtr getModel() { return _getModel(); } //! depracted //! \return create keyPair from passphrase if not exist, else return existing pointer @@ -37,7 +37,7 @@ namespace controller { std::string getPassphrase(ServerConfig::Mnemonic_Types type); protected: - UserBackups(model::table::UserBackups* dbModel); + UserBackup(model::table::UserBackup* dbModel); Poco::SharedPtr mKeyPair; }; diff --git a/src/cpp/model/Session.cpp b/src/cpp/model/Session.cpp index 463241fcd..2e24e8610 100644 --- a/src/cpp/model/Session.cpp +++ b/src/cpp/model/Session.cpp @@ -24,7 +24,7 @@ #include "../controller/User.h" -#include "../controller/UserBackups.h" +#include "../controller/UserBackup.h" #include "../controller/EmailVerificationCode.h" #include "table/ModelBase.h" @@ -777,7 +777,7 @@ UserStates Session::loadUser(const std::string& email, const std::string& passwo if (-2 == loginResult) { // check if we have access to the passphrase, if so we can reencrypt the private key auto user_model = mNewUser->getModel(); - auto user_backups = controller::UserBackups::load(user_model->getID()); + auto user_backups = controller::UserBackup::load(user_model->getID()); for (auto it = user_backups.begin(); it != user_backups.end(); it++) { auto key = std::unique_ptr((*it)->createGradidoKeyPair()); if (key->isTheSame(user_model->getPublicKey())) @@ -941,7 +941,7 @@ void Session::detectSessionState() if (USER_NO_KEYS == userState) { auto user_id = mSessionUser->getDBId(); - auto userBackups = controller::UserBackups::load(user_id); + auto userBackups = controller::UserBackup::load(user_id); // check passphrase, only possible while passphrase isn't crypted in db bool correctPassphraseFound = false; @@ -1157,7 +1157,7 @@ bool Session::generateKeys(bool savePrivkey, bool savePassphrase) } if (savePassphrase) { - auto user_backup = controller::UserBackups::create(user_model->getID(), passphrase->getString(), mnemonic_type); + auto user_backup = controller::UserBackup::create(user_model->getID(), passphrase->getString(), mnemonic_type); // sync version //user_backup->getModel()->insertIntoDB(false); diff --git a/src/cpp/model/User.cpp b/src/cpp/model/User.cpp index 27539ecf1..80763d337 100644 --- a/src/cpp/model/User.cpp +++ b/src/cpp/model/User.cpp @@ -12,7 +12,7 @@ #include "../SingletonManager/LanguageManager.h" #include "../SingletonManager/SingletonTaskObserver.h" -#include "../controller/UserBackups.h" +#include "../controller/UserBackup.h" #include "Poco/Data/Binding.h" @@ -1090,7 +1090,7 @@ MemoryBin* User::sign(const unsigned char* message, size_t messageSize) //addError(new Error("User::sign", "decrypt privkey failed")); - auto userBackups = controller::UserBackups::load(mDBId); + auto userBackups = controller::UserBackup::load(mDBId); // get privkey, only possible while passphrase isn't crypted in db bool correctPassphraseFound = false; diff --git a/src/cpp/model/table/CryptoKeys.cpp b/src/cpp/model/table/CryptoKey.cpp similarity index 75% rename from src/cpp/model/table/CryptoKeys.cpp rename to src/cpp/model/table/CryptoKey.cpp index e159f51cc..201047a5b 100644 --- a/src/cpp/model/table/CryptoKeys.cpp +++ b/src/cpp/model/table/CryptoKey.cpp @@ -1,20 +1,20 @@ -#include "CryptoKeys.h" +#include "CryptoKey.h" #include "../../lib/DataTypeConverter.h" using namespace Poco::Data::Keywords; namespace model { namespace table { - CryptoKeys::CryptoKeys() + CryptoKey::CryptoKey() { } - CryptoKeys::~CryptoKeys() + CryptoKey::~CryptoKey() { } - std::string CryptoKeys::toString() + std::string CryptoKey::toString() { assert(mKeyType < KEY_TYPE_COUNT && mKeyType >= 0); std::stringstream ss; @@ -24,7 +24,7 @@ namespace model { } - const char* CryptoKeys::typeToString(KeyType type) + const char* CryptoKey::typeToString(KeyType type) { switch (type) { case KEY_TYPE_ED25519_REF10: return "ed25519 ref10"; @@ -33,7 +33,7 @@ namespace model { return ""; } - Poco::Data::Statement CryptoKeys::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) + Poco::Data::Statement CryptoKey::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) { Poco::Data::Statement select(session); @@ -44,7 +44,7 @@ namespace model { return select; } - Poco::Data::Statement CryptoKeys::_loadIdFromDB(Poco::Data::Session session) + Poco::Data::Statement CryptoKey::_loadIdFromDB(Poco::Data::Session session) { Poco::Data::Statement select(session); lock(); @@ -56,7 +56,7 @@ namespace model { } - Poco::Data::Statement CryptoKeys::_insertIntoDB(Poco::Data::Session session) + Poco::Data::Statement CryptoKey::_insertIntoDB(Poco::Data::Session session) { Poco::Data::Statement insert(session); lock(); diff --git a/src/cpp/model/table/CryptoKeys.h b/src/cpp/model/table/CryptoKey.h similarity index 92% rename from src/cpp/model/table/CryptoKeys.h rename to src/cpp/model/table/CryptoKey.h index 15991c70b..1a04dd387 100644 --- a/src/cpp/model/table/CryptoKeys.h +++ b/src/cpp/model/table/CryptoKey.h @@ -13,11 +13,11 @@ namespace model { KEY_TYPE_COUNT }; - class CryptoKeys : public ModelBase + class CryptoKey : public ModelBase { public: - CryptoKeys(); - ~CryptoKeys(); + CryptoKey(); + ~CryptoKey(); // generic db operations const char* getTableName() const { return "crypto_keys"; } diff --git a/src/cpp/model/table/Groups.cpp b/src/cpp/model/table/Group.cpp similarity index 73% rename from src/cpp/model/table/Groups.cpp rename to src/cpp/model/table/Group.cpp index e99780783..458f8f0dd 100644 --- a/src/cpp/model/table/Groups.cpp +++ b/src/cpp/model/table/Group.cpp @@ -1,19 +1,19 @@ -#include "Groups.h" +#include "Group.h" using namespace Poco::Data::Keywords; namespace model { namespace table { - Groups::Groups() + Group::Group() { } - Groups::~Groups() + Group::~Group() { } - std::string Groups::toString() + std::string Group::toString() { std::stringstream ss; ss << "Alias: " << mAlias << std::endl; @@ -22,7 +22,7 @@ namespace model { return ss.str(); } - Poco::Data::Statement Groups::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) + Poco::Data::Statement Group::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) { Poco::Data::Statement select(session); @@ -32,7 +32,7 @@ namespace model { return select; } - Poco::Data::Statement Groups::_loadIdFromDB(Poco::Data::Session session) + Poco::Data::Statement Group::_loadIdFromDB(Poco::Data::Session session) { Poco::Data::Statement select(session); lock(); @@ -43,7 +43,7 @@ namespace model { return select; } - Poco::Data::Statement Groups::_insertIntoDB(Poco::Data::Session session) + Poco::Data::Statement Group::_insertIntoDB(Poco::Data::Session session) { Poco::Data::Statement insert(session); lock(); diff --git a/src/cpp/model/table/Groups.h b/src/cpp/model/table/Group.h similarity index 91% rename from src/cpp/model/table/Groups.h rename to src/cpp/model/table/Group.h index adc5789c0..bde1b0d68 100644 --- a/src/cpp/model/table/Groups.h +++ b/src/cpp/model/table/Group.h @@ -6,11 +6,11 @@ namespace model { namespace table { - class Groups : public ModelBase + class Group : public ModelBase { public: - Groups(); - ~Groups(); + Group(); + ~Group(); // generic db operations const char* getTableName() const { return "groups"; } diff --git a/src/cpp/model/table/HederaAccounts.cpp b/src/cpp/model/table/HederaAccount.cpp similarity index 66% rename from src/cpp/model/table/HederaAccounts.cpp rename to src/cpp/model/table/HederaAccount.cpp index 3c019374d..4018c653a 100644 --- a/src/cpp/model/table/HederaAccounts.cpp +++ b/src/cpp/model/table/HederaAccount.cpp @@ -1,21 +1,21 @@ -#include "HederaAccounts.h" +#include "HederaAccount.h" using namespace Poco::Data::Keywords; namespace model { namespace table { - HederaAccounts::HederaAccounts() + HederaAccount::HederaAccount() { } - HederaAccounts::~HederaAccounts() + HederaAccount::~HederaAccount() { } - std::string HederaAccounts::toString() + std::string HederaAccount::toString() { std::stringstream ss; ss << "user id: " << std::to_string(mUserId) << std::endl; @@ -28,7 +28,7 @@ namespace model { return ss.str(); } - Poco::Data::Statement HederaAccounts::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) + Poco::Data::Statement HederaAccount::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) { Poco::Data::Statement select(session); @@ -39,7 +39,16 @@ namespace model { return select; } - Poco::Data::Statement HederaAccounts::_loadIdFromDB(Poco::Data::Session session) + + Poco::Data::Statement HederaAccount::_loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName) + { + Poco::Data::Statement select(session); + select << "SELECT id, user_id, account_hedera_id, account_key_id, balance, updated FROM " << getTableName() + << " where " << fieldName << " LIKE ?"; + + return select; + } + Poco::Data::Statement HederaAccount::_loadIdFromDB(Poco::Data::Session session) { Poco::Data::Statement select(session); lock(); @@ -49,7 +58,7 @@ namespace model { unlock(); return select; } - Poco::Data::Statement HederaAccounts::_insertIntoDB(Poco::Data::Session session) + Poco::Data::Statement HederaAccount::_insertIntoDB(Poco::Data::Session session) { Poco::Data::Statement insert(session); lock(); @@ -59,5 +68,7 @@ namespace model { unlock(); return insert; } + + } } \ No newline at end of file diff --git a/src/cpp/model/table/HederaAccounts.h b/src/cpp/model/table/HederaAccount.h similarity index 72% rename from src/cpp/model/table/HederaAccounts.h rename to src/cpp/model/table/HederaAccount.h index 74b2063d4..c9c85b554 100644 --- a/src/cpp/model/table/HederaAccounts.h +++ b/src/cpp/model/table/HederaAccount.h @@ -2,15 +2,18 @@ #define GRADIDO_LOGIN_SERVER_MODEL_TABLE_HEDERA_ACCOUNTS_INCLUDE #include "ModelBase.h" +#include "Poco/Tuple.h" namespace model { namespace table { - class HederaAccounts : public ModelBase + typedef Poco::Tuple HederaAccountsTuple; + + class HederaAccount : public ModelBase { public: - HederaAccounts(); - ~HederaAccounts(); + HederaAccount(); + ~HederaAccount(); // generic db operations const char* getTableName() const { return "hedera_accounts"; } @@ -19,6 +22,7 @@ namespace model { protected: Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); + Poco::Data::Statement _loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName); Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session); Poco::Data::Statement _insertIntoDB(Poco::Data::Session session); diff --git a/src/cpp/model/table/HederaIds.cpp b/src/cpp/model/table/HederaId.cpp similarity index 74% rename from src/cpp/model/table/HederaIds.cpp rename to src/cpp/model/table/HederaId.cpp index 8eeed0e55..b048a0d71 100644 --- a/src/cpp/model/table/HederaIds.cpp +++ b/src/cpp/model/table/HederaId.cpp @@ -1,20 +1,20 @@ -#include "HederaIds.h" +#include "HederaId.h" using namespace Poco::Data::Keywords; namespace model { namespace table { - HederaIds::HederaIds() + HederaId::HederaId() { } - HederaIds::~HederaIds() + HederaId::~HederaId() { } - std::string HederaIds::toString() + std::string HederaId::toString() { std::stringstream ss; ss << "Shard Num: " << std::to_string(mShardNum) << std::endl; @@ -23,7 +23,7 @@ namespace model { return ss.str(); } - Poco::Data::Statement HederaIds::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) + Poco::Data::Statement HederaId::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) { Poco::Data::Statement select(session); @@ -34,7 +34,7 @@ namespace model { return select; } - Poco::Data::Statement HederaIds::_loadIdFromDB(Poco::Data::Session session) + Poco::Data::Statement HederaId::_loadIdFromDB(Poco::Data::Session session) { Poco::Data::Statement select(session); lock(); @@ -44,7 +44,7 @@ namespace model { unlock(); return select; } - Poco::Data::Statement HederaIds::_insertIntoDB(Poco::Data::Session session) + Poco::Data::Statement HederaId::_insertIntoDB(Poco::Data::Session session) { Poco::Data::Statement insert(session); lock(); diff --git a/src/cpp/model/table/HederaIds.h b/src/cpp/model/table/HederaId.h similarity index 91% rename from src/cpp/model/table/HederaIds.h rename to src/cpp/model/table/HederaId.h index eaa6612b8..ef35b2e70 100644 --- a/src/cpp/model/table/HederaIds.h +++ b/src/cpp/model/table/HederaId.h @@ -7,11 +7,11 @@ namespace model { namespace table { - class HederaIds : public ModelBase + class HederaId : public ModelBase { public: - HederaIds(); - ~HederaIds(); + HederaId(); + ~HederaId(); // generic db operations const char* getTableName() const { return "hedera_ids"; } diff --git a/src/cpp/model/table/HederaTopics.cpp b/src/cpp/model/table/HederaTopic.cpp similarity index 84% rename from src/cpp/model/table/HederaTopics.cpp rename to src/cpp/model/table/HederaTopic.cpp index aeed1ea05..ef80ea071 100644 --- a/src/cpp/model/table/HederaTopics.cpp +++ b/src/cpp/model/table/HederaTopic.cpp @@ -1,20 +1,20 @@ -#include "HederaTopics.h" +#include "HederaTopic.h" using namespace Poco::Data::Keywords; namespace model { namespace table { - HederaTopics::HederaTopics() + HederaTopic::HederaTopic() { } - HederaTopics::~HederaTopics() + HederaTopic::~HederaTopic() { } - std::string HederaTopics::toString() + std::string HederaTopic::toString() { std::stringstream ss; ss << "Topic Hedera id: " << std::to_string(mTopicHederaId) << std::endl; @@ -29,7 +29,7 @@ namespace model { return ss.str(); } - Poco::Data::Statement HederaTopics::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) + Poco::Data::Statement HederaTopic::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) { Poco::Data::Statement select(session); @@ -42,7 +42,7 @@ namespace model { return select; } - Poco::Data::Statement HederaTopics::_loadIdFromDB(Poco::Data::Session session) + Poco::Data::Statement HederaTopic::_loadIdFromDB(Poco::Data::Session session) { Poco::Data::Statement select(session); lock(); @@ -52,7 +52,7 @@ namespace model { unlock(); return select; } - Poco::Data::Statement HederaTopics::_insertIntoDB(Poco::Data::Session session) + Poco::Data::Statement HederaTopic::_insertIntoDB(Poco::Data::Session session) { Poco::Data::Statement insert(session); lock(); diff --git a/src/cpp/model/table/HederaTopics.h b/src/cpp/model/table/HederaTopic.h similarity index 92% rename from src/cpp/model/table/HederaTopics.h rename to src/cpp/model/table/HederaTopic.h index 4584026ab..fe5cc342b 100644 --- a/src/cpp/model/table/HederaTopics.h +++ b/src/cpp/model/table/HederaTopic.h @@ -6,11 +6,11 @@ namespace model { namespace table { - class HederaTopics : public ModelBase + class HederaTopic : public ModelBase { public: - HederaTopics(); - ~HederaTopics(); + HederaTopic(); + ~HederaTopic(); // generic db operations const char* getTableName() const { return "hedera_topics"; } diff --git a/src/cpp/model/table/User.cpp b/src/cpp/model/table/User.cpp index e6f694c71..745982a25 100644 --- a/src/cpp/model/table/User.cpp +++ b/src/cpp/model/table/User.cpp @@ -315,7 +315,7 @@ namespace model { ss << "created: " << Poco::DateTimeFormatter::format(mCreated, "%f.%m.%Y %H:%M:%S") << "
"; ss << "email checked: " << mEmailChecked << "
"; ss << "language key: " << mLanguageKey << "
"; - ss << "role: " << UserRoles::typeToString(getRole()) << "
"; + ss << "role: " << UserRole::typeToString(getRole()) << "
"; ss << "disabled: " << mDisabled << "
"; mm->releaseMemory(pubkeyHex); @@ -357,7 +357,7 @@ namespace model { userObj.set("ident_hash", DRMakeStringHash(mEmail.data(), mEmail.size())); userObj.set("disabled", mDisabled); try { - userObj.set("role", UserRoles::typeToString(getRole())); + userObj.set("role", UserRole::typeToString(getRole())); } catch (Poco::Exception ex) { addError(new ParamError("User::getJson", "exception by getting role", ex.displayText().data())); diff --git a/src/cpp/model/table/User.h b/src/cpp/model/table/User.h index 7f8e35c0a..5fb9de668 100644 --- a/src/cpp/model/table/User.h +++ b/src/cpp/model/table/User.h @@ -11,7 +11,7 @@ #include -#include "UserRoles.h" +#include "UserRole.h" namespace model { namespace table { diff --git a/src/cpp/model/table/UserBackups.cpp b/src/cpp/model/table/UserBackup.cpp similarity index 78% rename from src/cpp/model/table/UserBackups.cpp rename to src/cpp/model/table/UserBackup.cpp index 0dbf0adfa..e45a78066 100644 --- a/src/cpp/model/table/UserBackups.cpp +++ b/src/cpp/model/table/UserBackup.cpp @@ -1,4 +1,4 @@ -#include "UserBackups.h" +#include "UserBackup.h" #include "../../controller/User.h" using namespace Poco::Data::Keywords; @@ -6,31 +6,31 @@ using namespace Poco::Data::Keywords; namespace model { namespace table { - UserBackups::UserBackups() + UserBackup::UserBackup() : mUserId(0), mMnemonicType(0) { detectMnemonic(); } - UserBackups::UserBackups(int user_id, const std::string& passphrase, ServerConfig::Mnemonic_Types type) + UserBackup::UserBackup(int user_id, const std::string& passphrase, ServerConfig::Mnemonic_Types type) : mUserId(user_id), mPassphrase(passphrase), mMnemonicType(type) { detectMnemonic(); } - UserBackups::UserBackups(const UserBackupsTuple& tuple) + UserBackup::UserBackup(const UserBackupsTuple& tuple) : ModelBase(tuple.get<0>()), mUserId(tuple.get<1>()), mPassphrase(tuple.get<2>()), mMnemonicType(tuple.get<3>()) { detectMnemonic(); } - UserBackups::~UserBackups() + UserBackup::~UserBackup() { } - Poco::Data::Statement UserBackups::_insertIntoDB(Poco::Data::Session session) + Poco::Data::Statement UserBackup::_insertIntoDB(Poco::Data::Session session) { Poco::Data::Statement insert(session); @@ -43,7 +43,7 @@ namespace model { } - Poco::Data::Statement UserBackups::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) + Poco::Data::Statement UserBackup::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) { Poco::Data::Statement select(session); @@ -55,7 +55,7 @@ namespace model { return select; } - Poco::Data::Statement UserBackups::_loadIdFromDB(Poco::Data::Session session) + Poco::Data::Statement UserBackup::_loadIdFromDB(Poco::Data::Session session) { Poco::Data::Statement select(session); @@ -66,7 +66,7 @@ namespace model { return select; } - Poco::Data::Statement UserBackups::_loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName) + Poco::Data::Statement UserBackup::_loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName) { Poco::Data::Statement select(session); @@ -77,7 +77,7 @@ namespace model { return select; } - Poco::Data::Statement UserBackups::_loadFromDB(Poco::Data::Session session, const std::vector& fieldNames, MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/) + Poco::Data::Statement UserBackup::_loadFromDB(Poco::Data::Session session, const std::vector& fieldNames, MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/) { Poco::Data::Statement select(session); if (fieldNames.size() <= 1) { @@ -107,7 +107,7 @@ namespace model { } // generic db operations - std::string UserBackups::toString() + std::string UserBackup::toString() { std::stringstream ss; ss << "user_id: " << mUserId << std::endl; @@ -116,7 +116,7 @@ namespace model { return ss.str(); } - void UserBackups::detectMnemonic() + void UserBackup::detectMnemonic() { if (mMnemonicType == -1) { const static char* function_name = "UserBackups::detectMnemonic"; diff --git a/src/cpp/model/table/UserBackups.h b/src/cpp/model/table/UserBackup.h similarity index 88% rename from src/cpp/model/table/UserBackups.h rename to src/cpp/model/table/UserBackup.h index d307f8f5d..c5084b0f7 100644 --- a/src/cpp/model/table/UserBackups.h +++ b/src/cpp/model/table/UserBackup.h @@ -9,13 +9,13 @@ namespace model { typedef Poco::Tuple UserBackupsTuple; - class UserBackups : public ModelBase + class UserBackup : public ModelBase { public: - UserBackups(int user_id, const std::string& passphrase, ServerConfig::Mnemonic_Types type); - UserBackups(const UserBackupsTuple& tuple); - UserBackups(); - ~UserBackups(); + UserBackup(int user_id, const std::string& passphrase, ServerConfig::Mnemonic_Types type); + UserBackup(const UserBackupsTuple& tuple); + UserBackup(); + ~UserBackup(); // generic db operations const char* getTableName() const { return "user_backups"; } diff --git a/src/cpp/model/table/UserRoles.cpp b/src/cpp/model/table/UserRole.cpp similarity index 73% rename from src/cpp/model/table/UserRoles.cpp rename to src/cpp/model/table/UserRole.cpp index 0d1f673e9..28e314606 100644 --- a/src/cpp/model/table/UserRoles.cpp +++ b/src/cpp/model/table/UserRole.cpp @@ -1,4 +1,4 @@ -#include "UserRoles.h" +#include "UserRole.h" using namespace Poco::Data::Keywords; @@ -6,28 +6,28 @@ namespace model { namespace table { - UserRoles::UserRoles(int user_id, RoleType type) + UserRole::UserRole(int user_id, RoleType type) : mUserId(user_id), mType(type) { } - UserRoles::UserRoles(const UserRolesTuple& tuple) + UserRole::UserRole(const UserRolesTuple& tuple) : ModelBase(tuple.get<0>()), mUserId(tuple.get<1>()), mType(tuple.get<2>()) { } - UserRoles::UserRoles() + UserRole::UserRole() { } - UserRoles::~UserRoles() + UserRole::~UserRole() { } - Poco::Data::Statement UserRoles::_insertIntoDB(Poco::Data::Session session) + Poco::Data::Statement UserRole::_insertIntoDB(Poco::Data::Session session) { Poco::Data::Statement insert(session); @@ -40,7 +40,7 @@ namespace model { } - Poco::Data::Statement UserRoles::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) + Poco::Data::Statement UserRole::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) { Poco::Data::Statement select(session); @@ -52,7 +52,7 @@ namespace model { return select; } - Poco::Data::Statement UserRoles::_loadIdFromDB(Poco::Data::Session session) + Poco::Data::Statement UserRole::_loadIdFromDB(Poco::Data::Session session) { Poco::Data::Statement select(session); @@ -63,7 +63,7 @@ namespace model { return select; } - Poco::Data::Statement UserRoles::_loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName) + Poco::Data::Statement UserRole::_loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName) { Poco::Data::Statement select(session); @@ -74,7 +74,7 @@ namespace model { return select; } - Poco::Data::Statement UserRoles::_loadFromDB(Poco::Data::Session session, const std::vector& fieldNames, MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/) + Poco::Data::Statement UserRole::_loadFromDB(Poco::Data::Session session, const std::vector& fieldNames, MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/) { Poco::Data::Statement select(session); if (fieldNames.size() <= 1) { @@ -104,7 +104,7 @@ namespace model { } // generic db operations - std::string UserRoles::toString() + std::string UserRole::toString() { std::stringstream ss; ss << "user_id: " << mUserId << std::endl; @@ -112,7 +112,7 @@ namespace model { return ss.str(); } - const char* UserRoles::typeToString(RoleType type) + const char* UserRole::typeToString(RoleType type) { switch (type) { case ROLE_NOT_LOADED: return "not loaded"; diff --git a/src/cpp/model/table/UserRoles.h b/src/cpp/model/table/UserRole.h similarity index 90% rename from src/cpp/model/table/UserRoles.h rename to src/cpp/model/table/UserRole.h index 7b3fad790..7683bff94 100644 --- a/src/cpp/model/table/UserRoles.h +++ b/src/cpp/model/table/UserRole.h @@ -17,13 +17,13 @@ namespace model { typedef Poco::Tuple UserRolesTuple; - class UserRoles : public ModelBase + class UserRole : public ModelBase { public: - UserRoles(int user_id, RoleType type); - UserRoles(const UserRolesTuple& tuple); - UserRoles(); - ~UserRoles(); + UserRole(int user_id, RoleType type); + UserRole(const UserRolesTuple& tuple); + UserRole(); + ~UserRole(); // generic db operations const char* getTableName() const { return "user_roles"; } diff --git a/src/cpsp/adminCheckUserBackup.cpsp b/src/cpsp/adminCheckUserBackup.cpsp index bca35b05a..35ac38ad4 100644 --- a/src/cpsp/adminCheckUserBackup.cpsp +++ b/src/cpsp/adminCheckUserBackup.cpsp @@ -18,7 +18,7 @@ typedef Poco::Tuple, std::string> UserBack struct SListEntry { Poco::AutoPtr user; - std::vector> backups; + std::vector> backups; }; %> @@ -73,7 +73,7 @@ struct SListEntry SListEntry entry; entry.user = controller::User::create(); entry.user->load(user_id); - entry.backups = controller::UserBackups::load(user_id); + entry.backups = controller::UserBackup::load(user_id); notMatchingEntrys.push_back(entry); diff --git a/src/cpsp/adminUserPasswordReset.cpsp b/src/cpsp/adminUserPasswordReset.cpsp index 648a18f61..f534b8c4d 100644 --- a/src/cpsp/adminUserPasswordReset.cpsp +++ b/src/cpsp/adminUserPasswordReset.cpsp @@ -21,7 +21,7 @@ enum PageState PageState state = PAGE_ASK_EMAIL; Poco::AutoPtr user = controller::User::create(); Poco::AutoPtr code; - Poco::AutoPtr userBackup; + Poco::AutoPtr userBackup; bool validUser = false; std::string pageName = "Admin User Passwort Reset"; diff --git a/src/cpsp/repairDefectPassphrase.cpsp b/src/cpsp/repairDefectPassphrase.cpsp index fc9eba7fd..0e8c82e64 100644 --- a/src/cpsp/repairDefectPassphrase.cpsp +++ b/src/cpsp/repairDefectPassphrase.cpsp @@ -64,7 +64,7 @@ enum PageState else { mSession->setPassphrase(passphrase); - auto newPassphraseModel = controller::UserBackups::create( + auto newPassphraseModel = controller::UserBackup::create( user_model->getID(), passphrase->getString(), ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER_FIXED_CASES From f817374c463eb3af295642c9ec0ae1d6ba70dd8c Mon Sep 17 00:00:00 2001 From: Dario Date: Thu, 27 Aug 2020 08:35:18 +0200 Subject: [PATCH 011/293] add groups page for listing and add groups (only for admins) --- skeema/gradido_login/groups.sql | 1 + skeema/gradido_login/hedera_topics.sql | 2 +- src/cpp/HTTPInterface/AdminGroupsPage.cpp | 212 ++++++++++++++++++ src/cpp/HTTPInterface/AdminGroupsPage.h | 20 ++ .../PageRequestHandlerFactory.cpp | 6 + src/cpp/controller/Group.cpp | 69 ++++++ src/cpp/controller/Group.h | 33 +++ src/cpp/model/table/Group.cpp | 41 +++- src/cpp/model/table/Group.h | 19 +- src/cpp/model/table/ModelBase.cpp | 7 + src/cpp/model/table/ModelBase.h | 26 +++ src/cpsp/adminGroups.cpsp | 80 +++++++ 12 files changed, 510 insertions(+), 6 deletions(-) create mode 100644 src/cpp/HTTPInterface/AdminGroupsPage.cpp create mode 100644 src/cpp/HTTPInterface/AdminGroupsPage.h create mode 100644 src/cpp/controller/Group.cpp create mode 100644 src/cpp/controller/Group.h create mode 100644 src/cpsp/adminGroups.cpsp diff --git a/skeema/gradido_login/groups.sql b/skeema/gradido_login/groups.sql index 8c5e143bb..7d4c5a185 100644 --- a/skeema/gradido_login/groups.sql +++ b/skeema/gradido_login/groups.sql @@ -2,6 +2,7 @@ CREATE TABLE `groups` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `alias` varchar(190) NOT NULL, `name` varchar(255) NOT NULL, + `url` varchar(255) NOT NULL, `description` text, PRIMARY KEY (`id`), UNIQUE KEY `alias` (`alias`) diff --git a/skeema/gradido_login/hedera_topics.sql b/skeema/gradido_login/hedera_topics.sql index 6a58174c1..02f7e3b39 100644 --- a/skeema/gradido_login/hedera_topics.sql +++ b/skeema/gradido_login/hedera_topics.sql @@ -6,7 +6,7 @@ CREATE TABLE `hedera_topics` ( `group_id` int unsigned NOT NULL, `admin_key_id` int unsigned DEFAULT NULL, `submit_key_id` int unsigned DEFAULT NULL, - `current_timeout` timestamp NOT NULL DEFAULT '0', + `current_timeout` timestamp NOT NULL DEFAULT '2000-01-01 00:00:00', `sequence_number` bigint unsigned DEFAULT '0', `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), diff --git a/src/cpp/HTTPInterface/AdminGroupsPage.cpp b/src/cpp/HTTPInterface/AdminGroupsPage.cpp new file mode 100644 index 000000000..1e6619801 --- /dev/null +++ b/src/cpp/HTTPInterface/AdminGroupsPage.cpp @@ -0,0 +1,212 @@ +#include "AdminGroupsPage.h" +#include "Poco/Net/HTTPServerRequest.h" +#include "Poco/Net/HTTPServerResponse.h" +#include "Poco/Net/HTMLForm.h" +#include "Poco/DeflatingStream.h" + + +#line 7 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" + + #include "../controller/Group.h" +#line 1 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp" + +#include "../ServerConfig.h" + + +AdminGroupsPage::AdminGroupsPage(Session* arg): + SessionHTTPRequestHandler(arg) +{ +} + + +void AdminGroupsPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) +{ + response.setChunkedTransferEncoding(true); + response.setContentType("text/html"); + bool _compressResponse(request.hasToken("Accept-Encoding", "gzip")); + if (_compressResponse) response.set("Content-Encoding", "gzip"); + + Poco::Net::HTMLForm form(request, request.stream()); +#line 10 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" + + const char* pageName = "Gruppen"; + + // add + if(!form.empty()) { + auto alias = form.get("group-alias"); + if(alias == "") + { + addError(new Error("Add Group", "Alias is empty!")); + } + else + { + auto newGroup = controller::Group::create( + alias, + form.get("group-name", ""), + form.get("group-url", ""), + form.get("group-desc", "") + ); + newGroup->getModel()->insertIntoDB(false); + } + } + + // select all + auto groups = controller::Group::listAll(); + //auto groups = controller::Group::load("gdd1"); + //std::vector> groups; + +#line 3 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp" + + bool withMaterialIcons = false; + std::ostream& _responseStream = response.send(); + Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1); + std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream; + responseStream << "\n"; + // begin include header.cpsp + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "Gradido Login Server: "; +#line 11 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp" + responseStream << ( pageName ); + responseStream << "\n"; + responseStream << "\n"; +#line 13 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp" + if(withMaterialIcons) { responseStream << "\n"; + responseStream << "\n"; +#line 15 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp" + } responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << " "; + // end include header.cpsp + responseStream << "\n"; +#line 38 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" + responseStream << ( getErrorsHtml() ); + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "\t
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\t

Alle Gruppen

\n"; + responseStream << "\t\t
\t\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\t
ID
\n"; + responseStream << "\t\t\t\t
Name
\n"; + responseStream << "\t\t\t\t
Alias
\n"; + responseStream << "\t\t\t\t
Url
\n"; + responseStream << "\t\t\t\t
"; +#line 50 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" + responseStream << ( gettext("Description") ); + responseStream << "
\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t"; +#line 52 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" + for(auto it = groups.begin(); it != groups.end(); it++) { + auto group_model = (*it)->getModel(); responseStream << "\n"; + responseStream << "\t\t\t\t
\n"; + responseStream << "\t\t\t\t\t
"; +#line 55 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" + responseStream << ( group_model->getID() ); + responseStream << "
\n"; + responseStream << "\t\t\t\t\t
"; +#line 56 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" + responseStream << ( group_model->getName() ); + responseStream << "
\n"; + responseStream << "\t\t\t\t\t
"; +#line 57 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" + responseStream << ( group_model->getAlias() ); + responseStream << "
\n"; + responseStream << "\t\t\t\t\t
"; +#line 58 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" + responseStream << ( group_model->getUrl() ); + responseStream << "
\n"; + responseStream << "\t\t\t\t\t
"; +#line 59 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" + responseStream << ( group_model->getDescription()); + responseStream << "
\n"; + responseStream << "\t\t\t\t
\n"; + responseStream << "\t\t\t"; +#line 61 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" + } responseStream << "\n"; + responseStream << "\t\t
\n"; + responseStream << "\t
\n"; + responseStream << "\t
\n"; + responseStream << "\t

Eine neue Gruppe anlegen

\n"; + responseStream << "\t
\n"; + responseStream << "\t
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t
\n"; + responseStream << "
\n"; + // begin include footer.cpsp + responseStream << "
\n"; + responseStream << "

Copyright © Gradido 2020

\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << " "; +#line 6 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp" + responseStream << ( mTimeProfiler.string() ); + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << "

Login Server in Entwicklung

\n"; + responseStream << "

Alpha "; +#line 10 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp" + responseStream << ( ServerConfig::g_versionString ); + responseStream << "

\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << ""; + // end include footer.cpsp + responseStream << "\n"; + if (_compressResponse) _gzipStream.close(); +} diff --git a/src/cpp/HTTPInterface/AdminGroupsPage.h b/src/cpp/HTTPInterface/AdminGroupsPage.h new file mode 100644 index 000000000..43a99ffb4 --- /dev/null +++ b/src/cpp/HTTPInterface/AdminGroupsPage.h @@ -0,0 +1,20 @@ +#ifndef AdminGroupsPage_INCLUDED +#define AdminGroupsPage_INCLUDED + + +#include "Poco/Net/HTTPRequestHandler.h" + + +#include "SessionHTTPRequestHandler.h" + + +class AdminGroupsPage: public SessionHTTPRequestHandler +{ +public: + AdminGroupsPage(Session*); + + void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response); +}; + + +#endif // AdminGroupsPage_INCLUDED diff --git a/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp b/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp index 454cc930a..50dc610af 100644 --- a/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp +++ b/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp @@ -27,6 +27,7 @@ #include "PassphrasedTransaction.h" #include "AdminUserPasswordReset.h" #include "RegisterDirectPage.h" +#include "AdminGroupsPage.h" #include "DecodeTransactionPage.h" #include "RepairDefectPassphrase.h" @@ -206,6 +207,11 @@ Poco::Net::HTTPRequestHandler* PageRequestHandlerFactory::createRequestHandler(c pageRequestHandler->setProfiler(timeUsed); return pageRequestHandler; } + if (url_first_part == "/groups") { + auto pageRequestHandler = new AdminGroupsPage(s); + pageRequestHandler->setProfiler(timeUsed); + return pageRequestHandler; + } } if(url_first_part == "/logout") { diff --git a/src/cpp/controller/Group.cpp b/src/cpp/controller/Group.cpp new file mode 100644 index 000000000..d5b3eb2ba --- /dev/null +++ b/src/cpp/controller/Group.cpp @@ -0,0 +1,69 @@ + +#include "Group.h" + +namespace controller { + + Group::Group(model::table::Group* dbModel) + { + mDBModel = dbModel; + } + + Group::~Group() + { + + } + + Poco::AutoPtr Group::create(const std::string& alias, const std::string& name, const std::string& url, const std::string& description) + { + auto db = new model::table::Group(alias, name, url, description); + auto group = new Group(db); + return Poco::AutoPtr(group); + } + + std::vector> Group::load(const std::string& alias) + { + auto db = new model::table::Group(); + auto group_list = db->loadFromDB("alias", alias, 0); + + std::vector> resultVector; + resultVector.reserve(group_list.size()); + for (auto it = group_list.begin(); it != group_list.end(); it++) { + resultVector.push_back(new Group(new model::table::Group(*it))); + } + return resultVector; + } + + std::vector> Group::listAll() + { + auto db = new model::table::Group(); + std::vector group_list; + // throw an unresolved external symbol error + //group_list = db->loadAllFromDB(); + + // work around for not working call to loadAllFromDB + auto cm = ConnectionManager::getInstance(); + Poco::Data::Statement select(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER)); + + select << "SELECT id, alias, name, url, description FROM " << db->getTableName() + , Poco::Data::Keywords::into(group_list); + + size_t resultCount = 0; + try { + resultCount = select.execute(); + } + catch (Poco::Exception& ex) { + printf("[Group::listAll] poco exception: %s\n", ex.displayText().data()); + } + // work around end + std::vector> resultVector; + + resultVector.reserve(group_list.size()); + for (auto it = group_list.begin(); it != group_list.end(); it++) { + Poco::AutoPtr group_ptr(new Group(new model::table::Group(*it))); + resultVector.push_back(group_ptr); + } + return resultVector; + } + +} + diff --git a/src/cpp/controller/Group.h b/src/cpp/controller/Group.h new file mode 100644 index 000000000..e1ff29b64 --- /dev/null +++ b/src/cpp/controller/Group.h @@ -0,0 +1,33 @@ +#ifndef GRADIDO_LOGIN_SERVER_CONTROLLER_GROUP_INCLUDE +#define GRADIDO_LOGIN_SERVER_CONTROLLER_GROUP_INCLUDE + +#include "../model/table/Group.h" + +#include "Poco/SharedPtr.h" + +#include "TableControllerBase.h" + +namespace controller { + class Group : public TableControllerBase + { + public: + + ~Group(); + + static Poco::AutoPtr create(const std::string& alias, const std::string& name, const std::string& url, const std::string& description); + + static std::vector> load(const std::string& alias); + static std::vector> listAll(); + + inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } + + inline Poco::AutoPtr getModel() { return _getModel(); } + + + protected: + Group(model::table::Group* dbModel); + + }; +} + +#endif //GRADIDO_LOGIN_SERVER_CONTROLLER_GROUP_INCLUDE \ No newline at end of file diff --git a/src/cpp/model/table/Group.cpp b/src/cpp/model/table/Group.cpp index 458f8f0dd..c1a84e832 100644 --- a/src/cpp/model/table/Group.cpp +++ b/src/cpp/model/table/Group.cpp @@ -8,6 +8,19 @@ namespace model { { } + Group::Group(const std::string& alias, const std::string& name, const std::string& url, const std::string& description) + : mAlias(alias), mName(name), mUrl(url), mDescription(description) + { + + } + + Group::Group(GroupTuple tuple) + : ModelBase(tuple.get<0>()), + mAlias(tuple.get<1>()), mName(tuple.get<2>()), mUrl(tuple.get<3>()), mDescription(tuple.get<4>()) + { + + } + Group::~Group() { @@ -18,6 +31,7 @@ namespace model { std::stringstream ss; ss << "Alias: " << mAlias << std::endl; ss << "Name: " << mName << std::endl; + ss << "Url: " << mUrl << std::endl; ss << "Description:" << mDescription << std::endl; return ss.str(); } @@ -26,9 +40,28 @@ namespace model { { Poco::Data::Statement select(session); - select << "SELECT id, alias, name, description FROM " << getTableName() + select << "SELECT id, alias, name, url, description FROM " << getTableName() << " where " << fieldName << " = ?" - , into(mID), into(mAlias), into(mName), into(mDescription); + , into(mID), into(mAlias), into(mName), into(mUrl), into(mDescription); + + return select; + } + + Poco::Data::Statement Group::_loadAllFromDB(Poco::Data::Session session) + { + Poco::Data::Statement select(session); + + select << "SELECT id, alias, name, url, description FROM " << getTableName(); + + return select; + } + + Poco::Data::Statement Group::_loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName) + { + Poco::Data::Statement select(session); + // typedef Poco::Tuple, int> UserTuple; + select << "SELECT id, alias, name, url, description FROM " << getTableName() + << " where " << fieldName << " LIKE ?"; return select; } @@ -48,8 +81,8 @@ namespace model { Poco::Data::Statement insert(session); lock(); insert << "INSERT INTO " << getTableName() - << " (alias, name, description) VALUES(?,?,?)" - , use(mAlias), use(mName), use(mDescription); + << " (alias, name, url, description) VALUES(?,?,?,?)" + , use(mAlias), use(mName), use(mUrl), use(mDescription); unlock(); return insert; } diff --git a/src/cpp/model/table/Group.h b/src/cpp/model/table/Group.h index bde1b0d68..1f6296b92 100644 --- a/src/cpp/model/table/Group.h +++ b/src/cpp/model/table/Group.h @@ -2,30 +2,47 @@ #define GRADIDO_LOGIN_SERVER_MODEL_TABLE_GROUPS_INCLUDE #include "ModelBase.h" +#include "Poco/Tuple.h" namespace model { namespace table { + typedef Poco::Tuple GroupTuple; + class Group : public ModelBase { public: Group(); + Group(const std::string& alias, const std::string& name, const std::string& url, const std::string& description); + Group(GroupTuple userTuple); ~Group(); // generic db operations const char* getTableName() const { return "groups"; } std::string toString(); + inline const std::string& getAlias() const { return mAlias; } + inline const std::string& getName() const { std::shared_lock _lock(mSharedMutex); return mName; } + inline const std::string& getDescription() const { std::shared_lock _lock(mSharedMutex); return mDescription; } + inline const std::string& getUrl() const { std::shared_lock _lock(mSharedMutex); return mUrl; } + + inline void setName(const std::string& name) { std::unique_lock _lock(mSharedMutex); mName = name; } + inline void setDescription(const std::string& desc) { std::unique_lock _lock(mSharedMutex); mDescription = desc; } + inline void setUrl(const std::string& url) { std::unique_lock _lock(mSharedMutex); mUrl = url; } protected: Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); + Poco::Data::Statement _loadAllFromDB(Poco::Data::Session session); + Poco::Data::Statement _loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName); Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session); Poco::Data::Statement _insertIntoDB(Poco::Data::Session session); - + std::string mAlias; std::string mName; + std::string mUrl; std::string mDescription; + mutable std::shared_mutex mSharedMutex; }; } diff --git a/src/cpp/model/table/ModelBase.cpp b/src/cpp/model/table/ModelBase.cpp index 5ba5a5529..4b55ea084 100644 --- a/src/cpp/model/table/ModelBase.cpp +++ b/src/cpp/model/table/ModelBase.cpp @@ -137,6 +137,13 @@ namespace model { throw Poco::Exception(message); } + Poco::Data::Statement ModelBase::_loadAllFromDB(Poco::Data::Session session) + { + std::string message = getTableName(); + message += "::_loadAllFromDB not implemented"; + throw Poco::Exception(message); + } + Poco::DateTime ModelBase::parseElopageDate(std::string dateString) { std::string decodedDateString = ""; diff --git a/src/cpp/model/table/ModelBase.h b/src/cpp/model/table/ModelBase.h index 579fa8304..82e5c273e 100644 --- a/src/cpp/model/table/ModelBase.h +++ b/src/cpp/model/table/ModelBase.h @@ -42,6 +42,8 @@ namespace model { bool isExistInDB(const std::string& fieldName, const T& fieldValue); template std::vector loadFromDB(const std::string& fieldName, const WhereFieldType& fieldValue, int expectedResults = 0); + template + std::vector loadAllFromDB(); template size_t loadFromDB(const std::vector& fieldNames, const T1& field1Value, const T2& field2Value, MysqlConditionType conditionType = MYSQL_CONDITION_AND); template @@ -62,6 +64,7 @@ namespace model { virtual Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session) = 0; virtual Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName) = 0; virtual Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::vector& fieldNames, MysqlConditionType conditionType = MYSQL_CONDITION_AND); + virtual Poco::Data::Statement _loadAllFromDB(Poco::Data::Session session); virtual Poco::Data::Statement _loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName); virtual Poco::Data::Statement _loadMultipleFromDB(Poco::Data::Session session, const std::vector fieldNames, MysqlConditionType conditionType = MYSQL_CONDITION_AND); virtual Poco::Data::Statement _insertIntoDB(Poco::Data::Session session) = 0; @@ -145,6 +148,29 @@ namespace model { return results; } + template + std::vector loadAllFromDB() + { + std::vector results; + Poco::ScopedLock _lock(mWorkMutex); + + auto cm = ConnectionManager::getInstance(); + Poco::Data::Statement select = _loadAllFromDB(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER)); + select, Poco::Data::Keywords::into(results); + + size_t resultCount = 0; + try { + resultCount = select.execute(); + } + catch (Poco::Exception& ex) { + lock(); + addError(new ParamError(getTableName(), "mysql error by selecting all", ex.displayText().data())); + unlock(); + } + + return results; + } + template std::vector ModelBase::loadFromDB(const std::vector& fieldNames, const std::vector& fieldValues, MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/, int expectedResults/* = 0*/) { diff --git a/src/cpsp/adminGroups.cpsp b/src/cpsp/adminGroups.cpsp new file mode 100644 index 000000000..e357388af --- /dev/null +++ b/src/cpsp/adminGroups.cpsp @@ -0,0 +1,80 @@ +<%@ page class="AdminGroupsPage" %> +<%@ page form="true" %> +<%@ page compressed="true" %> +<%@ page baseClass="SessionHTTPRequestHandler" %> +<%@ page ctorArg="Session*" %> +<%@ header include="SessionHTTPRequestHandler.h" %> +<%! + #include "../controller/Group.h" +%> +<%% + const char* pageName = "Gruppen"; + + // add + if(!form.empty()) { + auto alias = form.get("group-alias"); + if(alias == "") + { + addError(new Error("Add Group", "Alias is empty!")); + } + else + { + auto newGroup = controller::Group::create( + alias, + form.get("group-name", ""), + form.get("group-url", ""), + form.get("group-desc", "") + ); + newGroup->getModel()->insertIntoDB(false); + } + } + + // select all + auto groups = controller::Group::listAll(); + //auto groups = controller::Group::load("gdd1"); + //std::vector> groups; + +%><%@ include file="header.cpsp" %> +<%= getErrorsHtml() %> +
+
+
+

Alle Gruppen

+
+
+
+
ID
+
Name
+
Alias
+
Url
+
<%= gettext("Description") %>
+
+ <% for(auto it = groups.begin(); it != groups.end(); it++) { + auto group_model = (*it)->getModel(); %> +
+
<%= group_model->getID() %>
+
<%= group_model->getName() %>
+
<%= group_model->getAlias() %>
+
<%= group_model->getUrl() %>
+
<%= group_model->getDescription()%>
+
+ <% } %> +
+
+
+

Eine neue Gruppe anlegen

+
+
+
+ + + + + + + + + "> +
+
+<%@ include file="footer.cpsp" %> From 6a8c0d07254e3a6fb39306b016115dc2e1030b03 Mon Sep 17 00:00:00 2001 From: Dario Date: Fri, 28 Aug 2020 12:33:11 +0200 Subject: [PATCH 012/293] add KeyPairHedera mostly copied from KeyPairEd25519 but not testet yet. Maybe I must use the iroha ed25519 implementation because in the past sodium don't work together with hedera --- src/cpp/Crypto/KeyPairHedera.cpp | 148 +++++++++++++++++++++++++++++++ src/cpp/Crypto/KeyPairHedera.h | 82 +++++++++++++++++ 2 files changed, 230 insertions(+) create mode 100644 src/cpp/Crypto/KeyPairHedera.cpp create mode 100644 src/cpp/Crypto/KeyPairHedera.h diff --git a/src/cpp/Crypto/KeyPairHedera.cpp b/src/cpp/Crypto/KeyPairHedera.cpp new file mode 100644 index 000000000..80c4649b1 --- /dev/null +++ b/src/cpp/Crypto/KeyPairHedera.cpp @@ -0,0 +1,148 @@ +#include "KeyPairHedera.h" +#include "../lib/DataTypeConverter.h" +#include + +#include "../SingletonManager/ErrorManager.h" + +KeyPairHedera::KeyPairHedera() + : mPrivateKey(nullptr) +{ + +} + + +KeyPairHedera::KeyPairHedera(const MemoryBin* privateKey, const MemoryBin* publicKey /* = nullptr*/) + : mPrivateKey(nullptr) +{ + auto derPrefixPriv = DataTypeConverter::hexToBin("302e020100300506032b657004220420"); + auto derPrefixPub = DataTypeConverter::hexToBin("302a300506032b6570032100"); + + auto mm = MemoryManager::getInstance(); + + if (privateKey) { + switch (privateKey->size()) { + case 48: + // key with prefix + if (0 == sodium_memcmp(*privateKey, *derPrefixPriv, derPrefixPriv->size())) { + //int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk, const unsigned char *seed); + auto seed = mm->getFreeMemory(crypto_sign_ed25519_SEEDBYTES); + memcpy(*seed, privateKey->data(derPrefixPriv->size()), crypto_sign_ed25519_SEEDBYTES); + createKeyFromSeed(seed); + break; + } + case 32: + createKeyFromSeed(privateKey); + break; + case 64: + //mPrivateKey = privateKey; + if (!mPrivateKey || mPrivateKey->size() != privateKey->size()) { + if (mPrivateKey) { + mm->releaseMemory(mPrivateKey); + } + mPrivateKey = mm->getFreeMemory(privateKey->size()); + memcpy(*mPrivateKey, *privateKey, privateKey->size()); + } + break; + default: + throw std::exception("[KeyPairHedera] invalid private key"); + } + crypto_sign_ed25519_sk_to_pk(mPublicKey, *mPrivateKey); + } + else if (publicKey) { + switch (publicKey->size()) + { + case 32: { // raw public key + memcpy(mPublicKey, *publicKey, publicKey->size()); + break; + } + case 44: // DER encoded public key + if (0 == sodium_memcmp(*publicKey, *derPrefixPub, derPrefixPub->size())) { + memcpy(mPublicKey, publicKey->data(derPrefixPub->size()), ed25519_pubkey_SIZE); + } + break; + default: + throw std::exception("[KeyPairHedera] invalid public key"); + } + } + + + mm->releaseMemory(derPrefixPriv); + mm->releaseMemory(derPrefixPub); +} + +KeyPairHedera::~KeyPairHedera() +{ + auto mm = MemoryManager::getInstance(); + if (mPrivateKey) { + mm->releaseMemory(mPrivateKey); + mPrivateKey = nullptr; + } +} + + +void KeyPairHedera::createKeyFromSeed(const MemoryBin* seed) +{ + assert(seed && seed->size() == crypto_sign_ed25519_SEEDBYTES); + + auto mm = MemoryManager::getInstance(); + auto secret_key = mm->getFreeMemory(crypto_sign_SECRETKEYBYTES); + crypto_sign_seed_keypair(mPublicKey, *secret_key, *seed); + + if (mPrivateKey) { + mm->releaseMemory(mPrivateKey); + } + mPrivateKey = secret_key; + + // iroha + //ed25519_privkey_SIZE + //ed25519_derive_public_key(const private_key_t* sk,public_key_t* pk); +} + +MemoryBin* KeyPairHedera::sign(const unsigned char* message, size_t messageSize) const +{ + if (!message || !messageSize) return nullptr; + if (!mPrivateKey) return nullptr; + auto mm = MemoryManager::getInstance(); + auto em = ErrorManager::getInstance(); + + const static char functionName[] = "KeyPairHedera::sign"; + + auto signBinBuffer = mm->getFreeMemory(crypto_sign_BYTES); + unsigned long long actualSignLength = 0; + + if (crypto_sign_detached(*signBinBuffer, &actualSignLength, message, messageSize, *mPrivateKey)) { + em->addError(new Error(functionName, "sign failed")); + auto messageHex = DataTypeConverter::binToHex(message, messageSize); + em->addError(new ParamError(functionName, "message as hex", messageHex)); + mm->releaseMemory(signBinBuffer); + return nullptr; + } + + if (crypto_sign_verify_detached(*signBinBuffer, message, messageSize, mPublicKey) != 0) { + // Incorrect signature! + //printf("c[KeyBuffer::%s] sign verify failed\n", __FUNCTION__); + em->addError(new Error(functionName, "sign verify failed")); + auto messageHex = DataTypeConverter::binToHex(message, messageSize); + em->addError(new ParamError(functionName, "message as hex", messageHex)); + mm->releaseMemory(signBinBuffer); + return nullptr; + } + + // debug + /*const size_t hex_sig_size = crypto_sign_BYTES * 2 + 1; + char sig_hex[hex_sig_size]; + sodium_bin2hex(sig_hex, hex_sig_size, *signBinBuffer, crypto_sign_BYTES); + printf("[User::sign] signature hex: %s\n", sig_hex); + */ + + return signBinBuffer; + +} + +bool KeyPairHedera::verify(const unsigned char* message, size_t messageSize, MemoryBin* signature) const +{ + if (crypto_sign_verify_detached(*signature, message, messageSize, mPublicKey) != 0) { + return false; + } + return true; +} \ No newline at end of file diff --git a/src/cpp/Crypto/KeyPairHedera.h b/src/cpp/Crypto/KeyPairHedera.h new file mode 100644 index 000000000..358a3b680 --- /dev/null +++ b/src/cpp/Crypto/KeyPairHedera.h @@ -0,0 +1,82 @@ +#ifndef __GRADIDO_LOGIN_SERVER_CRYPTO_HEDERA_KEYS_H +#define __GRADIDO_LOGIN_SERVER_CRYPTO_HEDERA_KEYS_H + +#include "IKeyPair.h" + +/*! +* \author: Dario Rekowski +* +* \date: 2020-08-28 +* +* \brief: Key Pairs class for ed25519 keys, used by hedera for transaction sign +*/ + + +#include "sodium.h" +#include "iroha-ed25519/include/ed25519/ed25519.h" + +class KeyPairHedera : public IKeyPair +{ +public: + //! \param privateKey: copy + //! \param publicKey: copy + //! + KeyPairHedera(const MemoryBin* privateKey, const MemoryBin* publicKey = nullptr); + + ~KeyPairHedera(); + + + //! \return caller take ownership of return value + MemoryBin* sign(const MemoryBin* message) const { return sign(message->data(), message->size()); } + inline MemoryBin* sign(const std::string& bodyBytes) const { return sign((const unsigned char*)bodyBytes.data(), bodyBytes.size()); } + MemoryBin* sign(const unsigned char* message, size_t messageSize) const; + + bool verify(const unsigned char* message, size_t messageSize, MemoryBin* signature) const; + + inline const unsigned char* getPublicKey() const { return mPublicKey; } + + inline bool isTheSame(const KeyPairHedera& b) const { + return 0 == sodium_memcmp(mPublicKey, b.mPublicKey, ed25519_pubkey_SIZE); + } + inline bool isTheSame(const unsigned char* pubkey) const { + if (!pubkey) + return false; + return 0 == sodium_memcmp(mPublicKey, pubkey, ed25519_pubkey_SIZE); + } + //! \return 0 if the same + //! \return -1 if not the same + //! \return 1 if hasn't private key + inline int isTheSame(const MemoryBin* privkey) const { + if (!mPrivateKey) return 1; + if (privkey->size() != mPrivateKey->size()) return -1; + return sodium_memcmp(*mPrivateKey, *privkey, privkey->size()); + } + + inline bool operator == (const KeyPairHedera& b) const { return isTheSame(b); } + inline bool operator != (const KeyPairHedera& b) const { return !isTheSame(b); } + + inline bool operator == (const unsigned char* b) const { return isTheSame(b); } + inline bool operator != (const unsigned char* b) const { return !isTheSame(b); } + + inline bool hasPrivateKey() const { return mPrivateKey != nullptr; } + + + +protected: + + KeyPairHedera(); + void createKeyFromSeed(const MemoryBin* seed); + +private: + // 64 Byte + //! \brief ed25519 libsodium private key + //! + //! TODO: replace MemoryBin by a memory obfuscation class which make it hard to steal the private key from memory + MemoryBin* mPrivateKey; + + // 32 Byte + //! \brief ed25519 libsodium public key + unsigned char mPublicKey[ed25519_pubkey_SIZE]; +}; + +#endif //__GRADIDO_LOGIN_SERVER_CRYPTO_HEDERA_KEYS_H \ No newline at end of file From d8bb2d5c1e2c2ea02c16db8745ae4d595a66f08a Mon Sep 17 00:00:00 2001 From: Dario Date: Fri, 28 Aug 2020 12:34:33 +0200 Subject: [PATCH 013/293] update comments, answer question --- src/cpp/Crypto/KeyPairEd25519.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cpp/Crypto/KeyPairEd25519.h b/src/cpp/Crypto/KeyPairEd25519.h index 75a1ce9f1..08da7030d 100644 --- a/src/cpp/Crypto/KeyPairEd25519.h +++ b/src/cpp/Crypto/KeyPairEd25519.h @@ -9,6 +9,7 @@ * \date: 2020-06-04 * * \brief: Key Pairs class for ed25519 keys, used for default gradido transactions + * TODO: add verify method */ @@ -75,6 +76,9 @@ private: //! \brief ed25519 libsodium private key //! //! Why it is a pointer and the public is an array? + //! Because MemoryBin should be replaced by a memory obfuscation class which make it harder to steal the private key from computer memory + //! And because private key can be nullptr for example to verify a signed message + //! TODO: replace MemoryBin by a memory obfuscation class which make it hard to steal the private key from memory MemoryBin* mSodiumSecret; From f8c7d76530cb7cd778c48c850fe661e200b62125 Mon Sep 17 00:00:00 2001 From: Dario Date: Fri, 28 Aug 2020 12:36:02 +0200 Subject: [PATCH 014/293] extend memory bin to get access of part of data, for example copy the last half of it --- src/cpp/SingletonManager/MemoryManager.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cpp/SingletonManager/MemoryManager.h b/src/cpp/SingletonManager/MemoryManager.h index 7cb9233f7..591148083 100644 --- a/src/cpp/SingletonManager/MemoryManager.h +++ b/src/cpp/SingletonManager/MemoryManager.h @@ -18,6 +18,7 @@ #include #include +#include #define MEMORY_MANAGER_PAGE_SIZE 10 @@ -41,6 +42,8 @@ public: inline unsigned char* data() { return mData; } inline const unsigned char* data() const { return mData; } + inline unsigned char* data(size_t startIndex) { assert(startIndex < mSize); return &mData[startIndex]; } + inline const unsigned char* data(size_t startIndex) const { assert(startIndex < mSize); return &mData[startIndex]; } std::string convertToHex(); //! \return 0 if ok //! -1 if bin is to small From fc11929fc1be96018f50d38fa18ed71a4c874b2d Mon Sep 17 00:00:00 2001 From: Dario Date: Fri, 28 Aug 2020 12:37:13 +0200 Subject: [PATCH 015/293] Add hedera account page files and classes needed for this --- .../HTTPInterface/AdminHederaAccountPage.cpp | 125 ++++++++++++++++++ .../HTTPInterface/AdminHederaAccountPage.h | 20 +++ .../PageRequestHandlerFactory.cpp | 12 ++ src/cpp/controller/HederaAccount.cpp | 69 ++++++++++ src/cpp/controller/HederaAccount.h | 33 +++++ src/cpp/model/table/CryptoKey.h | 4 +- src/cpp/model/table/HederaAccount.cpp | 14 ++ src/cpp/model/table/HederaAccount.h | 4 +- src/cpsp/adminTopic.cpsp | 23 ++++ src/cpsp/header_large.cpsp | 19 +++ 10 files changed, 320 insertions(+), 3 deletions(-) create mode 100644 src/cpp/HTTPInterface/AdminHederaAccountPage.cpp create mode 100644 src/cpp/HTTPInterface/AdminHederaAccountPage.h create mode 100644 src/cpp/controller/HederaAccount.cpp create mode 100644 src/cpp/controller/HederaAccount.h create mode 100644 src/cpsp/adminTopic.cpsp create mode 100644 src/cpsp/header_large.cpsp diff --git a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp new file mode 100644 index 000000000..0500a8996 --- /dev/null +++ b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp @@ -0,0 +1,125 @@ +#include "AdminHederaAccountPage.h" +#include "Poco/Net/HTTPServerRequest.h" +#include "Poco/Net/HTTPServerResponse.h" +#include "Poco/Net/HTMLForm.h" +#include "Poco/DeflatingStream.h" + + +#line 7 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + + #include "../controller/HederaAccount.h" +#line 1 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + +#include "../ServerConfig.h" + + +AdminHederaAccountPage::AdminHederaAccountPage(Session* arg): + SessionHTTPRequestHandler(arg) +{ +} + + +void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) +{ + response.setChunkedTransferEncoding(true); + response.setContentType("text/html"); + bool _compressResponse(request.hasToken("Accept-Encoding", "gzip")); + if (_compressResponse) response.set("Content-Encoding", "gzip"); + + Poco::Net::HTMLForm form(request, request.stream()); +#line 10 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + + const char* pageName = "Hedera Account"; + + // add + if(!form.empty()) { + + } + + + +#line 3 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + + bool withMaterialIcons = false; + std::ostream& _responseStream = response.send(); + Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1); + std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream; + responseStream << "\n"; + // begin include header_large.cpsp + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "Gradido Login Server: "; +#line 11 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + responseStream << ( pageName ); + responseStream << "\n"; + responseStream << "\n"; +#line 13 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + if(withMaterialIcons) { responseStream << "\n"; + responseStream << "\n"; +#line 15 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + } responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "\t\t
"; + // end include header_large.cpsp + responseStream << "\n"; +#line 21 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + responseStream << ( getErrorsHtml() ); + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "\t
\n"; + responseStream << "\t

Einen neuen Account anlegen

\n"; + responseStream << "\t
\n"; + responseStream << "\t
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t
\n"; + responseStream << "
\n"; + // begin include footer.cpsp + responseStream << "
\n"; + responseStream << "

Copyright © Gradido 2020

\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << " "; +#line 6 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp" + responseStream << ( mTimeProfiler.string() ); + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << "

Login Server in Entwicklung

\n"; + responseStream << "

Alpha "; +#line 10 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp" + responseStream << ( ServerConfig::g_versionString ); + responseStream << "

\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << ""; + // end include footer.cpsp + responseStream << "\n"; + if (_compressResponse) _gzipStream.close(); +} diff --git a/src/cpp/HTTPInterface/AdminHederaAccountPage.h b/src/cpp/HTTPInterface/AdminHederaAccountPage.h new file mode 100644 index 000000000..b35f6ffb3 --- /dev/null +++ b/src/cpp/HTTPInterface/AdminHederaAccountPage.h @@ -0,0 +1,20 @@ +#ifndef AdminHederaAccountPage_INCLUDED +#define AdminHederaAccountPage_INCLUDED + + +#include "Poco/Net/HTTPRequestHandler.h" + + +#include "SessionHTTPRequestHandler.h" + + +class AdminHederaAccountPage: public SessionHTTPRequestHandler +{ +public: + AdminHederaAccountPage(Session*); + + void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response); +}; + + +#endif // AdminHederaAccountPage_INCLUDED diff --git a/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp b/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp index 50dc610af..11cdb7d78 100644 --- a/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp +++ b/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp @@ -28,6 +28,8 @@ #include "AdminUserPasswordReset.h" #include "RegisterDirectPage.h" #include "AdminGroupsPage.h" +#include "AdminTopicPage.h" +#include "AdminHederaAccountPage.h" #include "DecodeTransactionPage.h" #include "RepairDefectPassphrase.h" @@ -212,6 +214,16 @@ Poco::Net::HTTPRequestHandler* PageRequestHandlerFactory::createRequestHandler(c pageRequestHandler->setProfiler(timeUsed); return pageRequestHandler; } + if (url_first_part == "/topic") { + auto pageRequestHandler = new AdminTopicPage(s); + pageRequestHandler->setProfiler(timeUsed); + return pageRequestHandler; + } + if (url_first_part == "/hedera_account") { + auto pageRequestHandler = new AdminHederaAccountPage(s); + pageRequestHandler->setProfiler(timeUsed); + return pageRequestHandler; + } } if(url_first_part == "/logout") { diff --git a/src/cpp/controller/HederaAccount.cpp b/src/cpp/controller/HederaAccount.cpp new file mode 100644 index 000000000..9a858bd7c --- /dev/null +++ b/src/cpp/controller/HederaAccount.cpp @@ -0,0 +1,69 @@ + +#include "HederaAccount.h" + +namespace controller { + + HederaAccount::HederaAccount(model::table::HederaAccount* dbModel) + { + mDBModel = dbModel; + } + + HederaAccount::~HederaAccount() + { + + } + + Poco::AutoPtr HederaAccount::create(int user_id, int account_hedera_id, int account_key_id, Poco::UInt64 balance/* = 0*/) + { + auto db = new model::table::HederaAccount(user_id, account_hedera_id, account_key_id, balance); + auto group = new HederaAccount(db); + return Poco::AutoPtr(group); + } + + std::vector> HederaAccount::load(const std::string& alias) + { + auto db = new model::table::HederaAccount(); + auto group_list = db->loadFromDB("alias", alias, 0); + + std::vector> resultVector; + resultVector.reserve(group_list.size()); + for (auto it = group_list.begin(); it != group_list.end(); it++) { + resultVector.push_back(new HederaAccount(new model::table::HederaAccount(*it))); + } + return resultVector; + } + + std::vector> HederaAccount::listAll() + { + auto db = new model::table::HederaAccount(); + std::vector group_list; + // throw an unresolved external symbol error + //group_list = db->loadAllFromDB(); + + // work around for not working call to loadAllFromDB + auto cm = ConnectionManager::getInstance(); + Poco::Data::Statement select(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER)); + + select << "SELECT id, alias, name, url, description FROM " << db->getTableName() + , Poco::Data::Keywords::into(group_list); + + size_t resultCount = 0; + try { + resultCount = select.execute(); + } + catch (Poco::Exception& ex) { + printf("[Group::listAll] poco exception: %s\n", ex.displayText().data()); + } + // work around end + std::vector> resultVector; + + resultVector.reserve(group_list.size()); + for (auto it = group_list.begin(); it != group_list.end(); it++) { + Poco::AutoPtr group_ptr(new HederaAccount(new model::table::HederaAccount(*it))); + resultVector.push_back(group_ptr); + } + return resultVector; + } + +} + diff --git a/src/cpp/controller/HederaAccount.h b/src/cpp/controller/HederaAccount.h new file mode 100644 index 000000000..9efd89c12 --- /dev/null +++ b/src/cpp/controller/HederaAccount.h @@ -0,0 +1,33 @@ +#ifndef GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_ACCOUNT_INCLUDE +#define GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_ACCOUNT_INCLUDE + +#include "../model/table/HederaAccount.h" + +#include "Poco/SharedPtr.h" + +#include "TableControllerBase.h" + +namespace controller { + class HederaAccount : public TableControllerBase + { + public: + + ~HederaAccount(); + + static Poco::AutoPtr create(int user_id, int account_hedera_id, int account_key_id, Poco::UInt64 balance = 0); + + static std::vector> load(const std::string& alias); + static std::vector> listAll(); + + inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } + + inline Poco::AutoPtr getModel() { return _getModel(); } + + + protected: + HederaAccount(model::table::HederaAccount* dbModel); + + }; +} + +#endif //GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_ACCOUNT_INCLUDE \ No newline at end of file diff --git a/src/cpp/model/table/CryptoKey.h b/src/cpp/model/table/CryptoKey.h index 1a04dd387..f4fd8bebf 100644 --- a/src/cpp/model/table/CryptoKey.h +++ b/src/cpp/model/table/CryptoKey.h @@ -8,8 +8,8 @@ namespace model { namespace table { enum KeyType { - KEY_TYPE_SODIUM_ED25519, - KEY_TYPE_ED25519_REF10, + KEY_TYPE_SODIUM_ED25519 = 0, + KEY_TYPE_ED25519_REF10 = 1, KEY_TYPE_COUNT }; diff --git a/src/cpp/model/table/HederaAccount.cpp b/src/cpp/model/table/HederaAccount.cpp index 4018c653a..63c6068bc 100644 --- a/src/cpp/model/table/HederaAccount.cpp +++ b/src/cpp/model/table/HederaAccount.cpp @@ -6,6 +6,20 @@ namespace model { namespace table { HederaAccount::HederaAccount() + : mUserId(0), mAccountHederaId(0), mAccountKeyId(0), mBalance(0) + { + + } + + HederaAccount::HederaAccount(int user_id, int account_hedera_id, int account_key_id, Poco::UInt64 balance/* = 0*/) + : mUserId(user_id), mAccountHederaId(account_hedera_id), mAccountKeyId(account_key_id), mBalance(balance) + { + + } + + HederaAccount::HederaAccount(const HederaAccountTuple& tuple) + : ModelBase(tuple.get<0>()), + mUserId(tuple.get<1>()), mAccountHederaId(tuple.get<2>()), mAccountKeyId(tuple.get<3>()), mBalance(tuple.get<4>()), mUpdated(tuple.get<5>()) { } diff --git a/src/cpp/model/table/HederaAccount.h b/src/cpp/model/table/HederaAccount.h index c9c85b554..ca56dfd62 100644 --- a/src/cpp/model/table/HederaAccount.h +++ b/src/cpp/model/table/HederaAccount.h @@ -7,12 +7,14 @@ namespace model { namespace table { - typedef Poco::Tuple HederaAccountsTuple; + typedef Poco::Tuple HederaAccountTuple; class HederaAccount : public ModelBase { public: HederaAccount(); + HederaAccount(int user_id, int account_hedera_id, int account_key_id, Poco::UInt64 balance = 0); + HederaAccount(const HederaAccountTuple& tuple); ~HederaAccount(); // generic db operations diff --git a/src/cpsp/adminTopic.cpsp b/src/cpsp/adminTopic.cpsp new file mode 100644 index 000000000..3eac5a976 --- /dev/null +++ b/src/cpsp/adminTopic.cpsp @@ -0,0 +1,23 @@ +<%@ page class="AdminTopicPage" %> +<%@ page form="true" %> +<%@ page compressed="true" %> +<%@ page baseClass="SessionHTTPRequestHandler" %> +<%@ page ctorArg="Session*" %> +<%@ header include="SessionHTTPRequestHandler.h" %> +<%! + +%> +<%% + const char* pageName = "Topic"; + + + +%><%@ include file="header_large.cpsp" %> +<%= getErrorsHtml() %> +
+

Topic Admin Page

+
+
+ +
+<%@ include file="footer.cpsp" %> diff --git a/src/cpsp/header_large.cpsp b/src/cpsp/header_large.cpsp new file mode 100644 index 000000000..2aa8f5f4b --- /dev/null +++ b/src/cpsp/header_large.cpsp @@ -0,0 +1,19 @@ +<%! +#include "../ServerConfig.h" +%><%% + bool withMaterialIcons = false; +%> + + + + + +Gradido Login Server: <%= pageName %> + +<% if(withMaterialIcons) { %> + +<% } %> + + +
+
\ No newline at end of file From e3cea5968b3e56376b896ffda64aa4f6361d2c88 Mon Sep 17 00:00:00 2001 From: Dario Date: Fri, 28 Aug 2020 13:14:33 +0200 Subject: [PATCH 016/293] add controller classes for new db tables crypto_keys and hedera_ids, update model tables for them --- src/cpp/Crypto/KeyPairHedera.cpp | 23 +++++++++++ src/cpp/Crypto/KeyPairHedera.h | 5 ++- src/cpp/SingletonManager/SessionManager.cpp | 1 + src/cpp/controller/CryptoKey.cpp | 44 +++++++++++++++++++++ src/cpp/controller/CryptoKey.h | 35 ++++++++++++++++ src/cpp/controller/HederaId.cpp | 32 +++++++++++++++ src/cpp/controller/HederaId.h | 32 +++++++++++++++ src/cpp/model/table/CryptoKey.cpp | 16 ++++++++ src/cpp/model/table/CryptoKey.h | 5 ++- src/cpp/model/table/HederaId.cpp | 7 ++++ src/cpp/model/table/HederaId.h | 1 + 11 files changed, 198 insertions(+), 3 deletions(-) create mode 100644 src/cpp/controller/CryptoKey.cpp create mode 100644 src/cpp/controller/CryptoKey.h create mode 100644 src/cpp/controller/HederaId.cpp create mode 100644 src/cpp/controller/HederaId.h diff --git a/src/cpp/Crypto/KeyPairHedera.cpp b/src/cpp/Crypto/KeyPairHedera.cpp index 80c4649b1..a0e0c5d43 100644 --- a/src/cpp/Crypto/KeyPairHedera.cpp +++ b/src/cpp/Crypto/KeyPairHedera.cpp @@ -145,4 +145,27 @@ bool KeyPairHedera::verify(const unsigned char* message, size_t messageSize, Mem return false; } return true; +} + +MemoryBin* KeyPairHedera::getCryptedPrivKey(const Poco::AutoPtr password) const +{ + if (password.isNull()) return nullptr; + if (!mPrivateKey) return nullptr; + + MemoryBin* encryptedKey = nullptr; + if (SecretKeyCryptography::AUTH_ENCRYPT_OK == password->encrypt(mPrivateKey, &encryptedKey)) { + return encryptedKey; + } + else { + return nullptr; + } + +} + +MemoryBin* KeyPairHedera::getPublicKeyCopy() const +{ + auto mm = MemoryManager::getInstance(); + auto public_key = mm->getFreeMemory(ed25519_pubkey_SIZE); + memcpy(*public_key, mPublicKey, ed25519_pubkey_SIZE); + return public_key; } \ No newline at end of file diff --git a/src/cpp/Crypto/KeyPairHedera.h b/src/cpp/Crypto/KeyPairHedera.h index 358a3b680..871453afc 100644 --- a/src/cpp/Crypto/KeyPairHedera.h +++ b/src/cpp/Crypto/KeyPairHedera.h @@ -13,6 +13,7 @@ #include "sodium.h" +#include "SecretKeyCryptography.h" #include "iroha-ed25519/include/ed25519/ed25519.h" class KeyPairHedera : public IKeyPair @@ -34,6 +35,7 @@ public: bool verify(const unsigned char* message, size_t messageSize, MemoryBin* signature) const; inline const unsigned char* getPublicKey() const { return mPublicKey; } + MemoryBin* getPublicKeyCopy() const; inline bool isTheSame(const KeyPairHedera& b) const { return 0 == sodium_memcmp(mPublicKey, b.mPublicKey, ed25519_pubkey_SIZE); @@ -60,7 +62,8 @@ public: inline bool hasPrivateKey() const { return mPrivateKey != nullptr; } - + //! \brief only way to get a private key.. encrypted + MemoryBin* getCryptedPrivKey(const Poco::AutoPtr password) const; protected: diff --git a/src/cpp/SingletonManager/SessionManager.cpp b/src/cpp/SingletonManager/SessionManager.cpp index 3c2144b1a..8de83d6c5 100644 --- a/src/cpp/SingletonManager/SessionManager.cpp +++ b/src/cpp/SingletonManager/SessionManager.cpp @@ -329,6 +329,7 @@ Session* SessionManager::getSession(int handle) //mWorkingMutex.lock(); auto it = mRequestSessionMap.find(handle); if (it != mRequestSessionMap.end()) { + printf("[SessionManager::getSession] found existing session, try if active...\n"); result = it->second; if (!result->isActive()) { //printf("[SessionManager::getSession] session isn't active\n"); diff --git a/src/cpp/controller/CryptoKey.cpp b/src/cpp/controller/CryptoKey.cpp new file mode 100644 index 000000000..809673bc5 --- /dev/null +++ b/src/cpp/controller/CryptoKey.cpp @@ -0,0 +1,44 @@ + +#include "CryptoKey.h" + +namespace controller { + + CryptoKey::CryptoKey(model::table::CryptoKey* dbModel) + { + mDBModel = dbModel; + } + + CryptoKey::~CryptoKey() + { + + } + + Poco::AutoPtr CryptoKey::create(const KeyPairHedera* hederaKeyPair, Poco::AutoPtr user) + { + auto mm = MemoryManager::getInstance(); + + auto encrypted_priv_key = hederaKeyPair->getCryptedPrivKey(user->getPassword()); + auto public_key = hederaKeyPair->getPublicKeyCopy(); + + auto db = new model::table::CryptoKey(encrypted_priv_key, public_key, model::table::KEY_TYPE_ED25519_HEDERA); + + mm->releaseMemory(encrypted_priv_key); + mm->releaseMemory(public_key); + + auto cryptoKey = new CryptoKey(db); + return Poco::AutoPtr(cryptoKey); + } + + Poco::AutoPtr CryptoKey::load(int id) + { + auto db = new model::table::CryptoKey(); + if (1 == db->loadFromDB("id", id)) { + auto cryptoKey = new CryptoKey(db); + return Poco::AutoPtr(cryptoKey); + } + return nullptr; + } + + +} + diff --git a/src/cpp/controller/CryptoKey.h b/src/cpp/controller/CryptoKey.h new file mode 100644 index 000000000..9e76123ef --- /dev/null +++ b/src/cpp/controller/CryptoKey.h @@ -0,0 +1,35 @@ +#ifndef GRADIDO_LOGIN_SERVER_CONTROLLER_CRYPTO_KEY_INCLUDE +#define GRADIDO_LOGIN_SERVER_CONTROLLER_CRYPTO_KEY_INCLUDE + +#include "../model/table/CryptoKey.h" +#include "../Crypto/KeyPairHedera.h" + +#include "Poco/SharedPtr.h" + +#include "TableControllerBase.h" +#include "User.h" + +namespace controller { + class CryptoKey : public TableControllerBase + { + public: + + ~CryptoKey(); + + static Poco::AutoPtr create(const KeyPairHedera* hederaKeyPair, Poco::AutoPtr user); + + //! if returned ptr is NULL, dataset not found + static Poco::AutoPtr load(int id); + + inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } + + inline Poco::AutoPtr getModel() { return _getModel(); } + + + protected: + CryptoKey(model::table::CryptoKey* dbModel); + + }; +} + +#endif //GRADIDO_LOGIN_SERVER_CONTROLLER_CRYPTO_KEY_INCLUDE \ No newline at end of file diff --git a/src/cpp/controller/HederaId.cpp b/src/cpp/controller/HederaId.cpp new file mode 100644 index 000000000..e6d281907 --- /dev/null +++ b/src/cpp/controller/HederaId.cpp @@ -0,0 +1,32 @@ +#include "HederaId.h" + +namespace controller { + + HederaId::HederaId(model::table::HederaId* dbModel) + { + mDBModel = dbModel; + } + + HederaId::~HederaId() + { + + } + + Poco::AutoPtr HederaId::create(Poco::UInt64 shardNum, Poco::UInt64 realmNum, Poco::UInt64 num) + { + auto db = new model::table::HederaId(shardNum, realmNum, num); + + auto hedera_id = new HederaId(db); + return Poco::AutoPtr(hedera_id); + } + + Poco::AutoPtr HederaId::load(int id) + { + auto db = new model::table::HederaId(); + if (1 == db->loadFromDB("id", id)) { + auto cryptoKey = new HederaId(db); + return Poco::AutoPtr(cryptoKey); + } + return nullptr; + } +} \ No newline at end of file diff --git a/src/cpp/controller/HederaId.h b/src/cpp/controller/HederaId.h new file mode 100644 index 000000000..f02e69373 --- /dev/null +++ b/src/cpp/controller/HederaId.h @@ -0,0 +1,32 @@ +#ifndef GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_ID_INCLUDE +#define GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_ID_INCLUDE + +#include "../model/table/HederaId.h" + +#include "Poco/SharedPtr.h" + +#include "TableControllerBase.h" + +namespace controller { + class HederaId : public TableControllerBase + { + public: + + ~HederaId(); + + static Poco::AutoPtr create(Poco::UInt64 shardNum, Poco::UInt64 realmNum, Poco::UInt64 num); + + static Poco::AutoPtr load(int id); + + inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } + + inline Poco::AutoPtr getModel() { return _getModel(); } + + + protected: + HederaId(model::table::HederaId* dbModel); + + }; +} + +#endif //GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_ID_INCLUDE \ No newline at end of file diff --git a/src/cpp/model/table/CryptoKey.cpp b/src/cpp/model/table/CryptoKey.cpp index 201047a5b..d36f44de6 100644 --- a/src/cpp/model/table/CryptoKey.cpp +++ b/src/cpp/model/table/CryptoKey.cpp @@ -9,6 +9,22 @@ namespace model { } + CryptoKey::CryptoKey(MemoryBin* privateKey, MemoryBin* publicKey, KeyType keyType) + : mKeyType(keyType) + { + if (!privateKey) { + mPrivateKey = Poco::Nullable(); + } else { + mPrivateKey = Poco::Nullable(Poco::Data::BLOB(*privateKey, privateKey->size())); + } + + if (!publicKey) { + mPublicKey = Poco::Nullable(); + } else { + mPublicKey = Poco::Nullable(Poco::Data::BLOB(*publicKey, publicKey->size())); + } + } + CryptoKey::~CryptoKey() { diff --git a/src/cpp/model/table/CryptoKey.h b/src/cpp/model/table/CryptoKey.h index f4fd8bebf..58d6df5dc 100644 --- a/src/cpp/model/table/CryptoKey.h +++ b/src/cpp/model/table/CryptoKey.h @@ -8,8 +8,8 @@ namespace model { namespace table { enum KeyType { - KEY_TYPE_SODIUM_ED25519 = 0, - KEY_TYPE_ED25519_REF10 = 1, + KEY_TYPE_ED25519_SODIUM = 0, + KEY_TYPE_ED25519_HEDERA = 1, KEY_TYPE_COUNT }; @@ -17,6 +17,7 @@ namespace model { { public: CryptoKey(); + CryptoKey(MemoryBin* privateKey, MemoryBin* publicKey, KeyType keyType); ~CryptoKey(); // generic db operations diff --git a/src/cpp/model/table/HederaId.cpp b/src/cpp/model/table/HederaId.cpp index b048a0d71..a4f25cc78 100644 --- a/src/cpp/model/table/HederaId.cpp +++ b/src/cpp/model/table/HederaId.cpp @@ -5,6 +5,13 @@ using namespace Poco::Data::Keywords; namespace model { namespace table { HederaId::HederaId() + : mShardNum(0), mRealmNum(0), mNum(0) + { + + } + + HederaId::HederaId(Poco::UInt64 shardNum, Poco::UInt64 realmNum, Poco::UInt64 num) + : mShardNum(shardNum), mRealmNum(realmNum), mNum(num) { } diff --git a/src/cpp/model/table/HederaId.h b/src/cpp/model/table/HederaId.h index ef35b2e70..c36d1f656 100644 --- a/src/cpp/model/table/HederaId.h +++ b/src/cpp/model/table/HederaId.h @@ -11,6 +11,7 @@ namespace model { { public: HederaId(); + HederaId(Poco::UInt64 shardNum, Poco::UInt64 realmNum, Poco::UInt64 num); ~HederaId(); // generic db operations From 48b46e6345ab7dcb212f494811446cb1dc6bba4a Mon Sep 17 00:00:00 2001 From: Dario Date: Fri, 28 Aug 2020 18:06:29 +0200 Subject: [PATCH 017/293] save entry of hedera account in db --- skeema/gradido_login/hedera_accounts.sql | 1 + .../HTTPInterface/AdminHederaAccountPage.cpp | 127 ++++++++++++++++-- src/cpp/SingletonManager/SessionManager.cpp | 2 + src/cpp/SingletonManager/SessionManager.h | 2 + src/cpp/controller/HederaAccount.cpp | 4 +- src/cpp/controller/HederaAccount.h | 2 +- src/cpp/model/table/CryptoKey.cpp | 4 +- src/cpp/model/table/HederaAccount.cpp | 29 ++-- src/cpp/model/table/HederaAccount.h | 12 +- 9 files changed, 159 insertions(+), 24 deletions(-) diff --git a/skeema/gradido_login/hedera_accounts.sql b/skeema/gradido_login/hedera_accounts.sql index 23ffa33d1..c8fcff4eb 100644 --- a/skeema/gradido_login/hedera_accounts.sql +++ b/skeema/gradido_login/hedera_accounts.sql @@ -4,6 +4,7 @@ CREATE TABLE `hedera_accounts` ( `account_hedera_id` int unsigned NOT NULL, `account_key_id` int unsigned NOT NULL, `balance` bigint unsigned NOT NULL DEFAULT '0', + `network_type` int NOT NULL DEFAULT '0', `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `account_hedera_id` (`account_hedera_id`), diff --git a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp index 0500a8996..884bc1cdc 100644 --- a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp +++ b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp @@ -7,7 +7,13 @@ #line 7 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" - #include "../controller/HederaAccount.h" + +#include "../controller/HederaAccount.h" +#include "../controller/HederaId.h" +#include "../controller/CryptoKey.h" +#include "../lib/DataTypeConverter.h" +#include "../SingletonManager/SessionManager.h" + #line 1 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" #include "../ServerConfig.h" @@ -27,15 +33,104 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request if (_compressResponse) response.set("Content-Encoding", "gzip"); Poco::Net::HTMLForm form(request, request.stream()); -#line 10 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 16 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" const char* pageName = "Hedera Account"; + auto sm = SessionManager::getInstance(); + auto mm = MemoryManager::getInstance(); + auto user = mSession->getNewUser(); // add if(!form.empty()) { + // collect + auto shardNumString = form.get("account-shard-num", "0"); + auto realmNumString = form.get("account-realm-num", "0"); + auto numString = form.get("account-num", "0"); + auto privateKeyString = form.get("account-private-key", ""); + auto publicKeyString = form.get("account-public-key", ""); + auto networkTypeString = form.get("account-network-type", "0"); + + int shardNum = 0; + int realmNum = 0; + int num = 0; + int networkType = 0; + + MemoryBin* privateKey = nullptr; + MemoryBin* publicKey = nullptr; + + // validate + if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "shard num not integer")); + } else { + if(DataTypeConverter::strToInt(shardNumString, shardNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting shardNumString to int")); + } + } + if(!sm->isValid(realmNumString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "realm num not integer")); + } else { + if(DataTypeConverter::strToInt(realmNumString, realmNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting realmNumString to int")); + } + } + if(!sm->isValid(numString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "num not integer")); + } else { + if(DataTypeConverter::strToInt(numString, num) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting num to int")); + } + } + if(!sm->isValid(privateKeyString, VALIDATE_ONLY_HEX)) { + addError(new Error("Account Keys", "private key not hex")); + } + if(!sm->isValid(publicKeyString, VALIDATE_ONLY_HEX)) { + addError(new Error("Account Keys", "public key not hex")); + } + if(!sm->isValid(networkTypeString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Network Type", "not integer")); + } else { + if(DataTypeConverter::strToInt(networkTypeString, networkType) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting network type to int")); + } + if(networkType < 0 || networkType >= (int)model::table::HEDERA_NET_COUNT) { + addError(new Error("Network Type", "invalid value")); + } + } + + if(0 == errorCount()) { + + auto hedera_id = controller::HederaId::create(shardNum, realmNum, num); + if(!hedera_id->getModel()->insertIntoDB(true)) { + addError(new Error("DB Error", "Error saving hedera id in DB")); + } + + privateKey = DataTypeConverter::hexToBin(privateKeyString); + publicKey = DataTypeConverter::hexToBin(publicKeyString); + + + KeyPairHedera key_pair(privateKey, publicKey); + mm->releaseMemory(privateKey); + mm->releaseMemory(publicKey); + auto crypto_key = controller::CryptoKey::create(&key_pair, user); + if(!crypto_key->getModel()->insertIntoDB(true)) { + addError(new Error("DB Error", "Error saving crypto key in DB")); + } + + if(0 == errorCount()) { + auto hedera_account = controller::HederaAccount::create( + user->getModel()->getID(), + hedera_id->getModel()->getID(), + crypto_key->getModel()->getID(), + 0, + (model::table::HederaNetworkType)networkType + ); + if(!hedera_account->getModel()->insertIntoDB(false)) { + addError(new Error("DB Error", "Error saving hedera account into DB")); + } + } + } } - #line 3 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" @@ -74,7 +169,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t
"; // end include header_large.cpsp responseStream << "\n"; -#line 21 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 116 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( getErrorsHtml() ); responseStream << "\n"; responseStream << "
\n"; @@ -84,15 +179,31 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t
\n"; responseStream << "\t\t
\n"; responseStream << "\t\t\t\n"; - responseStream << "\t\t\t\n"; - responseStream << "\t\t\t\n"; - responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t
\n"; diff --git a/src/cpp/SingletonManager/SessionManager.cpp b/src/cpp/SingletonManager/SessionManager.cpp index 8de83d6c5..8d0b77928 100644 --- a/src/cpp/SingletonManager/SessionManager.cpp +++ b/src/cpp/SingletonManager/SessionManager.cpp @@ -47,6 +47,8 @@ bool SessionManager::init() case VALIDATE_PASSWORD: mValidations[i] = new Poco::RegularExpression("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[@$!%*?&+-_])[A-Za-z0-9@$!%*?&+-_]{8,}$"); break; case VALIDATE_PASSPHRASE: mValidations[i] = new Poco::RegularExpression("^(?:[a-z]* ){23}[a-z]*\s*$"); break; case VALIDATE_HAS_NUMBER: mValidations[i] = new Poco::RegularExpression(".*[0-9].*"); break; + case VALIDATE_ONLY_INTEGER: mValidations[i] = new Poco::RegularExpression("^[0-9]*$"); break; + case VALIDATE_ONLY_HEX: mValidations[i] = new Poco::RegularExpression("^(0x)?[a-fA-F0-9]*$"); break; case VALIDATE_HAS_SPECIAL_CHARACTER: mValidations[i] = new Poco::RegularExpression(".*[@$!%*?&+-].*"); break; case VALIDATE_HAS_UPPERCASE_LETTER: mValidations[i] = new Poco::RegularExpression(".*[A-Z].*"); diff --git a/src/cpp/SingletonManager/SessionManager.h b/src/cpp/SingletonManager/SessionManager.h index 208de09be..d57162305 100644 --- a/src/cpp/SingletonManager/SessionManager.h +++ b/src/cpp/SingletonManager/SessionManager.h @@ -28,6 +28,8 @@ enum SessionValidationTypes { VALIDATE_PASSWORD, VALIDATE_PASSPHRASE, VALIDATE_HAS_NUMBER, + VALIDATE_ONLY_INTEGER, + VALIDATE_ONLY_HEX, VALIDATE_HAS_SPECIAL_CHARACTER, VALIDATE_HAS_UPPERCASE_LETTER, VALIDATE_HAS_LOWERCASE_LETTER, diff --git a/src/cpp/controller/HederaAccount.cpp b/src/cpp/controller/HederaAccount.cpp index 9a858bd7c..42a08eb27 100644 --- a/src/cpp/controller/HederaAccount.cpp +++ b/src/cpp/controller/HederaAccount.cpp @@ -13,9 +13,9 @@ namespace controller { } - Poco::AutoPtr HederaAccount::create(int user_id, int account_hedera_id, int account_key_id, Poco::UInt64 balance/* = 0*/) + Poco::AutoPtr HederaAccount::create(int user_id, int account_hedera_id, int account_key_id, Poco::UInt64 balance/* = 0*/, model::table::HederaNetworkType type/* = HEDERA_MAINNET*/) { - auto db = new model::table::HederaAccount(user_id, account_hedera_id, account_key_id, balance); + auto db = new model::table::HederaAccount(user_id, account_hedera_id, account_key_id, balance, type); auto group = new HederaAccount(db); return Poco::AutoPtr(group); } diff --git a/src/cpp/controller/HederaAccount.h b/src/cpp/controller/HederaAccount.h index 9efd89c12..fd2cb4b23 100644 --- a/src/cpp/controller/HederaAccount.h +++ b/src/cpp/controller/HederaAccount.h @@ -14,7 +14,7 @@ namespace controller { ~HederaAccount(); - static Poco::AutoPtr create(int user_id, int account_hedera_id, int account_key_id, Poco::UInt64 balance = 0); + static Poco::AutoPtr create(int user_id, int account_hedera_id, int account_key_id, Poco::UInt64 balance = 0, model::table::HederaNetworkType type = model::table::HEDERA_MAINNET); static std::vector> load(const std::string& alias); static std::vector> listAll(); diff --git a/src/cpp/model/table/CryptoKey.cpp b/src/cpp/model/table/CryptoKey.cpp index d36f44de6..9588f57e7 100644 --- a/src/cpp/model/table/CryptoKey.cpp +++ b/src/cpp/model/table/CryptoKey.cpp @@ -43,8 +43,8 @@ namespace model { const char* CryptoKey::typeToString(KeyType type) { switch (type) { - case KEY_TYPE_ED25519_REF10: return "ed25519 ref10"; - case KEY_TYPE_SODIUM_ED25519: return "sodium ed22519"; + case KEY_TYPE_ED25519_SODIUM: return "ed25519 ref10"; + case KEY_TYPE_ED25519_HEDERA: return "sodium ed22519"; } return ""; } diff --git a/src/cpp/model/table/HederaAccount.cpp b/src/cpp/model/table/HederaAccount.cpp index 63c6068bc..06538fdcb 100644 --- a/src/cpp/model/table/HederaAccount.cpp +++ b/src/cpp/model/table/HederaAccount.cpp @@ -6,20 +6,21 @@ namespace model { namespace table { HederaAccount::HederaAccount() - : mUserId(0), mAccountHederaId(0), mAccountKeyId(0), mBalance(0) + : mUserId(0), mAccountHederaId(0), mAccountKeyId(0), mBalance(0), mType(0) { } - HederaAccount::HederaAccount(int user_id, int account_hedera_id, int account_key_id, Poco::UInt64 balance/* = 0*/) - : mUserId(user_id), mAccountHederaId(account_hedera_id), mAccountKeyId(account_key_id), mBalance(balance) + HederaAccount::HederaAccount(int user_id, int account_hedera_id, int account_key_id, Poco::UInt64 balance/* = 0*/, HederaNetworkType type /*= HEDERA_MAINNET*/) + : mUserId(user_id), mAccountHederaId(account_hedera_id), mAccountKeyId(account_key_id), mBalance(balance), mType(type) { } HederaAccount::HederaAccount(const HederaAccountTuple& tuple) : ModelBase(tuple.get<0>()), - mUserId(tuple.get<1>()), mAccountHederaId(tuple.get<2>()), mAccountKeyId(tuple.get<3>()), mBalance(tuple.get<4>()), mUpdated(tuple.get<5>()) + mUserId(tuple.get<1>()), mAccountHederaId(tuple.get<2>()), mAccountKeyId(tuple.get<3>()), + mBalance(tuple.get<4>()), mType(tuple.get<5>()), mUpdated(tuple.get<6>()) { } @@ -37,18 +38,28 @@ namespace model { ss << "account crypto key id: " << std::to_string(mAccountKeyId) << std::endl; // balance in tinybars, 100,000,000 tinybar = 1 HashBar ss << "account balance: " << std::to_string((double)(mBalance) * 100000000.0) << " HBAR" << std::endl; + ss << "Hedera Net Type: " << hederaNetworkTypeToString((HederaNetworkType)mType) << std::endl; ss << "last update: " << Poco::DateTimeFormatter::format(mUpdated, "%f.%m.%Y %H:%M:%S") << std::endl; return ss.str(); } + const char* HederaAccount::hederaNetworkTypeToString(HederaNetworkType type) + { + switch (type) { + case HEDERA_MAINNET: return "Mainnet"; + case HEDERA_TESTNET: return "Testnet"; + default: return ""; + } + } + Poco::Data::Statement HederaAccount::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) { Poco::Data::Statement select(session); - select << "SELECT id, user_id, account_hedera_id, account_key_id, balance, updated FROM " << getTableName() + select << "SELECT id, user_id, account_hedera_id, account_key_id, balance, network_type, updated FROM " << getTableName() << " where " << fieldName << " = ?" - , into(mID), into(mUserId), into(mAccountHederaId), into(mAccountKeyId), into(mBalance), into(mUpdated); + , into(mID), into(mUserId), into(mAccountHederaId), into(mAccountKeyId), into(mBalance), into(mType), into(mUpdated); return select; @@ -57,7 +68,7 @@ namespace model { Poco::Data::Statement HederaAccount::_loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName) { Poco::Data::Statement select(session); - select << "SELECT id, user_id, account_hedera_id, account_key_id, balance, updated FROM " << getTableName() + select << "SELECT id, user_id, account_hedera_id, account_key_id, balance, network_type, updated FROM " << getTableName() << " where " << fieldName << " LIKE ?"; return select; @@ -77,8 +88,8 @@ namespace model { Poco::Data::Statement insert(session); lock(); insert << "INSERT INTO " << getTableName() - << " (user_id, account_hedera_id, account_key_id, balance) VALUES(?,?,?,?)" - , use(mUserId), use(mAccountHederaId), use(mAccountKeyId), use(mBalance); + << " (user_id, account_hedera_id, account_key_id, balance, network_type) VALUES(?,?,?,?,?)" + , use(mUserId), use(mAccountHederaId), use(mAccountKeyId), use(mBalance), use(mType); unlock(); return insert; } diff --git a/src/cpp/model/table/HederaAccount.h b/src/cpp/model/table/HederaAccount.h index ca56dfd62..2219fc521 100644 --- a/src/cpp/model/table/HederaAccount.h +++ b/src/cpp/model/table/HederaAccount.h @@ -7,13 +7,19 @@ namespace model { namespace table { - typedef Poco::Tuple HederaAccountTuple; + typedef Poco::Tuple HederaAccountTuple; + + enum HederaNetworkType { + HEDERA_MAINNET, + HEDERA_TESTNET, + HEDERA_NET_COUNT + }; class HederaAccount : public ModelBase { public: HederaAccount(); - HederaAccount(int user_id, int account_hedera_id, int account_key_id, Poco::UInt64 balance = 0); + HederaAccount(int user_id, int account_hedera_id, int account_key_id, Poco::UInt64 balance = 0, HederaNetworkType type = HEDERA_MAINNET); HederaAccount(const HederaAccountTuple& tuple); ~HederaAccount(); @@ -21,6 +27,7 @@ namespace model { const char* getTableName() const { return "hedera_accounts"; } std::string toString(); + static const char* hederaNetworkTypeToString(HederaNetworkType type); protected: Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); @@ -32,6 +39,7 @@ namespace model { int mAccountHederaId; int mAccountKeyId; Poco::UInt64 mBalance; + int mType; Poco::DateTime mUpdated; }; From 41d8649d7af36a96a1ac39985a62127908c1ea00 Mon Sep 17 00:00:00 2001 From: Dario Date: Mon, 31 Aug 2020 11:23:58 +0200 Subject: [PATCH 018/293] show and add node server and hedera accounts, model, controller and page --- skeema/gradido_login/crypto_keys.sql | 3 +- skeema/gradido_login/hedera_accounts.sql | 2 +- src/cpp/Crypto/KeyPairHedera.cpp | 12 +- src/cpp/Crypto/KeyPairHedera.h | 1 + src/cpp/HTTPInterface/AdminGroupsPage.cpp | 83 ++-- .../HTTPInterface/AdminHederaAccountPage.cpp | 112 ++++-- src/cpp/HTTPInterface/AdminNodeServerPage.cpp | 363 ++++++++++++++++++ src/cpp/HTTPInterface/AdminNodeServerPage.h | 20 + .../PageRequestHandlerFactory.cpp | 6 + .../SingletonManager/ConnectionManager.cpp | 6 +- src/cpp/SingletonManager/SessionManager.cpp | 2 + src/cpp/SingletonManager/SessionManager.h | 1 + src/cpp/controller/CryptoKey.cpp | 23 ++ src/cpp/controller/CryptoKey.h | 2 + src/cpp/controller/Group.cpp | 2 +- src/cpp/controller/HederaAccount.cpp | 14 +- src/cpp/controller/HederaAccount.h | 7 +- src/cpp/controller/NodeServer.cpp | 145 +++++++ src/cpp/controller/NodeServer.h | 52 +++ src/cpp/model/table/HederaAccount.h | 9 + src/cpp/model/table/HederaId.cpp | 31 +- src/cpp/model/table/HederaId.h | 3 + src/cpp/model/table/ModelBase.cpp | 14 +- src/cpp/model/table/NodeServer.cpp | 114 ++++++ src/cpp/model/table/NodeServer.h | 71 ++++ src/cpsp/adminGroups.cpsp | 22 +- src/cpsp/adminNodeServer.cpsp | 200 ++++++++++ src/cpsp/header_large.cpsp | 10 + 28 files changed, 1232 insertions(+), 98 deletions(-) create mode 100644 src/cpp/HTTPInterface/AdminNodeServerPage.cpp create mode 100644 src/cpp/HTTPInterface/AdminNodeServerPage.h create mode 100644 src/cpp/controller/NodeServer.cpp create mode 100644 src/cpp/controller/NodeServer.h create mode 100644 src/cpp/model/table/NodeServer.cpp create mode 100644 src/cpp/model/table/NodeServer.h create mode 100644 src/cpsp/adminNodeServer.cpsp diff --git a/skeema/gradido_login/crypto_keys.sql b/skeema/gradido_login/crypto_keys.sql index 43b511db2..c90750ae3 100644 --- a/skeema/gradido_login/crypto_keys.sql +++ b/skeema/gradido_login/crypto_keys.sql @@ -3,5 +3,6 @@ CREATE TABLE `crypto_keys` ( `private_key` varbinary(64) NOT NULL, `public_key` binary(32) NOT NULL, `crypto_key_type_id` int NOT NULL DEFAULT '0', - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + UNIQUE(`public_key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/skeema/gradido_login/hedera_accounts.sql b/skeema/gradido_login/hedera_accounts.sql index c8fcff4eb..8ce24b54d 100644 --- a/skeema/gradido_login/hedera_accounts.sql +++ b/skeema/gradido_login/hedera_accounts.sql @@ -5,7 +5,7 @@ CREATE TABLE `hedera_accounts` ( `account_key_id` int unsigned NOT NULL, `balance` bigint unsigned NOT NULL DEFAULT '0', `network_type` int NOT NULL DEFAULT '0', - `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `updated` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `account_hedera_id` (`account_hedera_id`), UNIQUE KEY `account_key_id` (`account_key_id`) diff --git a/src/cpp/Crypto/KeyPairHedera.cpp b/src/cpp/Crypto/KeyPairHedera.cpp index a0e0c5d43..0a3bf4bc2 100644 --- a/src/cpp/Crypto/KeyPairHedera.cpp +++ b/src/cpp/Crypto/KeyPairHedera.cpp @@ -46,9 +46,10 @@ KeyPairHedera::KeyPairHedera(const MemoryBin* privateKey, const MemoryBin* publi default: throw std::exception("[KeyPairHedera] invalid private key"); } - crypto_sign_ed25519_sk_to_pk(mPublicKey, *mPrivateKey); + + // check public } - else if (publicKey) { + if (publicKey) { switch (publicKey->size()) { case 32: { // raw public key @@ -64,8 +65,13 @@ KeyPairHedera::KeyPairHedera(const MemoryBin* privateKey, const MemoryBin* publi throw std::exception("[KeyPairHedera] invalid public key"); } } + auto public_key_2 = mm->getFreeMemory(ed25519_pubkey_SIZE); + crypto_sign_ed25519_sk_to_pk(*public_key_2, *mPrivateKey); + if (sodium_memcmp(*public_key_2, mPublicKey, ed25519_pubkey_SIZE) != 0) { + throw "public keys not match"; + } - + mm->releaseMemory(public_key_2); mm->releaseMemory(derPrefixPriv); mm->releaseMemory(derPrefixPub); } diff --git a/src/cpp/Crypto/KeyPairHedera.h b/src/cpp/Crypto/KeyPairHedera.h index 871453afc..115beebdb 100644 --- a/src/cpp/Crypto/KeyPairHedera.h +++ b/src/cpp/Crypto/KeyPairHedera.h @@ -70,6 +70,7 @@ protected: KeyPairHedera(); void createKeyFromSeed(const MemoryBin* seed); + private: // 64 Byte //! \brief ed25519 libsodium private key diff --git a/src/cpp/HTTPInterface/AdminGroupsPage.cpp b/src/cpp/HTTPInterface/AdminGroupsPage.cpp index 1e6619801..7e38cfde2 100644 --- a/src/cpp/HTTPInterface/AdminGroupsPage.cpp +++ b/src/cpp/HTTPInterface/AdminGroupsPage.cpp @@ -8,7 +8,7 @@ #line 7 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" #include "../controller/Group.h" -#line 1 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp" +#line 1 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" #include "../ServerConfig.h" @@ -55,14 +55,14 @@ void AdminGroupsPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco: //auto groups = controller::Group::load("gdd1"); //std::vector> groups; -#line 3 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp" +#line 3 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" bool withMaterialIcons = false; std::ostream& _responseStream = response.send(); Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1); std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream; responseStream << "\n"; - // begin include header.cpsp + // begin include header_large.cpsp responseStream << "\n"; responseStream << "\n"; responseStream << "\n"; @@ -70,47 +70,48 @@ void AdminGroupsPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco: responseStream << "\n"; responseStream << "\n"; responseStream << "Gradido Login Server: "; -#line 11 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp" +#line 11 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" responseStream << ( pageName ); responseStream << "\n"; responseStream << "\n"; -#line 13 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp" +#line 13 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" if(withMaterialIcons) { responseStream << "\n"; responseStream << "\n"; -#line 15 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp" +#line 15 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" } responseStream << "\n"; responseStream << "\n"; responseStream << "\n"; responseStream << "
\n"; - responseStream << "
\n"; - responseStream << " "; - // end include header.cpsp + responseStream << "\t\t
\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t
"; + // end include header_large.cpsp responseStream << "\n"; #line 38 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" responseStream << ( getErrorsHtml() ); @@ -122,11 +123,11 @@ void AdminGroupsPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco: responseStream << "\t\t
\t\n"; responseStream << "\t\t
\n"; responseStream << "\t\t\t
\n"; - responseStream << "\t\t\t\t
ID
\n"; - responseStream << "\t\t\t\t
Name
\n"; - responseStream << "\t\t\t\t
Alias
\n"; - responseStream << "\t\t\t\t
Url
\n"; - responseStream << "\t\t\t\t
"; + responseStream << "\t\t\t\t
ID
\n"; + responseStream << "\t\t\t\t
Name
\n"; + responseStream << "\t\t\t\t
Alias
\n"; + responseStream << "\t\t\t\t
Url
\n"; + responseStream << "\t\t\t\t
"; #line 50 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" responseStream << ( gettext("Description") ); responseStream << "
\n"; @@ -136,23 +137,23 @@ void AdminGroupsPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco: for(auto it = groups.begin(); it != groups.end(); it++) { auto group_model = (*it)->getModel(); responseStream << "\n"; responseStream << "\t\t\t\t
\n"; - responseStream << "\t\t\t\t\t
"; + responseStream << "\t\t\t\t\t
"; #line 55 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" responseStream << ( group_model->getID() ); responseStream << "
\n"; - responseStream << "\t\t\t\t\t
"; + responseStream << "\t\t\t\t\t
"; #line 56 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" responseStream << ( group_model->getName() ); responseStream << "
\n"; - responseStream << "\t\t\t\t\t
"; + responseStream << "\t\t\t\t\t
"; #line 57 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" responseStream << ( group_model->getAlias() ); responseStream << "
\n"; - responseStream << "\t\t\t\t\t
"; + responseStream << "\t\t\t\t\t
"; #line 58 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" responseStream << ( group_model->getUrl() ); responseStream << "
\n"; - responseStream << "\t\t\t\t\t
"; + responseStream << "\t\t\t\t\t
"; #line 59 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp" responseStream << ( group_model->getDescription()); responseStream << "
\n"; diff --git a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp index 884bc1cdc..0de7a6922 100644 --- a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp +++ b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp @@ -55,8 +55,8 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request int num = 0; int networkType = 0; - MemoryBin* privateKey = nullptr; - MemoryBin* publicKey = nullptr; + MemoryBin* private_key = nullptr; + MemoryBin* public_key = nullptr; // validate if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) { @@ -100,22 +100,22 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request if(0 == errorCount()) { auto hedera_id = controller::HederaId::create(shardNum, realmNum, num); - if(!hedera_id->getModel()->insertIntoDB(true)) { - addError(new Error("DB Error", "Error saving hedera id in DB")); + + private_key = DataTypeConverter::hexToBin(privateKeyString); + public_key = DataTypeConverter::hexToBin(publicKeyString); + + + KeyPairHedera key_pair(private_key, public_key); + auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE); + + if(crypto_key.isNull()) { + crypto_key = controller::CryptoKey::create(&key_pair, user); + if(!crypto_key->getModel()->insertIntoDB(true)) { + addError(new Error("DB Error", "Error saving crypto key in DB")); + } + } else { + printf("crypto key found in db\n"); } - - privateKey = DataTypeConverter::hexToBin(privateKeyString); - publicKey = DataTypeConverter::hexToBin(publicKeyString); - - - KeyPairHedera key_pair(privateKey, publicKey); - mm->releaseMemory(privateKey); - mm->releaseMemory(publicKey); - auto crypto_key = controller::CryptoKey::create(&key_pair, user); - if(!crypto_key->getModel()->insertIntoDB(true)) { - addError(new Error("DB Error", "Error saving crypto key in DB")); - } - if(0 == errorCount()) { auto hedera_account = controller::HederaAccount::create( user->getModel()->getID(), @@ -128,10 +128,15 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request addError(new Error("DB Error", "Error saving hedera account into DB")); } } + + mm->releaseMemory(private_key); + mm->releaseMemory(public_key); } } + // list accounts + auto hedera_accounts = controller::HederaAccount::load("user_id", user->getModel()->getID()); #line 3 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" @@ -166,13 +171,74 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\n"; responseStream << "\n"; responseStream << "
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t
\n"; responseStream << "\t\t
"; // end include header_large.cpsp responseStream << "\n"; -#line 116 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 121 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( getErrorsHtml() ); responseStream << "\n"; responseStream << "
\n"; + responseStream << "\t
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\t

Deine Hedera Accounts

\n"; + responseStream << "\t\t
\t\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\t
Hedera Id
\t\t\t\n"; + responseStream << "\t\t\t\t
Balance
\n"; + responseStream << "\t\t\t\t
Server Type
\n"; + responseStream << "\t\t\t\t
Last Updated
\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t"; +#line 134 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + for(auto it = hedera_accounts.begin(); it != hedera_accounts.end(); it++) { + auto hedera_account_model = (*it)->getModel(); + responseStream << "\n"; + responseStream << "\t\t\t\t
\n"; + responseStream << "\t\t\t\t\t
"; +#line 138 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + responseStream << ( (*it)->getHederaId()->getModel()->toString() ); + responseStream << "
\n"; + responseStream << "\t\t\t\t\t
"; +#line 139 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + responseStream << ( hedera_account_model->getBalanceDouble() ); + responseStream << " hbar
\n"; + responseStream << "\t\t\t\t\t
"; +#line 140 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + responseStream << ( model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) ); + responseStream << "
\n"; + responseStream << "\t\t\t\t\t
"; +#line 141 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + responseStream << ( hedera_account_model->getUpdatedString() ); + responseStream << "
\n"; + responseStream << "\t\t\t\t
\n"; + responseStream << "\t\t\t"; +#line 143 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + } responseStream << "\n"; + responseStream << "\t\t
\n"; + responseStream << "\t
\n"; responseStream << "\t
\n"; responseStream << "\t

Einen neuen Account anlegen

\n"; responseStream << "\t
\n"; @@ -189,21 +255,21 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\n"; diff --git a/src/cpp/HTTPInterface/AdminNodeServerPage.cpp b/src/cpp/HTTPInterface/AdminNodeServerPage.cpp new file mode 100644 index 000000000..c6c786aeb --- /dev/null +++ b/src/cpp/HTTPInterface/AdminNodeServerPage.cpp @@ -0,0 +1,363 @@ +#include "AdminNodeServerPage.h" +#include "Poco/Net/HTTPServerRequest.h" +#include "Poco/Net/HTTPServerResponse.h" +#include "Poco/Net/HTMLForm.h" +#include "Poco/DeflatingStream.h" + + +#line 7 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminNodeServer.cpsp" + + +#include "../controller/NodeServer.h" +#include "../controller/Group.h" +#include "../SingletonManager/SessionManager.h" +#include "../lib/DataTypeConverter.h" + +#line 1 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + +#include "../ServerConfig.h" + + +AdminNodeServerPage::AdminNodeServerPage(Session* arg): + SessionHTTPRequestHandler(arg) +{ +} + + +void AdminNodeServerPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) +{ + response.setChunkedTransferEncoding(true); + response.setContentType("text/html"); + bool _compressResponse(request.hasToken("Accept-Encoding", "gzip")); + if (_compressResponse) response.set("Content-Encoding", "gzip"); + + Poco::Net::HTMLForm form(request, request.stream()); +#line 15 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminNodeServer.cpsp" + + const char* pageName = "Node Server"; + auto sm = SessionManager::getInstance(); + + // add + if(!form.empty()) { + // collect + auto url = form.get("node-server-url", ""); + auto portString = form.get("node-server-port", ""); + auto nodeServerTypeString = form.get("node-server-type", "0"); + auto shardNumString = form.get("account-shard-num", "0"); + auto realmNumString = form.get("account-realm-num", "0"); + auto numString = form.get("account-num", "0"); + auto nodeServerGroupString = form.get("node-server-group", ""); + + int port = 0; + int shardNum = 0; + int realmNum = 0; + int num = 0; + model::table::NodeServerType nodeServerType = model::table::NODE_SERVER_NONE; + int group_id = 0; + + + // validate + if(!sm->isValid(url, VALIDATE_ONLY_URL)) { + addError(new ParamError("Node Server", "Url not valid, must start with http or https", url)); + + } + if(!sm->isValid(portString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Node Server", "Port isn't valid integer")); + } else { + if(DataTypeConverter::strToInt(portString, port) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int convert error", "Error converting port to int")); + } + } + + if(!sm->isValid(nodeServerTypeString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Node Server Type", "not integer")); + } else { + int node_server_type_int = 0; + if(DataTypeConverter::strToInt(nodeServerTypeString, node_server_type_int) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting node server type to int")); + } + if(node_server_type_int < 0 || node_server_type_int >= (int)model::table::NODE_SERVER_TYPE_COUNT) { + addError(new Error("Node Server Type", "invalid value")); + } else { + nodeServerType = (model::table::NodeServerType)node_server_type_int; + } + } + if(model::table::NodeServerIsHederaNode(nodeServerType)) { + + if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "shard num not integer")); + } else { + if(DataTypeConverter::strToInt(shardNumString, shardNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting shardNumString to int")); + } + } + if(!sm->isValid(realmNumString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "realm num not integer")); + } else { + if(DataTypeConverter::strToInt(realmNumString, realmNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting realmNumString to int")); + } + } + if(!sm->isValid(numString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "num not integer")); + } else { + if(DataTypeConverter::strToInt(numString, num) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting num to int")); + } + } + } else if(model::table::NodeServerHasGroup(nodeServerType)) { + if(!sm->isValid(nodeServerGroupString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Group id", "group_id not integer")); + } else { + if(DataTypeConverter::strToInt(nodeServerGroupString, group_id) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting group_id to int")); + } + } + } + + + + if(0 == errorCount()) { + int hedera_id_int = 0; + if(NodeServerIsHederaNode(nodeServerType)) { + auto hedera_id = controller::HederaId::create(shardNum, realmNum, num); + hedera_id_int = hedera_id->getModel()->getID(); + } + + auto node_server = controller::NodeServer::create( + url, port, group_id, (model::table::NodeServerType)nodeServerType, hedera_id_int + ); + if(!node_server->getModel()->insertIntoDB(false)) { + addError(new Error("DB Error", "Error saving Node Server in DB")); + } + } + } + auto groups = controller::Group::listAll(); + std::map group_indices; + int count = 0; + for(auto it = groups.begin(); it != groups.end(); it++) { + group_indices.insert(std::pair((*it)->getModel()->getID(), count)); + count++; + } + + auto node_servers = controller::NodeServer::listAll(); + + +#line 3 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + + bool withMaterialIcons = false; + std::ostream& _responseStream = response.send(); + Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1); + std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream; + responseStream << "\n"; + // begin include header_large.cpsp + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "Gradido Login Server: "; +#line 11 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + responseStream << ( pageName ); + responseStream << "\n"; + responseStream << "\n"; +#line 13 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + if(withMaterialIcons) { responseStream << "\n"; + responseStream << "\n"; +#line 15 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + } responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t
"; + // end include header_large.cpsp + responseStream << "\n"; +#line 126 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminNodeServer.cpsp" + responseStream << ( getErrorsHtml() ); + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "\t
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\t

Alle Node Server

\n"; + responseStream << "\t\t
\t\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\t
Server Type
\n"; + responseStream << "\t\t\t\t
Url:Port
\n"; + responseStream << "\t\t\t\t
Group / Hedera Id
\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t"; +#line 138 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminNodeServer.cpsp" + for(auto it = node_servers.begin(); it != node_servers.end(); it++) { + auto node_server_model = (*it)->getModel(); + responseStream << "\n"; + responseStream << "\t\t\t\t
\n"; + responseStream << "\t\t\t\t\t
"; +#line 142 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminNodeServer.cpsp" + responseStream << ( model::table::NodeServer::nodeServerTypeToString(node_server_model->getNodeServerType()) ); + responseStream << "
\n"; + responseStream << "\t\t\t\t\t
"; +#line 143 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminNodeServer.cpsp" + responseStream << ( node_server_model->getUrlWithPort() ); + responseStream << "
\n"; + responseStream << "\t\t\t\t\t
\n"; + responseStream << "\t\t\t\t\t\t"; +#line 145 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminNodeServer.cpsp" + if(node_server_model->isHederaNode()) { + auto hedera_id_model = (*it)->getHederaId()->getModel(); responseStream << "\n"; + responseStream << "\t\t\t\t\t\t\t"; +#line 147 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminNodeServer.cpsp" + responseStream << ( hedera_id_model->toString() ); + responseStream << "\n"; + responseStream << "\t\t\t\t\t\t"; +#line 148 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminNodeServer.cpsp" + } else if(node_server_model->hasGroup()){ + auto groupIt = group_indices.find(node_server_model->getGroupId()); + if(groupIt != group_indices.end()) { + auto group_model = groups[groupIt->second]->getModel(); responseStream << "\n"; + responseStream << "\t\t\t\t\t\t\t\tgetDescription() ); + responseStream << "\">"; +#line 152 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminNodeServer.cpsp" + responseStream << ( group_model->getName() ); + responseStream << "\n"; + responseStream << "\t\t\t\t\t\t\t"; +#line 153 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminNodeServer.cpsp" + } else { responseStream << "\n"; + responseStream << "\t\t\t\t\t\t\t\t"; +#line 154 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminNodeServer.cpsp" + responseStream << ( node_server_model->getGroupId() ); + responseStream << "\n"; + responseStream << "\t\t\t\t\t\t\t"; +#line 155 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminNodeServer.cpsp" + } responseStream << "\n"; + responseStream << "\t\t\t\t\t\t"; +#line 156 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminNodeServer.cpsp" + } responseStream << "\n"; + responseStream << "\t\t\t\t\t
\n"; + responseStream << "\t\t\t\t
\n"; + responseStream << "\t\t\t"; +#line 159 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminNodeServer.cpsp" + } responseStream << "\n"; + responseStream << "\t\t
\n"; + responseStream << "\t
\n"; + responseStream << "\t
\n"; + responseStream << "\t

Ein Node Server hinzufügen

\n"; + responseStream << "\t
\n"; + responseStream << "\t
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\tNur für Hedera Nodes\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\tNur für Gradido Nodes\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t
\n"; + responseStream << "
\n"; + responseStream << "\n"; + // begin include footer.cpsp + responseStream << "
\n"; + responseStream << "

Copyright © Gradido 2020

\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << " "; +#line 6 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp" + responseStream << ( mTimeProfiler.string() ); + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << "

Login Server in Entwicklung

\n"; + responseStream << "

Alpha "; +#line 10 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp" + responseStream << ( ServerConfig::g_versionString ); + responseStream << "

\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << ""; + // end include footer.cpsp + responseStream << "\n"; + if (_compressResponse) _gzipStream.close(); +} diff --git a/src/cpp/HTTPInterface/AdminNodeServerPage.h b/src/cpp/HTTPInterface/AdminNodeServerPage.h new file mode 100644 index 000000000..4a60b45e7 --- /dev/null +++ b/src/cpp/HTTPInterface/AdminNodeServerPage.h @@ -0,0 +1,20 @@ +#ifndef AdminNodeServerPage_INCLUDED +#define AdminNodeServerPage_INCLUDED + + +#include "Poco/Net/HTTPRequestHandler.h" + + +#include "SessionHTTPRequestHandler.h" + + +class AdminNodeServerPage: public SessionHTTPRequestHandler +{ +public: + AdminNodeServerPage(Session*); + + void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response); +}; + + +#endif // AdminNodeServerPage_INCLUDED diff --git a/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp b/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp index 11cdb7d78..b31e742c0 100644 --- a/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp +++ b/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp @@ -30,6 +30,7 @@ #include "AdminGroupsPage.h" #include "AdminTopicPage.h" #include "AdminHederaAccountPage.h" +#include "AdminNodeServerPage.h" #include "DecodeTransactionPage.h" #include "RepairDefectPassphrase.h" @@ -224,6 +225,11 @@ Poco::Net::HTTPRequestHandler* PageRequestHandlerFactory::createRequestHandler(c pageRequestHandler->setProfiler(timeUsed); return pageRequestHandler; } + if (url_first_part == "/nodes") { + auto pageRequestHandler = new AdminNodeServerPage(s); + pageRequestHandler->setProfiler(timeUsed); + return pageRequestHandler; + } } if(url_first_part == "/logout") { diff --git a/src/cpp/SingletonManager/ConnectionManager.cpp b/src/cpp/SingletonManager/ConnectionManager.cpp index c8752ee6e..05a8802ee 100644 --- a/src/cpp/SingletonManager/ConnectionManager.cpp +++ b/src/cpp/SingletonManager/ConnectionManager.cpp @@ -56,7 +56,7 @@ bool ConnectionManager::setConnectionsFromConfig(const Poco::Util::LayeredConfig dbConfig << "db=" << dbName << ";"; dbConfig << "user=" << config.getString(firstKeyPart + ".db.user", "root") << ";"; dbConfig << "password=" << config.getString(firstKeyPart + ".db.password", "") << ";"; - dbConfig << "auto-reconnect=false"; + dbConfig << "auto-reconnect=true"; setConnection(dbConfig.str(), type); @@ -73,10 +73,10 @@ Poco::Data::Session ConnectionManager::getConnection(ConnectionType type) throw Poco::NotFoundException("Connection Type unknown", std::to_string(type)); } auto session = mSessionPools.getPool(mSessionPoolNames[type]).get(); - if (!session.isConnected()) { + /*if (!session.isConnected()) { printf("reconnect called\n"); session.reconnect(); - } + }*/ //std::string dateTimeString = Poco::DateTimeFormatter::format(Poco::DateTime(), "%d.%m.%y %H:%M:%S"); //printf("[getConnection] %s impl: %p\n", dateTimeString.data(), session.impl()); return session; diff --git a/src/cpp/SingletonManager/SessionManager.cpp b/src/cpp/SingletonManager/SessionManager.cpp index 8d0b77928..f8dbb318f 100644 --- a/src/cpp/SingletonManager/SessionManager.cpp +++ b/src/cpp/SingletonManager/SessionManager.cpp @@ -49,6 +49,8 @@ bool SessionManager::init() case VALIDATE_HAS_NUMBER: mValidations[i] = new Poco::RegularExpression(".*[0-9].*"); break; case VALIDATE_ONLY_INTEGER: mValidations[i] = new Poco::RegularExpression("^[0-9]*$"); break; case VALIDATE_ONLY_HEX: mValidations[i] = new Poco::RegularExpression("^(0x)?[a-fA-F0-9]*$"); break; + //case VALIDATE_ONLY_URL: mValidations[i] = new Poco::RegularExpression("^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}$"); break; + case VALIDATE_ONLY_URL: mValidations[i] = new Poco::RegularExpression("^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\/?"); break; case VALIDATE_HAS_SPECIAL_CHARACTER: mValidations[i] = new Poco::RegularExpression(".*[@$!%*?&+-].*"); break; case VALIDATE_HAS_UPPERCASE_LETTER: mValidations[i] = new Poco::RegularExpression(".*[A-Z].*"); diff --git a/src/cpp/SingletonManager/SessionManager.h b/src/cpp/SingletonManager/SessionManager.h index d57162305..5968e3a25 100644 --- a/src/cpp/SingletonManager/SessionManager.h +++ b/src/cpp/SingletonManager/SessionManager.h @@ -30,6 +30,7 @@ enum SessionValidationTypes { VALIDATE_HAS_NUMBER, VALIDATE_ONLY_INTEGER, VALIDATE_ONLY_HEX, + VALIDATE_ONLY_URL, VALIDATE_HAS_SPECIAL_CHARACTER, VALIDATE_HAS_UPPERCASE_LETTER, VALIDATE_HAS_LOWERCASE_LETTER, diff --git a/src/cpp/controller/CryptoKey.cpp b/src/cpp/controller/CryptoKey.cpp index 809673bc5..2e7d343ec 100644 --- a/src/cpp/controller/CryptoKey.cpp +++ b/src/cpp/controller/CryptoKey.cpp @@ -1,5 +1,6 @@ #include "CryptoKey.h" +#include "../SingletonManager/ErrorManager.h" namespace controller { @@ -39,6 +40,28 @@ namespace controller { return nullptr; } + Poco::AutoPtr CryptoKey::load(MemoryBin* publicKey) + { + return load(*publicKey, publicKey->size()); + } + + Poco::AutoPtr CryptoKey::load(const unsigned char* publicKey, size_t size) + { + assert(publicKey); + assert(size); + + Poco::Data::BLOB public_key_blob(publicKey, size); + auto db = new model::table::CryptoKey(); + auto count = db->loadFromDB("public_key", public_key_blob); + if (!count) return nullptr; + if (1 == count) return new CryptoKey(db); + + auto em = ErrorManager::getInstance(); + em->addError(new Error("CryptoKey::load", "found more than one crypto key with same public key")); + em->sendErrorsAsEmail(); + return nullptr; + } + } diff --git a/src/cpp/controller/CryptoKey.h b/src/cpp/controller/CryptoKey.h index 9e76123ef..6e4e110bb 100644 --- a/src/cpp/controller/CryptoKey.h +++ b/src/cpp/controller/CryptoKey.h @@ -20,6 +20,8 @@ namespace controller { //! if returned ptr is NULL, dataset not found static Poco::AutoPtr load(int id); + static Poco::AutoPtr load(MemoryBin* publicKey); + static Poco::AutoPtr load(const unsigned char* publicKey, size_t size); inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } diff --git a/src/cpp/controller/Group.cpp b/src/cpp/controller/Group.cpp index d5b3eb2ba..2d809da07 100644 --- a/src/cpp/controller/Group.cpp +++ b/src/cpp/controller/Group.cpp @@ -23,7 +23,7 @@ namespace controller { std::vector> Group::load(const std::string& alias) { auto db = new model::table::Group(); - auto group_list = db->loadFromDB("alias", alias, 0); + auto group_list = db->loadFromDB("alias", alias, 1); std::vector> resultVector; resultVector.reserve(group_list.size()); diff --git a/src/cpp/controller/HederaAccount.cpp b/src/cpp/controller/HederaAccount.cpp index 42a08eb27..9f4ff5b40 100644 --- a/src/cpp/controller/HederaAccount.cpp +++ b/src/cpp/controller/HederaAccount.cpp @@ -20,15 +20,19 @@ namespace controller { return Poco::AutoPtr(group); } - std::vector> HederaAccount::load(const std::string& alias) + std::vector> HederaAccount::load(const std::string& fieldName, int fieldValue) { auto db = new model::table::HederaAccount(); - auto group_list = db->loadFromDB("alias", alias, 0); + auto hedera_account_list = db->loadFromDB(fieldName, fieldValue, 2); std::vector> resultVector; - resultVector.reserve(group_list.size()); - for (auto it = group_list.begin(); it != group_list.end(); it++) { - resultVector.push_back(new HederaAccount(new model::table::HederaAccount(*it))); + resultVector.reserve(hedera_account_list.size()); + for (auto it = hedera_account_list.begin(); it != hedera_account_list.end(); it++) { + //mHederaID + auto db = new model::table::HederaAccount(*it); + auto hedera_account = new HederaAccount(db); + hedera_account->mHederaID = HederaId::load(db->getAccountHederaId()); + resultVector.push_back(hedera_account); } return resultVector; } diff --git a/src/cpp/controller/HederaAccount.h b/src/cpp/controller/HederaAccount.h index fd2cb4b23..dd4c97435 100644 --- a/src/cpp/controller/HederaAccount.h +++ b/src/cpp/controller/HederaAccount.h @@ -1,6 +1,7 @@ #ifndef GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_ACCOUNT_INCLUDE #define GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_ACCOUNT_INCLUDE +#include "../controller/HederaId.h" #include "../model/table/HederaAccount.h" #include "Poco/SharedPtr.h" @@ -11,21 +12,23 @@ namespace controller { class HederaAccount : public TableControllerBase { public: - ~HederaAccount(); static Poco::AutoPtr create(int user_id, int account_hedera_id, int account_key_id, Poco::UInt64 balance = 0, model::table::HederaNetworkType type = model::table::HEDERA_MAINNET); - static std::vector> load(const std::string& alias); + static std::vector> load(const std::string& fieldName, int fieldValue); static std::vector> listAll(); inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } inline Poco::AutoPtr getModel() { return _getModel(); } + inline void setHederaId(Poco::AutoPtr hederaId) { mHederaID = hederaId; } + inline Poco::AutoPtr getHederaId() { return mHederaID; } protected: HederaAccount(model::table::HederaAccount* dbModel); + Poco::AutoPtr mHederaID; }; } diff --git a/src/cpp/controller/NodeServer.cpp b/src/cpp/controller/NodeServer.cpp new file mode 100644 index 000000000..6096b2839 --- /dev/null +++ b/src/cpp/controller/NodeServer.cpp @@ -0,0 +1,145 @@ +#include "NodeServer.h" +#include "../SingletonManager/ErrorManager.h" +#include "../SingletonManager/ConnectionManager.h" + +namespace controller { + + + NodeServer::NodeServer(model::table::NodeServer* dbModel) + { + mDBModel = dbModel; + } + + NodeServer::~NodeServer() + { + + } + + Poco::AutoPtr NodeServer::create(const std::string& url, int port, int groupId, model::table::NodeServerType type, int nodeHederaId) + { + auto db = new model::table::NodeServer(url, port, groupId, type, nodeHederaId); + auto group = new NodeServer(db); + return Poco::AutoPtr(group); + } + + std::vector> NodeServer::load(model::table::NodeServerType type, int group_id/* = 0*/) + { + auto db = new model::table::NodeServer(); + std::vector node_server_list; + + if (type == model::table::NODE_SERVER_HEDERA_MAINNET_NODE || type == model::table::NODE_SERVER_HEDERA_TESTNET_NODE) + { + node_server_list = db->loadFromDB("server_type", type, 4); + } + else if (type == model::table::NODE_SERVER_GRADIDO_NODE) + { + if (group_id) + { + node_server_list = db->loadFromDB( + { "server_type", "group_id" }, + { type, group_id }, + model::table::MYSQL_CONDITION_AND + ); + } + else + { + node_server_list = db->loadFromDB("server_type", type, 4); + } + } + //auto node_server_list = db->loadFromDB("alias", alias, 0); + + std::vector> resultVector; + resultVector.reserve(node_server_list.size()); + for (auto it = node_server_list.begin(); it != node_server_list.end(); it++) { + resultVector.push_back(new NodeServer(new model::table::NodeServer(*it))); + } + return resultVector; + } + + /* + SELECT * FROM table_name + ORDER BY RAND() + LIMIT 1; + */ + NodeServerConnection NodeServer::pick(model::table::NodeServerType type, int group_id/* = 0*/) + { + auto cm = ConnectionManager::getInstance(); + auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + NodeServerConnection result; + int hedera_node_id = 0; + + Poco::Data::Statement select(session); + select << "SELECT url, port"; + + if (model::table::NodeServerIsHederaNode(type)) { + select << ", node_hedera_id"; + } + select << " from node_servers ORDER BY RAND() LIMIT 1" + , Poco::Data::Keywords::into(result.url) + , Poco::Data::Keywords::into(result.port); + if (model::table::NodeServerIsHederaNode(type)) { + select, Poco::Data::Keywords::into(hedera_node_id); + } + try { + if (1 == select.execute()) { + if (model::table::NodeServerIsHederaNode(type)) { + result.hederaId = controller::HederaId::load(hedera_node_id); + } + return result; + } + } + catch (Poco::Exception& ex) { + auto em = ErrorManager::getInstance(); + const char* functionName = "NodeServer::pick"; + em->addError(new ParamError(functionName, "mysql error by pick: ", ex.message())); + em->addError(new ParamError(functionName, "server type: ", model::table::NodeServer::nodeServerTypeToString(type))); + em->addError(new ParamError(functionName, "group id", group_id)); + em->sendErrorsAsEmail(); + } + return result; + + } + + std::vector> NodeServer::listAll() + { + auto cm = ConnectionManager::getInstance(); + auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + Poco::Data::Statement select(session); + std::vector rows; + // typedef Poco::Tuple NodeServerFullTuple; + select << "SELECT n.id, n.url, n.port, n.group_id, n.server_type, n.node_hedera_id, h.shardNum, h.realmNum, h.num, n.last_live_sign " + << "FROM node_servers as n " + << "LEFT JOIN hedera_ids as h ON h.id = n.node_hedera_id" + , Poco::Data::Keywords::into(rows); + + try { + select.executeAsync(); + select.wait(); + } + catch (Poco::Exception& ex) { + auto em = ErrorManager::getInstance(); + const char* functionName = "NodeServer::listAll"; + em->addError(new ParamError(functionName, "mysql error by list all: ", ex.message())); + em->sendErrorsAsEmail(); + } + std::vector> results; + for (auto it = rows.begin(); it != rows.end(); it++) { + //NodeServer(const std::string& url, int port, int groupId, NodeServerType type, int nodeHederaId); + auto row = *it; + model::table::NodeServer* db = new model::table::NodeServer( + row.get<1>(), row.get<2>(), row.get<3>(), (model::table::NodeServerType)row.get<4>(), row.get<5>() + ); + db->setLastLiveSign(row.get<9>()); + db->setID(row.get<0>()); + Poco::AutoPtr node_server(new NodeServer(db)); + node_server->setHederaId(controller::HederaId::create( + row.get<6>(), row.get<7>(), row.get<8>() + )); + results.push_back(node_server); + + } + return results; + + } + +} \ No newline at end of file diff --git a/src/cpp/controller/NodeServer.h b/src/cpp/controller/NodeServer.h new file mode 100644 index 000000000..5a2750194 --- /dev/null +++ b/src/cpp/controller/NodeServer.h @@ -0,0 +1,52 @@ +#ifndef GRADIDO_LOGIN_SERVER_CONTROLLER_NODE_SERVER_INCLUDE +#define GRADIDO_LOGIN_SERVER_CONTROLLER_NODE_SERVER_INCLUDE + +#include "../model/table/NodeServer.h" +#include "../controller/HederaId.h" + +#include "Poco/SharedPtr.h" + +#include "TableControllerBase.h" + +namespace controller { + + struct NodeServerConnection + { + NodeServerConnection(const std::string& _url, int _port) : url(_url), port(_port) {} + NodeServerConnection() :port(0) {}; + + bool isValid() { return url != "" && port; } + std::string url; + int port; + + Poco::AutoPtr hederaId; + }; + + typedef Poco::Tuple NodeServerFullTuple; + + class NodeServer : public TableControllerBase + { + public: + + ~NodeServer(); + + static Poco::AutoPtr create(const std::string& url, int port, int groupId, model::table::NodeServerType type, int nodeHederaId); + + static std::vector> load(model::table::NodeServerType type, int group_id = 0); + static std::vector> listAll(); + // pick server randomly + NodeServerConnection pick(model::table::NodeServerType type, int group_id = 0); + inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } + + inline Poco::AutoPtr getModel() { return _getModel(); } + + inline void setHederaId(Poco::AutoPtr hederaId) { mHederaID = hederaId; } + inline Poco::AutoPtr getHederaId() { return mHederaID; } + protected: + NodeServer(model::table::NodeServer* dbModel); + Poco::AutoPtr mHederaID; + + }; +} + +#endif //GRADIDO_LOGIN_SERVER_CONTROLLER_NODE_SERVER_INCLUDE \ No newline at end of file diff --git a/src/cpp/model/table/HederaAccount.h b/src/cpp/model/table/HederaAccount.h index 2219fc521..c38af1df1 100644 --- a/src/cpp/model/table/HederaAccount.h +++ b/src/cpp/model/table/HederaAccount.h @@ -29,6 +29,15 @@ namespace model { static const char* hederaNetworkTypeToString(HederaNetworkType type); + inline int getAccountHederaId() { return mAccountHederaId; } + + inline Poco::UInt64 getBalance() { return mBalance; } + inline double getBalanceDouble() { return (double)mBalance / 100000000.0; } + + inline HederaNetworkType getNetworkType() { return (HederaNetworkType)mType; } + + inline std::string getUpdatedString() { return Poco::DateTimeFormatter::format(mUpdated, "%f.%m.%Y %H:%M:%S"); } + protected: Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); Poco::Data::Statement _loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName); diff --git a/src/cpp/model/table/HederaId.cpp b/src/cpp/model/table/HederaId.cpp index a4f25cc78..9f26f05c5 100644 --- a/src/cpp/model/table/HederaId.cpp +++ b/src/cpp/model/table/HederaId.cpp @@ -24,12 +24,37 @@ namespace model { std::string HederaId::toString() { std::stringstream ss; - ss << "Shard Num: " << std::to_string(mShardNum) << std::endl; - ss << "Realm Num: " << std::to_string(mRealmNum) << std::endl; - ss << "Num: " << std::to_string(mNum) << std::endl; + ss << std::to_string(mShardNum) << "." << std::to_string(mRealmNum) << "." << std::to_string(mNum) << std::endl; return ss.str(); } + int HederaId::getID() + { + auto cm = ConnectionManager::getInstance(); + Poco::ScopedLock _lock(mWorkMutex); + + assert(mNum != 0|| mShardNum != 0 || mRealmNum != 0); + if (mID) return mID; + + auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + Poco::Data::Statement select(session); + select << "SELECT id FROM " << getTableName() + << " where shardNum = ? AND realmNum = ? AND num = ?" + , into(mID), use(mShardNum), use(mRealmNum), use(mNum); + + try { + if (1 == select.execute()) { + return mID; + } + } + catch (Poco::Exception& ex) { + addError(new ParamError("HederaId::getID", "mysql error try to find existing entry", ex.message())); + sendErrorsAsEmail(); + } + insertIntoDB(true); + return mID; + } + Poco::Data::Statement HederaId::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) { diff --git a/src/cpp/model/table/HederaId.h b/src/cpp/model/table/HederaId.h index c36d1f656..8de69c2a9 100644 --- a/src/cpp/model/table/HederaId.h +++ b/src/cpp/model/table/HederaId.h @@ -18,6 +18,9 @@ namespace model { const char* getTableName() const { return "hedera_ids"; } std::string toString(); + //! \brief check if hedera id already in db, then return id, else insert in db and return + int getID(); + protected: Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); diff --git a/src/cpp/model/table/ModelBase.cpp b/src/cpp/model/table/ModelBase.cpp index 4b55ea084..7bb7301f6 100644 --- a/src/cpp/model/table/ModelBase.cpp +++ b/src/cpp/model/table/ModelBase.cpp @@ -43,21 +43,27 @@ namespace model { //printf("ModelBase::insertIntoDB with table: %s\n", getTableName()); auto cm = ConnectionManager::getInstance(); Poco::ScopedLock _lock(mWorkMutex); - Poco::Data::Statement insert = _insertIntoDB(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER)); + auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + Poco::Data::Statement insert = _insertIntoDB(session); size_t resultCount = 0; try { - if (insert.execute() == 1) { + if (insert.execute(true) == 1) { // load id from db if (loadId) { - Poco::Data::Statement select = _loadIdFromDB(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER)); + Poco::Data::Statement select = _loadIdFromDB(session); try { - return select.execute() == 1; + select.executeAsync(); + return select.wait() == 1; } catch (Poco::Exception& ex) { addError(new ParamError(getTableName(), "mysql error by select id", ex.displayText().data())); addError(new ParamError(getTableName(), "data set: ", toString().data())); } + select.reset(session); + select = _loadIdFromDB(session); + //Poco::Data::Statement select = _loadIdFromDB(session); + select.execute(); } else { return true; diff --git a/src/cpp/model/table/NodeServer.cpp b/src/cpp/model/table/NodeServer.cpp new file mode 100644 index 000000000..ae3bdbf81 --- /dev/null +++ b/src/cpp/model/table/NodeServer.cpp @@ -0,0 +1,114 @@ + +#include "NodeServer.h" + +using namespace Poco::Data::Keywords; + +namespace model { + namespace table { + + bool NodeServerIsHederaNode(NodeServerType type) { + return type == NODE_SERVER_HEDERA_MAINNET_NODE || type == NODE_SERVER_HEDERA_TESTNET_NODE; + } + bool NodeServerHasGroup(NodeServerType type) { + return type == NODE_SERVER_GRADIDO_NODE || type == NODE_SERVER_GRADIDO_COMMUNITY; + } + + + NodeServer::NodeServer() + : mPort(0), mGroupId(0), mServerType(0), mNodeHederaId(0) + { + + } + + NodeServer::NodeServer(const std::string& url, int port, int groupId, NodeServerType type, int nodeHederaId) + : mUrl(url), mPort(port), mGroupId(groupId), mServerType(type), mNodeHederaId(nodeHederaId) + { + } + + + + NodeServer::NodeServer(const NodeServerTuple& tuple) + : ModelBase(tuple.get<0>()), + mUrl(tuple.get<1>()), mPort(tuple.get<2>()), mGroupId(tuple.get<3>()), + mServerType(tuple.get<4>()), mNodeHederaId(tuple.get<5>()), mLastLiveSign(tuple.get<6>()) + { + + } + + NodeServer::~NodeServer() + { + + } + + std::string NodeServer::toString() + { + std::stringstream ss; + + ss << "id: " << getID() << std::endl; + ss << mUrl << ":" << mPort << std::endl; + ss << "group id: " << mGroupId << std::endl; + ss << "server type: " << nodeServerTypeToString((NodeServerType)mServerType) << std::endl; + ss << "node hedera id: " << mNodeHederaId << std::endl; + ss << "last live sign: " << Poco::DateTimeFormatter::format(mLastLiveSign, "%f.%m.%Y %H:%M:%S") << std::endl; + + return ss.str(); + } + + const char* NodeServer::nodeServerTypeToString(NodeServerType type) + { + switch (type) { + case NODE_SERVER_NONE: return "none"; + case NODE_SERVER_GRADIDO_NODE: return "Gradido Node"; + case NODE_SERVER_GRADIDO_COMMUNITY: return "Gradido Community"; + case NODE_SERVER_HEDERA_MAINNET_NODE: return "Hedera Mainnet Node"; + case NODE_SERVER_HEDERA_TESTNET_NODE: return "Hedera Testnet Node"; + default: return ""; + } + } + + Poco::Data::Statement NodeServer::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) + { + Poco::Data::Statement select(session); + + select << "SELECT id, url, port, group_id, server_type, node_hedera_id, last_live_sign FROM " << getTableName() + << " where " << fieldName << " = ?" + , into(mID), into(mUrl), into(mPort), into(mGroupId), into(mServerType), into(mNodeHederaId), into(mLastLiveSign); + + return select; + } + + Poco::Data::Statement NodeServer::_loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName) + { + Poco::Data::Statement select(session); + // typedef Poco::Tuple, int> UserTuple; + select << "SELECT id, url, port, group_id, server_type, node_hedera_id, last_live_sign FROM " << getTableName() + << " where " << fieldName << " LIKE ?"; + + return select; + } + + Poco::Data::Statement NodeServer::_loadIdFromDB(Poco::Data::Session session) + { + Poco::Data::Statement select(session); + lock(); + select << "SELECT id FROM " << getTableName() + << " where url = ? AND port = ? " + , into(mID), use(mUrl), use(mPort); + + unlock(); + return select; + } + + Poco::Data::Statement NodeServer::_insertIntoDB(Poco::Data::Session session) + { + Poco::Data::Statement insert(session); + lock(); + insert << "INSERT INTO " << getTableName() + << " (url, port, group_id, server_type, node_hedera_id) VALUES(?,?,?,?,?)" + , use(mUrl), use(mPort), use(mGroupId), use(mServerType), use(mNodeHederaId); + unlock(); + return insert; + } + + } +} \ No newline at end of file diff --git a/src/cpp/model/table/NodeServer.h b/src/cpp/model/table/NodeServer.h new file mode 100644 index 000000000..899be9196 --- /dev/null +++ b/src/cpp/model/table/NodeServer.h @@ -0,0 +1,71 @@ +#ifndef GRADIDO_LOGIN_SERVER_MODEL_TABLE_NODE_SERVER_INCLUDE +#define GRADIDO_LOGIN_SERVER_MODEL_TABLE_NODE_SERVER_INCLUDE + +#include "ModelBase.h" +#include "Poco/Tuple.h" + +namespace model { + namespace table { + + typedef Poco::Tuple NodeServerTuple; + + enum NodeServerType { + NODE_SERVER_NONE, + NODE_SERVER_GRADIDO_NODE, + NODE_SERVER_GRADIDO_COMMUNITY, + NODE_SERVER_HEDERA_MAINNET_NODE, + NODE_SERVER_HEDERA_TESTNET_NODE, + NODE_SERVER_TYPE_COUNT + }; + bool NodeServerIsHederaNode(NodeServerType type); + bool NodeServerHasGroup(NodeServerType type); + + + class NodeServer : public ModelBase + { + public: + NodeServer(); + NodeServer(const std::string& url, int port, int groupId, NodeServerType type, int nodeHederaId); + NodeServer(const NodeServerTuple& tuple); + ~NodeServer(); + + // generic db operations + const char* getTableName() const { return "node_servers"; } + std::string toString(); + + static const char* nodeServerTypeToString(NodeServerType type); + + inline void setLastLiveSign(Poco::DateTime lastLiveSign) { std::unique_lock _lock(mSharedMutex); mLastLiveSign = lastLiveSign; } + + inline std::string getUrl() const { return mUrl; } + inline int getPort() const { return mPort; } + inline std::string getUrlWithPort() const { return mUrl + ":" + std::to_string(mPort); } + inline int getGroupId() const { return mGroupId; } + inline NodeServerType getNodeServerType() const { return (NodeServerType)mServerType; } + inline bool isHederaNode() const { return NodeServerIsHederaNode((NodeServerType)mServerType);} + inline bool hasGroup() const {return NodeServerHasGroup((NodeServerType)mServerType);} + inline int getNodeHederaId() const { return mNodeHederaId; } + inline Poco::DateTime getLastLiveSign() const { std::shared_lock _lock(mSharedMutex); return mLastLiveSign; } + + protected: + Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); + Poco::Data::Statement _loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName); + Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session); + Poco::Data::Statement _insertIntoDB(Poco::Data::Session session); + + std::string mUrl; + int mPort; + int mGroupId; + int mServerType; + int mNodeHederaId; + Poco::DateTime mLastLiveSign; + + mutable std::shared_mutex mSharedMutex; + + }; + + } +} + + +#endif //GRADIDO_LOGIN_SERVER_MODEL_TABLE_NODE_SERVER_INCLUDE \ No newline at end of file diff --git a/src/cpsp/adminGroups.cpsp b/src/cpsp/adminGroups.cpsp index e357388af..014591b74 100644 --- a/src/cpsp/adminGroups.cpsp +++ b/src/cpsp/adminGroups.cpsp @@ -34,7 +34,7 @@ //auto groups = controller::Group::load("gdd1"); //std::vector> groups; -%><%@ include file="header.cpsp" %> +%><%@ include file="header_large.cpsp" %> <%= getErrorsHtml() %>
@@ -43,20 +43,20 @@
-
ID
-
Name
-
Alias
-
Url
-
<%= gettext("Description") %>
+
ID
+
Name
+
Alias
+
Url
+
<%= gettext("Description") %>
<% for(auto it = groups.begin(); it != groups.end(); it++) { auto group_model = (*it)->getModel(); %>
-
<%= group_model->getID() %>
-
<%= group_model->getName() %>
-
<%= group_model->getAlias() %>
-
<%= group_model->getUrl() %>
-
<%= group_model->getDescription()%>
+
<%= group_model->getID() %>
+
<%= group_model->getName() %>
+
<%= group_model->getAlias() %>
+
<%= group_model->getUrl() %>
+
<%= group_model->getDescription()%>
<% } %>
diff --git a/src/cpsp/adminNodeServer.cpsp b/src/cpsp/adminNodeServer.cpsp new file mode 100644 index 000000000..e4a0ff49d --- /dev/null +++ b/src/cpsp/adminNodeServer.cpsp @@ -0,0 +1,200 @@ +<%@ page class="AdminNodeServerPage" %> +<%@ page form="true" %> +<%@ page compressed="true" %> +<%@ page baseClass="SessionHTTPRequestHandler" %> +<%@ page ctorArg="Session*" %> +<%@ header include="SessionHTTPRequestHandler.h" %> +<%! + +#include "../controller/NodeServer.h" +#include "../controller/Group.h" +#include "../SingletonManager/SessionManager.h" +#include "../lib/DataTypeConverter.h" + +%> +<%% + const char* pageName = "Node Server"; + auto sm = SessionManager::getInstance(); + + // add + if(!form.empty()) { + // collect + auto url = form.get("node-server-url", ""); + auto portString = form.get("node-server-port", ""); + auto nodeServerTypeString = form.get("node-server-type", "0"); + auto shardNumString = form.get("account-shard-num", "0"); + auto realmNumString = form.get("account-realm-num", "0"); + auto numString = form.get("account-num", "0"); + auto nodeServerGroupString = form.get("node-server-group", ""); + + int port = 0; + int shardNum = 0; + int realmNum = 0; + int num = 0; + model::table::NodeServerType nodeServerType = model::table::NODE_SERVER_NONE; + int group_id = 0; + + + // validate + if(!sm->isValid(url, VALIDATE_ONLY_URL)) { + addError(new ParamError("Node Server", "Url not valid, must start with http or https", url)); + + } + if(!sm->isValid(portString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Node Server", "Port isn't valid integer")); + } else { + if(DataTypeConverter::strToInt(portString, port) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int convert error", "Error converting port to int")); + } + } + + if(!sm->isValid(nodeServerTypeString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Node Server Type", "not integer")); + } else { + int node_server_type_int = 0; + if(DataTypeConverter::strToInt(nodeServerTypeString, node_server_type_int) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting node server type to int")); + } + if(node_server_type_int < 0 || node_server_type_int >= (int)model::table::NODE_SERVER_TYPE_COUNT) { + addError(new Error("Node Server Type", "invalid value")); + } else { + nodeServerType = (model::table::NodeServerType)node_server_type_int; + } + } + if(model::table::NodeServerIsHederaNode(nodeServerType)) { + + if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "shard num not integer")); + } else { + if(DataTypeConverter::strToInt(shardNumString, shardNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting shardNumString to int")); + } + } + if(!sm->isValid(realmNumString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "realm num not integer")); + } else { + if(DataTypeConverter::strToInt(realmNumString, realmNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting realmNumString to int")); + } + } + if(!sm->isValid(numString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "num not integer")); + } else { + if(DataTypeConverter::strToInt(numString, num) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting num to int")); + } + } + } else if(model::table::NodeServerHasGroup(nodeServerType)) { + if(!sm->isValid(nodeServerGroupString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Group id", "group_id not integer")); + } else { + if(DataTypeConverter::strToInt(nodeServerGroupString, group_id) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting group_id to int")); + } + } + } + + + + if(0 == errorCount()) { + int hedera_id_int = 0; + if(NodeServerIsHederaNode(nodeServerType)) { + auto hedera_id = controller::HederaId::create(shardNum, realmNum, num); + hedera_id_int = hedera_id->getModel()->getID(); + } + + auto node_server = controller::NodeServer::create( + url, port, group_id, (model::table::NodeServerType)nodeServerType, hedera_id_int + ); + if(!node_server->getModel()->insertIntoDB(false)) { + addError(new Error("DB Error", "Error saving Node Server in DB")); + } + } + } + auto groups = controller::Group::listAll(); + std::map group_indices; + int count = 0; + for(auto it = groups.begin(); it != groups.end(); it++) { + group_indices.insert(std::pair((*it)->getModel()->getID(), count)); + count++; + } + + auto node_servers = controller::NodeServer::listAll(); + + +%><%@ include file="header_large.cpsp" %> +<%= getErrorsHtml() %> +
+
+
+

Alle Node Server

+
+
+
+
Server Type
+
Url:Port
+
Group / Hedera Id
+
+ <% for(auto it = node_servers.begin(); it != node_servers.end(); it++) { + auto node_server_model = (*it)->getModel(); + %> +
+
<%= model::table::NodeServer::nodeServerTypeToString(node_server_model->getNodeServerType()) %>
+
<%= node_server_model->getUrlWithPort() %>
+
+ <% if(node_server_model->isHederaNode()) { + auto hedera_id_model = (*it)->getHederaId()->getModel(); %> + <%= hedera_id_model->toString() %> + <% } else if(node_server_model->hasGroup()){ + auto groupIt = group_indices.find(node_server_model->getGroupId()); + if(groupIt != group_indices.end()) { + auto group_model = groups[groupIt->second]->getModel(); %> + <%= group_model->getName() %> + <% } else { %> + <%= node_server_model->getGroupId() %> + <% } %> + <% } %> +
+
+ <% } %> +
+
+
+

Ein Node Server hinzufügen

+
+
+
+ + + + + + +
+ Nur für Hedera Nodes + + + + +
+
+ Nur für Gradido Nodes + + +
+ + "> +
+
+ +<%@ include file="footer.cpsp" %> diff --git a/src/cpsp/header_large.cpsp b/src/cpsp/header_large.cpsp index 2aa8f5f4b..5f7a8a021 100644 --- a/src/cpsp/header_large.cpsp +++ b/src/cpsp/header_large.cpsp @@ -16,4 +16,14 @@
+
\ No newline at end of file From 5b899366d93816cfb7dd961a9c2f1019479ab753 Mon Sep 17 00:00:00 2001 From: Dario Date: Mon, 31 Aug 2020 15:05:54 +0200 Subject: [PATCH 019/293] add function to crypto key controller to get directly a KeyPairHedera --- src/cpp/Crypto/KeyPairHedera.cpp | 22 +++++++++++++--------- src/cpp/Crypto/KeyPairHedera.h | 1 + src/cpp/controller/CryptoKey.cpp | 17 +++++++++++++++++ src/cpp/controller/CryptoKey.h | 2 ++ src/cpp/model/table/CryptoKey.h | 5 +++++ 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/cpp/Crypto/KeyPairHedera.cpp b/src/cpp/Crypto/KeyPairHedera.cpp index 0a3bf4bc2..2846e9c43 100644 --- a/src/cpp/Crypto/KeyPairHedera.cpp +++ b/src/cpp/Crypto/KeyPairHedera.cpp @@ -10,13 +10,12 @@ KeyPairHedera::KeyPairHedera() } - -KeyPairHedera::KeyPairHedera(const MemoryBin* privateKey, const MemoryBin* publicKey /* = nullptr*/) +KeyPairHedera::KeyPairHedera(const MemoryBin* privateKey, const unsigned char* publicKey/* = nullptr*/, size_t publicKeySize/* = 0*/) : mPrivateKey(nullptr) { auto derPrefixPriv = DataTypeConverter::hexToBin("302e020100300506032b657004220420"); - auto derPrefixPub = DataTypeConverter::hexToBin("302a300506032b6570032100"); - + auto derPrefixPub = DataTypeConverter::hexToBin("302a300506032b6570032100"); + auto mm = MemoryManager::getInstance(); if (privateKey) { @@ -46,19 +45,19 @@ KeyPairHedera::KeyPairHedera(const MemoryBin* privateKey, const MemoryBin* publi default: throw std::exception("[KeyPairHedera] invalid private key"); } - + // check public } if (publicKey) { - switch (publicKey->size()) + switch (publicKeySize) { case 32: { // raw public key - memcpy(mPublicKey, *publicKey, publicKey->size()); + memcpy(mPublicKey, publicKey, publicKeySize); break; } case 44: // DER encoded public key - if (0 == sodium_memcmp(*publicKey, *derPrefixPub, derPrefixPub->size())) { - memcpy(mPublicKey, publicKey->data(derPrefixPub->size()), ed25519_pubkey_SIZE); + if (0 == sodium_memcmp(publicKey, *derPrefixPub, derPrefixPub->size())) { + memcpy(mPublicKey, &publicKey[derPrefixPub->size()], ed25519_pubkey_SIZE); } break; default: @@ -75,6 +74,11 @@ KeyPairHedera::KeyPairHedera(const MemoryBin* privateKey, const MemoryBin* publi mm->releaseMemory(derPrefixPriv); mm->releaseMemory(derPrefixPub); } +KeyPairHedera::KeyPairHedera(const MemoryBin* privateKey, const MemoryBin* publicKey /* = nullptr*/) + : KeyPairHedera(privateKey, publicKey->data(), publicKey->size()) +{ + +} KeyPairHedera::~KeyPairHedera() { diff --git a/src/cpp/Crypto/KeyPairHedera.h b/src/cpp/Crypto/KeyPairHedera.h index 115beebdb..7f0b7f3bc 100644 --- a/src/cpp/Crypto/KeyPairHedera.h +++ b/src/cpp/Crypto/KeyPairHedera.h @@ -22,6 +22,7 @@ public: //! \param privateKey: copy //! \param publicKey: copy //! + KeyPairHedera(const MemoryBin* privateKey, const unsigned char* publicKey = nullptr, size_t publicKeySize = 0); KeyPairHedera(const MemoryBin* privateKey, const MemoryBin* publicKey = nullptr); ~KeyPairHedera(); diff --git a/src/cpp/controller/CryptoKey.cpp b/src/cpp/controller/CryptoKey.cpp index 2e7d343ec..093a21e69 100644 --- a/src/cpp/controller/CryptoKey.cpp +++ b/src/cpp/controller/CryptoKey.cpp @@ -62,6 +62,23 @@ namespace controller { return nullptr; } + KeyPairHedera* CryptoKey::getKeyPair(Poco::AutoPtr user) + { + auto model = getModel(); + auto password = user->getPassword(); + auto mm = MemoryManager::getInstance(); + if (!password || !model->hasPrivateKeyEncrypted()) { + return nullptr; + } + MemoryBin* clearPassword = nullptr; + if (password->decrypt(model->getPrivateKeyEncrypted(), &clearPassword) != SecretKeyCryptography::AUTH_DECRYPT_OK) { + return nullptr; + } + KeyPairHedera* key_pair = new KeyPairHedera(clearPassword, model->getPublicKey(), model->getPublicKeySize()); + mm->releaseMemory(clearPassword); + return key_pair; + } + } diff --git a/src/cpp/controller/CryptoKey.h b/src/cpp/controller/CryptoKey.h index 6e4e110bb..12bb40e70 100644 --- a/src/cpp/controller/CryptoKey.h +++ b/src/cpp/controller/CryptoKey.h @@ -27,6 +27,8 @@ namespace controller { inline Poco::AutoPtr getModel() { return _getModel(); } + KeyPairHedera* getKeyPair(Poco::AutoPtr user); + protected: CryptoKey(model::table::CryptoKey* dbModel); diff --git a/src/cpp/model/table/CryptoKey.h b/src/cpp/model/table/CryptoKey.h index 58d6df5dc..7e50fc728 100644 --- a/src/cpp/model/table/CryptoKey.h +++ b/src/cpp/model/table/CryptoKey.h @@ -24,6 +24,11 @@ namespace model { const char* getTableName() const { return "crypto_keys"; } std::string toString(); + inline const unsigned char* getPublicKey() const { if (mPublicKey.isNull()) return nullptr; return mPublicKey.value().content().data(); } + size_t getPublicKeySize() const { if (mPublicKey.isNull()) return 0; return mPublicKey.value().content().size(); } + + inline bool hasPrivateKeyEncrypted() const { return !mPrivateKey.isNull(); } + inline const std::vector& getPrivateKeyEncrypted() const { return mPrivateKey.value().content(); } static const char* typeToString(KeyType type); protected: From 71edd964ac10df0b612f67e2f46f54e33a192ae7 Mon Sep 17 00:00:00 2001 From: Dario Date: Mon, 31 Aug 2020 19:55:56 +0200 Subject: [PATCH 020/293] compose hedera query to get balance, update CMakeLists.txt for adding missing libs for grpc --- CMakeLists.txt | 27 +++++- src/cpp/Crypto/KeyPairHedera.h | 1 + .../HTTPInterface/AdminHederaAccountPage.cpp | 68 +++++++++++---- src/cpp/controller/CryptoKey.cpp | 6 +- src/cpp/controller/CryptoKey.h | 2 +- src/cpp/controller/HederaAccount.cpp | 37 +++++++++ src/cpp/controller/HederaAccount.h | 5 +- src/cpp/controller/HederaId.cpp | 8 ++ src/cpp/controller/HederaId.h | 5 ++ src/cpp/controller/NodeServer.h | 4 +- src/cpp/main.cpp | 13 ++- src/cpp/model/hedera/Query.cpp | 83 +++++++++++++++++++ src/cpp/model/hedera/Query.h | 39 +++++++++ src/cpp/model/table/HederaAccount.cpp | 9 ++ src/cpp/model/table/HederaAccount.h | 9 +- src/cpp/model/table/HederaId.h | 4 + src/cpp/model/table/NodeServer.h | 3 +- 17 files changed, 295 insertions(+), 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b16d3bb4e..f246d7e52 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,9 +95,30 @@ find_library(MYSQL_LIBRARIES mariadbclient.lib PATHS "dependencies/mariadb-conne find_library(COMPILED_MARIADB_CLIENT_DEBUG mariadbclient PATHS "dependencies/mariadb-connector-c/build/libmariadb/Debug" REQUIRED) find_library(IROHA_ED25519 ed25519 PATHS "dependencies/iroha-ed25519/build/Debug" REQUIRED) set(GRPC_PATH "dependencies/grpc/_build/Debug") +set(GRPC_ABSL_PATH "dependencies/grpc/_build/third_party/abseil-cpp/absl/types/Debug") +set(GRPC_CARES_PATH "dependencies/grpc/_build/third_party/cares/cares/lib/Debug") +set(GRPC_BORING_SSL_PATH "dependencies/grpc/_build/third_party/boringssl-with-bazel/Debug") find_library(GRPC_PLUSPLUS grpc++ PATHS ${GRPC_PATH} REQUIRED) +find_library(GRPC_UNSECURE grpc++_unsecure PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_REFLECTION grpc++_reflection PATHS ${GRPC_PATH} REQUIRED) -set(GRPC_LIBS ${GRPC_PLUSPLUS} ${GRPC_REFLECTION}) +find_library(GRPC_LIB grpc PATHS ${GRPC_PATH} REQUIRED) +find_library(GRPC_ERROR_DETAILS grpc++_error_details PATHS ${GRPC_PATH} REQUIRED) +find_library(GRPC_RLIB gpr PATHS ${GRPC_PATH} REQUIRED) +find_library(GRPC_UPB upb PATHS ${GRPC_PATH} REQUIRED) +find_library(GRPC_ALTS grpc++_alts PATHS ${GRPC_PATH} REQUIRED) +find_library(GRPC_ADDRESS_SORTING address_sorting PATHS ${GRPC_PATH} REQUIRED) +find_library(GRPC_CARES cares PATHS ${GRPC_CARES_PATH} REQUIRED) +find_library(GRPC_BORING_SSL_CRYPTO crypto ${GRPC_BORING_SSL_PATH} REQUIRED) +find_library(GRPC_BORING_SSL_SSL ssl ${GRPC_BORING_SSL_PATH} REQUIRED) + +find_library(GRPC_ABSL_BAD_OPTIONAL_ACCESS absl_bad_optional_access ${GRPC_ABSL_PATH} REQUIRED) +set(GRPC_LIBS + ${GRPC_PLUSPLUS} ${GRPC_REFLECTION} ${GRPC_UNSECURE} ${GRPC_LIB} + ${GRPC_ERROR_DETAILS} ${GRPC_RLIB} ${GRPC_UPB} ${GRPC_ALTS} + ${GRPC_ABSL_BAD_OPTIONAL_ACCESS} ${GRPC_ADDRESS_SORTING} + ${GRPC_CARES} ${GRPC_BORING_SSL_CRYPTO} ${GRPC_BORING_SSL_SSL} +) + set(MYSQL_INCLUDE_DIR "dependencies/mariadb-connector-c/include") #set(POCO_DEBUG_PATH "I:/FremdCode/C++/poco/win64/lib/Debug") @@ -142,7 +163,9 @@ include_directories( endif(WIN32) -target_link_libraries(Gradido_LoginServer ${CONAN_LIBS} ${IROHA_ED25519}) +add_subdirectory("dependencies/grpc/third_party/abseil-cpp") + +target_link_libraries(Gradido_LoginServer absl::base absl::flat_hash_map absl::flags absl::memory absl::meta absl::numeric absl::strings ${CONAN_LIBS} ${IROHA_ED25519}) if(WIN32) TARGET_LINK_LIBRARIES(Gradido_LoginServer optimized ${MYSQL_LIBRARIES} Shlwapi) TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${COMPILED_MARIADB_CLIENT_DEBUG} Shlwapi) diff --git a/src/cpp/Crypto/KeyPairHedera.h b/src/cpp/Crypto/KeyPairHedera.h index 7f0b7f3bc..a3e4337e5 100644 --- a/src/cpp/Crypto/KeyPairHedera.h +++ b/src/cpp/Crypto/KeyPairHedera.h @@ -37,6 +37,7 @@ public: inline const unsigned char* getPublicKey() const { return mPublicKey; } MemoryBin* getPublicKeyCopy() const; + const static size_t getPublicKeySize() {return ed25519_pubkey_SIZE;} inline bool isTheSame(const KeyPairHedera& b) const { return 0 == sodium_memcmp(mPublicKey, b.mPublicKey, ed25519_pubkey_SIZE); diff --git a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp index 0de7a6922..0169083ef 100644 --- a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp +++ b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp @@ -14,6 +14,10 @@ #include "../lib/DataTypeConverter.h" #include "../SingletonManager/SessionManager.h" +#include "../ServerConfig.h" + +#include "Poco/URI.h" + #line 1 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" #include "../ServerConfig.h" @@ -33,15 +37,42 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request if (_compressResponse) response.set("Content-Encoding", "gzip"); Poco::Net::HTMLForm form(request, request.stream()); -#line 16 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 20 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" const char* pageName = "Hedera Account"; auto sm = SessionManager::getInstance(); auto mm = MemoryManager::getInstance(); auto user = mSession->getNewUser(); + Poco::URI uri(request.getURI()); + auto uri_query = uri.getQueryParameters(); + std::string action = ""; + std::string account_id_from_query; + if(uri_query[0].first == "action") { + action = uri_query[0].second; + } + if(uri_query[1].first == "account_id") { + account_id_from_query = uri_query[1].second; + } + for(auto it = uri_query.begin(); it != uri_query.end(); it++) { + printf("first: %s, second: %s\n", it->first.data(), it->second.data()); + } + + if(action == "updateBalance") { + int account_id = 0; + if(DataTypeConverter::strToInt(account_id_from_query, account_id) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting account_id_from_query to int")); + } else { + auto hedera_account = controller::HederaAccount::load("id", account_id); + if(!hedera_account.size() || hedera_account[0].isNull()) { + addError(new Error("Action Update Balance", "hedera id not found")); + } else { + hedera_account[0]->updateBalanceFromHedera(user); + } + } + } // add - if(!form.empty()) { + else if(!form.empty()) { // collect auto shardNumString = form.get("account-shard-num", "0"); auto realmNumString = form.get("account-realm-num", "0"); @@ -196,7 +227,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t
"; // end include header_large.cpsp responseStream << "\n"; -#line 121 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 152 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( getErrorsHtml() ); responseStream << "\n"; responseStream << "
\n"; @@ -210,32 +241,41 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t\t
Balance
\n"; responseStream << "\t\t\t\t
Server Type
\n"; responseStream << "\t\t\t\t
Last Updated
\n"; + responseStream << "\t\t\t\t
Aktionen
\n"; responseStream << "\t\t\t
\n"; responseStream << "\t\t\t"; -#line 134 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 166 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" for(auto it = hedera_accounts.begin(); it != hedera_accounts.end(); it++) { auto hedera_account_model = (*it)->getModel(); + auto updateUrl = ServerConfig::g_serverPath + "/hedera_account?action=updateBalance&account_id=" + std::to_string(hedera_account_model->getID()); responseStream << "\n"; responseStream << "\t\t\t\t
\n"; responseStream << "\t\t\t\t\t
"; -#line 138 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 171 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( (*it)->getHederaId()->getModel()->toString() ); responseStream << "
\n"; responseStream << "\t\t\t\t\t
"; -#line 139 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 172 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( hedera_account_model->getBalanceDouble() ); responseStream << " hbar
\n"; responseStream << "\t\t\t\t\t
"; -#line 140 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 173 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) ); responseStream << "
\n"; responseStream << "\t\t\t\t\t
"; -#line 141 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 174 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( hedera_account_model->getUpdatedString() ); responseStream << "
\n"; + responseStream << "\t\t\t\t\t
\n"; + responseStream << "\t\t\t\t\t\n"; responseStream << "\t\t\t\t
\n"; responseStream << "\t\t\t"; -#line 143 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 180 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" } responseStream << "\n"; responseStream << "\t\t
\n"; responseStream << "\t
\n"; @@ -255,21 +295,21 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\n"; diff --git a/src/cpp/controller/CryptoKey.cpp b/src/cpp/controller/CryptoKey.cpp index 093a21e69..3fabc25c5 100644 --- a/src/cpp/controller/CryptoKey.cpp +++ b/src/cpp/controller/CryptoKey.cpp @@ -62,19 +62,21 @@ namespace controller { return nullptr; } - KeyPairHedera* CryptoKey::getKeyPair(Poco::AutoPtr user) + std::unique_ptr CryptoKey::getKeyPair(Poco::AutoPtr user) { auto model = getModel(); auto password = user->getPassword(); auto mm = MemoryManager::getInstance(); if (!password || !model->hasPrivateKeyEncrypted()) { + printf("[CryptoKey::getKeyPair] return null, password empty or no private key\n"); return nullptr; } MemoryBin* clearPassword = nullptr; if (password->decrypt(model->getPrivateKeyEncrypted(), &clearPassword) != SecretKeyCryptography::AUTH_DECRYPT_OK) { + printf("[CryptoKey::getKeyPair] return null, error decrypting\n"); return nullptr; } - KeyPairHedera* key_pair = new KeyPairHedera(clearPassword, model->getPublicKey(), model->getPublicKeySize()); + auto key_pair = std::make_unique(clearPassword, model->getPublicKey(), model->getPublicKeySize()); mm->releaseMemory(clearPassword); return key_pair; } diff --git a/src/cpp/controller/CryptoKey.h b/src/cpp/controller/CryptoKey.h index 12bb40e70..fc69d042c 100644 --- a/src/cpp/controller/CryptoKey.h +++ b/src/cpp/controller/CryptoKey.h @@ -27,7 +27,7 @@ namespace controller { inline Poco::AutoPtr getModel() { return _getModel(); } - KeyPairHedera* getKeyPair(Poco::AutoPtr user); + std::unique_ptr getKeyPair(Poco::AutoPtr user); protected: diff --git a/src/cpp/controller/HederaAccount.cpp b/src/cpp/controller/HederaAccount.cpp index 9f4ff5b40..564752f72 100644 --- a/src/cpp/controller/HederaAccount.cpp +++ b/src/cpp/controller/HederaAccount.cpp @@ -1,5 +1,9 @@ #include "HederaAccount.h" +#include "NodeServer.h" +#include "CryptoKey.h" +#include "../model/hedera/Query.h" +#include "HederaRequest.h" namespace controller { @@ -69,5 +73,38 @@ namespace controller { return resultVector; } + bool HederaAccount::updateBalanceFromHedera(Poco::AutoPtr user) + { + static const char* functionName = "HederaAccount::updateBalanceFromHedera"; + + if (user.isNull() || !user->getModel()) { + printf("[%s] invalid user\n", functionName); + return false; + } + + auto account_model = getModel(); + auto hedera_node = NodeServer::pick(account_model->networkTypeToNodeServerType(account_model->getNetworkType())); + auto crypto_key = controller::CryptoKey::load(account_model->getCryptoKeyId()); + if (crypto_key.isNull()) { + printf("[%s] error, crypto key with id: %d not found\n", functionName, account_model->getCryptoKeyId()); + return false; + } + auto hedera_key_pair = crypto_key->getKeyPair(user); + if (!hedera_key_pair) { + printf("[%s] error decrypting private key with id: %d, with user: %d\n", functionName, account_model->getCryptoKeyId(), user->getModel()->getID()); + return false; + } + auto query = model::hedera::Query::getBalance(mHederaID, hedera_node); + if (!query) { + printf("[%s] error creating query\n", functionName); + } + query->sign(std::move(hedera_key_pair)); + + HederaRequest request; + request.request(query); + + return false; + } + } diff --git a/src/cpp/controller/HederaAccount.h b/src/cpp/controller/HederaAccount.h index dd4c97435..1a3fd9ace 100644 --- a/src/cpp/controller/HederaAccount.h +++ b/src/cpp/controller/HederaAccount.h @@ -1,7 +1,8 @@ #ifndef GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_ACCOUNT_INCLUDE #define GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_ACCOUNT_INCLUDE -#include "../controller/HederaId.h" +#include "HederaId.h" +#include "User.h" #include "../model/table/HederaAccount.h" #include "Poco/SharedPtr.h" @@ -26,6 +27,8 @@ namespace controller { inline void setHederaId(Poco::AutoPtr hederaId) { mHederaID = hederaId; } inline Poco::AutoPtr getHederaId() { return mHederaID; } + bool updateBalanceFromHedera(Poco::AutoPtr user); + protected: HederaAccount(model::table::HederaAccount* dbModel); Poco::AutoPtr mHederaID; diff --git a/src/cpp/controller/HederaId.cpp b/src/cpp/controller/HederaId.cpp index e6d281907..ce171a7a8 100644 --- a/src/cpp/controller/HederaId.cpp +++ b/src/cpp/controller/HederaId.cpp @@ -29,4 +29,12 @@ namespace controller { } return nullptr; } + + void HederaId::copyToProtoAccountId(proto::AccountID* protoAccountId) const + { + auto model = getModel(); + protoAccountId->set_shardnum(model->getShardNum()); + protoAccountId->set_realmnum(model->getRealmNum()); + protoAccountId->set_accountnum(model->getNum()); + } } \ No newline at end of file diff --git a/src/cpp/controller/HederaId.h b/src/cpp/controller/HederaId.h index f02e69373..ae9296a43 100644 --- a/src/cpp/controller/HederaId.h +++ b/src/cpp/controller/HederaId.h @@ -7,6 +7,8 @@ #include "TableControllerBase.h" +#include "../proto/hedera/BasicTypes.pb.h" + namespace controller { class HederaId : public TableControllerBase { @@ -21,6 +23,9 @@ namespace controller { inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } inline Poco::AutoPtr getModel() { return _getModel(); } + inline const model::table::HederaId* getModel() const { return _getModel(); } + + void copyToProtoAccountId(proto::AccountID* protoAccountId) const; protected: diff --git a/src/cpp/controller/NodeServer.h b/src/cpp/controller/NodeServer.h index 5a2750194..8cc4b4e23 100644 --- a/src/cpp/controller/NodeServer.h +++ b/src/cpp/controller/NodeServer.h @@ -15,6 +15,8 @@ namespace controller { NodeServerConnection(const std::string& _url, int _port) : url(_url), port(_port) {} NodeServerConnection() :port(0) {}; + std::string getUrlWithPort() const { return url + ":" + std::to_string(port); } + bool isValid() { return url != "" && port; } std::string url; int port; @@ -35,7 +37,7 @@ namespace controller { static std::vector> load(model::table::NodeServerType type, int group_id = 0); static std::vector> listAll(); // pick server randomly - NodeServerConnection pick(model::table::NodeServerType type, int group_id = 0); + static NodeServerConnection pick(model::table::NodeServerType type, int group_id = 0); inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } inline Poco::AutoPtr getModel() { return _getModel(); } diff --git a/src/cpp/main.cpp b/src/cpp/main.cpp index 715352f91..910db09ff 100644 --- a/src/cpp/main.cpp +++ b/src/cpp/main.cpp @@ -13,6 +13,7 @@ #include "model/table/EmailOptIn.h" #include "Poco/DateTimeParser.h" +#include #ifndef _TEST_BUILD @@ -35,8 +36,8 @@ int main(int argc, char** argv) ServerConfig::g_versionString = Poco::DateTimeFormatter::format(buildDateTime, "0.%y.%m.%d"); //ServerConfig::g_versionString = "0.20.KW13.02"; printf("Version: %s\n", ServerConfig::g_versionString.data()); - printf("User size: %d Bytes, Session size: %d Bytes\n", sizeof(User), sizeof(Session)); - printf("model sizes: User: %d Bytes, EmailOptIn: %d Bytes\n", sizeof(model::table::User), sizeof(model::table::EmailOptIn)); + printf("User size: %d Bytes, Session size: %d Bytes\n", (int)sizeof(User), (int)sizeof(Session)); + printf("model sizes: User: %d Bytes, EmailOptIn: %d Bytes\n", (int)sizeof(model::table::User), (int)sizeof(model::table::EmailOptIn)); // load word lists if (!ServerConfig::loadMnemonicWordLists()) { @@ -49,8 +50,12 @@ int main(int argc, char** argv) printf("test passphrase generation and transformation failed\n"); return -3; } - + grpc_init(); + Gradido_LoginServer app; - return app.run(argc, argv); + auto result = app.run(argc, argv); + + grpc_shutdown(); + return result; } #endif \ No newline at end of file diff --git a/src/cpp/model/hedera/Query.cpp b/src/cpp/model/hedera/Query.cpp index e69de29bb..d47449bc6 100644 --- a/src/cpp/model/hedera/Query.cpp +++ b/src/cpp/model/hedera/Query.cpp @@ -0,0 +1,83 @@ +#include "Query.h" +#include "Poco/Timestamp.h" +#include "../../SingletonManager/MemoryManager.h" + +namespace model { + namespace hedera { + + Query::Query(const controller::NodeServerConnection& connection) + : mConnection(connection) + { + + } + + Query::~Query() + { + + } + + Query* Query::getBalance(Poco::AutoPtr accountId, const controller::NodeServerConnection& connection) + { + + assert(!accountId.isNull() && accountId->getModel()); + + auto query = new Query(connection); + auto get_account_balance = query->mQueryProto.mutable_cryptogetaccountbalance(); + accountId->copyToProtoAccountId(get_account_balance->mutable_accountid()); + auto query_header = get_account_balance->mutable_header(); + query_header->set_responsetype(proto::ANSWER_ONLY); + auto transaction = query_header->mutable_payment(); + //auto transaction_body = transaction->mutable_body(); + // body content + // transaction id + auto transaction_id = query->mTransactionBody.mutable_transactionid(); + auto timestamp = transaction_id->mutable_transactionvalidstart(); + Poco::Timestamp now; + auto microseconds = now.epochMicroseconds() - now.epochTime() * now.resolution(); // 1*10^6 + timestamp->set_seconds(now.epochTime()); + timestamp->set_nanos(microseconds * 1000); + accountId->copyToProtoAccountId(transaction_id->mutable_accountid()); + // + // sdk default, but can be changed + query->mTransactionBody.set_transactionfee(100000000); + auto valid_duration = query->mTransactionBody.mutable_transactionvalidduration(); + // maximal 2 minutes + valid_duration->set_seconds(120); + auto crypto_transfer = query->mTransactionBody.mutable_cryptotransfer(); + auto transfer_list = crypto_transfer->mutable_transfers(); + auto account_amounts = transfer_list->mutable_accountamounts(); + account_amounts->Add(); + auto account_amount = account_amounts->Mutable(0); + account_amount->set_amount(0); + connection.hederaId->copyToProtoAccountId(account_amount->mutable_accountid()); + + return query; + } + + bool Query::sign(std::unique_ptr keyPairHedera) + { + auto mm = MemoryManager::getInstance(); + auto body_bytes = mTransactionBody.SerializeAsString(); + auto transaction = mQueryProto.mutable_cryptogetaccountbalance()->mutable_header()->mutable_payment(); + transaction->set_bodybytes(body_bytes.data()); + auto signature_map = transaction->mutable_sigmap(); + auto signature_pairs = signature_map->mutable_sigpair(); + signature_pairs->Add(); + auto signature_pair = signature_pairs->Mutable(0); + auto public_key = keyPairHedera->getPublicKey(); + + + auto sign = keyPairHedera->sign(body_bytes); + if (!sign) { + printf("[Query::sign] error signing message\n"); + return false; + } + signature_pair->set_pubkeyprefix(public_key, keyPairHedera->getPublicKeySize()); + signature_pair->set_ed25519(*sign, sign->size()); + + mm->releaseMemory(sign); + + return true; + } + } +} \ No newline at end of file diff --git a/src/cpp/model/hedera/Query.h b/src/cpp/model/hedera/Query.h index e69de29bb..8dff35024 100644 --- a/src/cpp/model/hedera/Query.h +++ b/src/cpp/model/hedera/Query.h @@ -0,0 +1,39 @@ +#ifndef _GRADIDO_LOGIN_SERVER_MODEL_HEDERA_QUERY_H +#define _GRADIDO_LOGIN_SERVER_MODEL_HEDERA_QUERY_H + +/*! + * @author: Dario Rekowski + * + * @date: 31.08.20 + * + * @brief: class for put together hedera querys (ask for state data, not a transaction, but needs a payment transaction) + * +*/ + +#include "../../proto/hedera/Query.pb.h" +#include "../../controller/NodeServer.h" +#include "../../Crypto/KeyPairHedera.h" + +namespace model { + namespace hedera { + class Query + { + public: + ~Query(); + static Query* getBalance(Poco::AutoPtr accountId, const controller::NodeServerConnection& connection); + bool sign(std::unique_ptr keyPairHedera); + + inline const proto::Query* getProtoQuery() const { return &mQueryProto; } + inline std::string getConnectionString() const { return mConnection.getUrlWithPort(); } + + protected: + Query(const controller::NodeServerConnection& connection); + proto::Query mQueryProto; + proto::TransactionBody mTransactionBody; + controller::NodeServerConnection mConnection; + }; + } +} + + +#endif //_GRADIDO_LOGIN_SERVER_MODEL_HEDERA_QUERY_H \ No newline at end of file diff --git a/src/cpp/model/table/HederaAccount.cpp b/src/cpp/model/table/HederaAccount.cpp index 06538fdcb..1485ff554 100644 --- a/src/cpp/model/table/HederaAccount.cpp +++ b/src/cpp/model/table/HederaAccount.cpp @@ -53,6 +53,15 @@ namespace model { } } + NodeServerType HederaAccount::networkTypeToNodeServerType(HederaNetworkType type) + { + switch (type) { + case HEDERA_MAINNET: return NODE_SERVER_HEDERA_MAINNET_NODE; + case HEDERA_TESTNET: return NODE_SERVER_HEDERA_TESTNET_NODE; + default: return NODE_SERVER_TYPE_NONE; + } + } + Poco::Data::Statement HederaAccount::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) { Poco::Data::Statement select(session); diff --git a/src/cpp/model/table/HederaAccount.h b/src/cpp/model/table/HederaAccount.h index c38af1df1..4d4dd6575 100644 --- a/src/cpp/model/table/HederaAccount.h +++ b/src/cpp/model/table/HederaAccount.h @@ -4,6 +4,8 @@ #include "ModelBase.h" #include "Poco/Tuple.h" +#include "NodeServer.h" + namespace model { namespace table { @@ -12,7 +14,7 @@ namespace model { enum HederaNetworkType { HEDERA_MAINNET, HEDERA_TESTNET, - HEDERA_NET_COUNT + HEDERA_NET_COUNT, }; class HederaAccount : public ModelBase @@ -28,13 +30,16 @@ namespace model { std::string toString(); static const char* hederaNetworkTypeToString(HederaNetworkType type); + static NodeServerType networkTypeToNodeServerType(HederaNetworkType type); - inline int getAccountHederaId() { return mAccountHederaId; } + inline int getAccountHederaId() const { return mAccountHederaId; } + inline int getCryptoKeyId() const { return mAccountKeyId; } inline Poco::UInt64 getBalance() { return mBalance; } inline double getBalanceDouble() { return (double)mBalance / 100000000.0; } inline HederaNetworkType getNetworkType() { return (HederaNetworkType)mType; } + inline std::string getUpdatedString() { return Poco::DateTimeFormatter::format(mUpdated, "%f.%m.%Y %H:%M:%S"); } diff --git a/src/cpp/model/table/HederaId.h b/src/cpp/model/table/HederaId.h index 8de69c2a9..9dc2029bc 100644 --- a/src/cpp/model/table/HederaId.h +++ b/src/cpp/model/table/HederaId.h @@ -21,6 +21,10 @@ namespace model { //! \brief check if hedera id already in db, then return id, else insert in db and return int getID(); + inline Poco::UInt64 getShardNum() const { return mShardNum; } + inline Poco::UInt64 getRealmNum() const { return mRealmNum; } + inline Poco::UInt64 getNum() const { return mNum; } + protected: Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); diff --git a/src/cpp/model/table/NodeServer.h b/src/cpp/model/table/NodeServer.h index 899be9196..4e592c822 100644 --- a/src/cpp/model/table/NodeServer.h +++ b/src/cpp/model/table/NodeServer.h @@ -15,7 +15,8 @@ namespace model { NODE_SERVER_GRADIDO_COMMUNITY, NODE_SERVER_HEDERA_MAINNET_NODE, NODE_SERVER_HEDERA_TESTNET_NODE, - NODE_SERVER_TYPE_COUNT + NODE_SERVER_TYPE_COUNT, + NODE_SERVER_TYPE_NONE }; bool NodeServerIsHederaNode(NodeServerType type); bool NodeServerHasGroup(NodeServerType type); From 43dd1a5082a4365cb0f27143cbf4b48eaffc000c Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 1 Sep 2020 11:06:20 +0200 Subject: [PATCH 021/293] update grpc to new version, update some things they don't work for create the first query to hedera --- CMakeLists.txt | 7 ++- skeema/gradido_login/crypto_keys.sql | 2 +- src/cpp/Crypto/KeyPairHedera.cpp | 5 ++ .../HTTPInterface/AdminHederaAccountPage.cpp | 49 ++++++++++--------- src/cpp/controller/CryptoKey.cpp | 4 ++ src/cpp/controller/HederaAccount.cpp | 12 ++++- src/cpp/controller/HederaAccount.h | 2 +- src/cpp/controller/NodeServer.cpp | 15 +++++- src/cpp/controller/NodeServer.h | 6 ++- src/cpp/lib/DataTypeConverter.h | 1 + src/cpp/model/hedera/Query.h | 2 +- 11 files changed, 73 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f246d7e52..6a24af9a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,6 +98,7 @@ set(GRPC_PATH "dependencies/grpc/_build/Debug") set(GRPC_ABSL_PATH "dependencies/grpc/_build/third_party/abseil-cpp/absl/types/Debug") set(GRPC_CARES_PATH "dependencies/grpc/_build/third_party/cares/cares/lib/Debug") set(GRPC_BORING_SSL_PATH "dependencies/grpc/_build/third_party/boringssl-with-bazel/Debug") +set(GRPC_RE2_PATH "dependencies/grpc/_build/third_party/re2/Debug") find_library(GRPC_PLUSPLUS grpc++ PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_UNSECURE grpc++_unsecure PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_REFLECTION grpc++_reflection PATHS ${GRPC_PATH} REQUIRED) @@ -110,13 +111,17 @@ find_library(GRPC_ADDRESS_SORTING address_sorting PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_CARES cares PATHS ${GRPC_CARES_PATH} REQUIRED) find_library(GRPC_BORING_SSL_CRYPTO crypto ${GRPC_BORING_SSL_PATH} REQUIRED) find_library(GRPC_BORING_SSL_SSL ssl ${GRPC_BORING_SSL_PATH} REQUIRED) +find_library(GRPC_RE2 re2 ${GRPC_RE2_PATH} REQUIRED) find_library(GRPC_ABSL_BAD_OPTIONAL_ACCESS absl_bad_optional_access ${GRPC_ABSL_PATH} REQUIRED) set(GRPC_LIBS ${GRPC_PLUSPLUS} ${GRPC_REFLECTION} ${GRPC_UNSECURE} ${GRPC_LIB} ${GRPC_ERROR_DETAILS} ${GRPC_RLIB} ${GRPC_UPB} ${GRPC_ALTS} ${GRPC_ABSL_BAD_OPTIONAL_ACCESS} ${GRPC_ADDRESS_SORTING} - ${GRPC_CARES} ${GRPC_BORING_SSL_CRYPTO} ${GRPC_BORING_SSL_SSL} + ${GRPC_CARES} + ${GRPC_BORING_SSL_CRYPTO} + ${GRPC_BORING_SSL_SSL} + ${GRPC_RE2} ) set(MYSQL_INCLUDE_DIR "dependencies/mariadb-connector-c/include") diff --git a/skeema/gradido_login/crypto_keys.sql b/skeema/gradido_login/crypto_keys.sql index c90750ae3..c79987755 100644 --- a/skeema/gradido_login/crypto_keys.sql +++ b/skeema/gradido_login/crypto_keys.sql @@ -1,6 +1,6 @@ CREATE TABLE `crypto_keys` ( `id` int unsigned NOT NULL AUTO_INCREMENT, - `private_key` varbinary(64) NOT NULL, + `private_key` binary(80) NOT NULL, `public_key` binary(32) NOT NULL, `crypto_key_type_id` int NOT NULL DEFAULT '0', PRIMARY KEY (`id`), diff --git a/src/cpp/Crypto/KeyPairHedera.cpp b/src/cpp/Crypto/KeyPairHedera.cpp index 2846e9c43..27d9731a7 100644 --- a/src/cpp/Crypto/KeyPairHedera.cpp +++ b/src/cpp/Crypto/KeyPairHedera.cpp @@ -162,8 +162,13 @@ MemoryBin* KeyPairHedera::getCryptedPrivKey(const Poco::AutoPtrencrypt(mPrivateKey, &encryptedKey)) { + auto encrypted_private_key_hex_string = DataTypeConverter::binToHex(encryptedKey); + printf("[KeyPairHedera::getCryptedPrivKey] encryptet private key hex: %s\n", encrypted_private_key_hex_string.data()); return encryptedKey; } else { diff --git a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp index 0169083ef..a9d4165c3 100644 --- a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp +++ b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp @@ -48,16 +48,14 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request auto uri_query = uri.getQueryParameters(); std::string action = ""; std::string account_id_from_query; - if(uri_query[0].first == "action") { - action = uri_query[0].second; + if(uri_query.size() >= 2) { + if(uri_query[0].first == "action") { + action = uri_query[0].second; + } + if(uri_query[1].first == "account_id") { + account_id_from_query = uri_query[1].second; + } } - if(uri_query[1].first == "account_id") { - account_id_from_query = uri_query[1].second; - } - for(auto it = uri_query.begin(); it != uri_query.end(); it++) { - printf("first: %s, second: %s\n", it->first.data(), it->second.data()); - } - if(action == "updateBalance") { int account_id = 0; if(DataTypeConverter::strToInt(account_id_from_query, account_id) != DataTypeConverter::NUMBER_PARSE_OKAY) { @@ -67,7 +65,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request if(!hedera_account.size() || hedera_account[0].isNull()) { addError(new Error("Action Update Balance", "hedera id not found")); } else { - hedera_account[0]->updateBalanceFromHedera(user); + hedera_account[0]->updateBalanceFromHedera(user, this); } } } @@ -227,7 +225,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t
"; // end include header_large.cpsp responseStream << "\n"; -#line 152 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 150 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( getErrorsHtml() ); responseStream << "\n"; responseStream << "
\n"; @@ -244,38 +242,38 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t\t
Aktionen
\n"; responseStream << "\t\t\t
\n"; responseStream << "\t\t\t"; -#line 166 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 164 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" for(auto it = hedera_accounts.begin(); it != hedera_accounts.end(); it++) { auto hedera_account_model = (*it)->getModel(); auto updateUrl = ServerConfig::g_serverPath + "/hedera_account?action=updateBalance&account_id=" + std::to_string(hedera_account_model->getID()); responseStream << "\n"; responseStream << "\t\t\t\t
\n"; responseStream << "\t\t\t\t\t
"; -#line 171 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 169 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( (*it)->getHederaId()->getModel()->toString() ); responseStream << "
\n"; responseStream << "\t\t\t\t\t
"; -#line 172 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 170 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( hedera_account_model->getBalanceDouble() ); responseStream << " hbar
\n"; responseStream << "\t\t\t\t\t
"; -#line 173 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 171 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) ); responseStream << "
\n"; responseStream << "\t\t\t\t\t
"; -#line 174 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 172 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( hedera_account_model->getUpdatedString() ); responseStream << "
\n"; responseStream << "\t\t\t\t\t
\n"; responseStream << "\t\t\t\t\t\n"; responseStream << "\t\t\t\t
\n"; responseStream << "\t\t\t"; -#line 180 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 178 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" } responseStream << "\n"; responseStream << "\t\t
\n"; responseStream << "\t
\n"; @@ -283,7 +281,10 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t

Einen neuen Account anlegen

\n"; responseStream << "\t
\n"; responseStream << "\t
\n"; - responseStream << "\t\t
\n"; + responseStream << "\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; @@ -295,21 +296,21 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t
\n"; diff --git a/src/cpp/controller/CryptoKey.cpp b/src/cpp/controller/CryptoKey.cpp index 3fabc25c5..79d68a62e 100644 --- a/src/cpp/controller/CryptoKey.cpp +++ b/src/cpp/controller/CryptoKey.cpp @@ -1,6 +1,7 @@ #include "CryptoKey.h" #include "../SingletonManager/ErrorManager.h" +#include "../lib/DataTypeConverter.h" namespace controller { @@ -72,6 +73,9 @@ namespace controller { return nullptr; } MemoryBin* clearPassword = nullptr; + auto encrypted_private_key = model->getPrivateKeyEncrypted(); + auto encrypted_private_key_hex_string = DataTypeConverter::binToHex(encrypted_private_key); + printf("[CryptoKey::getKeyPair] encrypted private key hex: %s\n", encrypted_private_key_hex_string.data()); if (password->decrypt(model->getPrivateKeyEncrypted(), &clearPassword) != SecretKeyCryptography::AUTH_DECRYPT_OK) { printf("[CryptoKey::getKeyPair] return null, error decrypting\n"); return nullptr; diff --git a/src/cpp/controller/HederaAccount.cpp b/src/cpp/controller/HederaAccount.cpp index 564752f72..6172db46c 100644 --- a/src/cpp/controller/HederaAccount.cpp +++ b/src/cpp/controller/HederaAccount.cpp @@ -73,7 +73,7 @@ namespace controller { return resultVector; } - bool HederaAccount::updateBalanceFromHedera(Poco::AutoPtr user) + bool HederaAccount::updateBalanceFromHedera(Poco::AutoPtr user, ErrorList* errorReceiver/* = nullptr*/) { static const char* functionName = "HederaAccount::updateBalanceFromHedera"; @@ -101,7 +101,15 @@ namespace controller { query->sign(std::move(hedera_key_pair)); HederaRequest request; - request.request(query); + try { + request.request(query); + } + catch (Poco::Exception& ex) { + printf("[HederaAccount::updateBalanceFromHedera] exception calling hedera request: %s\n", ex.displayText().data()); + } + if (errorReceiver) { + errorReceiver->getErrors(&request); + } return false; } diff --git a/src/cpp/controller/HederaAccount.h b/src/cpp/controller/HederaAccount.h index 1a3fd9ace..7f08adddc 100644 --- a/src/cpp/controller/HederaAccount.h +++ b/src/cpp/controller/HederaAccount.h @@ -27,7 +27,7 @@ namespace controller { inline void setHederaId(Poco::AutoPtr hederaId) { mHederaID = hederaId; } inline Poco::AutoPtr getHederaId() { return mHederaID; } - bool updateBalanceFromHedera(Poco::AutoPtr user); + bool updateBalanceFromHedera(Poco::AutoPtr user, ErrorList* errorReceiver = nullptr); protected: HederaAccount(model::table::HederaAccount* dbModel); diff --git a/src/cpp/controller/NodeServer.cpp b/src/cpp/controller/NodeServer.cpp index 6096b2839..625e61dad 100644 --- a/src/cpp/controller/NodeServer.cpp +++ b/src/cpp/controller/NodeServer.cpp @@ -1,9 +1,21 @@ #include "NodeServer.h" #include "../SingletonManager/ErrorManager.h" #include "../SingletonManager/ConnectionManager.h" +#include "Poco/RegularExpression.h" namespace controller { + Poco::RegularExpression g_filterHttp("^https?://"); + + std::string NodeServerConnection::getUriWithPort() const + { + std::string protocol; + g_filterHttp.extract(url, protocol); + return url.substr(protocol.size()) + ":" + std::to_string(port); + } + + + NodeServer::NodeServer(model::table::NodeServer* dbModel) { @@ -74,12 +86,13 @@ namespace controller { if (model::table::NodeServerIsHederaNode(type)) { select << ", node_hedera_id"; } - select << " from node_servers ORDER BY RAND() LIMIT 1" + select << " from node_servers where server_type = ? ORDER BY RAND() LIMIT 1" , Poco::Data::Keywords::into(result.url) , Poco::Data::Keywords::into(result.port); if (model::table::NodeServerIsHederaNode(type)) { select, Poco::Data::Keywords::into(hedera_node_id); } + select , Poco::Data::Keywords::bind((int)type); try { if (1 == select.execute()) { if (model::table::NodeServerIsHederaNode(type)) { diff --git a/src/cpp/controller/NodeServer.h b/src/cpp/controller/NodeServer.h index 8cc4b4e23..6945ac949 100644 --- a/src/cpp/controller/NodeServer.h +++ b/src/cpp/controller/NodeServer.h @@ -15,7 +15,11 @@ namespace controller { NodeServerConnection(const std::string& _url, int _port) : url(_url), port(_port) {} NodeServerConnection() :port(0) {}; - std::string getUrlWithPort() const { return url + ":" + std::to_string(port); } + // with http:// or https:// + inline std::string getUrlWithPort() const { return url + ":" + std::to_string(port); } + + // without http:// or https:// + std::string getUriWithPort() const; bool isValid() { return url != "" && port; } std::string url; diff --git a/src/cpp/lib/DataTypeConverter.h b/src/cpp/lib/DataTypeConverter.h index 46a767d97..0dad46954 100644 --- a/src/cpp/lib/DataTypeConverter.h +++ b/src/cpp/lib/DataTypeConverter.h @@ -31,6 +31,7 @@ namespace DataTypeConverter { std::string binToHex(const unsigned char* data, size_t size); std::string binToHex(const Poco::Nullable& nullableBin); inline std::string binToHex(const MemoryBin* data) { return binToHex(data->data(), data->size());} + inline std::string binToHex(const std::vector& data) { return binToHex(data.data(), data.size()); } //! \param pubkey pointer to array with crypto_sign_PUBLICKEYBYTES size std::string pubkeyToHex(const unsigned char* pubkey); diff --git a/src/cpp/model/hedera/Query.h b/src/cpp/model/hedera/Query.h index 8dff35024..ad9af855a 100644 --- a/src/cpp/model/hedera/Query.h +++ b/src/cpp/model/hedera/Query.h @@ -24,7 +24,7 @@ namespace model { bool sign(std::unique_ptr keyPairHedera); inline const proto::Query* getProtoQuery() const { return &mQueryProto; } - inline std::string getConnectionString() const { return mConnection.getUrlWithPort(); } + inline std::string getConnectionString() const { return mConnection.getUriWithPort(); } protected: Query(const controller::NodeServerConnection& connection); From c968a58cfa758655966b12848b2c88fe7e3f37e5 Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 1 Sep 2020 11:36:50 +0200 Subject: [PATCH 022/293] add some missing files --- skeema/gradido_login/node_servers.sql | 10 + src/cpp/HTTPInterface/AdminTopicPage.cpp | 128 +++++++++++ src/cpp/HTTPInterface/AdminTopicPage.h | 20 ++ .../HTTPInterface/PassphrasedTransaction.cpsp | 162 ++++++++++++++ src/cpp/controller/HederaRequest.cpp | 39 ++++ src/cpp/controller/HederaRequest.h | 39 ++++ src/cpsp/adminHederaAccount.cpsp | 203 ++++++++++++++++++ 7 files changed, 601 insertions(+) create mode 100644 skeema/gradido_login/node_servers.sql create mode 100644 src/cpp/HTTPInterface/AdminTopicPage.cpp create mode 100644 src/cpp/HTTPInterface/AdminTopicPage.h create mode 100644 src/cpp/HTTPInterface/PassphrasedTransaction.cpsp create mode 100644 src/cpp/controller/HederaRequest.cpp create mode 100644 src/cpp/controller/HederaRequest.h create mode 100644 src/cpsp/adminHederaAccount.cpsp diff --git a/skeema/gradido_login/node_servers.sql b/skeema/gradido_login/node_servers.sql new file mode 100644 index 000000000..88e4d8ac3 --- /dev/null +++ b/skeema/gradido_login/node_servers.sql @@ -0,0 +1,10 @@ +CREATE TABLE `node_servers` ( + `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `url` VARCHAR(255) NOT NULL, + `port` INT UNSIGNED NOT NULL, + `group_id` INT UNSIGNED NULL DEFAULT '0', + `server_type` INT UNSIGNED NOT NULL DEFAULT '0', + `node_hedera_id` INT UNSIGNED NULL DEFAULT '0', + `last_live_sign` DATETIME NOT NULL DEFAULT '2000-01-01 00:00:00', + PRIMARY KEY (`id`) +) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/src/cpp/HTTPInterface/AdminTopicPage.cpp b/src/cpp/HTTPInterface/AdminTopicPage.cpp new file mode 100644 index 000000000..d8926093e --- /dev/null +++ b/src/cpp/HTTPInterface/AdminTopicPage.cpp @@ -0,0 +1,128 @@ +#include "AdminTopicPage.h" +#include "Poco/Net/HTTPServerRequest.h" +#include "Poco/Net/HTTPServerResponse.h" +#include "Poco/Net/HTMLForm.h" +#include "Poco/DeflatingStream.h" + + +#line 7 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminTopic.cpsp" + + +#line 1 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + +#include "../ServerConfig.h" + + +AdminTopicPage::AdminTopicPage(Session* arg): + SessionHTTPRequestHandler(arg) +{ +} + + +void AdminTopicPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) +{ + response.setChunkedTransferEncoding(true); + response.setContentType("text/html"); + bool _compressResponse(request.hasToken("Accept-Encoding", "gzip")); + if (_compressResponse) response.set("Content-Encoding", "gzip"); + + Poco::Net::HTMLForm form(request, request.stream()); +#line 10 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminTopic.cpsp" + + const char* pageName = "Topic"; + + + +#line 3 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + + bool withMaterialIcons = false; + std::ostream& _responseStream = response.send(); + Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1); + std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream; + responseStream << "\n"; + // begin include header_large.cpsp + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "Gradido Login Server: "; +#line 11 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + responseStream << ( pageName ); + responseStream << "\n"; + responseStream << "\n"; +#line 13 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + if(withMaterialIcons) { responseStream << "\n"; + responseStream << "\n"; +#line 15 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + } responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t
"; + // end include header_large.cpsp + responseStream << "\n"; +#line 16 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminTopic.cpsp" + responseStream << ( getErrorsHtml() ); + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "\t

Topic Admin Page

\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << "\t\n"; + responseStream << "
\n"; + // begin include footer.cpsp + responseStream << "
\n"; + responseStream << "

Copyright © Gradido 2020

\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << " "; +#line 6 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp" + responseStream << ( mTimeProfiler.string() ); + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << "

Login Server in Entwicklung

\n"; + responseStream << "

Alpha "; +#line 10 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp" + responseStream << ( ServerConfig::g_versionString ); + responseStream << "

\n"; + responseStream << "
\n"; + responseStream << "
\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << ""; + // end include footer.cpsp + responseStream << "\n"; + if (_compressResponse) _gzipStream.close(); +} diff --git a/src/cpp/HTTPInterface/AdminTopicPage.h b/src/cpp/HTTPInterface/AdminTopicPage.h new file mode 100644 index 000000000..b02e5856c --- /dev/null +++ b/src/cpp/HTTPInterface/AdminTopicPage.h @@ -0,0 +1,20 @@ +#ifndef AdminTopicPage_INCLUDED +#define AdminTopicPage_INCLUDED + + +#include "Poco/Net/HTTPRequestHandler.h" + + +#include "SessionHTTPRequestHandler.h" + + +class AdminTopicPage: public SessionHTTPRequestHandler +{ +public: + AdminTopicPage(Session*); + + void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response); +}; + + +#endif // AdminTopicPage_INCLUDED diff --git a/src/cpp/HTTPInterface/PassphrasedTransaction.cpsp b/src/cpp/HTTPInterface/PassphrasedTransaction.cpsp new file mode 100644 index 000000000..debc1f296 --- /dev/null +++ b/src/cpp/HTTPInterface/PassphrasedTransaction.cpsp @@ -0,0 +1,162 @@ +<%@ page class="PassphrasedTransaction" %> +<%@ page form="true" %> +<%@ page compressed="true" %> +<%@ page baseClass="PageRequestMessagedHandler" %> +<%@ header include="PageRequestMessagedHandler.h" %> +<%! +#include "../SingletonManager/MemoryManager.h" +#include "../SingletonManager/SessionManager.h" +#include "../Crypto/KeyPair.h" +#include "../ServerConfig.h" + +#include "Poco/JSON/Object.h" +#include "Poco/JSON/Parser.h" +#include "Poco/Net/HTTPSClientSession.h" +#include "Poco/Net/HTTPRequest.h" +#include "Poco/Net/HTTPResponse.h" + +enum PageState { + PAGE_STATE_INPUT, + PAGE_STATE_SUCCESS +}; +%> +<%% + std::string pageName = "Gradidos mit Passphrase überweisen"; + PageState state = PAGE_STATE_INPUT; + Mnemonic* wordSource = &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]; + auto sm = SessionManager::getInstance(); + auto mm = MemoryManager::getInstance(); + std::string errorString =""; + + if(!form.empty()) { + auto passphrase = form.get("passphrase", ""); + bool passphraseValid = User::validatePassphrase(passphrase, &wordSource); + bool keysGenerated = false; + KeyPair keys; + if(!passphraseValid) + { + addError(new Error("Passphrase", "Fehler beim validieren der Passphrase")); + } + else + { + keysGenerated = keys.generateFromPassphrase(passphrase.data(), wordSource); + if(!keysGenerated) + { + addError(new Error("Passphrase", "Konnte keine Keys aus der Passphrase generieren")); + } + } + if(passphraseValid && keysGenerated) + { + // create session only for transaction + int session_id = 0; + auto session = sm->getNewSession(&session_id); + // create payload + Poco::JSON::Object requestJson; + Poco::JSON::Object pubkeys; + pubkeys.set("sender", keys.getPubkeyHex()); + pubkeys.set("receiver", form.get("recevier", "")); + requestJson.set("method", "moveTransaction"); + requestJson.set("pubkeys", pubkeys); + requestJson.set("memo", form.get("memo", "")); + requestJson.set("session_id", session_id); + + printf("[PassphrasedTransaction] prepare request\n"); + + // send to php server + Poco::Net::HTTPSClientSession httpsClientSession(ServerConfig::g_php_serverHost, 443); + Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, "/JsonRequestHandler"); + + request.setChunkedTransferEncoding(true); + std::ostream& requestStream = httpsClientSession.sendRequest(request); + requestJson.stringify(requestStream); + + Poco::Net::HTTPResponse response; + std::istream& request_stream = httpsClientSession.receiveResponse(response); + + std::stringstream responseStringStream; + for (std::string line; std::getline(request_stream, line); ) { + responseStringStream << line << std::endl; + } + + // extract parameter from request + Poco::JSON::Parser jsonParser; + Poco::Dynamic::Var parsedJson; + + printf("[PassphrasedTransaction] parse request result\n"); + try { + parsedJson = jsonParser.parse(responseStringStream); + + Poco::JSON::Object object = *parsedJson.extract(); + auto jsonState = object.get("state"); + std::string stateString = jsonState.convert(); + if (stateString == "error") { + addError(new Error("Transfer", "php server return error")); + if (!object.isNull("msg")) { + addError(new ParamError("php server", "msg:", object.get("msg").convert().data())); + } + if (!object.isNull("details")) { + addError(new ParamError("php server", "details:", object.get("details").convert().data())); + } + } else if(stateString == "success") { + printf("[PassphrasedTransaction] request success, wait on transaction ready\n"); + auto currentActiveTransaction = session->getNextReadyTransaction(); + while(currentActiveTransaction.isNull()) { + Poco::Thread::sleep(10); + currentActiveTransaction = session->getNextReadyTransaction(); + } + if(!currentActiveTransaction->isTransfer()) { + addError(new Error("Transaction", "Falsche Transaktion, bitte erst alle anderen Transaktionen abschließen und dann Seite neuladen")); + } else { + //auto signing = new SigningTransaction(currentActiveTransaction, user); + printf("[PassphrasedTransaction] cannot sign, implementation missing\n"); + /*if(!signing->run()) { + + } else { + addError(new Error("Transaction", "Fehler beim signieren, bitter erneut versuchen")); + }*/ + // remove transaction from list + //mSession->finalizeTransaction(true, true); + } + } + } + catch (Poco::Exception& ex) { + //printf("[JsonRequestHandler::handleRequest] Exception: %s\n", ex.displayText().data()); + addError(new ParamError("Transfer", "Fehler beim erstellen der Transaktion, bitte erneut versuchen", ex.displayText().data())); + errorString = responseStringStream.str(); + sm->releaseSession(session); + session = nullptr; + } + if(session) { + sm->releaseSession(session); + } + } + } + + +%><%@ include file="header_old.cpsp" %> +<% if("" == errorString) { %> + <%= errorString %> +<% } %> +
+ <%= getErrorsHtml() %> + <% if(PAGE_STATE_INPUT == state) { %> + +
+
+

+

+

+

+

+ + "/> +

+

+
+
+ <% } else if(PAGE_STATE_SUCCESS == state) { %> +

Gradidos wurden erfolgreich überwiesen.

+ Weitere Gradidos überweisen + <% } %> +
+<%@ include file="footer.cpsp" %> diff --git a/src/cpp/controller/HederaRequest.cpp b/src/cpp/controller/HederaRequest.cpp new file mode 100644 index 000000000..ec1c6c2a0 --- /dev/null +++ b/src/cpp/controller/HederaRequest.cpp @@ -0,0 +1,39 @@ +#include "HederaRequest.h" +#include "../proto/hedera/CryptoService.grpc.pb.h" + +#include +#include +#include +#include +#include + +HederaRequest::HederaRequest() +{ + +} + +HederaRequest::~HederaRequest() +{ + +} + +HederaRequestReturn HederaRequest::request(model::hedera::Query* query) +{ + auto channel = grpc::CreateChannel(query->getConnectionString(), grpc::InsecureChannelCredentials()); + grpc::ClientContext context; + std::chrono::system_clock::time_point deadline = std::chrono::system_clock::now() + + std::chrono::milliseconds(100); + context.set_deadline(deadline); + + auto proto_query = query->getProtoQuery(); + proto::Response* response = nullptr; + if (proto_query->has_cryptogetaccountbalance()) { + auto stub = proto::CryptoService::NewStub(channel); + auto connect_string = query->getConnectionString(); + printf("try connection to hedera with: %s\n", connect_string.data()); + auto status = stub->cryptoGetBalance(&context, *proto_query, response); + addError(new ParamError("Hedera Request", "crypto get balance", status.error_message())); + printf("[HederaRequest::request] error details: %s\n", status.error_details().data()); + } + return HEDERA_REQUEST_RETURN_OK; +} \ No newline at end of file diff --git a/src/cpp/controller/HederaRequest.h b/src/cpp/controller/HederaRequest.h new file mode 100644 index 000000000..692215f8d --- /dev/null +++ b/src/cpp/controller/HederaRequest.h @@ -0,0 +1,39 @@ +#ifndef __GRADIDO_LOGIN_SERVER_LIB_HEDERA_REQUEST_ +#define __GRADIDO_LOGIN_SERVER_LIB_HEDERA_REQUEST_ +/*! +* +* \author: Dario Rekowski +* +* \date: 31.08.2020 +* +* \brief: Class for Hedera Requests +* +*/ + +#include "../controller/NodeServer.h" +#include "../model/hedera/Query.h" + +enum HederaRequestReturn +{ + HEDERA_REQUEST_RETURN_OK, + HEDERA_REQUEST_RETURN_PARSE_ERROR, + HEDERA_REQUEST_RETURN_ERROR, + HEDERA_REQUEST_CONNECT_ERROR +}; + +// NodeServerConnection +class HederaRequest : public ErrorList +{ +public: + HederaRequest(); + ~HederaRequest(); + + HederaRequestReturn request(model::hedera::Query* query); + +protected: + +}; + + +#endif //__GRADIDO_LOGIN_SERVER_LIB_HEDERA_REQUEST_ +// \ No newline at end of file diff --git a/src/cpsp/adminHederaAccount.cpsp b/src/cpsp/adminHederaAccount.cpsp new file mode 100644 index 000000000..b4fd1f485 --- /dev/null +++ b/src/cpsp/adminHederaAccount.cpsp @@ -0,0 +1,203 @@ +<%@ page class="AdminHederaAccountPage" %> +<%@ page form="true" %> +<%@ page compressed="true" %> +<%@ page baseClass="SessionHTTPRequestHandler" %> +<%@ page ctorArg="Session*" %> +<%@ header include="SessionHTTPRequestHandler.h" %> +<%! + +#include "../controller/HederaAccount.h" +#include "../controller/HederaId.h" +#include "../controller/CryptoKey.h" +#include "../lib/DataTypeConverter.h" +#include "../SingletonManager/SessionManager.h" + +#include "../ServerConfig.h" + +#include "Poco/URI.h" + +%> +<%% + const char* pageName = "Hedera Account"; + auto sm = SessionManager::getInstance(); + auto mm = MemoryManager::getInstance(); + auto user = mSession->getNewUser(); + + Poco::URI uri(request.getURI()); + auto uri_query = uri.getQueryParameters(); + std::string action = ""; + std::string account_id_from_query; + if(uri_query.size() >= 2) { + if(uri_query[0].first == "action") { + action = uri_query[0].second; + } + if(uri_query[1].first == "account_id") { + account_id_from_query = uri_query[1].second; + } + } + if(action == "updateBalance") { + int account_id = 0; + if(DataTypeConverter::strToInt(account_id_from_query, account_id) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting account_id_from_query to int")); + } else { + auto hedera_account = controller::HederaAccount::load("id", account_id); + if(!hedera_account.size() || hedera_account[0].isNull()) { + addError(new Error("Action Update Balance", "hedera id not found")); + } else { + hedera_account[0]->updateBalanceFromHedera(user, this); + } + } + } + // add + else if(!form.empty()) { + // collect + auto shardNumString = form.get("account-shard-num", "0"); + auto realmNumString = form.get("account-realm-num", "0"); + auto numString = form.get("account-num", "0"); + auto privateKeyString = form.get("account-private-key", ""); + auto publicKeyString = form.get("account-public-key", ""); + auto networkTypeString = form.get("account-network-type", "0"); + + int shardNum = 0; + int realmNum = 0; + int num = 0; + int networkType = 0; + + MemoryBin* private_key = nullptr; + MemoryBin* public_key = nullptr; + + // validate + if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "shard num not integer")); + } else { + if(DataTypeConverter::strToInt(shardNumString, shardNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting shardNumString to int")); + } + } + if(!sm->isValid(realmNumString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "realm num not integer")); + } else { + if(DataTypeConverter::strToInt(realmNumString, realmNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting realmNumString to int")); + } + } + if(!sm->isValid(numString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "num not integer")); + } else { + if(DataTypeConverter::strToInt(numString, num) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting num to int")); + } + } + if(!sm->isValid(privateKeyString, VALIDATE_ONLY_HEX)) { + addError(new Error("Account Keys", "private key not hex")); + } + if(!sm->isValid(publicKeyString, VALIDATE_ONLY_HEX)) { + addError(new Error("Account Keys", "public key not hex")); + } + if(!sm->isValid(networkTypeString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Network Type", "not integer")); + } else { + if(DataTypeConverter::strToInt(networkTypeString, networkType) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting network type to int")); + } + if(networkType < 0 || networkType >= (int)model::table::HEDERA_NET_COUNT) { + addError(new Error("Network Type", "invalid value")); + } + } + + if(0 == errorCount()) { + + auto hedera_id = controller::HederaId::create(shardNum, realmNum, num); + + private_key = DataTypeConverter::hexToBin(privateKeyString); + public_key = DataTypeConverter::hexToBin(publicKeyString); + + + KeyPairHedera key_pair(private_key, public_key); + auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE); + + if(crypto_key.isNull()) { + crypto_key = controller::CryptoKey::create(&key_pair, user); + if(!crypto_key->getModel()->insertIntoDB(true)) { + addError(new Error("DB Error", "Error saving crypto key in DB")); + } + } else { + printf("crypto key found in db\n"); + } + if(0 == errorCount()) { + auto hedera_account = controller::HederaAccount::create( + user->getModel()->getID(), + hedera_id->getModel()->getID(), + crypto_key->getModel()->getID(), + 0, + (model::table::HederaNetworkType)networkType + ); + if(!hedera_account->getModel()->insertIntoDB(false)) { + addError(new Error("DB Error", "Error saving hedera account into DB")); + } + } + + mm->releaseMemory(private_key); + mm->releaseMemory(public_key); + } + + } + + // list accounts + auto hedera_accounts = controller::HederaAccount::load("user_id", user->getModel()->getID()); + +%><%@ include file="header_large.cpsp" %> +<%= getErrorsHtml() %> +
+
+
+

Deine Hedera Accounts

+
+
+
+
Hedera Id
+
Balance
+
Server Type
+
Last Updated
+
Aktionen
+
+ <% for(auto it = hedera_accounts.begin(); it != hedera_accounts.end(); it++) { + auto hedera_account_model = (*it)->getModel(); + auto updateUrl = ServerConfig::g_serverPath + "/hedera_account?action=updateBalance&account_id=" + std::to_string(hedera_account_model->getID()); + %> +
+
<%= (*it)->getHederaId()->getModel()->toString() %>
+
<%= hedera_account_model->getBalanceDouble() %> hbar
+
<%= model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) %>
+
<%= hedera_account_model->getUpdatedString() %>
+
+ +
+ <% } %> +
+
+
+

Einen neuen Account anlegen

+
+
+
+ + + + + + + + + + + "> +
+
+<%@ include file="footer.cpsp" %> From e866e53d60f3507ffd328b3e9d95766915f675fa Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 1 Sep 2020 11:40:19 +0200 Subject: [PATCH 023/293] missing class name --- dependencies/grpc | 2 +- src/cpp/model/table/ModelBase.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies/grpc b/dependencies/grpc index f57a0619b..7d7e45676 160000 --- a/dependencies/grpc +++ b/dependencies/grpc @@ -1 +1 @@ -Subproject commit f57a0619bc5697ea98c2d5b2c983c7024f43a5db +Subproject commit 7d7e4567625db7cfebf8969a225948097a3f9f89 diff --git a/src/cpp/model/table/ModelBase.h b/src/cpp/model/table/ModelBase.h index 82e5c273e..04ce4ffe4 100644 --- a/src/cpp/model/table/ModelBase.h +++ b/src/cpp/model/table/ModelBase.h @@ -149,7 +149,7 @@ namespace model { } template - std::vector loadAllFromDB() + std::vector ModelBase::loadAllFromDB() { std::vector results; Poco::ScopedLock _lock(mWorkMutex); From 3e3bd6d012c12943932764b27bec160b504d09fb Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 1 Sep 2020 11:47:19 +0200 Subject: [PATCH 024/293] fix error only occuring in linux --- src/cpp/controller/Group.cpp | 3 ++- src/cpp/controller/HederaAccount.cpp | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/cpp/controller/Group.cpp b/src/cpp/controller/Group.cpp index 2d809da07..f835e6986 100644 --- a/src/cpp/controller/Group.cpp +++ b/src/cpp/controller/Group.cpp @@ -42,7 +42,8 @@ namespace controller { // work around for not working call to loadAllFromDB auto cm = ConnectionManager::getInstance(); - Poco::Data::Statement select(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER)); + auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + Poco::Data::Statement select(session); select << "SELECT id, alias, name, url, description FROM " << db->getTableName() , Poco::Data::Keywords::into(group_list); diff --git a/src/cpp/controller/HederaAccount.cpp b/src/cpp/controller/HederaAccount.cpp index 6172db46c..58c71b5ec 100644 --- a/src/cpp/controller/HederaAccount.cpp +++ b/src/cpp/controller/HederaAccount.cpp @@ -46,10 +46,11 @@ namespace controller { auto db = new model::table::HederaAccount(); std::vector group_list; // throw an unresolved external symbol error - //group_list = db->loadAllFromDB(); + group_list = db->loadAllFromDB(); // work around for not working call to loadAllFromDB - auto cm = ConnectionManager::getInstance(); + /*auto cm = ConnectionManager::getInstance(); + Poco::Data::Statement select(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER)); select << "SELECT id, alias, name, url, description FROM " << db->getTableName() @@ -62,7 +63,7 @@ namespace controller { catch (Poco::Exception& ex) { printf("[Group::listAll] poco exception: %s\n", ex.displayText().data()); } - // work around end + //*/ //work around end std::vector> resultVector; resultVector.reserve(group_list.size()); From 72b4389be450a9f4ad08c3b0985612bef4fd328e Mon Sep 17 00:00:00 2001 From: Dario Date: Wed, 2 Sep 2020 14:06:23 +0200 Subject: [PATCH 025/293] use protobuf from inside grpc, even for parsing protofiles for easy version switch, fix html error --- CMakeLists.txt | 15 ++++++++++++++- README | 1 + conanfile.txt | 1 - compile_proto.sh => parse_proto.sh | 0 .../HTTPInterface/AdminHederaAccountPage.cpp | 17 ++++++++--------- src/cpp/controller/HederaAccount.cpp | 1 - src/cpp/controller/HederaRequest.cpp | 10 +++++++++- src/cpp/model/hedera/Query.cpp | 4 ++-- src/cpsp/adminHederaAccount.cpsp | 1 - windows_parse_proto.sh | 19 +++++++++++++++++++ 10 files changed, 53 insertions(+), 16 deletions(-) rename compile_proto.sh => parse_proto.sh (100%) mode change 100755 => 100644 create mode 100644 windows_parse_proto.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a24af9a3..fc2eb1771 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,8 @@ project(Gradido_LoginServer C CXX) SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin" ) SET ( CMAKE_CXX_FLAGS "-std=c++17" ) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) include_directories( "dependencies" @@ -12,6 +14,7 @@ include_directories( "dependencies/mariadb-connector-c/build/include" "dependencies/spirit-po/include" "dependencies/grpc/include" + "dependencies/grpc/third_party/protobuf/src" "src/cpp/proto" #"dependencies/mariadb-connector-c/build/include" #"dependencies/mariadb-connector-c/include" @@ -99,6 +102,7 @@ set(GRPC_ABSL_PATH "dependencies/grpc/_build/third_party/abseil-cpp/absl/types/D set(GRPC_CARES_PATH "dependencies/grpc/_build/third_party/cares/cares/lib/Debug") set(GRPC_BORING_SSL_PATH "dependencies/grpc/_build/third_party/boringssl-with-bazel/Debug") set(GRPC_RE2_PATH "dependencies/grpc/_build/third_party/re2/Debug") +set(GRPC_PROTOBUF_DEBUG_PATH "dependencies/grpc/_build/third_party/protobuf/Debug") find_library(GRPC_PLUSPLUS grpc++ PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_UNSECURE grpc++_unsecure PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_REFLECTION grpc++_reflection PATHS ${GRPC_PATH} REQUIRED) @@ -112,6 +116,9 @@ find_library(GRPC_CARES cares PATHS ${GRPC_CARES_PATH} REQUIRED) find_library(GRPC_BORING_SSL_CRYPTO crypto ${GRPC_BORING_SSL_PATH} REQUIRED) find_library(GRPC_BORING_SSL_SSL ssl ${GRPC_BORING_SSL_PATH} REQUIRED) find_library(GRPC_RE2 re2 ${GRPC_RE2_PATH} REQUIRED) +find_library(PROTOBUF_LIB_DEBUG libprotobufd ${GRPC_PROTOBUF_DEBUG_PATH} REQUIRED) +find_library(PROTOBUF_LIB_LITE_DEBUG libprotobuf-lited ${GRPC_PROTOBUF_DEBUG_PATH} REQUIRED) +find_library(PROTOBUF_LIBC_DEBUG libprotocd ${GRPC_PROTOBUF_DEBUG_PATH} REQUIRED) find_library(GRPC_ABSL_BAD_OPTIONAL_ACCESS absl_bad_optional_access ${GRPC_ABSL_PATH} REQUIRED) set(GRPC_LIBS @@ -123,6 +130,12 @@ set(GRPC_LIBS ${GRPC_BORING_SSL_SSL} ${GRPC_RE2} ) +set(PROTOBUF_DEBUG_LIBS + ${PROTOBUF_LIB_DEBUG} + ${PROTOBUF_LIB_LITE_DEBUG} + ${PROTOBUF_LIBC_DEBUG} +) + set(MYSQL_INCLUDE_DIR "dependencies/mariadb-connector-c/include") @@ -174,7 +187,7 @@ target_link_libraries(Gradido_LoginServer absl::base absl::flat_hash_map absl::f if(WIN32) TARGET_LINK_LIBRARIES(Gradido_LoginServer optimized ${MYSQL_LIBRARIES} Shlwapi) TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${COMPILED_MARIADB_CLIENT_DEBUG} Shlwapi) -TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${GRPC_LIBS}) +TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${GRPC_LIBS} ${PROTOBUF_DEBUG_LIBS}) else(WIN32) target_link_libraries(Gradido_LoginServer libmariadb protoc protobuf -pthread) endif(WIN32) diff --git a/README b/README index 89783a878..993dd4afa 100644 --- a/README +++ b/README @@ -25,6 +25,7 @@ mkdir _build cd _build cmake .. make +# under windows build at least release for protoc.exe and grpc c++ plugin cd ../../../ # get more dependencies with conan (need conan from https://conan.io/) diff --git a/conanfile.txt b/conanfile.txt index 96bd6f5c8..a6c09d9fa 100644 --- a/conanfile.txt +++ b/conanfile.txt @@ -1,7 +1,6 @@ [requires] Poco/1.9.4@pocoproject/stable libsodium/1.0.18@bincrafters/stable -protobuf/3.9.1@bincrafters/stable boost/1.71.0@conan/stable gtest/1.8.1@bincrafters/stable diff --git a/compile_proto.sh b/parse_proto.sh old mode 100755 new mode 100644 similarity index 100% rename from compile_proto.sh rename to parse_proto.sh diff --git a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp index a9d4165c3..e98a02d92 100644 --- a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp +++ b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp @@ -264,16 +264,15 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request #line 172 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( hedera_account_model->getUpdatedString() ); responseStream << "
\n"; - responseStream << "\t\t\t\t\t
\n"; responseStream << "\t\t\t\t\t\n"; responseStream << "\t\t\t\t
\n"; responseStream << "\t\t\t"; -#line 178 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 177 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" } responseStream << "\n"; responseStream << "\t\t
\n"; responseStream << "\t
\n"; @@ -282,7 +281,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t
\n"; responseStream << "\t
\n"; responseStream << "\t\t
\n"; responseStream << "\t\t\t\n"; @@ -296,21 +295,21 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t
\n"; diff --git a/src/cpp/controller/HederaAccount.cpp b/src/cpp/controller/HederaAccount.cpp index 58c71b5ec..57cb14672 100644 --- a/src/cpp/controller/HederaAccount.cpp +++ b/src/cpp/controller/HederaAccount.cpp @@ -28,7 +28,6 @@ namespace controller { { auto db = new model::table::HederaAccount(); auto hedera_account_list = db->loadFromDB(fieldName, fieldValue, 2); - std::vector> resultVector; resultVector.reserve(hedera_account_list.size()); for (auto it = hedera_account_list.begin(); it != hedera_account_list.end(); it++) { diff --git a/src/cpp/controller/HederaRequest.cpp b/src/cpp/controller/HederaRequest.cpp index ec1c6c2a0..32c6772c6 100644 --- a/src/cpp/controller/HederaRequest.cpp +++ b/src/cpp/controller/HederaRequest.cpp @@ -1,6 +1,8 @@ #include "HederaRequest.h" #include "../proto/hedera/CryptoService.grpc.pb.h" +#include "../lib/DataTypeConverter.h" + #include #include #include @@ -22,16 +24,22 @@ HederaRequestReturn HederaRequest::request(model::hedera::Query* query) auto channel = grpc::CreateChannel(query->getConnectionString(), grpc::InsecureChannelCredentials()); grpc::ClientContext context; std::chrono::system_clock::time_point deadline = std::chrono::system_clock::now() + - std::chrono::milliseconds(100); + std::chrono::milliseconds(10000); context.set_deadline(deadline); + grpc::CompletionQueue cq; auto proto_query = query->getProtoQuery(); + auto proto_query_serialized = proto_query->SerializeAsString(); + auto query_hex_string = DataTypeConverter::binToHex((unsigned char*)proto_query_serialized.data(), proto_query_serialized.size()); + printf("[HederaRequest::request] query as hex: %s\n", query_hex_string.data()); proto::Response* response = nullptr; if (proto_query->has_cryptogetaccountbalance()) { auto stub = proto::CryptoService::NewStub(channel); auto connect_string = query->getConnectionString(); printf("try connection to hedera with: %s\n", connect_string.data()); + //auto stream = stub->PrepareAsynccryptoGetBalance(&context, *proto_query, &cq); auto status = stub->cryptoGetBalance(&context, *proto_query, response); + //stream->StartCall(); addError(new ParamError("Hedera Request", "crypto get balance", status.error_message())); printf("[HederaRequest::request] error details: %s\n", status.error_details().data()); } diff --git a/src/cpp/model/hedera/Query.cpp b/src/cpp/model/hedera/Query.cpp index d47449bc6..39b3700c4 100644 --- a/src/cpp/model/hedera/Query.cpp +++ b/src/cpp/model/hedera/Query.cpp @@ -25,7 +25,7 @@ namespace model { auto get_account_balance = query->mQueryProto.mutable_cryptogetaccountbalance(); accountId->copyToProtoAccountId(get_account_balance->mutable_accountid()); auto query_header = get_account_balance->mutable_header(); - query_header->set_responsetype(proto::ANSWER_ONLY); + query_header->set_responsetype(proto::COST_ANSWER); auto transaction = query_header->mutable_payment(); //auto transaction_body = transaction->mutable_body(); // body content @@ -48,7 +48,7 @@ namespace model { auto account_amounts = transfer_list->mutable_accountamounts(); account_amounts->Add(); auto account_amount = account_amounts->Mutable(0); - account_amount->set_amount(0); + account_amount->set_amount(1000); connection.hederaId->copyToProtoAccountId(account_amount->mutable_accountid()); return query; diff --git a/src/cpsp/adminHederaAccount.cpsp b/src/cpsp/adminHederaAccount.cpsp index b4fd1f485..5379e4ef4 100644 --- a/src/cpsp/adminHederaAccount.cpsp +++ b/src/cpsp/adminHederaAccount.cpsp @@ -170,7 +170,6 @@
<%= hedera_account_model->getBalanceDouble() %> hbar
<%= model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) %>
<%= hedera_account_model->getUpdatedString() %>
-
diff --git a/windows_parse_proto.sh b/windows_parse_proto.sh new file mode 100644 index 000000000..4c5d56d47 --- /dev/null +++ b/windows_parse_proto.sh @@ -0,0 +1,19 @@ +#!/bin/bash +if [ ! -d "./src/cpp/proto" ] ; then + mkdir ./src/cpp/proto +fi +if [ ! -d "./src/cpp/proto/gradido" ] ; then + mkdir ./src/cpp/proto/gradido +fi +PROTOC_PATH=./dependencies/grpc/_build/third_party/protobuf/Release +CPP_PLUGIN_PATH=./dependencies/grpc/_build/Release +$PROTOC_PATH/protoc --cpp_out=./src/cpp/proto --proto_path=./src/proto ./src/proto/gradido/*.proto + +if [ ! -d "./src/cpp/proto/hedera" ] ; then + mkdir ./src/cpp/proto/hedera +fi + +GOOGLE_PROTOBUF_INCLUDES=./dependencies/grpc/third_party/protobuf/src +$PROTOC_PATH/protoc --plugin=protoc-gen-grpc=$CPP_PLUGIN_PATH/grpc_cpp_plugin.exe --cpp_out=./src/cpp/proto/hedera --grpc_out=./src/cpp/proto/hedera --proto_path=$GOOGLE_PROTOBUF_INCLUDES --proto_path=./src/proto/hedera/hedera-protobuf/src/main/proto ./src/proto/hedera/hedera-protobuf/src/main/proto/*.proto + + From 43f7038af723d0153066cc9d11c9dd14d079ab09 Mon Sep 17 00:00:00 2001 From: Dario Date: Thu, 3 Sep 2020 12:43:32 +0200 Subject: [PATCH 026/293] hedera query get balance now working =D --- .../HTTPInterface/AdminHederaAccountPage.cpp | 36 +++++--- src/cpp/HTTPInterface/ElopageWebhook.h | 4 +- .../PageRequestMessagedHandler.h | 4 +- src/cpp/JSONInterface/JsonRequestHandler.cpp | 2 +- src/cpp/JSONInterface/JsonRequestHandler.h | 4 +- src/cpp/SingletonManager/ConnectionManager.h | 4 +- src/cpp/SingletonManager/ErrorManager.cpp | 14 +-- src/cpp/SingletonManager/ErrorManager.h | 10 +- src/cpp/SingletonManager/SessionManager.cpp | 6 +- src/cpp/SingletonManager/SessionManager.h | 2 +- src/cpp/controller/HederaAccount.cpp | 24 ++++- src/cpp/controller/HederaAccount.h | 2 +- src/cpp/controller/HederaRequest.cpp | 62 ++++++++++--- src/cpp/controller/HederaRequest.h | 8 +- src/cpp/lib/DataTypeConverter.cpp | 9 +- src/cpp/lib/DataTypeConverter.h | 5 +- src/cpp/lib/Error.cpp | 10 +- src/cpp/lib/Error.h | 25 ++--- src/cpp/lib/JsonRequest.cpp | 91 ++++++++++++++++++- src/cpp/lib/JsonRequest.h | 6 +- src/cpp/lib/MultithreadContainer.cpp | 4 +- src/cpp/lib/Notification.cpp | 7 ++ src/cpp/lib/Notification.h | 24 +++++ .../{ErrorList.cpp => NotificationList.cpp} | 49 ++++++---- .../lib/{ErrorList.h => NotificationList.h} | 17 ++-- src/cpp/lib/Success.cpp | 52 +++++++++++ src/cpp/lib/Success.h | 30 ++++++ src/cpp/model/Session.h | 4 +- src/cpp/model/TransactionBase.h | 4 +- src/cpp/model/User.cpp | 4 +- src/cpp/model/User.h | 8 +- src/cpp/model/email/Email.h | 4 +- .../hedera/CryptoTransferTransaction.cpp | 53 +++++++++++ .../model/hedera/CryptoTransferTransaction.h | 40 ++++++++ src/cpp/model/hedera/Query.cpp | 80 ++++++++-------- src/cpp/model/hedera/Query.h | 6 +- src/cpp/model/hedera/Response.cpp | 32 +++++++ src/cpp/model/hedera/Response.h | 38 ++++++++ src/cpp/model/hedera/Transaction.cpp | 43 +++++++++ src/cpp/model/hedera/Transaction.h | 38 ++++++++ src/cpp/model/hedera/TransactionBody.cpp | 47 ++++++++++ src/cpp/model/hedera/TransactionBody.h | 39 ++++++++ src/cpp/model/table/ModelBase.h | 2 +- src/cpp/tasks/ProcessingTransaction.h | 4 +- src/cpp/tasks/SigningTransaction.h | 4 +- src/cpp/tasks/Task.cpp | 4 +- src/cpsp/adminHederaAccount.cpsp | 7 ++ 47 files changed, 796 insertions(+), 176 deletions(-) create mode 100644 src/cpp/lib/Notification.cpp create mode 100644 src/cpp/lib/Notification.h rename src/cpp/lib/{ErrorList.cpp => NotificationList.cpp} (75%) rename src/cpp/lib/{ErrorList.h => NotificationList.h} (76%) create mode 100644 src/cpp/lib/Success.cpp create mode 100644 src/cpp/lib/Success.h create mode 100644 src/cpp/model/hedera/CryptoTransferTransaction.cpp create mode 100644 src/cpp/model/hedera/CryptoTransferTransaction.h diff --git a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp index e98a02d92..fa99a7b35 100644 --- a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp +++ b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp @@ -12,6 +12,8 @@ #include "../controller/HederaId.h" #include "../controller/CryptoKey.h" #include "../lib/DataTypeConverter.h" +#include "../lib/Profiler.h" +#include "../lib/Success.h" #include "../SingletonManager/SessionManager.h" #include "../ServerConfig.h" @@ -37,12 +39,14 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request if (_compressResponse) response.set("Content-Encoding", "gzip"); Poco::Net::HTMLForm form(request, request.stream()); -#line 20 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 22 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" const char* pageName = "Hedera Account"; auto sm = SessionManager::getInstance(); auto mm = MemoryManager::getInstance(); auto user = mSession->getNewUser(); + Profiler hedera_time; + std::string hedera_time_string; Poco::URI uri(request.getURI()); auto uri_query = uri.getQueryParameters(); @@ -65,7 +69,9 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request if(!hedera_account.size() || hedera_account[0].isNull()) { addError(new Error("Action Update Balance", "hedera id not found")); } else { + hedera_time.reset(); hedera_account[0]->updateBalanceFromHedera(user, this); + addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string())); } } } @@ -225,7 +231,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t
"; // end include header_large.cpsp responseStream << "\n"; -#line 150 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 156 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( getErrorsHtml() ); responseStream << "\n"; responseStream << "
\n"; @@ -242,37 +248,37 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t\t
Aktionen
\n"; responseStream << "\t\t\t
\n"; responseStream << "\t\t\t"; -#line 164 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 171 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" for(auto it = hedera_accounts.begin(); it != hedera_accounts.end(); it++) { auto hedera_account_model = (*it)->getModel(); auto updateUrl = ServerConfig::g_serverPath + "/hedera_account?action=updateBalance&account_id=" + std::to_string(hedera_account_model->getID()); responseStream << "\n"; responseStream << "\t\t\t\t
\n"; responseStream << "\t\t\t\t\t
"; -#line 169 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 176 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( (*it)->getHederaId()->getModel()->toString() ); responseStream << "
\n"; responseStream << "\t\t\t\t\t
"; -#line 170 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 177 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( hedera_account_model->getBalanceDouble() ); responseStream << " hbar
\n"; responseStream << "\t\t\t\t\t
"; -#line 171 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 178 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) ); responseStream << "
\n"; responseStream << "\t\t\t\t\t
"; -#line 172 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 179 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( hedera_account_model->getUpdatedString() ); responseStream << "
\n"; responseStream << "\t\t\t\t\t\n"; responseStream << "\t\t\t\t
\n"; responseStream << "\t\t\t"; -#line 177 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 184 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" } responseStream << "\n"; responseStream << "\t\t
\n"; responseStream << "\t
\n"; @@ -281,7 +287,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t
\n"; responseStream << "\t
\n"; responseStream << "\t\t
\n"; responseStream << "\t\t\t\n"; @@ -295,21 +301,21 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t
\n"; diff --git a/src/cpp/HTTPInterface/ElopageWebhook.h b/src/cpp/HTTPInterface/ElopageWebhook.h index bf8ea4efc..77c60b155 100644 --- a/src/cpp/HTTPInterface/ElopageWebhook.h +++ b/src/cpp/HTTPInterface/ElopageWebhook.h @@ -4,7 +4,7 @@ #include "PageRequestMessagedHandler.h" #include "../tasks/CPUTask.h" -#include "../lib/ErrorList.h" +#include "../lib/NotificationList.h" #include "Poco/Net/NameValueCollection.h" @@ -14,7 +14,7 @@ public: void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response); }; -class HandleElopageRequestTask : public UniLib::controller::CPUTask, protected ErrorList +class HandleElopageRequestTask : public UniLib::controller::CPUTask, protected NotificationList { public: HandleElopageRequestTask(Poco::Net::NameValueCollection& requestData); diff --git a/src/cpp/HTTPInterface/PageRequestMessagedHandler.h b/src/cpp/HTTPInterface/PageRequestMessagedHandler.h index 2e47b398d..396fc8a4e 100644 --- a/src/cpp/HTTPInterface/PageRequestMessagedHandler.h +++ b/src/cpp/HTTPInterface/PageRequestMessagedHandler.h @@ -2,7 +2,7 @@ #define PAGE_REQUEST_MESSAGE_HANDLER_INCLUDED #include "../model/Session.h" -#include "../lib/ErrorList.h" +#include "../lib/NotificationList.h" #include "../lib/Profiler.h" #include "../SingletonManager/LanguageManager.h" @@ -11,7 +11,7 @@ #include "Poco/Net/HTMLForm.h" #include "Poco/RegularExpression.h" -class PageRequestMessagedHandler : public Poco::Net::HTTPRequestHandler, public ErrorList +class PageRequestMessagedHandler : public Poco::Net::HTTPRequestHandler, public NotificationList { public: PageRequestMessagedHandler() {} diff --git a/src/cpp/JSONInterface/JsonRequestHandler.cpp b/src/cpp/JSONInterface/JsonRequestHandler.cpp index 123c36268..47abb959a 100644 --- a/src/cpp/JSONInterface/JsonRequestHandler.cpp +++ b/src/cpp/JSONInterface/JsonRequestHandler.cpp @@ -48,7 +48,7 @@ void JsonRequestHandler::handleRequest(Poco::Net::HTTPServerRequest& request, Po } -Poco::Dynamic::Var JsonRequestHandler::parseJsonWithErrorPrintFile(std::istream& request_stream, ErrorList* errorHandler /* = nullptr*/, const char* functionName /* = nullptr*/) +Poco::Dynamic::Var JsonRequestHandler::parseJsonWithErrorPrintFile(std::istream& request_stream, NotificationList* errorHandler /* = nullptr*/, const char* functionName /* = nullptr*/) { // debugging answer diff --git a/src/cpp/JSONInterface/JsonRequestHandler.h b/src/cpp/JSONInterface/JsonRequestHandler.h index 72230bfe4..90c3e3171 100644 --- a/src/cpp/JSONInterface/JsonRequestHandler.h +++ b/src/cpp/JSONInterface/JsonRequestHandler.h @@ -4,7 +4,7 @@ #include "Poco/Net/HTTPRequestHandler.h" #include "Poco/JSON/Object.h" -#include "../lib/ErrorList.h" +#include "../lib/NotificationList.h" class JsonRequestHandler : public Poco::Net::HTTPRequestHandler @@ -15,7 +15,7 @@ public: virtual Poco::JSON::Object* handle(Poco::Dynamic::Var params) = 0; - static Poco::Dynamic::Var parseJsonWithErrorPrintFile(std::istream& request_stream, ErrorList* errorHandler = nullptr, const char* functionName = nullptr); + static Poco::Dynamic::Var parseJsonWithErrorPrintFile(std::istream& request_stream, NotificationList* errorHandler = nullptr, const char* functionName = nullptr); protected: Poco::JSON::Object* mResultJson; diff --git a/src/cpp/SingletonManager/ConnectionManager.h b/src/cpp/SingletonManager/ConnectionManager.h index 795808515..0dfd8b54c 100644 --- a/src/cpp/SingletonManager/ConnectionManager.h +++ b/src/cpp/SingletonManager/ConnectionManager.h @@ -9,7 +9,7 @@ #include "../MySQL/Poco/Connector.h" #include "Poco/Exception.h" -#include "../lib/ErrorList.h" +#include "../lib/NotificationList.h" enum ConnectionType { CONNECTION_MYSQL_LOGIN_SERVER, @@ -17,7 +17,7 @@ enum ConnectionType { CONNECTION_MAX }; -class ConnectionManager : public ErrorList +class ConnectionManager : public NotificationList { public: ~ConnectionManager(); diff --git a/src/cpp/SingletonManager/ErrorManager.cpp b/src/cpp/SingletonManager/ErrorManager.cpp index 090a6f9dd..b4df67974 100644 --- a/src/cpp/SingletonManager/ErrorManager.cpp +++ b/src/cpp/SingletonManager/ErrorManager.cpp @@ -4,7 +4,7 @@ #include "Poco/Net/SecureSMTPClientSession.h" #include "Poco/Net/StringPartSource.h" -#include "../lib/ErrorList.h" +#include "../lib/NotificationList.h" #include "../model/email/Email.h" @@ -34,19 +34,19 @@ ErrorManager::~ErrorManager() mErrorsMap.clear(); } -void ErrorManager::addError(Error* error, bool log/* = true*/) +void ErrorManager::addError(Notification* error, bool log/* = true*/) { DHASH id = DRMakeStringHash(error->getFunctionName()); mWorkingMutex.lock(); auto it = mErrorsMap.find(id); - std::list* list = nullptr; + std::list* list = nullptr; //printf("[ErrorManager::addError] error with function: %s, %s\n", error->getFunctionName(), error->getMessage()); if(log) mLogging.error("[ErrorManager::addError] %s", error->getString(false)); if (it == mErrorsMap.end()) { - list = new std::list; - mErrorsMap.insert(std::pair*>(id, list)); + list = new std::list; + mErrorsMap.insert(std::pair*>(id, list)); } else { list = it->second; @@ -62,9 +62,9 @@ void ErrorManager::addError(Error* error, bool log/* = true*/) } -int ErrorManager::getErrors(ErrorList* send) +int ErrorManager::getErrors(NotificationList* send) { - Error* error = nullptr; + Notification* error = nullptr; int iCount = 0; while (error = send->getLastError()) { addError(error, false); diff --git a/src/cpp/SingletonManager/ErrorManager.h b/src/cpp/SingletonManager/ErrorManager.h index e59bd7d35..a0e427d9e 100644 --- a/src/cpp/SingletonManager/ErrorManager.h +++ b/src/cpp/SingletonManager/ErrorManager.h @@ -15,7 +15,7 @@ #include #include #include -#include "../lib/ErrorList.h" +#include "../lib/NotificationList.h" #include "../lib/DRHash.h" #include "../tasks/CPUTask.h" @@ -24,7 +24,7 @@ #include "Poco/Net/MailMessage.h" -class ErrorManager : public IErrorCollection +class ErrorManager : public INotificationCollection { public: ~ErrorManager(); @@ -32,9 +32,9 @@ public: static ErrorManager* getInstance(); // will called delete on error - virtual void addError(Error* error, bool log = true); + virtual void addError(Notification* error, bool log = true); - int getErrors(ErrorList* send); + int getErrors(NotificationList* send); virtual void sendErrorsAsEmail(); @@ -43,7 +43,7 @@ protected: // access mutex Poco::Mutex mWorkingMutex; - std::map*> mErrorsMap; + std::map*> mErrorsMap; // how many errors should be stored // poco logging diff --git a/src/cpp/SingletonManager/SessionManager.cpp b/src/cpp/SingletonManager/SessionManager.cpp index f8dbb318f..bbeaf9052 100644 --- a/src/cpp/SingletonManager/SessionManager.cpp +++ b/src/cpp/SingletonManager/SessionManager.cpp @@ -170,7 +170,7 @@ Session* SessionManager::getNewSession(int* handle) } } else { - ErrorList errors; + NotificationList errors; errors.addError(new Error(functionName, "found dead locked session, keeping in memory without reference")); errors.addError(new ParamError(functionName, "last succeeded lock:", result->getLastSucceededLock().data())); errors.sendErrorsAsEmail(); @@ -235,7 +235,7 @@ bool SessionManager::releaseSession(int requestHandleSession) session->setActive(false); } else { - ErrorList errors; + NotificationList errors; errors.addError(new Error("SessionManager::releaseSession", "found dead locked session")); errors.sendErrorsAsEmail(); mRequestSessionMap.erase(requestHandleSession); @@ -531,7 +531,7 @@ void SessionManager::deleteLoginCookies(Poco::Net::HTTPServerRequest& request, P //session_id = atoi(cookies.get("GRADIDO_LOGIN").data()); } -bool SessionManager::checkPwdValidation(const std::string& pwd, ErrorList* errorReciver) +bool SessionManager::checkPwdValidation(const std::string& pwd, NotificationList* errorReciver) { if (!isValid(pwd, VALIDATE_PASSWORD)) { errorReciver->addError(new Error("Passwort", "Bitte gebe ein gültiges Password ein mit mindestens 8 Zeichen, Groß- und Kleinbuchstaben, mindestens einer Zahl und einem Sonderzeichen (@$!%*?&+-_) ein!")); diff --git a/src/cpp/SingletonManager/SessionManager.h b/src/cpp/SingletonManager/SessionManager.h index 5968e3a25..99ef301f0 100644 --- a/src/cpp/SingletonManager/SessionManager.h +++ b/src/cpp/SingletonManager/SessionManager.h @@ -69,7 +69,7 @@ public: bool isValid(const std::string& subject, SessionValidationTypes validationType); //! \return true if password is valid - bool checkPwdValidation(const std::string& pwd, ErrorList* errorReciver); + bool checkPwdValidation(const std::string& pwd, NotificationList* errorReciver); void checkTimeoutSession(); diff --git a/src/cpp/controller/HederaAccount.cpp b/src/cpp/controller/HederaAccount.cpp index 57cb14672..6fabe2848 100644 --- a/src/cpp/controller/HederaAccount.cpp +++ b/src/cpp/controller/HederaAccount.cpp @@ -73,7 +73,7 @@ namespace controller { return resultVector; } - bool HederaAccount::updateBalanceFromHedera(Poco::AutoPtr user, ErrorList* errorReceiver/* = nullptr*/) + bool HederaAccount::updateBalanceFromHedera(Poco::AutoPtr user, NotificationList* errorReceiver/* = nullptr*/) { static const char* functionName = "HederaAccount::updateBalanceFromHedera"; @@ -86,27 +86,45 @@ namespace controller { auto hedera_node = NodeServer::pick(account_model->networkTypeToNodeServerType(account_model->getNetworkType())); auto crypto_key = controller::CryptoKey::load(account_model->getCryptoKeyId()); if (crypto_key.isNull()) { - printf("[%s] error, crypto key with id: %d not found\n", functionName, account_model->getCryptoKeyId()); + if (errorReceiver) { errorReceiver->addError(new Error("Keys", "could not found crypto key for account"));} + else { printf("[%s] error, crypto key with id: %d not found\n", functionName, account_model->getCryptoKeyId()); } return false; } auto hedera_key_pair = crypto_key->getKeyPair(user); if (!hedera_key_pair) { + if (errorReceiver) { errorReceiver->addError(new Error("Keys", "error decrypting private key"));} printf("[%s] error decrypting private key with id: %d, with user: %d\n", functionName, account_model->getCryptoKeyId(), user->getModel()->getID()); return false; } + auto query = model::hedera::Query::getBalance(mHederaID, hedera_node); + if (!query) { printf("[%s] error creating query\n", functionName); } query->sign(std::move(hedera_key_pair)); HederaRequest request; + model::hedera::Response response; try { - request.request(query); + if (HEDERA_REQUEST_RETURN_OK == request.request(query, &response) && proto::OK == response.getResponseCode()) { + account_model->updateIntoDB("balance", response.getAccountBalance()); + } + else { + if (errorReceiver) { + errorReceiver->addError(new Error("Hedera", "Hedera request failed")); + errorReceiver->addError(new ParamError("Hedera", "Hedera Response Code", proto::ResponseCodeEnum_Name(response.getResponseCode()))); + } + else { + printf("[%s] hedera response code: %s\n", functionName, proto::ResponseCodeEnum_Name(response.getResponseCode()).data()); + } + } + //request.requestViaPHPRelay(query); } catch (Poco::Exception& ex) { printf("[HederaAccount::updateBalanceFromHedera] exception calling hedera request: %s\n", ex.displayText().data()); } + if (errorReceiver) { errorReceiver->getErrors(&request); } diff --git a/src/cpp/controller/HederaAccount.h b/src/cpp/controller/HederaAccount.h index 7f08adddc..d76420b78 100644 --- a/src/cpp/controller/HederaAccount.h +++ b/src/cpp/controller/HederaAccount.h @@ -27,7 +27,7 @@ namespace controller { inline void setHederaId(Poco::AutoPtr hederaId) { mHederaID = hederaId; } inline Poco::AutoPtr getHederaId() { return mHederaID; } - bool updateBalanceFromHedera(Poco::AutoPtr user, ErrorList* errorReceiver = nullptr); + bool updateBalanceFromHedera(Poco::AutoPtr user, NotificationList* errorReceiver = nullptr); protected: HederaAccount(model::table::HederaAccount* dbModel); diff --git a/src/cpp/controller/HederaRequest.cpp b/src/cpp/controller/HederaRequest.cpp index 32c6772c6..308ffa5e8 100644 --- a/src/cpp/controller/HederaRequest.cpp +++ b/src/cpp/controller/HederaRequest.cpp @@ -9,6 +9,7 @@ #include #include + HederaRequest::HederaRequest() { @@ -19,29 +20,62 @@ HederaRequest::~HederaRequest() } -HederaRequestReturn HederaRequest::request(model::hedera::Query* query) +HederaRequestReturn HederaRequest::request(model::hedera::Query* query, model::hedera::Response* response, Poco::UInt64 fee/* = 0*/) { auto channel = grpc::CreateChannel(query->getConnectionString(), grpc::InsecureChannelCredentials()); + grpc::ClientContext context; std::chrono::system_clock::time_point deadline = std::chrono::system_clock::now() + - std::chrono::milliseconds(10000); + std::chrono::milliseconds(5000); context.set_deadline(deadline); - grpc::CompletionQueue cq; + //grpc::CompletionQueue cq; auto proto_query = query->getProtoQuery(); + auto proto_query_serialized = proto_query->SerializeAsString(); - auto query_hex_string = DataTypeConverter::binToHex((unsigned char*)proto_query_serialized.data(), proto_query_serialized.size()); - printf("[HederaRequest::request] query as hex: %s\n", query_hex_string.data()); - proto::Response* response = nullptr; + //auto query_hex_string = DataTypeConverter::binToHex((unsigned char*)proto_query_serialized.data(), proto_query_serialized.size()); + //printf("[HederaRequest::request] query as hex: %s\n", query_hex_string.data()); + + auto proto_response = response->getResponsePtr(); + auto connect_string = query->getConnectionString(); + if (proto_query->has_cryptogetaccountbalance()) { - auto stub = proto::CryptoService::NewStub(channel); - auto connect_string = query->getConnectionString(); - printf("try connection to hedera with: %s\n", connect_string.data()); - //auto stream = stub->PrepareAsynccryptoGetBalance(&context, *proto_query, &cq); - auto status = stub->cryptoGetBalance(&context, *proto_query, response); - //stream->StartCall(); - addError(new ParamError("Hedera Request", "crypto get balance", status.error_message())); - printf("[HederaRequest::request] error details: %s\n", status.error_details().data()); + auto stub = proto::CryptoService::NewStub(channel); + // crypto account get balance currently hasn't fees + query->setResponseType(proto::ANSWER_ONLY); + + auto status = stub->cryptoGetBalance(&context, *proto_query, proto_response); + if (status.ok()) { + return HEDERA_REQUEST_RETURN_OK; + } + else { + addError(new ParamError("Hedera Request", "crypto get balance error message:", status.error_message())); + addError(new ParamError("Hedera Request", "details: ", status.error_details())); + return HEDERA_REQUEST_RETURN_ERROR; + } + + } return HEDERA_REQUEST_RETURN_OK; +} + +#include "Poco/JSON/Object.h" +#include "../lib/JsonRequest.h" + +HederaRequestReturn HederaRequest::requestViaPHPRelay(model::hedera::Query* query) +{ + JsonRequest phpRelay("***REMOVED***", 88); + Poco::Net::NameValueCollection parameters; + std::string query_string = query->getProtoQuery()->SerializeAsString(); + //auto query_base64 = DataTypeConverter::binToBase64((const unsigned char*)query_string.data(), query_string.size(), sodium_base64_VARIANT_URLSAFE_NO_PADDING); + //auto findPos = query_string.find_first_of("\u"); + auto query_hex = DataTypeConverter::binToHex((const unsigned char*)query_string.data(), query_string.size()); + parameters.set("content", query_hex.substr(0, query_hex.size()-1)); + parameters.set("server", query->getConnectionString()); + parameters.set("method", "getBalance"); + parameters.set("service", "crypto"); + phpRelay.requestGRPCRelay(parameters); + //phpRelay.request("") + + return HEDERA_REQUEST_RETURN_OK; } \ No newline at end of file diff --git a/src/cpp/controller/HederaRequest.h b/src/cpp/controller/HederaRequest.h index 692215f8d..327ee7634 100644 --- a/src/cpp/controller/HederaRequest.h +++ b/src/cpp/controller/HederaRequest.h @@ -12,6 +12,8 @@ #include "../controller/NodeServer.h" #include "../model/hedera/Query.h" +#include "../model/hedera/Transaction.h" +#include "../model/hedera/Response.h" enum HederaRequestReturn { @@ -22,13 +24,15 @@ enum HederaRequestReturn }; // NodeServerConnection -class HederaRequest : public ErrorList +class HederaRequest : public NotificationList { public: HederaRequest(); ~HederaRequest(); - HederaRequestReturn request(model::hedera::Query* query); + HederaRequestReturn request(model::hedera::Query* query, model::hedera::Response* response, Poco::UInt64 fee = 0); + //! for testing, didn't work server say invalid json :/ + HederaRequestReturn requestViaPHPRelay(model::hedera::Query* query); protected: diff --git a/src/cpp/lib/DataTypeConverter.cpp b/src/cpp/lib/DataTypeConverter.cpp index a97cb8d0e..72e6aceb8 100644 --- a/src/cpp/lib/DataTypeConverter.cpp +++ b/src/cpp/lib/DataTypeConverter.cpp @@ -138,18 +138,17 @@ namespace DataTypeConverter } - std::string binToBase64(const MemoryBin* data) + std::string binToBase64(const unsigned char* data, size_t size, int variant /*= sodium_base64_VARIANT_ORIGINAL*/) { auto mm = MemoryManager::getInstance(); - size_t binSize = data->size(); - size_t encodedSize = sodium_base64_encoded_len(binSize, sodium_base64_VARIANT_ORIGINAL); - + + size_t encodedSize = sodium_base64_encoded_len(size, variant); auto base64 = mm->getFreeMemory(encodedSize); memset(*base64, 0, encodedSize); size_t resultBinSize = 0; - if (0 != sodium_bin2base64(*base64, encodedSize, *data, binSize, sodium_base64_VARIANT_ORIGINAL)) { + if (nullptr == sodium_bin2base64(*base64, encodedSize, data, size, variant)) { mm->releaseMemory(base64); return ""; } diff --git a/src/cpp/lib/DataTypeConverter.h b/src/cpp/lib/DataTypeConverter.h index 0dad46954..d970d697d 100644 --- a/src/cpp/lib/DataTypeConverter.h +++ b/src/cpp/lib/DataTypeConverter.h @@ -9,6 +9,8 @@ #include "Poco/Data/LOB.h" #include "../SingletonManager/LanguageManager.h" +#include "sodium.h" + namespace DataTypeConverter { enum NumberParseState @@ -25,8 +27,9 @@ namespace DataTypeConverter { MemoryBin* hexToBin(const std::string& hexString); MemoryBin* base64ToBin(const std::string& base64String); - std::string binToBase64(const MemoryBin* data); + std::string binToBase64(const unsigned char* data, size_t size, int variant = sodium_base64_VARIANT_ORIGINAL); + inline std::string binToBase64(const MemoryBin* data, int variant = sodium_base64_VARIANT_ORIGINAL) { return binToBase64(data->data(), data->size(), variant); } std::string binToHex(const unsigned char* data, size_t size); std::string binToHex(const Poco::Nullable& nullableBin); diff --git a/src/cpp/lib/Error.cpp b/src/cpp/lib/Error.cpp index c44f48711..9897d7930 100644 --- a/src/cpp/lib/Error.cpp +++ b/src/cpp/lib/Error.cpp @@ -2,7 +2,7 @@ Error::Error(const char* functionName, const char* message) - : mFunctionName(functionName), mMessage(message) + : Notification(functionName, message) { } @@ -12,7 +12,7 @@ Error::~Error() } -std::string Error::getString(bool withNewline/* = true*/) +std::string Error::getString(bool withNewline/* = true*/) const { std::stringstream ss; ss << mFunctionName << ": " << mMessage; @@ -20,7 +20,7 @@ std::string Error::getString(bool withNewline/* = true*/) return ss.str(); } -std::string Error::getHtmlString() +std::string Error::getHtmlString() const { std::stringstream ss; ss << mFunctionName << ": " << mMessage; @@ -28,7 +28,7 @@ std::string Error::getHtmlString() return ss.str(); } -std::string ParamError::getString(bool withNewline/* = true*/) +std::string ParamError::getString(bool withNewline/* = true*/) const { std::stringstream ss; ss << mFunctionName << ": " << mMessage << " " << mParam; @@ -36,7 +36,7 @@ std::string ParamError::getString(bool withNewline/* = true*/) return ss.str(); } -std::string ParamError::getHtmlString() +std::string ParamError::getHtmlString() const { std::stringstream ss; ss << mFunctionName << ": " << mMessage << " " << mParam << std::endl; diff --git a/src/cpp/lib/Error.h b/src/cpp/lib/Error.h index e85b01455..444a2ddc0 100644 --- a/src/cpp/lib/Error.h +++ b/src/cpp/lib/Error.h @@ -10,23 +10,24 @@ #ifndef DR_LUA_WEB_MODULE_ERROR_ERROR_H #define DR_LUA_WEB_MODULE_ERROR_ERROR_H -#include +#include "Notification.h" + #include -class Error + +class Error : public Notification { public: Error(const char* functionName, const char* message); ~Error(); - const char* getFunctionName() { return mFunctionName.data(); } - const char* getMessage() { return mMessage.data(); } - virtual std::string getString(bool withNewline = true); - virtual std::string getHtmlString(); + virtual std::string getString(bool withNewline = true) const; + virtual std::string getHtmlString() const; + + virtual bool isError() { return true; } protected: - std::string mFunctionName; - std::string mMessage; + }; class ParamError : public Error @@ -44,18 +45,18 @@ public: mParam = ss.str(); } - virtual std::string getString(bool withNewline = true); - virtual std::string getHtmlString(); + virtual std::string getString(bool withNewline = true) const; + virtual std::string getHtmlString() const; protected: std::string mParam; }; -class IErrorCollection +class INotificationCollection { public: - virtual void addError(Error*, bool log = true) = 0; + virtual void addError(Notification*, bool log = true) = 0; }; #endif // DR_LUA_WEB_MODULE_ERROR_ERROR_H diff --git a/src/cpp/lib/JsonRequest.cpp b/src/cpp/lib/JsonRequest.cpp index 5e5bedb47..da8bb19bb 100644 --- a/src/cpp/lib/JsonRequest.cpp +++ b/src/cpp/lib/JsonRequest.cpp @@ -37,7 +37,6 @@ JsonRequestReturn JsonRequest::request(const char* methodName, const Poco::Net:: try { Profiler phpRequestTime; Poco::Net::HTTPSClientSession httpsClientSession(mServerHost, mServerPort); - Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, "/JsonRequestHandler"); request.setChunkedTransferEncoding(true); @@ -99,5 +98,95 @@ JsonRequestReturn JsonRequest::request(const char* methodName, const Poco::Net:: return JSON_REQUEST_CONNECT_ERROR; } + return JSON_REQUEST_RETURN_OK; +} +#include "Poco/JSON/Stringifier.h" +JsonRequestReturn JsonRequest::requestGRPCRelay(const Poco::Net::NameValueCollection& payload) +{ + static const char* functionName = "JsonRequest::requestGRPCRelay"; + Poco::JSON::Object requestJson; + + for (auto it = payload.begin(); it != payload.end(); it++) { + requestJson.set(it->first, it->second); + } + + // send post request via https + // 443 = HTTPS Default + // TODO: adding port into ServerConfig + try { + Profiler phpRequestTime; + Poco::Net::HTTPClientSession httpClientSession(mServerHost, mServerPort); + Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, "/hedera_rpc_relay/gRPCProxy.php"); + + request.setChunkedTransferEncoding(false); + std::ostream& requestStream = httpClientSession.sendRequest(request); + requestJson.stringify(requestStream); + + std::stringstream ss; + requestJson.stringify(ss); + auto f = fopen("grpc.txt", "wt"); + std::string grpc = ss.str(); + fwrite(grpc.data(), grpc.size(), 1, f); + fclose(f); + + Poco::Net::HTTPResponse response; + std::istream& request_stream = httpClientSession.receiveResponse(response); + + // debugging answer + + std::stringstream responseStringStream; + for (std::string line; std::getline(request_stream, line); ) { + responseStringStream << line << std::endl; + } + Poco::Logger& speedLog = Poco::Logger::get("SpeedLog"); + speedLog.information("[gRPC relay] php server time: %s", phpRequestTime.string()); + + // extract parameter from request + Poco::JSON::Parser jsonParser; + Poco::Dynamic::Var parsedJson; + try { + parsedJson = jsonParser.parse(responseStringStream.str()); + } + catch (Poco::Exception& ex) { + addError(new ParamError(functionName, "error parsing request answer grpc relay", ex.displayText().data())); + + std::string fileName = "response_grpc_"; + fileName += ".html"; + + FILE* f = fopen(fileName.data(), "wt"); + std::string responseString = responseStringStream.str(); + fwrite(responseString.data(), 1, responseString.size(), f); + fclose(f); + // */ + sendErrorsAsEmail(responseStringStream.str()); + return JSON_REQUEST_RETURN_PARSE_ERROR; + } + + Poco::JSON::Object object = *parsedJson.extract(); + auto state = object.get("state"); + std::string stateString = state.convert(); + if (stateString == "error") { + addError(new Error(functionName, "php server return error")); + if (!object.isNull("msg")) { + addError(new ParamError(functionName, "msg:", object.get("msg").convert().data())); + } + if (!object.isNull("details")) { + addError(new ParamError(functionName, "details:", object.get("details").convert().data())); + } + sendErrorsAsEmail(); + return JSON_REQUEST_RETURN_ERROR; + } + ss.clear(); + Poco::JSON::Stringifier::stringify(object, ss); + printf("json request result: %s\n", ss.str().data()); + } + catch (Poco::Exception& e) { + addError(new ParamError(functionName, "connect error to php server", e.displayText().data())); + sendErrorsAsEmail(); + return JSON_REQUEST_CONNECT_ERROR; + } + + + return JSON_REQUEST_RETURN_OK; } \ No newline at end of file diff --git a/src/cpp/lib/JsonRequest.h b/src/cpp/lib/JsonRequest.h index 87350c002..e13046594 100644 --- a/src/cpp/lib/JsonRequest.h +++ b/src/cpp/lib/JsonRequest.h @@ -8,7 +8,7 @@ * */ -#include "ErrorList.h" +#include "NotificationList.h" #include "Poco/Net/NameValueCollection.h" #ifndef __GRADIDO_LOGIN_SERVER_LIB_JSON_REQUEST_ @@ -22,17 +22,19 @@ enum JsonRequestReturn JSON_REQUEST_CONNECT_ERROR }; -class JsonRequest : public ErrorList +class JsonRequest : public NotificationList { public: JsonRequest(const std::string& serverHost, int serverPort); ~JsonRequest(); JsonRequestReturn request(const char* methodName, const Poco::Net::NameValueCollection& payload); + JsonRequestReturn requestGRPCRelay(const Poco::Net::NameValueCollection& payload); protected: int mServerPort; std::string mServerHost; + }; diff --git a/src/cpp/lib/MultithreadContainer.cpp b/src/cpp/lib/MultithreadContainer.cpp index fc72593a1..d73a6a882 100644 --- a/src/cpp/lib/MultithreadContainer.cpp +++ b/src/cpp/lib/MultithreadContainer.cpp @@ -1,5 +1,5 @@ #include "MultithreadContainer.h" -#include "ErrorList.h" +#include "NotificationList.h" namespace UniLib { namespace lib { @@ -14,7 +14,7 @@ namespace UniLib { } } catch (Poco::TimeoutException& ex) { - ErrorList errors; + NotificationList errors; errors.addError(new ParamError(functionName, "lock timeout", ex.displayText())); if (mLastSucceededLock != "") { errors.addError(new ParamError(functionName, "last succeed lock by ", mLastSucceededLock.data())); diff --git a/src/cpp/lib/Notification.cpp b/src/cpp/lib/Notification.cpp new file mode 100644 index 000000000..15d622923 --- /dev/null +++ b/src/cpp/lib/Notification.cpp @@ -0,0 +1,7 @@ +#include "Notification.h" + +Notification::Notification(const char* functionName, const char* message) + : mFunctionName(functionName), mMessage(message) +{ + +} \ No newline at end of file diff --git a/src/cpp/lib/Notification.h b/src/cpp/lib/Notification.h new file mode 100644 index 000000000..419b861bc --- /dev/null +++ b/src/cpp/lib/Notification.h @@ -0,0 +1,24 @@ +#ifndef GRADIDO_LOGIN_SERVER_LIB_NOTIFICATION_H +#define GRADIDO_LOGIN_SERVER_LIB_NOTIFICATION_H + +#include + +class Notification +{ +public: + Notification(const char* functionName, const char* message); + + const char* getFunctionName() { return mFunctionName.data(); } + const char* getMessage() { return mMessage.data(); } + virtual std::string getString(bool withNewline = true) const = 0; + virtual std::string getHtmlString() const = 0; + + virtual bool isError() { return false; } + virtual bool isSuccess() { return false; } + +protected: + std::string mFunctionName; + std::string mMessage; +}; + +#endif //GRADIDO_LOGIN_SERVER_LIB_NOTIFICATION_H \ No newline at end of file diff --git a/src/cpp/lib/ErrorList.cpp b/src/cpp/lib/NotificationList.cpp similarity index 75% rename from src/cpp/lib/ErrorList.cpp rename to src/cpp/lib/NotificationList.cpp index 0a03afb01..48e96b685 100644 --- a/src/cpp/lib/ErrorList.cpp +++ b/src/cpp/lib/NotificationList.cpp @@ -1,4 +1,4 @@ -#include "ErrorList.h" +#include "NotificationList.h" #include "../ServerConfig.h" @@ -42,13 +42,13 @@ int SendErrorMessage::run() // ------------------------------------------------------------------------------------ -ErrorList::ErrorList() +NotificationList::NotificationList() : mLogging(Poco::Logger::get("errorLog")) { } -ErrorList::~ErrorList() +NotificationList::~NotificationList() { while (mErrorStack.size() > 0) { delete mErrorStack.top(); @@ -56,7 +56,7 @@ ErrorList::~ErrorList() } } -void ErrorList::addError(Error* error, bool log/* = true */) +void NotificationList::addError(Notification* error, bool log/* = true */) { if (log) { @@ -67,13 +67,18 @@ void ErrorList::addError(Error* error, bool log/* = true */) mErrorStack.push(error); } -Error* ErrorList::getLastError() +void NotificationList::addNotification(Notification* notification) +{ + mErrorStack.push(notification); +} + +Notification* NotificationList::getLastError() { if (mErrorStack.size() == 0) { return nullptr; } - Error* error = mErrorStack.top(); + Notification* error = mErrorStack.top(); if (error) { mErrorStack.pop(); } @@ -81,7 +86,7 @@ Error* ErrorList::getLastError() return error; } -void ErrorList::clearErrors() +void NotificationList::clearErrors() { while (mErrorStack.size()) { auto error = mErrorStack.top(); @@ -93,9 +98,9 @@ void ErrorList::clearErrors() } -int ErrorList::getErrors(ErrorList* send) +int NotificationList::getErrors(NotificationList* send) { - Error* error = nullptr; + Notification* error = nullptr; int iCount = 0; while (error = send->getLastError()) { addError(error, false); @@ -104,7 +109,7 @@ int ErrorList::getErrors(ErrorList* send) return iCount; } -void ErrorList::printErrors() +void NotificationList::printErrors() { while (mErrorStack.size() > 0) { auto error = mErrorStack.top(); @@ -114,14 +119,19 @@ void ErrorList::printErrors() } } -std::string ErrorList::getErrorsHtml() +std::string NotificationList::getErrorsHtml() { std::string res; res = "
    "; while (mErrorStack.size() > 0) { auto error = mErrorStack.top(); mErrorStack.pop(); - res += "
  • "; + if (error->isError()) { + res += "
  • "; + } + else if (error->isSuccess()) { + res += "
  • "; + } res += error->getHtmlString(); res += "
  • "; delete error; @@ -130,15 +140,20 @@ std::string ErrorList::getErrorsHtml() return res; } -std::string ErrorList::getErrorsHtmlNewFormat() +std::string NotificationList::getErrorsHtmlNewFormat() { std::string html; while (mErrorStack.size() > 0) { - auto error = std::unique_ptr(mErrorStack.top()); + auto error = std::unique_ptr(mErrorStack.top()); mErrorStack.pop(); - html += "
    "; - html += "report_problem"; + if (error->isError()) { + html += "
    "; + html += "report_problem"; + } + else if (error->isSuccess()) { + html += "
    "; + } html += ""; html += error->getHtmlString(); html += ""; @@ -154,7 +169,7 @@ std::string ErrorList::getErrorsHtmlNewFormat() */ -void ErrorList::sendErrorsAsEmail(std::string rawHtml/* = ""*/) +void NotificationList::sendErrorsAsEmail(std::string rawHtml/* = ""*/) { auto em = EmailManager::getInstance(); /*auto message = new Poco::Net::MailMessage(); diff --git a/src/cpp/lib/ErrorList.h b/src/cpp/lib/NotificationList.h similarity index 76% rename from src/cpp/lib/ErrorList.h rename to src/cpp/lib/NotificationList.h index 3940a23c7..a3b2edcf1 100644 --- a/src/cpp/lib/ErrorList.h +++ b/src/cpp/lib/NotificationList.h @@ -19,27 +19,28 @@ #include "Poco/Net/StringPartSource.h" #include "Poco/Logger.h" -class ErrorList : public IErrorCollection +class NotificationList : public INotificationCollection { public: - ErrorList(); - ~ErrorList(); + NotificationList(); + ~NotificationList(); // push error, error will be deleted in deconstructor - virtual void addError(Error* error, bool log = true); + virtual void addError(Notification* error, bool log = true); + void addNotification(Notification* notification); // return error on top of stack, please delete after using - Error* getLastError(); + Notification* getLastError(); inline size_t errorCount() { return mErrorStack.size(); } // delete all errors void clearErrors(); - static int moveErrors(ErrorList* recv, ErrorList* send) { + static int moveErrors(NotificationList* recv, NotificationList* send) { return recv->getErrors(send); } - int getErrors(ErrorList* send); + int getErrors(NotificationList* send); void printErrors(); std::string getErrorsHtml(); @@ -48,7 +49,7 @@ public: void sendErrorsAsEmail(std::string rawHtml = ""); protected: - std::stack mErrorStack; + std::stack mErrorStack; // poco logging Poco::Logger& mLogging; }; diff --git a/src/cpp/lib/Success.cpp b/src/cpp/lib/Success.cpp new file mode 100644 index 000000000..5cf23f3b8 --- /dev/null +++ b/src/cpp/lib/Success.cpp @@ -0,0 +1,52 @@ +#include "Success.h" +#include + +Success::Success(const char* functionName, const char* message) + : Notification(functionName, message) +{ + +} + +std::string Success::getString(bool withNewline/* = true*/) const +{ + std::stringstream ss; + ss << mFunctionName << ": " << mMessage; + if (withNewline) ss << std::endl; + + return ss.str(); +} +std::string Success::getHtmlString() const +{ + std::stringstream ss; + ss << mFunctionName << ": " << mMessage; + + return ss.str(); +} + +ParamSuccess::ParamSuccess(const char* functionName, const char* message, std::string param) + : Success(functionName, message), mParam(param) +{ + +} + +ParamSuccess::ParamSuccess(const char* functionName, const char* message, int param) + : Success(functionName, message), mParam(std::to_string(param)) +{ + +} + +std::string ParamSuccess::getString(bool withNewline/* = true*/) const +{ + std::stringstream ss; + ss << mFunctionName << ": " << mMessage << " " << mParam; + if (withNewline) ss << std::endl; + + return ss.str(); +} +std::string ParamSuccess::getHtmlString() const +{ + std::stringstream ss; + ss << mFunctionName << ": " << mMessage << " " << mParam; + + return ss.str(); +} \ No newline at end of file diff --git a/src/cpp/lib/Success.h b/src/cpp/lib/Success.h new file mode 100644 index 000000000..4fc4b4fcf --- /dev/null +++ b/src/cpp/lib/Success.h @@ -0,0 +1,30 @@ +#ifndef GRADIDO_LOGIN_SERVER_LIB_SUCCESS_H +#define GRADIDO_LOGIN_SERVER_LIB_SUCCESS_H + +#include "Notification.h" + +class Success : public Notification +{ +public: + Success(const char* functionName, const char* message); + + std::string getString(bool withNewline = true) const; + std::string getHtmlString() const; + + virtual bool isSuccess() { return true; } +}; + +class ParamSuccess : public Success +{ +public: + ParamSuccess(const char* functionName, const char* message, std::string param); + ParamSuccess(const char* functionName, const char* message, int param); + + std::string getString(bool withNewline = true) const; + std::string getHtmlString() const; + +protected: + std::string mParam; +}; + +#endif //GRADIDO_LOGIN_SERVER_LIB_SUCCESS_H \ No newline at end of file diff --git a/src/cpp/model/Session.h b/src/cpp/model/Session.h index 69a9612e0..6557ef30e 100644 --- a/src/cpp/model/Session.h +++ b/src/cpp/model/Session.h @@ -10,7 +10,7 @@ #ifndef DR_LUA_WEB_MODULE_SESSION_SESSION_H #define DR_LUA_WEB_MODULE_SESSION_SESSION_H -#include "../lib/ErrorList.h" +#include "../lib/NotificationList.h" #include "User.h" #include "../controller/User.h" @@ -54,7 +54,7 @@ class UpdateUserPasswordPage; class PassphrasePage; class RepairDefectPassphrase; -class Session : public ErrorList, public UniLib::lib::MultithreadContainer +class Session : public NotificationList, public UniLib::lib::MultithreadContainer { friend WriteEmailVerification; friend SessionManager; diff --git a/src/cpp/model/TransactionBase.h b/src/cpp/model/TransactionBase.h index 84406fddb..5bb0bad14 100644 --- a/src/cpp/model/TransactionBase.h +++ b/src/cpp/model/TransactionBase.h @@ -11,11 +11,11 @@ #pragma warning(disable:4800) -#include "../lib/ErrorList.h" +#include "../lib/NotificationList.h" #include "../proto/gradido/BasicTypes.pb.h" #include "../SingletonManager/MemoryManager.h" -class TransactionBase : public ErrorList, public UniLib::lib::MultithreadContainer +class TransactionBase : public NotificationList, public UniLib::lib::MultithreadContainer { public: TransactionBase(const std::string& memo); diff --git a/src/cpp/model/User.cpp b/src/cpp/model/User.cpp index 80763d337..a57324cf8 100644 --- a/src/cpp/model/User.cpp +++ b/src/cpp/model/User.cpp @@ -732,7 +732,7 @@ void User::setEmailChecked() unlock(); } -bool User::validatePwd(const std::string& pwd, ErrorList* validationErrorsToPrint) +bool User::validatePwd(const std::string& pwd, NotificationList* validationErrorsToPrint) { auto mm = MemoryManager::getInstance(); auto cmpCryptoKey = createCryptoKey(pwd); @@ -935,7 +935,7 @@ MemoryBin* User::createCryptoKey(const std::string& password) return key; } -User::passwordHashed User::createPasswordHashed(MemoryBin* cryptoKey, ErrorList* errorReceiver/* = nullptr*/) +User::passwordHashed User::createPasswordHashed(MemoryBin* cryptoKey, NotificationList* errorReceiver/* = nullptr*/) { if (sizeof(User::passwordHashed) != crypto_shorthash_BYTES) { throw Poco::Exception("crypto_shorthash_BYTES != sizeof(User::passwordHashed)"); diff --git a/src/cpp/model/User.h b/src/cpp/model/User.h index c041cea7d..cc1a8be86 100644 --- a/src/cpp/model/User.h +++ b/src/cpp/model/User.h @@ -4,7 +4,7 @@ #include "../Crypto/KeyPair.h" #include //#include "ModelBase.h" -#include "../lib/ErrorList.h" +#include "../lib/NotificationList.h" #include "Poco/Thread.h" #include "Poco/Types.h" @@ -50,7 +50,7 @@ enum UserFields USER_FIELDS_LANGUAGE }; -class User : public ErrorList +class User : public NotificationList { friend UserCreateCryptoKey; friend UserWriteIntoDB; @@ -115,7 +115,7 @@ public: bool isEmptyPassword(); //bool setNewPassword(const std::string& newPassword); bool updatePassword(const std::string& newPassword, const std::string& passphrase, Poco::AutoPtr newUser); - bool validatePwd(const std::string& pwd, ErrorList* validationErrorsToPrint); + bool validatePwd(const std::string& pwd, NotificationList* validationErrorsToPrint); bool validateIdentHash(HASH hash); MemoryBin* encrypt(const MemoryBin* data); @@ -134,7 +134,7 @@ protected: typedef Poco::UInt64 passwordHashed; MemoryBin* createCryptoKey(const std::string& password); - static passwordHashed createPasswordHashed(MemoryBin* cryptoKey, ErrorList* errorReceiver = nullptr); + static passwordHashed createPasswordHashed(MemoryBin* cryptoKey, NotificationList* errorReceiver = nullptr); inline void setCryptoKey(MemoryBin* cryptoKey) { lock(); mCryptoKey = cryptoKey; unlock(); } //void detectState(); diff --git a/src/cpp/model/email/Email.h b/src/cpp/model/email/Email.h index d2887a26c..0fc52cac0 100644 --- a/src/cpp/model/email/Email.h +++ b/src/cpp/model/email/Email.h @@ -17,7 +17,7 @@ #include "../../SingletonManager/LanguageManager.h" -#include "../../lib/ErrorList.h" +#include "../../lib/NotificationList.h" namespace model { using namespace Poco; @@ -39,7 +39,7 @@ namespace model { EMAIL_MAX }; - class Email: public ErrorList + class Email: public NotificationList { public: Email(AutoPtr emailVerification, AutoPtr user, EmailType type); diff --git a/src/cpp/model/hedera/CryptoTransferTransaction.cpp b/src/cpp/model/hedera/CryptoTransferTransaction.cpp new file mode 100644 index 000000000..828a85645 --- /dev/null +++ b/src/cpp/model/hedera/CryptoTransferTransaction.cpp @@ -0,0 +1,53 @@ +#include "CryptoTransferTransaction.h" + +namespace model { + namespace hedera { + + CryptoTransferTransaction::CryptoTransferTransaction() + : mCryptoTransfer(nullptr) + { + mCryptoTransfer = new proto::CryptoTransferTransactionBody; + } + + CryptoTransferTransaction::~CryptoTransferTransaction() + { + if (mCryptoTransfer) { + delete mCryptoTransfer; + mCryptoTransfer = nullptr; + } + } + + void CryptoTransferTransaction::addSender(Poco::AutoPtr senderAccountId, Poco::UInt64 amountTinybars) + { + auto transfers = mCryptoTransfer->mutable_transfers(); + auto accountAmounts = transfers->add_accountamounts(); + accountAmounts->set_amount(-(Poco::Int64)amountTinybars); + senderAccountId->copyToProtoAccountId(accountAmounts->mutable_accountid()); + } + void CryptoTransferTransaction::addReceiver(Poco::AutoPtr receiverAccountId, Poco::UInt64 amountTinybars) + { + auto transfers = mCryptoTransfer->mutable_transfers(); + auto accountAmounts = transfers->add_accountamounts(); + accountAmounts->set_amount(amountTinybars); + receiverAccountId->copyToProtoAccountId(accountAmounts->mutable_accountid()); + } + + bool CryptoTransferTransaction::validate() + { + auto transfers = mCryptoTransfer->mutable_transfers(); + auto account_amounts = transfers->accountamounts(); + Poco::Int64 sum = 0; + for (int i = 0; i < transfers->accountamounts_size(); i++) { + auto account_amount = account_amounts.Mutable(i); + sum += account_amount->amount(); + } + return 0 == sum && transfers->accountamounts_size() > 0; + } + + void CryptoTransferTransaction::resetPointer() + { + mCryptoTransfer = nullptr; + } + } +} + diff --git a/src/cpp/model/hedera/CryptoTransferTransaction.h b/src/cpp/model/hedera/CryptoTransferTransaction.h new file mode 100644 index 000000000..04aacafea --- /dev/null +++ b/src/cpp/model/hedera/CryptoTransferTransaction.h @@ -0,0 +1,40 @@ +#ifndef _GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CRYPTO_TRANSFER_TRANSACTION_H +#define _GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CRYPTO_TRANSFER_TRANSACTION_H + +/*! +* @author: Dario Rekowski +* +* @date: 02.09.20 +* +* @brief: class for creating a hedera transfer transaction +* +*/ + +#include "../../proto/hedera/CryptoTransfer.pb.h" +#include "../../controller/HederaId.h" + +namespace model { + namespace hedera { + class CryptoTransferTransaction + { + public: + CryptoTransferTransaction(); + ~CryptoTransferTransaction(); + + void addSender(Poco::AutoPtr senderAccountId, Poco::UInt64 amountTinybars); + void addReceiver(Poco::AutoPtr receiverAccountId, Poco::UInt64 amountTinybars); + + bool validate(); + // set pointer to zero, after hand over pointer to transaction body + void resetPointer(); + + inline proto::CryptoTransferTransactionBody* getProtoTransactionBody() { return mCryptoTransfer; } + + protected: + proto::CryptoTransferTransactionBody* mCryptoTransfer; + }; + } +} + + +#endif //_GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CRYPTO_TRANSFER_TRANSACTION_H \ No newline at end of file diff --git a/src/cpp/model/hedera/Query.cpp b/src/cpp/model/hedera/Query.cpp index 39b3700c4..de4fdec99 100644 --- a/src/cpp/model/hedera/Query.cpp +++ b/src/cpp/model/hedera/Query.cpp @@ -2,18 +2,24 @@ #include "Poco/Timestamp.h" #include "../../SingletonManager/MemoryManager.h" +#include "Transaction.h" +#include "TransactionBody.h" +#include "CryptoTransferTransaction.h" + namespace model { namespace hedera { Query::Query(const controller::NodeServerConnection& connection) - : mConnection(connection) + : mConnection(connection), mTransactionBody(nullptr) { } Query::~Query() { - + if (mTransactionBody) { + delete mTransactionBody; + } } Query* Query::getBalance(Poco::AutoPtr accountId, const controller::NodeServerConnection& connection) @@ -26,58 +32,46 @@ namespace model { accountId->copyToProtoAccountId(get_account_balance->mutable_accountid()); auto query_header = get_account_balance->mutable_header(); query_header->set_responsetype(proto::COST_ANSWER); - auto transaction = query_header->mutable_payment(); + + query->mTransactionBody = new TransactionBody(accountId, connection); + CryptoTransferTransaction crypto_transaction; + crypto_transaction.addSender(accountId, 0); + crypto_transaction.addReceiver(connection.hederaId, 0); + query->mTransactionBody->setCryptoTransfer(crypto_transaction); + + //auto transaction = query_header->mutable_payment(); //auto transaction_body = transaction->mutable_body(); // body content - // transaction id - auto transaction_id = query->mTransactionBody.mutable_transactionid(); - auto timestamp = transaction_id->mutable_transactionvalidstart(); - Poco::Timestamp now; - auto microseconds = now.epochMicroseconds() - now.epochTime() * now.resolution(); // 1*10^6 - timestamp->set_seconds(now.epochTime()); - timestamp->set_nanos(microseconds * 1000); - accountId->copyToProtoAccountId(transaction_id->mutable_accountid()); - // - // sdk default, but can be changed - query->mTransactionBody.set_transactionfee(100000000); - auto valid_duration = query->mTransactionBody.mutable_transactionvalidduration(); - // maximal 2 minutes - valid_duration->set_seconds(120); - auto crypto_transfer = query->mTransactionBody.mutable_cryptotransfer(); - auto transfer_list = crypto_transfer->mutable_transfers(); - auto account_amounts = transfer_list->mutable_accountamounts(); - account_amounts->Add(); - auto account_amount = account_amounts->Mutable(0); - account_amount->set_amount(1000); - connection.hederaId->copyToProtoAccountId(account_amount->mutable_accountid()); + // node account id + return query; } bool Query::sign(std::unique_ptr keyPairHedera) { - auto mm = MemoryManager::getInstance(); - auto body_bytes = mTransactionBody.SerializeAsString(); - auto transaction = mQueryProto.mutable_cryptogetaccountbalance()->mutable_header()->mutable_payment(); - transaction->set_bodybytes(body_bytes.data()); - auto signature_map = transaction->mutable_sigmap(); - auto signature_pairs = signature_map->mutable_sigpair(); - signature_pairs->Add(); - auto signature_pair = signature_pairs->Mutable(0); - auto public_key = keyPairHedera->getPublicKey(); + Transaction transaction; + auto sign_result = transaction.sign(std::move(keyPairHedera), mTransactionBody); + auto query_header = mQueryProto.mutable_cryptogetaccountbalance()->mutable_header(); + query_header->set_allocated_payment(transaction.getTransaction()); + transaction.resetPointer(); - - auto sign = keyPairHedera->sign(body_bytes); - if (!sign) { - printf("[Query::sign] error signing message\n"); - return false; - } - signature_pair->set_pubkeyprefix(public_key, keyPairHedera->getPublicKeySize()); - signature_pair->set_ed25519(*sign, sign->size()); + return sign_result; + } - mm->releaseMemory(sign); + void Query::setResponseType(proto::ResponseType type) + { + auto get_account_balance = mQueryProto.mutable_cryptogetaccountbalance(); + auto query_header = get_account_balance->mutable_header(); + query_header->set_responsetype(type); - return true; + } + + proto::ResponseType Query::getResponseType() + { + auto get_account_balance = mQueryProto.mutable_cryptogetaccountbalance(); + auto query_header = get_account_balance->mutable_header(); + return query_header->responsetype(); } } } \ No newline at end of file diff --git a/src/cpp/model/hedera/Query.h b/src/cpp/model/hedera/Query.h index ad9af855a..fa9b06471 100644 --- a/src/cpp/model/hedera/Query.h +++ b/src/cpp/model/hedera/Query.h @@ -13,6 +13,7 @@ #include "../../proto/hedera/Query.pb.h" #include "../../controller/NodeServer.h" #include "../../Crypto/KeyPairHedera.h" +#include "TransactionBody.h" namespace model { namespace hedera { @@ -23,13 +24,16 @@ namespace model { static Query* getBalance(Poco::AutoPtr accountId, const controller::NodeServerConnection& connection); bool sign(std::unique_ptr keyPairHedera); + void setResponseType(proto::ResponseType type); + proto::ResponseType getResponseType(); + void setFee(Poco::UInt64 fee); inline const proto::Query* getProtoQuery() const { return &mQueryProto; } inline std::string getConnectionString() const { return mConnection.getUriWithPort(); } protected: Query(const controller::NodeServerConnection& connection); proto::Query mQueryProto; - proto::TransactionBody mTransactionBody; + TransactionBody* mTransactionBody; controller::NodeServerConnection mConnection; }; } diff --git a/src/cpp/model/hedera/Response.cpp b/src/cpp/model/hedera/Response.cpp index e69de29bb..a39c5364e 100644 --- a/src/cpp/model/hedera/Response.cpp +++ b/src/cpp/model/hedera/Response.cpp @@ -0,0 +1,32 @@ +#include "Response.h" + +namespace model { + namespace hedera { + Response::Response() + { + } + + Response::~Response() + { + + } + + Poco::UInt64 Response::getAccountBalance() + { + if (isCryptoGetAccountBalanceResponse()) { + auto balance_response = mResponseProto.cryptogetaccountbalance(); + return balance_response.balance(); + } + return 0; + } + + proto::ResponseCodeEnum Response::getResponseCode() + { + if (isCryptoGetAccountBalanceResponse()) { + auto balance_response = mResponseProto.cryptogetaccountbalance(); + return balance_response.header().nodetransactionprecheckcode(); + } + return proto::NOT_SUPPORTED; + } + } +} \ No newline at end of file diff --git a/src/cpp/model/hedera/Response.h b/src/cpp/model/hedera/Response.h index e69de29bb..779f5e982 100644 --- a/src/cpp/model/hedera/Response.h +++ b/src/cpp/model/hedera/Response.h @@ -0,0 +1,38 @@ +#ifndef _GRADIDO_LOGIN_SERVER_MODEL_HEDERA_RESPONSE_H +#define _GRADIDO_LOGIN_SERVER_MODEL_HEDERA_RESPONSE_H + +/*! +* @author: Dario Rekowski +* +* @date: 03.09.20 +* +* @brief: class for simply accessing hedera responses +* +*/ + +#include "../../proto/hedera/Response.pb.h" +#include "Poco/Types.h" + +namespace model { + namespace hedera { + class Response + { + public: + Response(); + ~Response(); + + inline proto::Response* getResponsePtr() { return &mResponseProto; } + Poco::UInt64 getAccountBalance(); + proto::ResponseCodeEnum getResponseCode(); + + inline bool isCryptoGetAccountBalanceResponse() { return mResponseProto.has_cryptogetaccountbalance(); } + + protected: + proto::Response mResponseProto; + + }; + } +} + + +#endif //_GRADIDO_LOGIN_SERVER_MODEL_HEDERA_RESPONSE_H \ No newline at end of file diff --git a/src/cpp/model/hedera/Transaction.cpp b/src/cpp/model/hedera/Transaction.cpp index e69de29bb..0dadbcb4c 100644 --- a/src/cpp/model/hedera/Transaction.cpp +++ b/src/cpp/model/hedera/Transaction.cpp @@ -0,0 +1,43 @@ +#include "Transaction.h" + +namespace model { + namespace hedera { + Transaction::Transaction() + : mTransaction(nullptr) + { + mTransaction = new proto::Transaction; + } + + Transaction::~Transaction() + { + if (mTransaction) { + delete mTransaction; + mTransaction = nullptr; + } + } + + bool Transaction::sign(std::unique_ptr keyPairHedera, const TransactionBody* transactionBody) + { + auto mm = MemoryManager::getInstance(); + auto transaction_body_proto = transactionBody->getProtoTransactionBody(); + auto body_bytes = transaction_body_proto->SerializeAsString(); + mTransaction->set_bodybytes(body_bytes.data()); + auto signature_map = mTransaction->mutable_sigmap(); + auto signature_pairs = signature_map->mutable_sigpair(); + signature_map->add_sigpair(); + auto signature_pair = signature_pairs->Mutable(0); + auto public_key = keyPairHedera->getPublicKey(); + + auto sign = keyPairHedera->sign(body_bytes); + if (!sign) { + printf("[Query::sign] error signing message\n"); + return false; + } + signature_pair->set_pubkeyprefix(public_key, keyPairHedera->getPublicKeySize()); + signature_pair->set_ed25519(*sign, sign->size()); + + mm->releaseMemory(sign); + return true; + } + } +} \ No newline at end of file diff --git a/src/cpp/model/hedera/Transaction.h b/src/cpp/model/hedera/Transaction.h index e69de29bb..3acf46ff9 100644 --- a/src/cpp/model/hedera/Transaction.h +++ b/src/cpp/model/hedera/Transaction.h @@ -0,0 +1,38 @@ +#ifndef _GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_H +#define _GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_H + +/*! +* @author: Dario Rekowski +* +* @date: 02.09.20 +* +* @brief: class for composing hedera transaction +* +*/ + +#include "../../proto/hedera/Transaction.pb.h" +#include "../../Crypto/KeyPairHedera.h" +#include "TransactionBody.h" + +namespace model { + namespace hedera { + class Transaction + { + public: + Transaction(); + ~Transaction(); + + bool sign(std::unique_ptr keyPairHedera, const TransactionBody* transactionBody); + + inline proto::Transaction* getTransaction() { return mTransaction; } + void resetPointer() { mTransaction = nullptr; } + + protected: + + proto::Transaction* mTransaction; + }; + } +} + + +#endif //_GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_H \ No newline at end of file diff --git a/src/cpp/model/hedera/TransactionBody.cpp b/src/cpp/model/hedera/TransactionBody.cpp index e69de29bb..f1979b6bf 100644 --- a/src/cpp/model/hedera/TransactionBody.cpp +++ b/src/cpp/model/hedera/TransactionBody.cpp @@ -0,0 +1,47 @@ +#include "TransactionBody.h" + +namespace model { + namespace hedera { + TransactionBody::TransactionBody(Poco::AutoPtr operatorAccountId, const controller::NodeServerConnection& connection) + { + connection.hederaId->copyToProtoAccountId(mTransactionBody.mutable_nodeaccountid()); + auto transaction_id = mTransactionBody.mutable_transactionid(); + operatorAccountId->copyToProtoAccountId(transaction_id->mutable_accountid()); + mTransactionBody.set_transactionfee(10000); + auto transaction_valid_duration = mTransactionBody.mutable_transactionvalidduration(); + transaction_valid_duration->set_seconds(120); + + updateTimestamp(); + } + + TransactionBody::~TransactionBody() + { + + } + + bool TransactionBody::setCryptoTransfer(CryptoTransferTransaction& cryptoTransferTransaction) + { + if (cryptoTransferTransaction.validate()) { + mTransactionBody.set_allocated_cryptotransfer(cryptoTransferTransaction.getProtoTransactionBody()); + cryptoTransferTransaction.resetPointer(); + return true; + } + return false; + } + + void TransactionBody::setMemo(const std::string& memo) + { + mTransactionBody.set_memo(memo); + } + + void TransactionBody::updateTimestamp() + { + auto transaction_id = mTransactionBody.mutable_transactionid(); + auto timestamp = transaction_id->mutable_transactionvalidstart(); + Poco::Timestamp now; + auto microseconds = now.epochMicroseconds() - now.epochTime() * now.resolution(); // 1*10^6 + timestamp->set_seconds(now.epochTime()); + timestamp->set_nanos(microseconds * 1000); + } + } +} \ No newline at end of file diff --git a/src/cpp/model/hedera/TransactionBody.h b/src/cpp/model/hedera/TransactionBody.h index e69de29bb..3663c4a59 100644 --- a/src/cpp/model/hedera/TransactionBody.h +++ b/src/cpp/model/hedera/TransactionBody.h @@ -0,0 +1,39 @@ +#ifndef _GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_BODY_H +#define _GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_BODY_H + +/*! +* @author: Dario Rekowski +* +* @date: 02.09.20 +* +* @brief: class for composing transaction body for hedera transaction +* +*/ + +#include "../../proto/hedera/TransactionBody.pb.h" +#include "../../controller/NodeServer.h" +#include "CryptoTransferTransaction.h" + +namespace model { + namespace hedera { + class TransactionBody + { + public: + TransactionBody(Poco::AutoPtr operatorAccountId, const controller::NodeServerConnection& connection); + ~TransactionBody(); + + void setMemo(const std::string& memo); + + bool setCryptoTransfer(CryptoTransferTransaction& cryptoTransferTransaction); + + inline const proto::TransactionBody* getProtoTransactionBody() const { return &mTransactionBody; } + + protected: + void updateTimestamp(); + proto::TransactionBody mTransactionBody; + }; + } +} + + +#endif //_GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_BODY_H \ No newline at end of file diff --git a/src/cpp/model/table/ModelBase.h b/src/cpp/model/table/ModelBase.h index 04ce4ffe4..b71b37a89 100644 --- a/src/cpp/model/table/ModelBase.h +++ b/src/cpp/model/table/ModelBase.h @@ -24,7 +24,7 @@ namespace model { MYSQL_CONDITION_OR }; - class ModelBase : public UniLib::lib::MultithreadContainer, public ErrorList + class ModelBase : public UniLib::lib::MultithreadContainer, public NotificationList { public: ModelBase(int id) :mID(id), mReferenceCount(1) {} diff --git a/src/cpp/tasks/ProcessingTransaction.h b/src/cpp/tasks/ProcessingTransaction.h index de58e5f8c..2bf2beb83 100644 --- a/src/cpp/tasks/ProcessingTransaction.h +++ b/src/cpp/tasks/ProcessingTransaction.h @@ -3,7 +3,7 @@ #include "CPUTask.h" -#include "../lib/ErrorList.h" +#include "../lib/NotificationList.h" #include "../lib/DRHash.h" #include "../model/TransactionBase.h" @@ -26,7 +26,7 @@ class TransactionCreation; class TransactionTransfer; class SigningTransaction; -class ProcessingTransaction : public UniLib::controller::CPUTask, public ErrorList +class ProcessingTransaction : public UniLib::controller::CPUTask, public NotificationList { friend SigningTransaction; public: diff --git a/src/cpp/tasks/SigningTransaction.h b/src/cpp/tasks/SigningTransaction.h index 4781052cb..30c962bf0 100644 --- a/src/cpp/tasks/SigningTransaction.h +++ b/src/cpp/tasks/SigningTransaction.h @@ -3,7 +3,7 @@ #include "CPUTask.h" -#include "../lib/ErrorList.h" +#include "../lib/NotificationList.h" #include "../model/TransactionBase.h" #include "../model/User.h" #include "../controller/User.h" @@ -19,7 +19,7 @@ * @desc: Task for signing Transactions */ -class SigningTransaction : public UniLib::controller::CPUTask, public ErrorList +class SigningTransaction : public UniLib::controller::CPUTask, public NotificationList { public: SigningTransaction(Poco::AutoPtr processingeTransaction, Poco::AutoPtr newUser); diff --git a/src/cpp/tasks/Task.cpp b/src/cpp/tasks/Task.cpp index e75b1a53d..07bb4c3fc 100644 --- a/src/cpp/tasks/Task.cpp +++ b/src/cpp/tasks/Task.cpp @@ -1,5 +1,5 @@ #include "Task.h" -#include "../lib/ErrorList.h" +#include "../lib/NotificationList.h" namespace UniLib { namespace controller { @@ -87,7 +87,7 @@ namespace UniLib { mWorkingMutex.lock(500); } catch (Poco::TimeoutException& ex) { - ErrorList errors; + NotificationList errors; errors.addError(new ParamError("Task::lock", getResourceType(), ex.displayText())); errors.sendErrorsAsEmail(); } diff --git a/src/cpsp/adminHederaAccount.cpsp b/src/cpsp/adminHederaAccount.cpsp index 5379e4ef4..3e8795d24 100644 --- a/src/cpsp/adminHederaAccount.cpsp +++ b/src/cpsp/adminHederaAccount.cpsp @@ -10,6 +10,8 @@ #include "../controller/HederaId.h" #include "../controller/CryptoKey.h" #include "../lib/DataTypeConverter.h" +#include "../lib/Profiler.h" +#include "../lib/Success.h" #include "../SingletonManager/SessionManager.h" #include "../ServerConfig.h" @@ -22,6 +24,8 @@ auto sm = SessionManager::getInstance(); auto mm = MemoryManager::getInstance(); auto user = mSession->getNewUser(); + Profiler hedera_time; + std::string hedera_time_string; Poco::URI uri(request.getURI()); auto uri_query = uri.getQueryParameters(); @@ -44,7 +48,9 @@ if(!hedera_account.size() || hedera_account[0].isNull()) { addError(new Error("Action Update Balance", "hedera id not found")); } else { + hedera_time.reset(); hedera_account[0]->updateBalanceFromHedera(user, this); + addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string())); } } } @@ -148,6 +154,7 @@ %><%@ include file="header_large.cpsp" %> <%= getErrorsHtml() %> +
    From e143a5c72954967d06738890c4b0035a68e19db7 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 4 Sep 2020 14:40:44 +0000 Subject: [PATCH 027/293] js for login server --- .../JsonRequestHandlerController.php | 2 + .../TransactionSendCoinsController.php | 2 +- webroot/js/time_calculations.js | 68 +++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 webroot/js/time_calculations.js diff --git a/src/Controller/JsonRequestHandlerController.php b/src/Controller/JsonRequestHandlerController.php index af93d2190..cced85daa 100644 --- a/src/Controller/JsonRequestHandlerController.php +++ b/src/Controller/JsonRequestHandlerController.php @@ -66,8 +66,10 @@ class JsonRequestHandlerController extends AppController { } //! \param $transactionCreated creation of transaction in timestamp in seconds + //! -1 if transaction couldn't decode //! \param $transactionBodyBase64Sha256 generic hash from transaction body serialized and converted to base64 //! using sodium_crypto_generichash to calculate + // hash also in base64 format //! \param $error short error name in user language //! \param $errorDetails more detailed error message in user language private function errorInTransaction($transactionCreated, $transactionBodyBase64GenericHash, $error, $errorDetails) { diff --git a/src/Controller/TransactionSendCoinsController.php b/src/Controller/TransactionSendCoinsController.php index 40cccb90e..d49038148 100644 --- a/src/Controller/TransactionSendCoinsController.php +++ b/src/Controller/TransactionSendCoinsController.php @@ -187,7 +187,7 @@ class TransactionSendCoinsController extends AppController $this->set('timeUsed', microtime(true) - $startTime); return; } - if($requestAnswear['data']['userData']['disabled']) { + if(isset($requestAnswear['data']['userData']['disabled']) && $requestAnswear['data']['userData']['disabled']) { $this->Flash->error(__('Der Empfänger ist deaktiviert, daher können ihm zurzeit keine Gradidos gesendet werden.')); $this->set('timeUsed', microtime(true) - $startTime); return; diff --git a/webroot/js/time_calculations.js b/webroot/js/time_calculations.js new file mode 100644 index 000000000..7ca61c492 --- /dev/null +++ b/webroot/js/time_calculations.js @@ -0,0 +1,68 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + + + +var SECONDS_TO_YEAR = 31536000; +var SECONDS_TO_DAY = 86400; +var SECONDS_TO_HOUR = 3600; +var SECONDS_TO_MINUTE = 60; +SECONDS_TO = { + YEAR: SECONDS_TO_YEAR, + DAY: SECONDS_TO_DAY, + HOUR: SECONDS_TO_HOUR, + MINUTE: SECONDS_TO_MINUTE +}; + + + +function getReadableAge(timestamp) { + if(timestamp === undefined) { + return "no timestamp" + } + var ageSeconds = ((new Date()).getTime()/1000) - timestamp; + if(ageSeconds < SECONDS_TO_MINUTE) { + return Math.round(ageSeconds) + " seconds"; + } else if(ageSeconds < SECONDS_TO_HOUR) { + return "~ " + Math.round(ageSeconds / SECONDS_TO_MINUTE) + " minutes"; + } else if(ageSeconds < SECONDS_TO_DAY) { + return "~ " + Math.round(ageSeconds / SECONDS_TO_HOUR) + " hours"; + } else if(ageSeconds < SECONDS_TO_YEAR) { + return "~ " + Math.round(ageSeconds / SECONDS_TO_DAY) + " days"; + } else { + return "~ " + Math.round(ageSeconds / SECONDS_TO_YEAR) + " years"; + } +} + +function getExactTimeDuration(durationSeconds) { + var parts = { + seconds: durationSeconds, + minutes: 0, + hours: 0, + days: 0, + years: 0 + }; + var durationString = ''; + for(var i in SECONDS_TO) { + if(parts.seconds > SECONDS_TO[i]) { + var partIndexName = i.toLowerCase() + 's'; + parts[partIndexName] = Math.floor(parts.seconds / SECONDS_TO[i]); + parts.seconds -= parts[partIndexName] * SECONDS_TO[i]; + if(durationString.length > 0) { + durationString += ', '; + } + var unitName = partIndexName; + if(parts[partIndexName] === 1) { + unitName = partIndexName.substring(0, partIndexName.length-1); + } + durationString += parts[partIndexName] + ' ' + unitName; + break; + } + + } + return durationString; + +} \ No newline at end of file From a7ecfa45d9aad0b91129bd67f7043317a950b172 Mon Sep 17 00:00:00 2001 From: team-devstage Date: Mon, 7 Sep 2020 16:34:33 +0200 Subject: [PATCH 028/293] update grd styles --- mithril_client | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mithril_client b/mithril_client index 21d4a0a5e..a04d47699 160000 --- a/mithril_client +++ b/mithril_client @@ -1 +1 @@ -Subproject commit 21d4a0a5e9a19f251e26c0ae07ce74be2fa99bbf +Subproject commit a04d4769974b9d93ba72e490ed7dca3fbaed768c From db8c6947232eeb4d853a79ea5f605a2a1dde0c08 Mon Sep 17 00:00:00 2001 From: Dario Date: Wed, 9 Sep 2020 19:34:00 +0200 Subject: [PATCH 029/293] updates for hedera transactions and saving crypto keys also clear un-encrypted --- skeema/gradido_login/hedera_topics.sql | 1 + src/cpp/Crypto/KeyPairHedera.cpp | 42 ++-- src/cpp/Crypto/KeyPairHedera.h | 8 +- .../HTTPInterface/AdminHederaAccountPage.cpp | 5 +- src/cpp/HTTPInterface/AdminTopicPage.cpp | 180 ++++++++++++++---- src/cpp/controller/CryptoKey.cpp | 62 ++++-- src/cpp/controller/CryptoKey.h | 6 +- src/cpp/controller/HederaAccount.cpp | 12 +- src/cpp/controller/HederaAccount.h | 4 +- src/cpp/controller/HederaRequest.cpp | 12 ++ src/cpp/controller/HederaRequest.h | 1 + src/cpp/controller/HederaTopic.cpp | 26 +++ src/cpp/controller/HederaTopic.h | 38 ++++ src/cpp/main.cpp | 16 +- src/cpp/model/hedera/ConsensusCreateTopic.cpp | 45 +++++ src/cpp/model/hedera/ConsensusCreateTopic.h | 31 +++ .../model/hedera/CryptoCreateTransaction.cpp | 16 ++ .../model/hedera/CryptoCreateTransaction.h | 23 +++ src/cpp/model/hedera/Query.cpp | 6 +- src/cpp/model/hedera/Query.h | 7 +- src/cpp/model/hedera/Transaction.cpp | 1 + src/cpp/model/hedera/Transaction.h | 3 +- src/cpp/model/hedera/TransactionBody.cpp | 15 ++ src/cpp/model/hedera/TransactionBody.h | 9 +- src/cpp/model/table/CryptoKey.cpp | 25 ++- src/cpp/model/table/CryptoKey.h | 12 +- src/cpp/model/table/HederaAccount.cpp | 1 + src/cpp/model/table/HederaAccount.h | 1 + src/cpp/model/table/HederaTopic.cpp | 17 +- src/cpp/model/table/HederaTopic.h | 14 ++ src/cpsp/adminHederaAccount.cpsp | 5 +- src/cpsp/adminTopic.cpsp | 112 ++++++++++- 32 files changed, 651 insertions(+), 105 deletions(-) create mode 100644 src/cpp/controller/HederaTopic.cpp create mode 100644 src/cpp/controller/HederaTopic.h create mode 100644 src/cpp/model/hedera/CryptoCreateTransaction.cpp create mode 100644 src/cpp/model/hedera/CryptoCreateTransaction.h diff --git a/skeema/gradido_login/hedera_topics.sql b/skeema/gradido_login/hedera_topics.sql index 02f7e3b39..b9adaefc2 100644 --- a/skeema/gradido_login/hedera_topics.sql +++ b/skeema/gradido_login/hedera_topics.sql @@ -1,6 +1,7 @@ CREATE TABLE `hedera_topics` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `topic_hedera_id` int unsigned NOT NULL, + `name` VARCHAR(255) NOT NULL DEFAULT '', `auto_renew_account_hedera_id` int unsigned DEFAULT NULL, `auto_renew_period` int unsigned NOT NULL DEFAULT '0', `group_id` int unsigned NOT NULL, diff --git a/src/cpp/Crypto/KeyPairHedera.cpp b/src/cpp/Crypto/KeyPairHedera.cpp index 27d9731a7..62643cc99 100644 --- a/src/cpp/Crypto/KeyPairHedera.cpp +++ b/src/cpp/Crypto/KeyPairHedera.cpp @@ -10,7 +10,7 @@ KeyPairHedera::KeyPairHedera() } -KeyPairHedera::KeyPairHedera(const MemoryBin* privateKey, const unsigned char* publicKey/* = nullptr*/, size_t publicKeySize/* = 0*/) +KeyPairHedera::KeyPairHedera(const unsigned char* privateKey, size_t privateKeySize, const unsigned char* publicKey/* = nullptr*/, size_t publicKeySize/* = 0*/) : mPrivateKey(nullptr) { auto derPrefixPriv = DataTypeConverter::hexToBin("302e020100300506032b657004220420"); @@ -19,27 +19,28 @@ KeyPairHedera::KeyPairHedera(const MemoryBin* privateKey, const unsigned char* p auto mm = MemoryManager::getInstance(); if (privateKey) { - switch (privateKey->size()) { + switch (privateKeySize) { case 48: // key with prefix - if (0 == sodium_memcmp(*privateKey, *derPrefixPriv, derPrefixPriv->size())) { + if (0 == sodium_memcmp(privateKey, *derPrefixPriv, derPrefixPriv->size())) { //int crypto_sign_seed_keypair(unsigned char *pk, unsigned char *sk, const unsigned char *seed); auto seed = mm->getFreeMemory(crypto_sign_ed25519_SEEDBYTES); - memcpy(*seed, privateKey->data(derPrefixPriv->size()), crypto_sign_ed25519_SEEDBYTES); - createKeyFromSeed(seed); + memcpy(*seed, &privateKey[derPrefixPriv->size()], crypto_sign_ed25519_SEEDBYTES); + createKeyFromSeed(seed->data(), seed->size()); + mm->releaseMemory(seed); break; } case 32: - createKeyFromSeed(privateKey); + createKeyFromSeed(privateKey, privateKeySize); break; case 64: //mPrivateKey = privateKey; - if (!mPrivateKey || mPrivateKey->size() != privateKey->size()) { + if (!mPrivateKey || mPrivateKey->size() != privateKeySize) { if (mPrivateKey) { mm->releaseMemory(mPrivateKey); } - mPrivateKey = mm->getFreeMemory(privateKey->size()); - memcpy(*mPrivateKey, *privateKey, privateKey->size()); + mPrivateKey = mm->getFreeMemory(privateKeySize); + memcpy(*mPrivateKey, privateKey, privateKeySize); } break; default: @@ -75,11 +76,17 @@ KeyPairHedera::KeyPairHedera(const MemoryBin* privateKey, const unsigned char* p mm->releaseMemory(derPrefixPub); } KeyPairHedera::KeyPairHedera(const MemoryBin* privateKey, const MemoryBin* publicKey /* = nullptr*/) - : KeyPairHedera(privateKey, publicKey->data(), publicKey->size()) + : KeyPairHedera(privateKey->data(), privateKey->size(), publicKey->data(), publicKey->size()) { } +KeyPairHedera::KeyPairHedera(const std::vector& privateKey, const unsigned char* publicKey/* = nullptr*/, size_t publicKeySize/* = 0*/) + : KeyPairHedera(privateKey.data(), privateKey.size(), publicKey, publicKeySize) +{ + +} + KeyPairHedera::~KeyPairHedera() { auto mm = MemoryManager::getInstance(); @@ -90,13 +97,13 @@ KeyPairHedera::~KeyPairHedera() } -void KeyPairHedera::createKeyFromSeed(const MemoryBin* seed) +void KeyPairHedera::createKeyFromSeed(const unsigned char* seed, size_t seedSize) { - assert(seed && seed->size() == crypto_sign_ed25519_SEEDBYTES); + assert(seed && seedSize == crypto_sign_ed25519_SEEDBYTES); auto mm = MemoryManager::getInstance(); auto secret_key = mm->getFreeMemory(crypto_sign_SECRETKEYBYTES); - crypto_sign_seed_keypair(mPublicKey, *secret_key, *seed); + crypto_sign_seed_keypair(mPublicKey, *secret_key, seed); if (mPrivateKey) { mm->releaseMemory(mPrivateKey); @@ -177,6 +184,15 @@ MemoryBin* KeyPairHedera::getCryptedPrivKey(const Poco::AutoPtrgetFreeMemory(mPrivateKey->size()); + memcpy(*private_key_copy, *mPrivateKey, mPrivateKey->size()); + return private_key_copy; +} + MemoryBin* KeyPairHedera::getPublicKeyCopy() const { auto mm = MemoryManager::getInstance(); diff --git a/src/cpp/Crypto/KeyPairHedera.h b/src/cpp/Crypto/KeyPairHedera.h index a3e4337e5..b308cbe9e 100644 --- a/src/cpp/Crypto/KeyPairHedera.h +++ b/src/cpp/Crypto/KeyPairHedera.h @@ -22,8 +22,9 @@ public: //! \param privateKey: copy //! \param publicKey: copy //! - KeyPairHedera(const MemoryBin* privateKey, const unsigned char* publicKey = nullptr, size_t publicKeySize = 0); + KeyPairHedera(const unsigned char* privateKey, size_t privateKeySize, const unsigned char* publicKey = nullptr, size_t publicKeySize = 0); KeyPairHedera(const MemoryBin* privateKey, const MemoryBin* publicKey = nullptr); + KeyPairHedera(const std::vector& privateKey, const unsigned char* publicKey = nullptr, size_t publicKeySize = 0); ~KeyPairHedera(); @@ -64,13 +65,14 @@ public: inline bool hasPrivateKey() const { return mPrivateKey != nullptr; } - //! \brief only way to get a private key.. encrypted + //! \brief MemoryBin* getCryptedPrivKey(const Poco::AutoPtr password) const; + MemoryBin* getPrivateKeyCopy() const; protected: KeyPairHedera(); - void createKeyFromSeed(const MemoryBin* seed); + void createKeyFromSeed(const unsigned char* seed, size_t seedSize); private: diff --git a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp index fa99a7b35..54a416bef 100644 --- a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp +++ b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp @@ -70,7 +70,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request addError(new Error("Action Update Balance", "hedera id not found")); } else { hedera_time.reset(); - hedera_account[0]->updateBalanceFromHedera(user, this); + hedera_account[0]->hederaAccountGetBalance(user, this); addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string())); } } @@ -318,7 +318,8 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request #line 206 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( gettext("Add Account") ); responseStream << "\">\n"; - responseStream << "\t\n"; + responseStream << "\t\t\n"; + responseStream << "\t
    \n"; responseStream << "
    \n"; // begin include footer.cpsp responseStream << "
    \n"; diff --git a/src/cpp/HTTPInterface/AdminTopicPage.cpp b/src/cpp/HTTPInterface/AdminTopicPage.cpp index d8926093e..66fb252d7 100644 --- a/src/cpp/HTTPInterface/AdminTopicPage.cpp +++ b/src/cpp/HTTPInterface/AdminTopicPage.cpp @@ -7,8 +7,10 @@ #line 7 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminTopic.cpsp" - -#line 1 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + #include "../controller/HederaAccount.h" + #include "../controller/Group.h" + #include "../ServerConfig.h" +#line 1 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp" #include "../ServerConfig.h" @@ -27,20 +29,34 @@ void AdminTopicPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco:: if (_compressResponse) response.set("Content-Encoding", "gzip"); Poco::Net::HTMLForm form(request, request.stream()); -#line 10 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminTopic.cpsp" +#line 12 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminTopic.cpsp" const char* pageName = "Topic"; + auto user = mSession->getNewUser(); + + int auto_renew_period = 604800; // 7 Tage + int auto_renew_account = 0; + int group_id = 0; + + auto hedera_accounts = controller::HederaAccount::load("user_id", user->getModel()->getID()); + + auto groups = controller::Group::listAll(); + std::map group_indices; + int count = 0; + for(auto it = groups.begin(); it != groups.end(); it++) { + group_indices.insert(std::pair((*it)->getModel()->getID(), count)); + count++; + } - -#line 3 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" +#line 3 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp" bool withMaterialIcons = false; std::ostream& _responseStream = response.send(); Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1); std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream; responseStream << "\n"; - // begin include header_large.cpsp + // begin include header.cpsp responseStream << "\n"; responseStream << "\n"; responseStream << "\n"; @@ -48,57 +64,132 @@ void AdminTopicPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco:: responseStream << "\n"; responseStream << "\n"; responseStream << "Gradido Login Server: "; -#line 11 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" +#line 11 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp" responseStream << ( pageName ); responseStream << "\n"; responseStream << "\n"; -#line 13 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" +#line 13 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp" if(withMaterialIcons) { responseStream << "\n"; responseStream << "\n"; -#line 15 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" +#line 15 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp" } responseStream << "\n"; responseStream << "\n"; responseStream << "\n"; responseStream << "
    \n"; - responseStream << "\t\t
    \n"; - responseStream << "\t\t\t
    \n"; - responseStream << "\t\t\t\t\n"; - responseStream << "\t\t\t
    \n"; - responseStream << "\t\t
    \n"; - responseStream << "\t\t
    "; - // end include header_large.cpsp + responseStream << "
    \n"; + responseStream << " "; + // end include header.cpsp responseStream << "\n"; -#line 16 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminTopic.cpsp" + responseStream << "\n"; +#line 40 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminTopic.cpsp" responseStream << ( getErrorsHtml() ); responseStream << "\n"; responseStream << "
    \n"; responseStream << "\t

    Topic Admin Page

    \n"; responseStream << "
    \n"; - responseStream << "
    \n"; - responseStream << "\t\n"; + responseStream << "
    \n"; + responseStream << "\t
    \n"; + responseStream << "\t

    Ein neues Topic anlegen

    \n"; + responseStream << "\t
    \n"; + responseStream << "\t
    \n"; + responseStream << "\t\t
    \n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t
    \n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\n"; + responseStream << "\t
    \n"; responseStream << "
    \n"; // begin include footer.cpsp responseStream << "
    \n"; @@ -124,5 +215,18 @@ void AdminTopicPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco:: responseStream << ""; // end include footer.cpsp responseStream << "\n"; + responseStream << "\n"; + responseStream << ""; if (_compressResponse) _gzipStream.close(); } diff --git a/src/cpp/controller/CryptoKey.cpp b/src/cpp/controller/CryptoKey.cpp index 79d68a62e..aa8df1b8d 100644 --- a/src/cpp/controller/CryptoKey.cpp +++ b/src/cpp/controller/CryptoKey.cpp @@ -15,16 +15,25 @@ namespace controller { } - Poco::AutoPtr CryptoKey::create(const KeyPairHedera* hederaKeyPair, Poco::AutoPtr user) + Poco::AutoPtr CryptoKey::create(const KeyPairHedera* hederaKeyPair, Poco::AutoPtr user, bool saveEncrypted/* = true*/) { auto mm = MemoryManager::getInstance(); - auto encrypted_priv_key = hederaKeyPair->getCryptedPrivKey(user->getPassword()); + MemoryBin* private_key = nullptr; auto public_key = hederaKeyPair->getPublicKeyCopy(); - auto db = new model::table::CryptoKey(encrypted_priv_key, public_key, model::table::KEY_TYPE_ED25519_HEDERA); + model::table::KeyType key_type; + if (saveEncrypted) { + key_type = model::table::KEY_TYPE_ED25519_HEDERA_ENCRYPTED; + private_key = hederaKeyPair->getCryptedPrivKey(user->getPassword()); + } + else { + key_type = model::table::KEY_TYPE_ED25519_HEDERA_CLEAR; + private_key = hederaKeyPair->getPrivateKeyCopy(); + } + auto db = new model::table::CryptoKey(private_key, public_key, key_type); - mm->releaseMemory(encrypted_priv_key); + mm->releaseMemory(private_key); mm->releaseMemory(public_key); auto cryptoKey = new CryptoKey(db); @@ -63,28 +72,49 @@ namespace controller { return nullptr; } - std::unique_ptr CryptoKey::getKeyPair(Poco::AutoPtr user) + std::unique_ptr CryptoKey::getKeyPair(Poco::AutoPtr user) const { auto model = getModel(); - auto password = user->getPassword(); - auto mm = MemoryManager::getInstance(); - if (!password || !model->hasPrivateKeyEncrypted()) { - printf("[CryptoKey::getKeyPair] return null, password empty or no private key\n"); + assert(model); + + if (!model->isEncrypted()) { + return getKeyPair(); + } + + if (!model->hasPrivateKey()) { + printf("[CryptoKey::getKeyPair] return null, no private key\n"); return nullptr; } - MemoryBin* clearPassword = nullptr; - auto encrypted_private_key = model->getPrivateKeyEncrypted(); - auto encrypted_private_key_hex_string = DataTypeConverter::binToHex(encrypted_private_key); - printf("[CryptoKey::getKeyPair] encrypted private key hex: %s\n", encrypted_private_key_hex_string.data()); - if (password->decrypt(model->getPrivateKeyEncrypted(), &clearPassword) != SecretKeyCryptography::AUTH_DECRYPT_OK) { + + auto password = user->getPassword(); + auto mm = MemoryManager::getInstance(); + if (!password) { + printf("[CryptoKey::getKeyPair] return null, password empty\n"); + } + MemoryBin* clearPrivateKey = nullptr; + auto encrypted_private_key = model->getPrivateKey(); + //auto encrypted_private_key_hex_string = DataTypeConverter::binToHex(encrypted_private_key); + //printf("[CryptoKey::getKeyPair] encrypted private key hex: %s\n", encrypted_private_key_hex_string.data()); + if (password->decrypt(model->getPrivateKey(), &clearPrivateKey) != SecretKeyCryptography::AUTH_DECRYPT_OK) { printf("[CryptoKey::getKeyPair] return null, error decrypting\n"); return nullptr; } - auto key_pair = std::make_unique(clearPassword, model->getPublicKey(), model->getPublicKeySize()); - mm->releaseMemory(clearPassword); + auto key_pair = std::make_unique(clearPrivateKey->data(), clearPrivateKey->size(), model->getPublicKey(), model->getPublicKeySize()); + mm->releaseMemory(clearPrivateKey); return key_pair; } + std::unique_ptr CryptoKey::getKeyPair() const + { + auto model = getModel(); + assert(model); + if (!model->hasPrivateKey() || model->isEncrypted()) { + printf("[CryptoKey::getKeyPair] no private key or encrypted\n"); + return nullptr; + } + + return std::make_unique(model->getPrivateKey(), model->getPublicKey(), model->getPublicKeySize()); + } } diff --git a/src/cpp/controller/CryptoKey.h b/src/cpp/controller/CryptoKey.h index fc69d042c..ef48c88f1 100644 --- a/src/cpp/controller/CryptoKey.h +++ b/src/cpp/controller/CryptoKey.h @@ -16,7 +16,7 @@ namespace controller { ~CryptoKey(); - static Poco::AutoPtr create(const KeyPairHedera* hederaKeyPair, Poco::AutoPtr user); + static Poco::AutoPtr create(const KeyPairHedera* hederaKeyPair, Poco::AutoPtr user, bool saveEncrypted = true); //! if returned ptr is NULL, dataset not found static Poco::AutoPtr load(int id); @@ -26,8 +26,10 @@ namespace controller { inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } inline Poco::AutoPtr getModel() { return _getModel(); } + inline const model::table::CryptoKey* getModel() const { return _getModel(); } - std::unique_ptr getKeyPair(Poco::AutoPtr user); + std::unique_ptr getKeyPair(Poco::AutoPtr user) const; + std::unique_ptr getKeyPair() const; protected: diff --git a/src/cpp/controller/HederaAccount.cpp b/src/cpp/controller/HederaAccount.cpp index 6fabe2848..e4873ecf0 100644 --- a/src/cpp/controller/HederaAccount.cpp +++ b/src/cpp/controller/HederaAccount.cpp @@ -73,7 +73,7 @@ namespace controller { return resultVector; } - bool HederaAccount::updateBalanceFromHedera(Poco::AutoPtr user, NotificationList* errorReceiver/* = nullptr*/) + bool HederaAccount::hederaAccountGetBalance(Poco::AutoPtr user, NotificationList* errorReceiver/* = nullptr*/) { static const char* functionName = "HederaAccount::updateBalanceFromHedera"; @@ -132,5 +132,15 @@ namespace controller { return false; } + + std::string HederaAccount::toShortSelectOptionName() + { + std::stringstream ss; + auto model = getModel(); + ss << model::table::HederaAccount::hederaNetworkTypeToString((model::table::HederaNetworkType)model->getNetworkType()) << " "; + ss << mHederaID->getModel()->toString() << " " << ((double)model->getBalance() / 100000000.0) << " Hbar"; + return ss.str(); + } + } diff --git a/src/cpp/controller/HederaAccount.h b/src/cpp/controller/HederaAccount.h index d76420b78..a9a53d528 100644 --- a/src/cpp/controller/HederaAccount.h +++ b/src/cpp/controller/HederaAccount.h @@ -22,12 +22,14 @@ namespace controller { inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } + std::string HederaAccount::toShortSelectOptionName(); + inline Poco::AutoPtr getModel() { return _getModel(); } inline void setHederaId(Poco::AutoPtr hederaId) { mHederaID = hederaId; } inline Poco::AutoPtr getHederaId() { return mHederaID; } - bool updateBalanceFromHedera(Poco::AutoPtr user, NotificationList* errorReceiver = nullptr); + bool hederaAccountGetBalance(Poco::AutoPtr user, NotificationList* errorReceiver = nullptr); protected: HederaAccount(model::table::HederaAccount* dbModel); diff --git a/src/cpp/controller/HederaRequest.cpp b/src/cpp/controller/HederaRequest.cpp index 308ffa5e8..64998fa6a 100644 --- a/src/cpp/controller/HederaRequest.cpp +++ b/src/cpp/controller/HederaRequest.cpp @@ -59,6 +59,18 @@ HederaRequestReturn HederaRequest::request(model::hedera::Query* query, model::h return HEDERA_REQUEST_RETURN_OK; } +HederaRequestReturn HederaRequest::request(model::hedera::Transaction* transaction, model::hedera::Response* response) +{ + auto channel = grpc::CreateChannel(transaction->getConnectionString(), grpc::InsecureChannelCredentials()); + + grpc::ClientContext context; + std::chrono::system_clock::time_point deadline = std::chrono::system_clock::now() + + std::chrono::milliseconds(5000); + context.set_deadline(deadline); + + return HEDERA_REQUEST_RETURN_OK; +} + #include "Poco/JSON/Object.h" #include "../lib/JsonRequest.h" diff --git a/src/cpp/controller/HederaRequest.h b/src/cpp/controller/HederaRequest.h index 327ee7634..34bd304a1 100644 --- a/src/cpp/controller/HederaRequest.h +++ b/src/cpp/controller/HederaRequest.h @@ -31,6 +31,7 @@ public: ~HederaRequest(); HederaRequestReturn request(model::hedera::Query* query, model::hedera::Response* response, Poco::UInt64 fee = 0); + HederaRequestReturn request(model::hedera::Transaction* transaction, model::hedera::Response* response); //! for testing, didn't work server say invalid json :/ HederaRequestReturn requestViaPHPRelay(model::hedera::Query* query); diff --git a/src/cpp/controller/HederaTopic.cpp b/src/cpp/controller/HederaTopic.cpp new file mode 100644 index 000000000..3885c31d8 --- /dev/null +++ b/src/cpp/controller/HederaTopic.cpp @@ -0,0 +1,26 @@ +#include "HederaTopic.h" +#include "../model/hedera/Transaction.h" + +namespace controller { + HederaTopic::HederaTopic(model::table::HederaTopic* dbModel) + { + mDBModel = dbModel; + } + HederaTopic::~HederaTopic() + { + + } + + Poco::AutoPtr HederaTopic::create(const std::string& name, int autoRenewAccountId, int autoRenewPeriod, int groupId) + { + auto db = new model::table::HederaTopic(name, autoRenewAccountId, autoRenewPeriod, groupId); + + auto hedera_topic = new HederaTopic(db); + return Poco::AutoPtr(hedera_topic); + } + + Poco::UInt64 HederaTopic::hederaCreateTopic() + { + + } +} \ No newline at end of file diff --git a/src/cpp/controller/HederaTopic.h b/src/cpp/controller/HederaTopic.h new file mode 100644 index 000000000..de5552e39 --- /dev/null +++ b/src/cpp/controller/HederaTopic.h @@ -0,0 +1,38 @@ +#ifndef __GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_TOPIC_H +#define __GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_TOPIC_H + +/*! +* +* \author: Dario Rekowski +* +* \date: 03.09.2020 +* +* \brief: Class for Hedera Topic, connct db table with hedera object +* +*/ +#include "TableControllerBase.h" +#include "../model/table/HederaTopic.h" + +namespace controller { + class HederaTopic : public TableControllerBase + { + public: + + ~HederaTopic(); + + static Poco::AutoPtr create(const std::string& name, int autoRenewAccountId, int autoRenewPeriod, int groupId); + + //! \brief hedera call to create a hedera topic + Poco::UInt64 hederaCreateTopic(); + + inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } + + inline Poco::AutoPtr getModel() { return _getModel(); } + + + protected: + HederaTopic(model::table::HederaTopic* dbModel); + + }; + +#endif //__GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_TOPIC_H \ No newline at end of file diff --git a/src/cpp/main.cpp b/src/cpp/main.cpp index 910db09ff..899779fef 100644 --- a/src/cpp/main.cpp +++ b/src/cpp/main.cpp @@ -45,17 +45,25 @@ int main(int argc, char** argv) printf("[Gradido_LoginServer::main] error loading mnemonic Word List"); return -2; } + printf("[Gradido_LoginServer::main] mnemonic word lists loaded!\n"); if (!ImportantTests::passphraseGenerationAndTransformation()) { printf("test passphrase generation and transformation failed\n"); return -3; } + printf("[Gradido_LoginServer::main] passed important tests\n"); grpc_init(); Gradido_LoginServer app; - auto result = app.run(argc, argv); - - grpc_shutdown(); - return result; + try { + auto result = app.run(argc, argv); + grpc_shutdown(); + return result; + } + catch (Poco::Exception& ex) { + printf("[Gradido_LoginServer::main] exception by starting server: %s\n", ex.displayText().data()); + } + return -1; + } #endif \ No newline at end of file diff --git a/src/cpp/model/hedera/ConsensusCreateTopic.cpp b/src/cpp/model/hedera/ConsensusCreateTopic.cpp index e69de29bb..6ca423102 100644 --- a/src/cpp/model/hedera/ConsensusCreateTopic.cpp +++ b/src/cpp/model/hedera/ConsensusCreateTopic.cpp @@ -0,0 +1,45 @@ +#include "ConsensusCreateTopic.h" + +namespace model { + namespace hedera { + ConsensusCreateTopic::ConsensusCreateTopic(Poco::AutoPtr autoRenewHederaAccountId, Poco::UInt32 autoRenewPeriod) + : mProtoCreateTopic(nullptr) + { + mProtoCreateTopic = new proto::ConsensusCreateTopicTransactionBody; + auto auto_renew_period = mProtoCreateTopic->mutable_autorenewperiod(); + auto_renew_period->set_seconds(autoRenewPeriod); + + auto auto_renew_account = mProtoCreateTopic->mutable_autorenewaccount(); + autoRenewHederaAccountId->copyToProtoAccountId(auto_renew_account); + + } + ConsensusCreateTopic::~ConsensusCreateTopic() + { + if (mProtoCreateTopic) { + delete mProtoCreateTopic; + mProtoCreateTopic = nullptr; + } + } + + void ConsensusCreateTopic::setAdminKey(const MemoryBin* adminPublicKey) + { + auto admin_key = mProtoCreateTopic->mutable_adminkey(); + auto admin_key_string = admin_key->mutable_ed25519(); + *admin_key_string = std::string((const char)*adminPublicKey, adminPublicKey->size()); + } + void ConsensusCreateTopic::setSubmitKey(const MemoryBin* submitPublicKey) + { + auto submit_key = mProtoCreateTopic->mutable_submitkey(); + auto submit_key_string = submit_key->mutable_ed25519(); + *submit_key_string = std::string((const char)*submitPublicKey, submitPublicKey->size()); + } + + bool ConsensusCreateTopic::validate() + { + if (mProtoCreateTopic->autorenewperiod().seconds() > 86400 && 0 != mProtoCreateTopic->autorenewaccount().accountnum()) { + return true; + } + return false; + } + } +} \ No newline at end of file diff --git a/src/cpp/model/hedera/ConsensusCreateTopic.h b/src/cpp/model/hedera/ConsensusCreateTopic.h index e69de29bb..e61da46f3 100644 --- a/src/cpp/model/hedera/ConsensusCreateTopic.h +++ b/src/cpp/model/hedera/ConsensusCreateTopic.h @@ -0,0 +1,31 @@ +#ifndef __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_CREATE_TOPIC_H +#define __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_CREATE_TOPIC_H + +#include "../../proto/hedera/ConsensusCreateTopic.pb.h" +#include "../../SingletonManager/MemoryManager.h" + +#include "../../controller/HederaId.h" + +namespace model { + namespace hedera { + class ConsensusCreateTopic + { + public: + ConsensusCreateTopic(Poco::AutoPtr autoRenewHederaAccountId, Poco::UInt32 autoRenewPeriod); + ~ConsensusCreateTopic(); + + inline void setMemo(const std::string& memo) { mProtoCreateTopic->set_memo(memo); } + void setAdminKey(const MemoryBin* adminPublicKey); + void setSubmitKey(const MemoryBin* submitPublicKey); + + bool validate(); + + inline proto::ConsensusCreateTopicTransactionBody* getProtoTransactionBody() { return mProtoCreateTopic; } + inline void resetPointer() { mProtoCreateTopic = nullptr; } + protected: + proto::ConsensusCreateTopicTransactionBody* mProtoCreateTopic; + }; + } +} + +#endif //__GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_CREATE_TOPIC_H \ No newline at end of file diff --git a/src/cpp/model/hedera/CryptoCreateTransaction.cpp b/src/cpp/model/hedera/CryptoCreateTransaction.cpp new file mode 100644 index 000000000..696a8d6e7 --- /dev/null +++ b/src/cpp/model/hedera/CryptoCreateTransaction.cpp @@ -0,0 +1,16 @@ +#include "CryptoCreateTransaction.h" + +namespace model { + namespace hedera { + + CryptoCreateTransaction::CryptoCreateTransaction() + { + } + + CryptoCreateTransaction::~CryptoCreateTransaction() + { + + } + + } +} \ No newline at end of file diff --git a/src/cpp/model/hedera/CryptoCreateTransaction.h b/src/cpp/model/hedera/CryptoCreateTransaction.h new file mode 100644 index 000000000..e1425ebf5 --- /dev/null +++ b/src/cpp/model/hedera/CryptoCreateTransaction.h @@ -0,0 +1,23 @@ +#ifndef __GRADIDO_LOGIN_MODEL_HEDERA_CRYPTO_CREATE_TRANSACTION_H +#define __GRADIDO_LOGIN_MODEL_HEDERA_CRYPTO_CREATE_TRANSACTION_H + +#include "../../proto/hedera/CryptoCreate.pb.h" + +namespace model { + namespace hedera { + + class CryptoCreateTransaction + { + public: + CryptoCreateTransaction(); + ~CryptoCreateTransaction(); + + protected: + proto::CryptoCreateTransactionBody* mCryptoCreateBody; + }; + } +} + + + +#endif //__GRADIDO_LOGIN_MODEL_HEDERA_CRYPTO_CREATE_TRANSACTION_H \ No newline at end of file diff --git a/src/cpp/model/hedera/Query.cpp b/src/cpp/model/hedera/Query.cpp index de4fdec99..11a8eb735 100644 --- a/src/cpp/model/hedera/Query.cpp +++ b/src/cpp/model/hedera/Query.cpp @@ -9,8 +9,8 @@ namespace model { namespace hedera { - Query::Query(const controller::NodeServerConnection& connection) - : mConnection(connection), mTransactionBody(nullptr) + Query::Query() + : mTransactionBody(nullptr) { } @@ -27,7 +27,7 @@ namespace model { assert(!accountId.isNull() && accountId->getModel()); - auto query = new Query(connection); + auto query = new Query; auto get_account_balance = query->mQueryProto.mutable_cryptogetaccountbalance(); accountId->copyToProtoAccountId(get_account_balance->mutable_accountid()); auto query_header = get_account_balance->mutable_header(); diff --git a/src/cpp/model/hedera/Query.h b/src/cpp/model/hedera/Query.h index fa9b06471..376528314 100644 --- a/src/cpp/model/hedera/Query.h +++ b/src/cpp/model/hedera/Query.h @@ -26,15 +26,14 @@ namespace model { void setResponseType(proto::ResponseType type); proto::ResponseType getResponseType(); - void setFee(Poco::UInt64 fee); + inline const proto::Query* getProtoQuery() const { return &mQueryProto; } - inline std::string getConnectionString() const { return mConnection.getUriWithPort(); } + inline std::string getConnectionString() const { return mTransactionBody->getConnectionString(); } protected: - Query(const controller::NodeServerConnection& connection); + Query(); proto::Query mQueryProto; TransactionBody* mTransactionBody; - controller::NodeServerConnection mConnection; }; } } diff --git a/src/cpp/model/hedera/Transaction.cpp b/src/cpp/model/hedera/Transaction.cpp index 0dadbcb4c..4699e71ea 100644 --- a/src/cpp/model/hedera/Transaction.cpp +++ b/src/cpp/model/hedera/Transaction.cpp @@ -19,6 +19,7 @@ namespace model { bool Transaction::sign(std::unique_ptr keyPairHedera, const TransactionBody* transactionBody) { auto mm = MemoryManager::getInstance(); + mConnection = transactionBody->getConnection(); auto transaction_body_proto = transactionBody->getProtoTransactionBody(); auto body_bytes = transaction_body_proto->SerializeAsString(); mTransaction->set_bodybytes(body_bytes.data()); diff --git a/src/cpp/model/hedera/Transaction.h b/src/cpp/model/hedera/Transaction.h index 3acf46ff9..d5e9434bd 100644 --- a/src/cpp/model/hedera/Transaction.h +++ b/src/cpp/model/hedera/Transaction.h @@ -25,11 +25,12 @@ namespace model { bool sign(std::unique_ptr keyPairHedera, const TransactionBody* transactionBody); inline proto::Transaction* getTransaction() { return mTransaction; } + inline std::string getConnectionString() const { return mConnection.getUriWithPort(); } void resetPointer() { mTransaction = nullptr; } protected: - proto::Transaction* mTransaction; + controller::NodeServerConnection mConnection; }; } } diff --git a/src/cpp/model/hedera/TransactionBody.cpp b/src/cpp/model/hedera/TransactionBody.cpp index f1979b6bf..f215ada23 100644 --- a/src/cpp/model/hedera/TransactionBody.cpp +++ b/src/cpp/model/hedera/TransactionBody.cpp @@ -3,6 +3,7 @@ namespace model { namespace hedera { TransactionBody::TransactionBody(Poco::AutoPtr operatorAccountId, const controller::NodeServerConnection& connection) + : mConnection(connection) { connection.hederaId->copyToProtoAccountId(mTransactionBody.mutable_nodeaccountid()); auto transaction_id = mTransactionBody.mutable_transactionid(); @@ -29,10 +30,24 @@ namespace model { return false; } + bool TransactionBody::setCreateTopic(ConsensusCreateTopic& consensusCreateTopicTransaction) + { + if (consensusCreateTopicTransaction.validate()) { + mTransactionBody.set_allocated_consensuscreatetopic(consensusCreateTopicTransaction.getProtoTransactionBody()); + consensusCreateTopicTransaction.resetPointer(); + return true; + } + return false; + } + void TransactionBody::setMemo(const std::string& memo) { mTransactionBody.set_memo(memo); } + void TransactionBody::setFee(Poco::UInt64 fee) + { + mTransactionBody.set_transactionfee(fee); + } void TransactionBody::updateTimestamp() { diff --git a/src/cpp/model/hedera/TransactionBody.h b/src/cpp/model/hedera/TransactionBody.h index 3663c4a59..ba421e014 100644 --- a/src/cpp/model/hedera/TransactionBody.h +++ b/src/cpp/model/hedera/TransactionBody.h @@ -13,6 +13,7 @@ #include "../../proto/hedera/TransactionBody.pb.h" #include "../../controller/NodeServer.h" #include "CryptoTransferTransaction.h" +#include "ConsensusCreateTopic.h" namespace model { namespace hedera { @@ -23,14 +24,20 @@ namespace model { ~TransactionBody(); void setMemo(const std::string& memo); - + void setFee(Poco::UInt64 fee); + bool setCryptoTransfer(CryptoTransferTransaction& cryptoTransferTransaction); + bool setCreateTopic(ConsensusCreateTopic& consensusCreateTopicTransaction); + //bool inline const proto::TransactionBody* getProtoTransactionBody() const { return &mTransactionBody; } + inline std::string getConnectionString() const { return mConnection.getUriWithPort(); } + inline controller::NodeServerConnection getConnection() const { return mConnection; } protected: void updateTimestamp(); proto::TransactionBody mTransactionBody; + controller::NodeServerConnection mConnection; }; } } diff --git a/src/cpp/model/table/CryptoKey.cpp b/src/cpp/model/table/CryptoKey.cpp index 9588f57e7..a4f1034e3 100644 --- a/src/cpp/model/table/CryptoKey.cpp +++ b/src/cpp/model/table/CryptoKey.cpp @@ -43,12 +43,33 @@ namespace model { const char* CryptoKey::typeToString(KeyType type) { switch (type) { - case KEY_TYPE_ED25519_SODIUM: return "ed25519 ref10"; - case KEY_TYPE_ED25519_HEDERA: return "sodium ed22519"; + case KEY_TYPE_ED25519_SODIUM_ENCRYPTED: return "ed25519 sodium encrypted"; + case KEY_TYPE_ED25519_HEDERA_ENCRYPTED: return "ed22519 for hedera encrypted"; + case KEY_TYPE_ED25519_SODIUM_CLEAR: return "ed25519 sodium clear"; + case KEY_TYPE_ED25519_HEDERA_CLEAR: return "ed25519 hedera clear"; } return ""; } + bool CryptoKey::hasPrivateKeyEncrypted() const + { + const KeyType type = (KeyType)(mKeyType); + if (type == KEY_TYPE_ED25519_HEDERA_ENCRYPTED || type == KEY_TYPE_ED25519_SODIUM_ENCRYPTED) { + return !mPrivateKey.isNull(); + } + return false; + } + + bool CryptoKey::isEncrypted() const + { + const KeyType type = (KeyType)(mKeyType); + if (type == KEY_TYPE_ED25519_HEDERA_ENCRYPTED || + type == KEY_TYPE_ED25519_SODIUM_ENCRYPTED) { + return true; + } + return false; + } + Poco::Data::Statement CryptoKey::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) { Poco::Data::Statement select(session); diff --git a/src/cpp/model/table/CryptoKey.h b/src/cpp/model/table/CryptoKey.h index 7e50fc728..c1fa0b66d 100644 --- a/src/cpp/model/table/CryptoKey.h +++ b/src/cpp/model/table/CryptoKey.h @@ -8,8 +8,10 @@ namespace model { namespace table { enum KeyType { - KEY_TYPE_ED25519_SODIUM = 0, - KEY_TYPE_ED25519_HEDERA = 1, + KEY_TYPE_ED25519_SODIUM_ENCRYPTED = 0, + KEY_TYPE_ED25519_HEDERA_ENCRYPTED = 1, + KEY_TYPE_ED25519_SODIUM_CLEAR = 2, + KEY_TYPE_ED25519_HEDERA_CLEAR = 3, KEY_TYPE_COUNT }; @@ -27,8 +29,10 @@ namespace model { inline const unsigned char* getPublicKey() const { if (mPublicKey.isNull()) return nullptr; return mPublicKey.value().content().data(); } size_t getPublicKeySize() const { if (mPublicKey.isNull()) return 0; return mPublicKey.value().content().size(); } - inline bool hasPrivateKeyEncrypted() const { return !mPrivateKey.isNull(); } - inline const std::vector& getPrivateKeyEncrypted() const { return mPrivateKey.value().content(); } + bool hasPrivateKeyEncrypted() const; + bool isEncrypted() const; + inline bool hasPrivateKey() const { return !mPrivateKey.isNull(); } + inline const std::vector& getPrivateKey() const { return mPrivateKey.value().content(); } static const char* typeToString(KeyType type); protected: diff --git a/src/cpp/model/table/HederaAccount.cpp b/src/cpp/model/table/HederaAccount.cpp index 1485ff554..2479c09cc 100644 --- a/src/cpp/model/table/HederaAccount.cpp +++ b/src/cpp/model/table/HederaAccount.cpp @@ -44,6 +44,7 @@ namespace model { return ss.str(); } + const char* HederaAccount::hederaNetworkTypeToString(HederaNetworkType type) { switch (type) { diff --git a/src/cpp/model/table/HederaAccount.h b/src/cpp/model/table/HederaAccount.h index 4d4dd6575..6b0d636a0 100644 --- a/src/cpp/model/table/HederaAccount.h +++ b/src/cpp/model/table/HederaAccount.h @@ -28,6 +28,7 @@ namespace model { // generic db operations const char* getTableName() const { return "hedera_accounts"; } std::string toString(); + static const char* hederaNetworkTypeToString(HederaNetworkType type); static NodeServerType networkTypeToNodeServerType(HederaNetworkType type); diff --git a/src/cpp/model/table/HederaTopic.cpp b/src/cpp/model/table/HederaTopic.cpp index ef80ea071..b91ea0864 100644 --- a/src/cpp/model/table/HederaTopic.cpp +++ b/src/cpp/model/table/HederaTopic.cpp @@ -5,6 +5,14 @@ using namespace Poco::Data::Keywords; namespace model { namespace table { HederaTopic::HederaTopic() + : mTopicHederaId(0), mAutoRenewAccountHederaId(0), mAutoRenewPeriod(0), mGroupId(0), mAdminKeyId(0), mSubmitKeyId(0),mSequenceNumber(0) + { + + } + + HederaTopic::HederaTopic(const std::string& name, int autoRenewAccountId, int autoRenewPeriod, int groupId) + : mTopicHederaId(0), mName(name), mAutoRenewAccountHederaId(autoRenewAccountId), mAutoRenewPeriod(autoRenewAccountId), mGroupId(groupId), + mAdminKeyId(0), mSubmitKeyId(0), mSequenceNumber(0) { } @@ -18,6 +26,7 @@ namespace model { { std::stringstream ss; ss << "Topic Hedera id: " << std::to_string(mTopicHederaId) << std::endl; + ss << "Name: " << mName << std::endl; ss << "Auto Renew Account Hedera id: " << std::to_string(mAutoRenewAccountHederaId) << std::endl; ss << "Auto Renew Period: " << std::to_string(mAutoRenewPeriod) << " seconds" << std::endl; ss << "Group id: " << std::to_string(mGroupId) << std::endl; @@ -33,10 +42,10 @@ namespace model { { Poco::Data::Statement select(session); - select << "SELECT id, topic_hedera_id, auto_renew_account_hedera_id, auto_renew_period, " + select << "SELECT id, topic_hedera_id, name, auto_renew_account_hedera_id, auto_renew_period, " << "group_id, admin_key_id, submit_key_id, current_timeout, sequence_number, updated FROM " << getTableName() << " where " << fieldName << " = ?" - , into(mID), into(mTopicHederaId), into(mAutoRenewAccountHederaId), into(mAutoRenewPeriod) + , into(mID), into(mTopicHederaId), into(mName), into(mAutoRenewAccountHederaId), into(mAutoRenewPeriod) , into(mGroupId), into(mAdminKeyId), into(mSubmitKeyId), into(mCurrentTimeout), into(mSequenceNumber), into(mUpdated); return select; @@ -57,9 +66,9 @@ namespace model { Poco::Data::Statement insert(session); lock(); insert << "INSERT INTO " << getTableName() - << " (topic_hedera_id, auto_renew_account_hedera_id, auto_renew_period," + << " (topic_hedera_id, name, auto_renew_account_hedera_id, auto_renew_period," << " group_id, admin_key_id, submit_key_id, current_timeout, sequence_number) VALUES(?,?,?,?,?,?,?,?)" - , use(mTopicHederaId), use(mAutoRenewAccountHederaId), use(mAutoRenewPeriod) + , use(mTopicHederaId), use(mName), use(mAutoRenewAccountHederaId), use(mAutoRenewPeriod) , use(mGroupId), use(mAdminKeyId), use(mSubmitKeyId), use(mCurrentTimeout), use(mSequenceNumber), use(mUpdated); unlock(); return insert; diff --git a/src/cpp/model/table/HederaTopic.h b/src/cpp/model/table/HederaTopic.h index fe5cc342b..3c8cb6f16 100644 --- a/src/cpp/model/table/HederaTopic.h +++ b/src/cpp/model/table/HederaTopic.h @@ -10,12 +10,25 @@ namespace model { { public: HederaTopic(); + HederaTopic(const std::string& name, int autoRenewAccountId, int autoRenewPeriod, int groupId); ~HederaTopic(); // generic db operations const char* getTableName() const { return "hedera_topics"; } std::string toString(); + inline Poco::UInt32 getTopicHederaId() const { return mTopicHederaId; } + inline std::string getName() const { return mName; } + inline Poco::UInt32 getAutoRenewAccountId() const { return mAutoRenewAccountHederaId; } + inline Poco::UInt32 getAutoRenewPeriod() const { return mAutoRenewPeriod; } + inline Poco::UInt32 getGroupId() const { return mGroupId;} + inline Poco::DateTime getCurrentTimoout() const { return mCurrentTimeout; } + inline Poco::UInt64 getSequenceNumber() const { return mSequenceNumber; } + inline Poco::DateTime getUpdated() const { return mUpdated; } + + inline void setTopicHederaID(Poco::UInt32 topidHederaId) { mTopicHederaId = topidHederaId;} + inline void setSequeceNumber(Poco::UInt64 sequenceNumber) { mSequenceNumber = sequenceNumber; } + inline void setCurrentTimeout(Poco::DateTime currentTimeOut) { mCurrentTimeout = currentTimeOut; } protected: Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); @@ -23,6 +36,7 @@ namespace model { Poco::Data::Statement _insertIntoDB(Poco::Data::Session session); Poco::UInt32 mTopicHederaId; + std::string mName; Poco::UInt32 mAutoRenewAccountHederaId; // in seconds Poco::UInt32 mAutoRenewPeriod; diff --git a/src/cpsp/adminHederaAccount.cpsp b/src/cpsp/adminHederaAccount.cpsp index 3e8795d24..95d6992b7 100644 --- a/src/cpsp/adminHederaAccount.cpsp +++ b/src/cpsp/adminHederaAccount.cpsp @@ -49,7 +49,7 @@ addError(new Error("Action Update Balance", "hedera id not found")); } else { hedera_time.reset(); - hedera_account[0]->updateBalanceFromHedera(user, this); + hedera_account[0]->hederaAccountGetBalance(user, this); addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string())); } } @@ -204,6 +204,7 @@ <% } %> "> - + +
    <%@ include file="footer.cpsp" %> diff --git a/src/cpsp/adminTopic.cpsp b/src/cpsp/adminTopic.cpsp index 3eac5a976..ffef4ea18 100644 --- a/src/cpsp/adminTopic.cpsp +++ b/src/cpsp/adminTopic.cpsp @@ -5,19 +5,123 @@ <%@ page ctorArg="Session*" %> <%@ header include="SessionHTTPRequestHandler.h" %> <%! - + #include "../controller/HederaAccount.h" + #include "../controller/Group.h" + #include "../SingletonManager/SessionManager.h" + #include "../ServerConfig.h" + #include "../lib/DataTypeConverter.h" %> <%% const char* pageName = "Topic"; + auto user = mSession->getNewUser(); + auto sm = SessionManager::getInstance(); + + std::string name = ""; + int auto_renew_account = 0; + int auto_renew_period = 604800; // 7 Tage + + int group_id = 0; + if(!form.empty()) { + name = form.get("topic-name", ""); + auto auto_renew_account_string = form.get("topic-auto-renew-account", "0"); + auto auto_renew_period_string = form.get("topic-auto-renew-period", "604800"); + auto group_id_string = form.get("topic-group", "-1"); + + if(name != "" && !sm->isValid(name, VALIDATE_NAME)) { + addError(new Error("Topic", "Name not valid, at least 3 Character")); + } + + if(!sm->isValid(auto_renew_account_string, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Topic", "auto renew account id not an integer")); + } else { + if(DataTypeConverter::strToInt(auto_renew_account_string, auto_renew_account) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int convert error", "Error converting auto renew account id to int")); + } + } + + if(!sm->isValid(auto_renew_period_string, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Topic", "auto renew period not an integer")); + } else { + if(DataTypeConverter::strToInt(auto_renew_period_string, auto_renew_period) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int convert error", "Error converting auto renew period to int")); + } + } -%><%@ include file="header_large.cpsp" %> + if(!sm->isValid(group_id_string, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Topic", "group_id not an integer")); + } else { + if(DataTypeConverter::strToInt(group_id_string, group_id) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int convert error", "Error converting group_id to int")); + } + } + } + + + auto hedera_accounts = controller::HederaAccount::load("user_id", user->getModel()->getID()); + + auto groups = controller::Group::listAll(); + std::map group_indices; + int count = 0; + for(auto it = groups.begin(); it != groups.end(); it++) { + group_indices.insert(std::pair((*it)->getModel()->getID(), count)); + count++; + } + + +%><%@ include file="header.cpsp" %> + <%= getErrorsHtml() %>

    Topic Admin Page

    -
    - +
    +
    +

    Ein neues Topic anlegen

    +
    +
    +
    + + + + + +
    + + + + "> + +
    <%@ include file="footer.cpsp" %> + + \ No newline at end of file From 941d66fc6a89446b725c40b412f932b1571ae0b4 Mon Sep 17 00:00:00 2001 From: Dario Date: Thu, 10 Sep 2020 11:11:37 +0200 Subject: [PATCH 030/293] fix compile error (missing }) --- src/cpp/controller/HederaTopic.cpp | 4 ++-- src/cpp/controller/HederaTopic.h | 1 + src/cpp/model/hedera/ConsensusCreateTopic.cpp | 4 +++- src/cpp/model/hedera/ConsensusCreateTopic.h | 5 +++-- src/cpp/model/hedera/TransactionBody.h | 4 +++- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/cpp/controller/HederaTopic.cpp b/src/cpp/controller/HederaTopic.cpp index 3885c31d8..31d18a94c 100644 --- a/src/cpp/controller/HederaTopic.cpp +++ b/src/cpp/controller/HederaTopic.cpp @@ -1,5 +1,5 @@ #include "HederaTopic.h" -#include "../model/hedera/Transaction.h" +//#include "../model/hedera/Transaction.h" namespace controller { HederaTopic::HederaTopic(model::table::HederaTopic* dbModel) @@ -21,6 +21,6 @@ namespace controller { Poco::UInt64 HederaTopic::hederaCreateTopic() { - + return 0; } } \ No newline at end of file diff --git a/src/cpp/controller/HederaTopic.h b/src/cpp/controller/HederaTopic.h index de5552e39..4c2ebefb6 100644 --- a/src/cpp/controller/HederaTopic.h +++ b/src/cpp/controller/HederaTopic.h @@ -34,5 +34,6 @@ namespace controller { HederaTopic(model::table::HederaTopic* dbModel); }; +} #endif //__GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_TOPIC_H \ No newline at end of file diff --git a/src/cpp/model/hedera/ConsensusCreateTopic.cpp b/src/cpp/model/hedera/ConsensusCreateTopic.cpp index 6ca423102..a20985593 100644 --- a/src/cpp/model/hedera/ConsensusCreateTopic.cpp +++ b/src/cpp/model/hedera/ConsensusCreateTopic.cpp @@ -1,3 +1,5 @@ + + #include "ConsensusCreateTopic.h" namespace model { @@ -42,4 +44,4 @@ namespace model { return false; } } -} \ No newline at end of file +} diff --git a/src/cpp/model/hedera/ConsensusCreateTopic.h b/src/cpp/model/hedera/ConsensusCreateTopic.h index e61da46f3..b639ee305 100644 --- a/src/cpp/model/hedera/ConsensusCreateTopic.h +++ b/src/cpp/model/hedera/ConsensusCreateTopic.h @@ -1,10 +1,10 @@ #ifndef __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_CREATE_TOPIC_H #define __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_CREATE_TOPIC_H -#include "../../proto/hedera/ConsensusCreateTopic.pb.h" -#include "../../SingletonManager/MemoryManager.h" +#include "../../SingletonManager/MemoryManager.h" #include "../../controller/HederaId.h" +#include "../../proto/hedera/ConsensusCreateTopic.pb.h" namespace model { namespace hedera { @@ -28,4 +28,5 @@ namespace model { } } + #endif //__GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_CREATE_TOPIC_H \ No newline at end of file diff --git a/src/cpp/model/hedera/TransactionBody.h b/src/cpp/model/hedera/TransactionBody.h index ba421e014..7be8d2105 100644 --- a/src/cpp/model/hedera/TransactionBody.h +++ b/src/cpp/model/hedera/TransactionBody.h @@ -10,11 +10,13 @@ * */ -#include "../../proto/hedera/TransactionBody.pb.h" + #include "../../controller/NodeServer.h" #include "CryptoTransferTransaction.h" #include "ConsensusCreateTopic.h" +#include "../../proto/hedera/TransactionBody.pb.h" + namespace model { namespace hedera { class TransactionBody From eaf95f87e49a81cd239cb75266366d8a413940b4 Mon Sep 17 00:00:00 2001 From: Dario Date: Fri, 11 Sep 2020 12:29:06 +0200 Subject: [PATCH 031/293] change encryption state of crypto_keys --- skeema/gradido_login/crypto_keys.sql | 2 +- src/cpp/Crypto/KeyPairHedera.cpp | 1 + src/cpp/Crypto/KeyPairHedera.h | 3 + .../HTTPInterface/AdminHederaAccountPage.cpp | 139 ++++++++++++------ src/cpp/controller/CryptoKey.cpp | 30 ++++ src/cpp/controller/CryptoKey.h | 11 +- src/cpp/controller/HederaAccount.cpp | 62 ++++++-- src/cpp/controller/HederaAccount.h | 10 +- src/cpp/controller/HederaId.cpp | 10 ++ src/cpp/controller/HederaId.h | 2 + src/cpp/model/table/CryptoKey.cpp | 65 +++++++- src/cpp/model/table/CryptoKey.h | 9 ++ src/cpp/model/table/HederaAccount.h | 1 + src/cpp/model/table/HederaId.cpp | 1 + src/cpp/model/table/ModelBase.cpp | 18 +++ src/cpp/model/table/ModelBase.h | 1 + src/cpsp/adminHederaAccount.cpsp | 101 +++++++++---- 17 files changed, 377 insertions(+), 89 deletions(-) diff --git a/skeema/gradido_login/crypto_keys.sql b/skeema/gradido_login/crypto_keys.sql index c79987755..1e5d6bad8 100644 --- a/skeema/gradido_login/crypto_keys.sql +++ b/skeema/gradido_login/crypto_keys.sql @@ -1,6 +1,6 @@ CREATE TABLE `crypto_keys` ( `id` int unsigned NOT NULL AUTO_INCREMENT, - `private_key` binary(80) NOT NULL, + `private_key` varbinary(80) NOT NULL, `public_key` binary(32) NOT NULL, `crypto_key_type_id` int NOT NULL DEFAULT '0', PRIMARY KEY (`id`), diff --git a/src/cpp/Crypto/KeyPairHedera.cpp b/src/cpp/Crypto/KeyPairHedera.cpp index 62643cc99..e3a377864 100644 --- a/src/cpp/Crypto/KeyPairHedera.cpp +++ b/src/cpp/Crypto/KeyPairHedera.cpp @@ -184,6 +184,7 @@ MemoryBin* KeyPairHedera::getCryptedPrivKey(const Poco::AutoPtr password) const; MemoryBin* getPrivateKeyCopy() const; + inline std::string getPrivateKeyHex(const Poco::AutoPtr password) const { if (!mPrivateKey) return "0x0"; return DataTypeConverter::binToHex(mPrivateKey); } protected: diff --git a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp index 54a416bef..3247e1130 100644 --- a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp +++ b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp @@ -51,40 +51,58 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request Poco::URI uri(request.getURI()); auto uri_query = uri.getQueryParameters(); std::string action = ""; - std::string account_id_from_query; + Poco::AutoPtr query_hedera_account; + + // parsing get query params if(uri_query.size() >= 2) { if(uri_query[0].first == "action") { action = uri_query[0].second; } if(uri_query[1].first == "account_id") { + std::string account_id_from_query; + int account_id = 0; account_id_from_query = uri_query[1].second; - } - } - if(action == "updateBalance") { - int account_id = 0; - if(DataTypeConverter::strToInt(account_id_from_query, account_id) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting account_id_from_query to int")); - } else { - auto hedera_account = controller::HederaAccount::load("id", account_id); - if(!hedera_account.size() || hedera_account[0].isNull()) { - addError(new Error("Action Update Balance", "hedera id not found")); + if(DataTypeConverter::strToInt(account_id_from_query, account_id) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting account_id_from_query to int")); } else { - hedera_time.reset(); - hedera_account[0]->hederaAccountGetBalance(user, this); - addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string())); + auto hedera_accounts = controller::HederaAccount::load("id", account_id); + if(!hedera_accounts.size() || hedera_accounts[0].isNull()) { + addError(new Error("Action", "hedera account not found")); + } else { + query_hedera_account = hedera_accounts[0]; + } } } } - // add - else if(!form.empty()) { + // actions + if(!query_hedera_account.isNull()) + { + if(action == "updateBalance") + { + hedera_time.reset(); + query_hedera_account->hederaAccountGetBalance(user); + addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string())); + } + else if(action == "changeEncryption") + { + if(query_hedera_account->changeEncryption(user)) { + addNotification(new Success("Hedera Account", "success in changing encryption")); + } + } + } + else if(!form.empty()) // add + { // collect auto shardNumString = form.get("account-shard-num", "0"); auto realmNumString = form.get("account-realm-num", "0"); auto numString = form.get("account-num", "0"); auto privateKeyString = form.get("account-private-key", ""); + auto privateKeyEncryptedString = form.get("account-private-key-encrypted", "false"); auto publicKeyString = form.get("account-public-key", ""); auto networkTypeString = form.get("account-network-type", "0"); + //printf("private key encrypted: %s\n", privateKeyEncryptedString.data()); + int shardNum = 0; int realmNum = 0; int num = 0; @@ -144,7 +162,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE); if(crypto_key.isNull()) { - crypto_key = controller::CryptoKey::create(&key_pair, user); + crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true"); if(!crypto_key->getModel()->insertIntoDB(true)) { addError(new Error("DB Error", "Error saving crypto key in DB")); } @@ -152,15 +170,26 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request printf("crypto key found in db\n"); } if(0 == errorCount()) { - auto hedera_account = controller::HederaAccount::create( - user->getModel()->getID(), - hedera_id->getModel()->getID(), - crypto_key->getModel()->getID(), - 0, - (model::table::HederaNetworkType)networkType - ); - if(!hedera_account->getModel()->insertIntoDB(false)) { - addError(new Error("DB Error", "Error saving hedera account into DB")); + + if(hedera_id->isExistInDB()) { + auto hedera_account = controller::HederaAccount::load(hedera_id); + if(hedera_account.isNull()) { + addError(new Error("DB Error", "Couldn't load hedera account from db, but it should exist")); + } else { + addError(new Error("Hedera Account", "Account already exist (same account id")); + } + + } else { + auto hedera_account = controller::HederaAccount::create( + user->getModel()->getID(), + hedera_id->getModel()->getID(), + crypto_key->getModel()->getID(), + 0, + (model::table::HederaNetworkType)networkType + ); + if(!hedera_account->getModel()->insertIntoDB(false)) { + addError(new Error("DB Error", "Error saving hedera account into DB")); + } } } @@ -169,7 +198,9 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request } } - + if(!query_hedera_account.isNull()) { + getErrors(query_hedera_account); + } // list accounts auto hedera_accounts = controller::HederaAccount::load("user_id", user->getModel()->getID()); @@ -231,7 +262,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t
    "; // end include header_large.cpsp responseStream << "\n"; -#line 156 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 187 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( getErrorsHtml() ); responseStream << "\n"; responseStream << "
    \n"; @@ -244,41 +275,63 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t\t
    Hedera Id
    \t\t\t\n"; responseStream << "\t\t\t\t
    Balance
    \n"; responseStream << "\t\t\t\t
    Server Type
    \n"; + responseStream << "\t\t\t\t
    Verschlüsselt?
    \n"; responseStream << "\t\t\t\t
    Last Updated
    \n"; responseStream << "\t\t\t\t
    Aktionen
    \n"; responseStream << "\t\t\t
    \n"; responseStream << "\t\t\t"; -#line 171 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 203 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" for(auto it = hedera_accounts.begin(); it != hedera_accounts.end(); it++) { auto hedera_account_model = (*it)->getModel(); auto updateUrl = ServerConfig::g_serverPath + "/hedera_account?action=updateBalance&account_id=" + std::to_string(hedera_account_model->getID()); + std::string changeEncryption(""); + if(hedera_account_model->getUserId() == user->getModel()->getID()) { + changeEncryption = ServerConfig::g_serverPath + "/hedera_account?action=changeEncryption&account_id=" + std::to_string(hedera_account_model->getID()); + } + //printf("change encryption: %s\n", changeEncryption.data()); responseStream << "\n"; responseStream << "\t\t\t\t
    \n"; responseStream << "\t\t\t\t\t
    "; -#line 176 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 213 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( (*it)->getHederaId()->getModel()->toString() ); responseStream << "
    \n"; responseStream << "\t\t\t\t\t
    "; -#line 177 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 214 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( hedera_account_model->getBalanceDouble() ); responseStream << " hbar
    \n"; responseStream << "\t\t\t\t\t
    "; -#line 178 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 215 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) ); responseStream << "
    \n"; responseStream << "\t\t\t\t\t
    "; -#line 179 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 216 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + responseStream << ( (*it)->getCryptoKey()->getModel()->isEncrypted() ? "Ja": "Nein" ); + responseStream << "
    \n"; + responseStream << "\t\t\t\t\t
    "; +#line 217 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( hedera_account_model->getUpdatedString() ); responseStream << "
    \n"; - responseStream << "\t\t\t\t\t\n"; + responseStream << "\t\t\t\t\t"; +#line 221 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + if(changeEncryption != "") { responseStream << "\n"; + responseStream << "\t\t\t\t\t\t\n"; + responseStream << "\t\t\t\t\t"; +#line 225 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + } responseStream << "\n"; responseStream << "\t\t\t\t
    \n"; responseStream << "\t\t\t"; -#line 184 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 227 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" } responseStream << "\n"; responseStream << "\t\t
    \n"; responseStream << "\t
    \n"; @@ -287,7 +340,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t
    \n"; responseStream << "\t
    \n"; responseStream << "\t\t
    \n"; responseStream << "\t\t\t\n"; @@ -296,26 +349,28 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t
    \n"; diff --git a/src/cpp/controller/CryptoKey.cpp b/src/cpp/controller/CryptoKey.cpp index aa8df1b8d..338ad05a4 100644 --- a/src/cpp/controller/CryptoKey.cpp +++ b/src/cpp/controller/CryptoKey.cpp @@ -113,8 +113,38 @@ namespace controller { return nullptr; } + return std::make_unique(model->getPrivateKey(), model->getPublicKey(), model->getPublicKeySize()); } + bool CryptoKey::changeEncryption(Poco::AutoPtr user) + { + auto key_pair = getKeyPair(user); + if (!key_pair || !key_pair->hasPrivateKey()) { + addError(new Error("Crypto Key", "key pair or private key was null")); + return false; + } + auto model = getModel(); + auto mm = MemoryManager::getInstance(); + // update key type + model->changeKeyTypeToggleEncrypted(); + MemoryBin* private_key = nullptr; + if (model->isEncrypted()) { + private_key = key_pair->getCryptedPrivKey(user->getPassword()); + } + else { + private_key = key_pair->getPrivateKeyCopy(); + } + if (!private_key) { + addError(new Error("Crypto Key", " private_key not get")); + return false; + } + model->setPrivateKey(private_key); + // save changes into db + model->updatePrivkeyAndKeyType(); + + mm->releaseMemory(private_key); + return true; + } } diff --git a/src/cpp/controller/CryptoKey.h b/src/cpp/controller/CryptoKey.h index ef48c88f1..ddd2a7435 100644 --- a/src/cpp/controller/CryptoKey.h +++ b/src/cpp/controller/CryptoKey.h @@ -9,9 +9,15 @@ #include "TableControllerBase.h" #include "User.h" + + namespace controller { - class CryptoKey : public TableControllerBase + + class HederaAccount; + + class CryptoKey : public TableControllerBase, public NotificationList { + friend HederaAccount; public: ~CryptoKey(); @@ -31,8 +37,11 @@ namespace controller { std::unique_ptr getKeyPair(Poco::AutoPtr user) const; std::unique_ptr getKeyPair() const; + protected: + + bool changeEncryption(Poco::AutoPtr user); CryptoKey(model::table::CryptoKey* dbModel); }; diff --git a/src/cpp/controller/HederaAccount.cpp b/src/cpp/controller/HederaAccount.cpp index e4873ecf0..22a82c929 100644 --- a/src/cpp/controller/HederaAccount.cpp +++ b/src/cpp/controller/HederaAccount.cpp @@ -40,6 +40,20 @@ namespace controller { return resultVector; } + Poco::AutoPtr HederaAccount::load(Poco::AutoPtr hederaId) + { + if (!hederaId->isExistInDB()) return nullptr; + + auto db = new model::table::HederaAccount(); + auto result_count = db->loadFromDB("account_hedera_id", hederaId->getModel()->getID()); + if (1 == result_count) { + return new HederaAccount(db); + } + // maybe change later to using error manager and send email + printf("[HederaAccount::load] result_count not expected: %d\n", result_count); + return nullptr; + } + std::vector> HederaAccount::listAll() { auto db = new model::table::HederaAccount(); @@ -73,7 +87,13 @@ namespace controller { return resultVector; } - bool HederaAccount::hederaAccountGetBalance(Poco::AutoPtr user, NotificationList* errorReceiver/* = nullptr*/) + Poco::AutoPtr HederaAccount::getCryptoKey() const + { + auto model = getModel(); + return controller::CryptoKey::load(model->getCryptoKeyId()); + } + + bool HederaAccount::hederaAccountGetBalance(Poco::AutoPtr user) { static const char* functionName = "HederaAccount::updateBalanceFromHedera"; @@ -86,13 +106,13 @@ namespace controller { auto hedera_node = NodeServer::pick(account_model->networkTypeToNodeServerType(account_model->getNetworkType())); auto crypto_key = controller::CryptoKey::load(account_model->getCryptoKeyId()); if (crypto_key.isNull()) { - if (errorReceiver) { errorReceiver->addError(new Error("Keys", "could not found crypto key for account"));} - else { printf("[%s] error, crypto key with id: %d not found\n", functionName, account_model->getCryptoKeyId()); } + addError(new Error("Keys", "could not found crypto key for account")); + printf("[%s] error, crypto key with id: %d not found\n", functionName, account_model->getCryptoKeyId()); return false; } auto hedera_key_pair = crypto_key->getKeyPair(user); if (!hedera_key_pair) { - if (errorReceiver) { errorReceiver->addError(new Error("Keys", "error decrypting private key"));} + addError(new Error("Keys", "error decrypting private key")); printf("[%s] error decrypting private key with id: %d, with user: %d\n", functionName, account_model->getCryptoKeyId(), user->getModel()->getID()); return false; } @@ -111,13 +131,8 @@ namespace controller { account_model->updateIntoDB("balance", response.getAccountBalance()); } else { - if (errorReceiver) { - errorReceiver->addError(new Error("Hedera", "Hedera request failed")); - errorReceiver->addError(new ParamError("Hedera", "Hedera Response Code", proto::ResponseCodeEnum_Name(response.getResponseCode()))); - } - else { - printf("[%s] hedera response code: %s\n", functionName, proto::ResponseCodeEnum_Name(response.getResponseCode()).data()); - } + addError(new Error("Hedera", "Hedera request failed")); + addError(new ParamError("Hedera", "Hedera Response Code", proto::ResponseCodeEnum_Name(response.getResponseCode()))); } //request.requestViaPHPRelay(query); } @@ -125,13 +140,32 @@ namespace controller { printf("[HederaAccount::updateBalanceFromHedera] exception calling hedera request: %s\n", ex.displayText().data()); } - if (errorReceiver) { - errorReceiver->getErrors(&request); - } + getErrors(&request); return false; } + bool HederaAccount::changeEncryption(Poco::AutoPtr user) + { + assert(!user.isNull() && user->getModel()); + auto model = getModel(); + assert(!model.isNull()); + + if (user->getModel()->getID() != model->getUserId()) { + addError(new Error("Hedera Account", "wrong user")); + return false; + } + auto crypto_key = controller::CryptoKey::load(model->getCryptoKeyId()); + if (crypto_key.isNull()) { + addError(new Error("Hedera Account", "couldn't find crypto key")); + return false; + } + bool result = crypto_key->changeEncryption(user); + getErrors(crypto_key); + return result; + + } + std::string HederaAccount::toShortSelectOptionName() { diff --git a/src/cpp/controller/HederaAccount.h b/src/cpp/controller/HederaAccount.h index a9a53d528..77f34aa87 100644 --- a/src/cpp/controller/HederaAccount.h +++ b/src/cpp/controller/HederaAccount.h @@ -8,9 +8,10 @@ #include "Poco/SharedPtr.h" #include "TableControllerBase.h" +#include "CryptoKey.h" namespace controller { - class HederaAccount : public TableControllerBase + class HederaAccount : public TableControllerBase, public NotificationList { public: ~HederaAccount(); @@ -18,6 +19,7 @@ namespace controller { static Poco::AutoPtr create(int user_id, int account_hedera_id, int account_key_id, Poco::UInt64 balance = 0, model::table::HederaNetworkType type = model::table::HEDERA_MAINNET); static std::vector> load(const std::string& fieldName, int fieldValue); + static Poco::AutoPtr load(Poco::AutoPtr hederaId); static std::vector> listAll(); inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } @@ -25,11 +27,15 @@ namespace controller { std::string HederaAccount::toShortSelectOptionName(); inline Poco::AutoPtr getModel() { return _getModel(); } + inline const model::table::HederaAccount* getModel() const { return _getModel(); } inline void setHederaId(Poco::AutoPtr hederaId) { mHederaID = hederaId; } inline Poco::AutoPtr getHederaId() { return mHederaID; } - bool hederaAccountGetBalance(Poco::AutoPtr user, NotificationList* errorReceiver = nullptr); + Poco::AutoPtr getCryptoKey() const; + + bool hederaAccountGetBalance(Poco::AutoPtr user); + bool changeEncryption(Poco::AutoPtr user); protected: HederaAccount(model::table::HederaAccount* dbModel); diff --git a/src/cpp/controller/HederaId.cpp b/src/cpp/controller/HederaId.cpp index ce171a7a8..de2cf1dfa 100644 --- a/src/cpp/controller/HederaId.cpp +++ b/src/cpp/controller/HederaId.cpp @@ -37,4 +37,14 @@ namespace controller { protoAccountId->set_realmnum(model->getRealmNum()); protoAccountId->set_accountnum(model->getNum()); } + + bool HederaId::isExistInDB() + { + auto model = getModel(); + if (model->getID() > 0) return true; + //std::vector loadFromDB(const std::vector& fieldNames, const std::vector& fieldValues, MysqlConditionType conditionType = MYSQL_CONDITION_AND, int expectedResults = 0); + model->isExistInDB(); + return model->getID() != 0; + + } } \ No newline at end of file diff --git a/src/cpp/controller/HederaId.h b/src/cpp/controller/HederaId.h index ae9296a43..1cf967927 100644 --- a/src/cpp/controller/HederaId.h +++ b/src/cpp/controller/HederaId.h @@ -20,6 +20,8 @@ namespace controller { static Poco::AutoPtr load(int id); + bool isExistInDB(); + inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } inline Poco::AutoPtr getModel() { return _getModel(); } diff --git a/src/cpp/model/table/CryptoKey.cpp b/src/cpp/model/table/CryptoKey.cpp index a4f1034e3..f461edc02 100644 --- a/src/cpp/model/table/CryptoKey.cpp +++ b/src/cpp/model/table/CryptoKey.cpp @@ -1,5 +1,5 @@ #include "CryptoKey.h" -#include "../../lib/DataTypeConverter.h" + using namespace Poco::Data::Keywords; namespace model { @@ -51,6 +51,8 @@ namespace model { return ""; } + + bool CryptoKey::hasPrivateKeyEncrypted() const { const KeyType type = (KeyType)(mKeyType); @@ -70,6 +72,39 @@ namespace model { return false; } + void CryptoKey::setPrivateKey(const MemoryBin* privateKey) + { + if (!privateKey) { + mPrivateKey = Poco::Nullable(); + } + else { + mPrivateKey = Poco::Nullable(Poco::Data::BLOB(*privateKey, privateKey->size())); + } + + } + + bool CryptoKey::changeKeyTypeToggleEncrypted() + { + const KeyType type = (KeyType)(mKeyType); + if (type == KEY_TYPE_ED25519_SODIUM_ENCRYPTED) { + mKeyType = KEY_TYPE_ED25519_SODIUM_CLEAR; + return true; + } + if (type == KEY_TYPE_ED25519_HEDERA_ENCRYPTED) { + mKeyType = KEY_TYPE_ED25519_HEDERA_CLEAR; + return true; + } + if (type == KEY_TYPE_ED25519_SODIUM_CLEAR) { + mKeyType = KEY_TYPE_ED25519_SODIUM_ENCRYPTED; + return true; + } + if (type == KEY_TYPE_ED25519_HEDERA_CLEAR) { + mKeyType = KEY_TYPE_ED25519_HEDERA_ENCRYPTED; + return true; + } + return false; + } + Poco::Data::Statement CryptoKey::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) { Poco::Data::Statement select(session); @@ -103,5 +138,33 @@ namespace model { unlock(); return insert; } + + size_t CryptoKey::updatePrivkeyAndKeyType() + { + Poco::ScopedLock _lock(mWorkMutex); + if (mPrivateKey.isNull() || !mID) { + return 0; + } + auto cm = ConnectionManager::getInstance(); + auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + + Poco::Data::Statement update(session); + + update << "UPDATE " << getTableName() << " SET private_key = ?, crypto_key_type_id = ? where id = ?;", + use(mPrivateKey), use(mKeyType), use(mID); + + + size_t resultCount = 0; + try { + return update.execute(); + } + catch (Poco::Exception& ex) { + addError(new ParamError(getTableName(), "[updatePrivkeyAndKeyType] mysql error by update", ex.displayText().data())); + addError(new ParamError(getTableName(), "data set: \n", toString().data())); + } + //printf("data valid: %s\n", toString().data()); + return 0; + } + } } \ No newline at end of file diff --git a/src/cpp/model/table/CryptoKey.h b/src/cpp/model/table/CryptoKey.h index c1fa0b66d..0dcbb618f 100644 --- a/src/cpp/model/table/CryptoKey.h +++ b/src/cpp/model/table/CryptoKey.h @@ -3,6 +3,7 @@ #include "ModelBase.h" #include "Poco/Types.h" +#include "../../lib/DataTypeConverter.h" namespace model { namespace table { @@ -27,13 +28,21 @@ namespace model { std::string toString(); inline const unsigned char* getPublicKey() const { if (mPublicKey.isNull()) return nullptr; return mPublicKey.value().content().data(); } + inline std::string getPublicKeyHexString() const { return DataTypeConverter::binToHex(mPublicKey); }; size_t getPublicKeySize() const { if (mPublicKey.isNull()) return 0; return mPublicKey.value().content().size(); } bool hasPrivateKeyEncrypted() const; bool isEncrypted() const; + bool changeKeyTypeToggleEncrypted(); inline bool hasPrivateKey() const { return !mPrivateKey.isNull(); } inline const std::vector& getPrivateKey() const { return mPrivateKey.value().content(); } + size_t updatePrivkeyAndKeyType(); + + //! \brief set encrypted private key + //! \param privateKey copy data, didn't move memory bin + void setPrivateKey(const MemoryBin* privateKey); + static const char* typeToString(KeyType type); protected: Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); diff --git a/src/cpp/model/table/HederaAccount.h b/src/cpp/model/table/HederaAccount.h index 6b0d636a0..699330adf 100644 --- a/src/cpp/model/table/HederaAccount.h +++ b/src/cpp/model/table/HederaAccount.h @@ -35,6 +35,7 @@ namespace model { inline int getAccountHederaId() const { return mAccountHederaId; } inline int getCryptoKeyId() const { return mAccountKeyId; } + inline int getUserId() const { return mUserId; } inline Poco::UInt64 getBalance() { return mBalance; } inline double getBalanceDouble() { return (double)mBalance / 100000000.0; } diff --git a/src/cpp/model/table/HederaId.cpp b/src/cpp/model/table/HederaId.cpp index 9f26f05c5..d6ceb8cb7 100644 --- a/src/cpp/model/table/HederaId.cpp +++ b/src/cpp/model/table/HederaId.cpp @@ -55,6 +55,7 @@ namespace model { return mID; } + Poco::Data::Statement HederaId::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) { diff --git a/src/cpp/model/table/ModelBase.cpp b/src/cpp/model/table/ModelBase.cpp index 7bb7301f6..49b470d7a 100644 --- a/src/cpp/model/table/ModelBase.cpp +++ b/src/cpp/model/table/ModelBase.cpp @@ -78,6 +78,24 @@ namespace model { return false; } + bool ModelBase::isExistInDB() + { + auto cm = ConnectionManager::getInstance(); + Poco::ScopedLock _lock(mWorkMutex); + auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + + Poco::Data::Statement select = _loadIdFromDB(session); + try { + select.executeAsync(); + return select.wait() == 1; + } + catch (Poco::Exception& ex) { + addError(new ParamError(getTableName(), "mysql error by select id, check if exist in db", ex.displayText().data())); + addError(new ParamError(getTableName(), "data set: ", toString().data())); + } + return false; + } + bool ModelBase::deleteFromDB() { Poco::ScopedLock _lock(mWorkMutex); diff --git a/src/cpp/model/table/ModelBase.h b/src/cpp/model/table/ModelBase.h index b71b37a89..7be066b31 100644 --- a/src/cpp/model/table/ModelBase.h +++ b/src/cpp/model/table/ModelBase.h @@ -40,6 +40,7 @@ namespace model { size_t loadFromDB(const std::string& fieldName, const T& fieldValue); template bool isExistInDB(const std::string& fieldName, const T& fieldValue); + bool isExistInDB(); template std::vector loadFromDB(const std::string& fieldName, const WhereFieldType& fieldValue, int expectedResults = 0); template diff --git a/src/cpsp/adminHederaAccount.cpsp b/src/cpsp/adminHederaAccount.cpsp index 95d6992b7..b55701b1b 100644 --- a/src/cpsp/adminHederaAccount.cpsp +++ b/src/cpsp/adminHederaAccount.cpsp @@ -30,40 +30,58 @@ Poco::URI uri(request.getURI()); auto uri_query = uri.getQueryParameters(); std::string action = ""; - std::string account_id_from_query; + Poco::AutoPtr query_hedera_account; + + // parsing get query params if(uri_query.size() >= 2) { if(uri_query[0].first == "action") { action = uri_query[0].second; } if(uri_query[1].first == "account_id") { + std::string account_id_from_query; + int account_id = 0; account_id_from_query = uri_query[1].second; - } - } - if(action == "updateBalance") { - int account_id = 0; - if(DataTypeConverter::strToInt(account_id_from_query, account_id) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting account_id_from_query to int")); - } else { - auto hedera_account = controller::HederaAccount::load("id", account_id); - if(!hedera_account.size() || hedera_account[0].isNull()) { - addError(new Error("Action Update Balance", "hedera id not found")); + if(DataTypeConverter::strToInt(account_id_from_query, account_id) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting account_id_from_query to int")); } else { - hedera_time.reset(); - hedera_account[0]->hederaAccountGetBalance(user, this); - addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string())); + auto hedera_accounts = controller::HederaAccount::load("id", account_id); + if(!hedera_accounts.size() || hedera_accounts[0].isNull()) { + addError(new Error("Action", "hedera account not found")); + } else { + query_hedera_account = hedera_accounts[0]; + } } } } - // add - else if(!form.empty()) { + // actions + if(!query_hedera_account.isNull()) + { + if(action == "updateBalance") + { + hedera_time.reset(); + query_hedera_account->hederaAccountGetBalance(user); + addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string())); + } + else if(action == "changeEncryption") + { + if(query_hedera_account->changeEncryption(user)) { + addNotification(new Success("Hedera Account", "success in changing encryption")); + } + } + } + else if(!form.empty()) // add + { // collect auto shardNumString = form.get("account-shard-num", "0"); auto realmNumString = form.get("account-realm-num", "0"); auto numString = form.get("account-num", "0"); auto privateKeyString = form.get("account-private-key", ""); + auto privateKeyEncryptedString = form.get("account-private-key-encrypted", "false"); auto publicKeyString = form.get("account-public-key", ""); auto networkTypeString = form.get("account-network-type", "0"); + //printf("private key encrypted: %s\n", privateKeyEncryptedString.data()); + int shardNum = 0; int realmNum = 0; int num = 0; @@ -123,7 +141,7 @@ auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE); if(crypto_key.isNull()) { - crypto_key = controller::CryptoKey::create(&key_pair, user); + crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true"); if(!crypto_key->getModel()->insertIntoDB(true)) { addError(new Error("DB Error", "Error saving crypto key in DB")); } @@ -131,15 +149,26 @@ printf("crypto key found in db\n"); } if(0 == errorCount()) { - auto hedera_account = controller::HederaAccount::create( - user->getModel()->getID(), - hedera_id->getModel()->getID(), - crypto_key->getModel()->getID(), - 0, - (model::table::HederaNetworkType)networkType - ); - if(!hedera_account->getModel()->insertIntoDB(false)) { - addError(new Error("DB Error", "Error saving hedera account into DB")); + + if(hedera_id->isExistInDB()) { + auto hedera_account = controller::HederaAccount::load(hedera_id); + if(hedera_account.isNull()) { + addError(new Error("DB Error", "Couldn't load hedera account from db, but it should exist")); + } else { + addError(new Error("Hedera Account", "Account already exist (same account id")); + } + + } else { + auto hedera_account = controller::HederaAccount::create( + user->getModel()->getID(), + hedera_id->getModel()->getID(), + crypto_key->getModel()->getID(), + 0, + (model::table::HederaNetworkType)networkType + ); + if(!hedera_account->getModel()->insertIntoDB(false)) { + addError(new Error("DB Error", "Error saving hedera account into DB")); + } } } @@ -148,7 +177,9 @@ } } - + if(!query_hedera_account.isNull()) { + getErrors(query_hedera_account); + } // list accounts auto hedera_accounts = controller::HederaAccount::load("user_id", user->getModel()->getID()); @@ -165,21 +196,33 @@
    Hedera Id
    Balance
    Server Type
    +
    Verschlüsselt?
    Last Updated
    Aktionen
    <% for(auto it = hedera_accounts.begin(); it != hedera_accounts.end(); it++) { auto hedera_account_model = (*it)->getModel(); auto updateUrl = ServerConfig::g_serverPath + "/hedera_account?action=updateBalance&account_id=" + std::to_string(hedera_account_model->getID()); + std::string changeEncryption(""); + if(hedera_account_model->getUserId() == user->getModel()->getID()) { + changeEncryption = ServerConfig::g_serverPath + "/hedera_account?action=changeEncryption&account_id=" + std::to_string(hedera_account_model->getID()); + } + //printf("change encryption: %s\n", changeEncryption.data()); %>
    <%= (*it)->getHederaId()->getModel()->toString() %>
    <%= hedera_account_model->getBalanceDouble() %> hbar
    <%= model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) %>
    +
    <%= (*it)->getCryptoKey()->getModel()->isEncrypted() ? "Ja": "Nein" %>
    <%= hedera_account_model->getUpdatedString() %>
    - + <% if(changeEncryption != "") { %> + + <% } %>
    <% } %>
    @@ -195,6 +238,8 @@ + + From 7449f73e89ccb6d1cae09716eac5bc9d6ee7e8f0 Mon Sep 17 00:00:00 2001 From: Dario Date: Mon, 14 Sep 2020 21:09:18 +0200 Subject: [PATCH 032/293] Update code for sending transaction over hedera --- src/cpp/Crypto/KeyPairHedera.cpp | 18 + src/cpp/Crypto/KeyPairHedera.h | 7 +- .../HTTPInterface/AdminHederaAccountPage.cpp | 364 ++++++++++++------ .../SingletonManager/HederaTaskManager.cpp | 17 + src/cpp/SingletonManager/HederaTaskManager.h | 23 ++ src/cpp/SingletonManager/SessionManager.cpp | 1 + src/cpp/SingletonManager/SessionManager.h | 1 + src/cpp/controller/HederaAccount.cpp | 75 +++- src/cpp/controller/HederaAccount.h | 9 + src/cpp/controller/HederaId.cpp | 47 +++ src/cpp/controller/HederaId.h | 6 + src/cpp/controller/HederaRequest.cpp | 28 ++ src/cpp/controller/HederaRequest.h | 7 + src/cpp/controller/HederaTopic.cpp | 2 + src/cpp/controller/HederaTopic.h | 4 +- src/cpp/lib/DataTypeConverter.cpp | 28 ++ src/cpp/lib/DataTypeConverter.h | 1 + .../model/hedera/ConsensusSubmitMessage.cpp | 42 ++ src/cpp/model/hedera/ConsensusSubmitMessage.h | 32 ++ .../model/hedera/CryptoCreateTransaction.cpp | 22 +- .../model/hedera/CryptoCreateTransaction.h | 10 +- .../hedera/CryptoTransferTransaction.cpp | 5 - .../model/hedera/CryptoTransferTransaction.h | 2 +- src/cpp/model/hedera/Transaction.cpp | 29 ++ src/cpp/model/hedera/Transaction.h | 3 + src/cpp/model/hedera/TransactionBody.cpp | 46 ++- src/cpp/model/hedera/TransactionBody.h | 16 + src/cpp/model/hedera/TransactionResponse.cpp | 18 + src/cpp/model/hedera/TransactionResponse.h | 30 ++ src/cpp/model/table/HederaId.cpp | 7 + src/cpp/model/table/HederaId.h | 4 +- src/cpp/tasks/HederaTask.cpp | 0 src/cpp/tasks/HederaTask.h | 15 + src/cpp/tasks/SigningTransaction.cpp | 41 ++ src/cpsp/adminHederaAccount.cpsp | 291 +++++++++----- 35 files changed, 1009 insertions(+), 242 deletions(-) create mode 100644 src/cpp/SingletonManager/HederaTaskManager.cpp create mode 100644 src/cpp/SingletonManager/HederaTaskManager.h create mode 100644 src/cpp/model/hedera/TransactionResponse.cpp create mode 100644 src/cpp/model/hedera/TransactionResponse.h create mode 100644 src/cpp/tasks/HederaTask.cpp create mode 100644 src/cpp/tasks/HederaTask.h diff --git a/src/cpp/Crypto/KeyPairHedera.cpp b/src/cpp/Crypto/KeyPairHedera.cpp index e3a377864..c2738e886 100644 --- a/src/cpp/Crypto/KeyPairHedera.cpp +++ b/src/cpp/Crypto/KeyPairHedera.cpp @@ -96,6 +96,24 @@ KeyPairHedera::~KeyPairHedera() } } +KeyPairHedera* KeyPairHedera::create() +{ + /* + The crypto_sign_keypair() function randomly generates a secret key and a corresponding public key. + The public key is put into pk (crypto_sign_PUBLICKEYBYTES bytes) + and the secret key into sk (crypto_sign_SECRETKEYBYTES bytes). + */ + + assert(getPublicKeySize() == crypto_sign_PUBLICKEYBYTES); + + auto mm = MemoryManager::getInstance(); + auto private_key = mm->getFreeMemory(crypto_sign_SECRETKEYBYTES); + auto public_key = mm->getFreeMemory(getPublicKeySize()); + + crypto_sign_keypair(*public_key, *private_key); + return new KeyPairHedera(private_key, public_key); +} + void KeyPairHedera::createKeyFromSeed(const unsigned char* seed, size_t seedSize) { diff --git a/src/cpp/Crypto/KeyPairHedera.h b/src/cpp/Crypto/KeyPairHedera.h index 4613618c5..769f29af6 100644 --- a/src/cpp/Crypto/KeyPairHedera.h +++ b/src/cpp/Crypto/KeyPairHedera.h @@ -26,6 +26,9 @@ public: KeyPairHedera(const unsigned char* privateKey, size_t privateKeySize, const unsigned char* publicKey = nullptr, size_t publicKeySize = 0); KeyPairHedera(const MemoryBin* privateKey, const MemoryBin* publicKey = nullptr); KeyPairHedera(const std::vector& privateKey, const unsigned char* publicKey = nullptr, size_t publicKeySize = 0); + + + static KeyPairHedera* create(); ~KeyPairHedera(); @@ -43,12 +46,12 @@ public: const static size_t getPublicKeySize() {return ed25519_pubkey_SIZE;} inline bool isTheSame(const KeyPairHedera& b) const { - return 0 == sodium_memcmp(mPublicKey, b.mPublicKey, ed25519_pubkey_SIZE); + return 0 == sodium_memcmp(mPublicKey, b.mPublicKey, getPublicKeySize()); } inline bool isTheSame(const unsigned char* pubkey) const { if (!pubkey) return false; - return 0 == sodium_memcmp(mPublicKey, pubkey, ed25519_pubkey_SIZE); + return 0 == sodium_memcmp(mPublicKey, pubkey, getPublicKeySize()); } //! \return 0 if the same //! \return -1 if not the same diff --git a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp index 3247e1130..5ff4f7218 100644 --- a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp +++ b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp @@ -45,6 +45,9 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request auto sm = SessionManager::getInstance(); auto mm = MemoryManager::getInstance(); auto user = mSession->getNewUser(); + int auto_renew_period = 604800; // 7 Tage + int auto_renew_account = 0; + double initial_balance = 0.0; Profiler hedera_time; std::string hedera_time_string; @@ -80,8 +83,11 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request if(action == "updateBalance") { hedera_time.reset(); - query_hedera_account->hederaAccountGetBalance(user); - addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string())); + if(query_hedera_account->hederaAccountGetBalance(user)) { + addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string())); + } else { + addError(new ParamError("Hedera", "crypto get balance failed in ", hedera_time.string())); + } } else if(action == "changeEncryption") { @@ -90,113 +96,150 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request } } } - else if(!form.empty()) // add + else if(!form.empty()) // add or create { - // collect - auto shardNumString = form.get("account-shard-num", "0"); - auto realmNumString = form.get("account-realm-num", "0"); - auto numString = form.get("account-num", "0"); - auto privateKeyString = form.get("account-private-key", ""); - auto privateKeyEncryptedString = form.get("account-private-key-encrypted", "false"); - auto publicKeyString = form.get("account-public-key", ""); - auto networkTypeString = form.get("account-network-type", "0"); + auto creationButton = form.get("create",""); + if(creationButton != "") { - //printf("private key encrypted: %s\n", privateKeyEncryptedString.data()); - - int shardNum = 0; - int realmNum = 0; - int num = 0; - int networkType = 0; - - MemoryBin* private_key = nullptr; - MemoryBin* public_key = nullptr; - - // validate - if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) { - addError(new Error("Account ID", "shard num not integer")); - } else { - if(DataTypeConverter::strToInt(shardNumString, shardNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting shardNumString to int")); - } - } - if(!sm->isValid(realmNumString, VALIDATE_ONLY_INTEGER)) { - addError(new Error("Account ID", "realm num not integer")); - } else { - if(DataTypeConverter::strToInt(realmNumString, realmNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting realmNumString to int")); - } - } - if(!sm->isValid(numString, VALIDATE_ONLY_INTEGER)) { - addError(new Error("Account ID", "num not integer")); - } else { - if(DataTypeConverter::strToInt(numString, num) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting num to int")); - } - } - if(!sm->isValid(privateKeyString, VALIDATE_ONLY_HEX)) { - addError(new Error("Account Keys", "private key not hex")); - } - if(!sm->isValid(publicKeyString, VALIDATE_ONLY_HEX)) { - addError(new Error("Account Keys", "public key not hex")); - } - if(!sm->isValid(networkTypeString, VALIDATE_ONLY_INTEGER)) { - addError(new Error("Network Type", "not integer")); - } else { - if(DataTypeConverter::strToInt(networkTypeString, networkType) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting network type to int")); - } - if(networkType < 0 || networkType >= (int)model::table::HEDERA_NET_COUNT) { - addError(new Error("Network Type", "invalid value")); - } - } - - if(0 == errorCount()) { - - auto hedera_id = controller::HederaId::create(shardNum, realmNum, num); + // collect + auto auto_renew_account_string = form.get("account-auto-renew-account", "0"); + auto auto_renew_period_string = form.get("account-auto-renew-period", "604800"); + auto account_initial_balance_string = form.get("account-initial-balance", "0"); - private_key = DataTypeConverter::hexToBin(privateKeyString); - public_key = DataTypeConverter::hexToBin(publicKeyString); - - - KeyPairHedera key_pair(private_key, public_key); - auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE); - - if(crypto_key.isNull()) { - crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true"); - if(!crypto_key->getModel()->insertIntoDB(true)) { - addError(new Error("DB Error", "Error saving crypto key in DB")); - } + if(!sm->isValid(auto_renew_account_string, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account", "auto renew account id not an integer")); } else { - printf("crypto key found in db\n"); - } - if(0 == errorCount()) { - - if(hedera_id->isExistInDB()) { - auto hedera_account = controller::HederaAccount::load(hedera_id); - if(hedera_account.isNull()) { - addError(new Error("DB Error", "Couldn't load hedera account from db, but it should exist")); - } else { - addError(new Error("Hedera Account", "Account already exist (same account id")); - } - - } else { - auto hedera_account = controller::HederaAccount::create( - user->getModel()->getID(), - hedera_id->getModel()->getID(), - crypto_key->getModel()->getID(), - 0, - (model::table::HederaNetworkType)networkType - ); - if(!hedera_account->getModel()->insertIntoDB(false)) { - addError(new Error("DB Error", "Error saving hedera account into DB")); - } + if(DataTypeConverter::strToInt(auto_renew_account_string, auto_renew_account) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int convert error", "Error converting auto renew account id to int")); } } - mm->releaseMemory(private_key); - mm->releaseMemory(public_key); - } + if(!sm->isValid(auto_renew_period_string, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account", "auto renew period not an integer")); + } else { + if(DataTypeConverter::strToInt(auto_renew_period_string, auto_renew_period) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int convert error", "Error converting auto renew period to int")); + } + } + + if(!sm->isValid(account_initial_balance_string, VALIDATE_ONLY_DECIMAL)) { + addError(new Error("Account", "initial balance not an decimal")); + } else { + if(DataTypeConverter::strToDouble(account_initial_balance_string, initial_balance) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Double convert error", "Error converting initial balance to double")); + } + } + if(0 == errorCount()) + { + } + + } else { + // collect + auto shardNumString = form.get("account-shard-num", "0"); + auto realmNumString = form.get("account-realm-num", "0"); + auto numString = form.get("account-num", "0"); + auto privateKeyString = form.get("account-private-key", ""); + auto privateKeyEncryptedString = form.get("account-private-key-encrypted", "false"); + auto publicKeyString = form.get("account-public-key", ""); + auto networkTypeString = form.get("account-network-type", "0"); + + //printf("private key encrypted: %s\n", privateKeyEncryptedString.data()); + + int shardNum = 0; + int realmNum = 0; + int num = 0; + int networkType = 0; + + MemoryBin* private_key = nullptr; + MemoryBin* public_key = nullptr; + + // validate + if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "shard num not integer")); + } else { + if(DataTypeConverter::strToInt(shardNumString, shardNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting shardNumString to int")); + } + } + if(!sm->isValid(realmNumString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "realm num not integer")); + } else { + if(DataTypeConverter::strToInt(realmNumString, realmNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting realmNumString to int")); + } + } + if(!sm->isValid(numString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "num not integer")); + } else { + if(DataTypeConverter::strToInt(numString, num) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting num to int")); + } + } + if(!sm->isValid(privateKeyString, VALIDATE_ONLY_HEX)) { + addError(new Error("Account Keys", "private key not hex")); + } + if(!sm->isValid(publicKeyString, VALIDATE_ONLY_HEX)) { + addError(new Error("Account Keys", "public key not hex")); + } + if(!sm->isValid(networkTypeString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Network Type", "not integer")); + } else { + if(DataTypeConverter::strToInt(networkTypeString, networkType) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting network type to int")); + } + if(networkType < 0 || networkType >= (int)model::table::HEDERA_NET_COUNT) { + addError(new Error("Network Type", "invalid value")); + } + } + + if(0 == errorCount()) { + + auto hedera_id = controller::HederaId::create(shardNum, realmNum, num); + + private_key = DataTypeConverter::hexToBin(privateKeyString); + public_key = DataTypeConverter::hexToBin(publicKeyString); + + + KeyPairHedera key_pair(private_key, public_key); + auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE); + + if(crypto_key.isNull()) { + crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true"); + if(!crypto_key->getModel()->insertIntoDB(true)) { + addError(new Error("DB Error", "Error saving crypto key in DB")); + } + } else { + printf("crypto key found in db\n"); + } + if(0 == errorCount()) { + + if(hedera_id->isExistInDB()) { + auto hedera_account = controller::HederaAccount::load(hedera_id); + if(hedera_account.isNull()) { + addError(new Error("DB Error", "Couldn't load hedera account from db, but it should exist")); + } else { + addError(new Error("Hedera Account", "Account already exist (same account id")); + } + + } else { + auto hedera_account = controller::HederaAccount::create( + user->getModel()->getID(), + hedera_id->getModel()->getID(), + crypto_key->getModel()->getID(), + 0, + (model::table::HederaNetworkType)networkType + ); + if(!hedera_account->getModel()->insertIntoDB(false)) { + addError(new Error("DB Error", "Error saving hedera account into DB")); + } + } + } + + mm->releaseMemory(private_key); + mm->releaseMemory(public_key); + } + } } if(!query_hedera_account.isNull()) { getErrors(query_hedera_account); @@ -262,7 +305,15 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t
    "; // end include header_large.cpsp responseStream << "\n"; -#line 187 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + responseStream << "\n"; +#line 238 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( getErrorsHtml() ); responseStream << "\n"; responseStream << "
    \n"; @@ -280,7 +331,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t\t
    Aktionen
    \n"; responseStream << "\t\t\t
    \n"; responseStream << "\t\t\t"; -#line 203 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 254 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" for(auto it = hedera_accounts.begin(); it != hedera_accounts.end(); it++) { auto hedera_account_model = (*it)->getModel(); auto updateUrl = ServerConfig::g_serverPath + "/hedera_account?action=updateBalance&account_id=" + std::to_string(hedera_account_model->getID()); @@ -288,59 +339,63 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request if(hedera_account_model->getUserId() == user->getModel()->getID()) { changeEncryption = ServerConfig::g_serverPath + "/hedera_account?action=changeEncryption&account_id=" + std::to_string(hedera_account_model->getID()); } + auto isEncrypted = (*it)->getCryptoKey()->getModel()->isEncrypted(); //printf("change encryption: %s\n", changeEncryption.data()); responseStream << "\n"; responseStream << "\t\t\t\t
    \n"; responseStream << "\t\t\t\t\t
    "; -#line 213 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 265 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( (*it)->getHederaId()->getModel()->toString() ); responseStream << "
    \n"; responseStream << "\t\t\t\t\t
    "; -#line 214 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 266 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( hedera_account_model->getBalanceDouble() ); responseStream << " hbar
    \n"; responseStream << "\t\t\t\t\t
    "; -#line 215 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 267 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) ); responseStream << "
    \n"; - responseStream << "\t\t\t\t\t
    "; -#line 216 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" - responseStream << ( (*it)->getCryptoKey()->getModel()->isEncrypted() ? "Ja": "Nein" ); + responseStream << "\t\t\t\t\t
    "; +#line 268 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + responseStream << ( isEncrypted ? "Ja": "Nein" ); responseStream << "
    \n"; responseStream << "\t\t\t\t\t
    "; -#line 217 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 269 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( hedera_account_model->getUpdatedString() ); responseStream << "
    \n"; responseStream << "\t\t\t\t\t\n"; responseStream << "\t\t\t\t\t"; -#line 221 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 273 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" if(changeEncryption != "") { responseStream << "\n"; responseStream << "\t\t\t\t\t\t\n"; responseStream << "\t\t\t\t\t"; -#line 225 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 277 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" } responseStream << "\n"; responseStream << "\t\t\t\t
    \n"; responseStream << "\t\t\t"; -#line 227 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 279 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" } responseStream << "\n"; responseStream << "\t\t
    \n"; responseStream << "\t
    \n"; responseStream << "\t
    \n"; - responseStream << "\t

    Einen neuen Account anlegen

    \n"; + responseStream << "\t

    Ein existierenden Account eintragen

    \n"; responseStream << "\t
    \n"; responseStream << "\t
    \n"; responseStream << "\t\t
    \n"; responseStream << "\t\t\t\n"; @@ -356,25 +411,75 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; - responseStream << "\t\t\t\n"; responseStream << "\t\t
    \n"; responseStream << "\t
    \n"; + responseStream << "\t
    \n"; + responseStream << "\t\t

    Ein neuen Account anlegen

    \n"; + responseStream << "\t\t

    Bei Hedera einen neuen Account anlegen und zum Start Hashbars von einem existierenden Account überweisen.

    \n"; + responseStream << "\t
    \n"; + responseStream << "\t
    \n"; + responseStream << "\t\t
    \n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t
    \n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t\n"; + responseStream << "\t
    \n"; responseStream << "
    \n"; // begin include footer.cpsp responseStream << "
    \n"; @@ -400,5 +505,18 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << ""; // end include footer.cpsp responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; if (_compressResponse) _gzipStream.close(); } diff --git a/src/cpp/SingletonManager/HederaTaskManager.cpp b/src/cpp/SingletonManager/HederaTaskManager.cpp new file mode 100644 index 000000000..f54ca58f3 --- /dev/null +++ b/src/cpp/SingletonManager/HederaTaskManager.cpp @@ -0,0 +1,17 @@ +#include "HederaTaskManager.h" + +HederaTaskManager* HederaTaskManager::getInstance() +{ + static HederaTaskManager one; + return &one; +} + +HederaTaskManager::HederaTaskManager() +{ + +} + +HederaTaskManager::~HederaTaskManager() +{ + +} \ No newline at end of file diff --git a/src/cpp/SingletonManager/HederaTaskManager.h b/src/cpp/SingletonManager/HederaTaskManager.h new file mode 100644 index 000000000..361ace551 --- /dev/null +++ b/src/cpp/SingletonManager/HederaTaskManager.h @@ -0,0 +1,23 @@ +#ifndef __GRADIDO_LOGIN_SINGLETON_MANAGER_HEDERA_TASK_MANAGER_H +#define __GRADIDO_LOGIN_SINGLETON_MANAGER_HEDERA_TASK_MANAGER_H + +/*! + * @author: Dario Rekowski + * + * @date: 11.09.2020 + * + * @brief: Manage Hedera Task, waiting on Consensus for Hedera Transactions + * +*/ + +class HederaTaskManager +{ +public: + ~HederaTaskManager(); + + static HederaTaskManager* getInstance(); +protected: + HederaTaskManager(); +}; + +#endif //__GRADIDO_LOGIN_SINGLETON_MANAGER_HEDERA_TASK_MANAGER_H \ No newline at end of file diff --git a/src/cpp/SingletonManager/SessionManager.cpp b/src/cpp/SingletonManager/SessionManager.cpp index bbeaf9052..4e99b85e4 100644 --- a/src/cpp/SingletonManager/SessionManager.cpp +++ b/src/cpp/SingletonManager/SessionManager.cpp @@ -48,6 +48,7 @@ bool SessionManager::init() case VALIDATE_PASSPHRASE: mValidations[i] = new Poco::RegularExpression("^(?:[a-z]* ){23}[a-z]*\s*$"); break; case VALIDATE_HAS_NUMBER: mValidations[i] = new Poco::RegularExpression(".*[0-9].*"); break; case VALIDATE_ONLY_INTEGER: mValidations[i] = new Poco::RegularExpression("^[0-9]*$"); break; + case VALIDATE_ONLY_DECIMAL: mValidations[i] = new Poco::RegularExpression("^[0-9]*(\.|,)[0-9]*$"); break; case VALIDATE_ONLY_HEX: mValidations[i] = new Poco::RegularExpression("^(0x)?[a-fA-F0-9]*$"); break; //case VALIDATE_ONLY_URL: mValidations[i] = new Poco::RegularExpression("^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}$"); break; case VALIDATE_ONLY_URL: mValidations[i] = new Poco::RegularExpression("^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\/?"); break; diff --git a/src/cpp/SingletonManager/SessionManager.h b/src/cpp/SingletonManager/SessionManager.h index 99ef301f0..4596d2064 100644 --- a/src/cpp/SingletonManager/SessionManager.h +++ b/src/cpp/SingletonManager/SessionManager.h @@ -29,6 +29,7 @@ enum SessionValidationTypes { VALIDATE_PASSPHRASE, VALIDATE_HAS_NUMBER, VALIDATE_ONLY_INTEGER, + VALIDATE_ONLY_DECIMAL, VALIDATE_ONLY_HEX, VALIDATE_ONLY_URL, VALIDATE_HAS_SPECIAL_CHARACTER, diff --git a/src/cpp/controller/HederaAccount.cpp b/src/cpp/controller/HederaAccount.cpp index 22a82c929..25f3c7245 100644 --- a/src/cpp/controller/HederaAccount.cpp +++ b/src/cpp/controller/HederaAccount.cpp @@ -3,8 +3,13 @@ #include "NodeServer.h" #include "CryptoKey.h" #include "../model/hedera/Query.h" +//#include "../model/hedera/Tr" #include "HederaRequest.h" +#include "../SingletonManager/ErrorManager.h" + +using namespace Poco::Data::Keywords; + namespace controller { HederaAccount::HederaAccount(model::table::HederaAccount* dbModel) @@ -54,6 +59,51 @@ namespace controller { return nullptr; } + Poco::AutoPtr HederaAccount::pick(model::table::HederaNetworkType networkType, bool encrypted/* = false*/) + { + auto cm = ConnectionManager::getInstance(); + auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + Poco::Data::Statement select(session); + + Poco::Tuple result_tuple; + int crypto_key_type = encrypted ? model::table::KEY_TYPE_ED25519_HEDERA_ENCRYPTED : model::table::KEY_TYPE_ED25519_HEDERA_CLEAR; + //id, user_id, account_hedera_id, account_key_id, balance, network_type, updated + + select << "SELECT account.id, account.user_id, account.account_hedera_id, account.account_key_id, account.balance, i.shardNum, i.realmNum, i.num FROM hedera_accounts as account " + << "JOIN hedera_ids as i ON(i.id = account.account_hedera_id) " + << "JOIN crypto_keys as k ON(k.id = account.account_key_id) " + << "WHERE account.network_type = ? AND k.crypto_key_type_id = ? ORDER BY RAND() LIMIT 1 ", + into(result_tuple), use(networkType), use(crypto_key_type); + + try { + select.executeAsync(); + select.wait(); + if (1 == select.rowsExtracted()) { + auto db = new model::table::HederaAccount( + result_tuple.get<1>(), result_tuple.get<2>(), result_tuple.get<3>(), + result_tuple.get<4>(), networkType + ); + db->setID(result_tuple.get<0>()); + Poco::AutoPtr hedera_account(new HederaAccount(db)); + auto hedera_id_db = new model::table::HederaId(result_tuple.get<5>(), result_tuple.get<6>(), result_tuple.get<7>()); + Poco::AutoPtr hedera_id(new HederaId(hedera_id_db)); + hedera_account->setHederaId(hedera_id); + return hedera_account; + } + } + catch (Poco::Exception& ex) { + auto em = ErrorManager::getInstance(); + static const char* function_name = "HederaAccount::pick"; + em->addError(new ParamError(function_name, "mysql error: ", ex.displayText())); + em->addError(new ParamError(function_name, "network type: ", networkType)); + em->addError(new ParamError(function_name, "encrypted: ", (int)encrypted)); + em->sendErrorsAsEmail(); + } + + return nullptr; + + } + std::vector> HederaAccount::listAll() { auto db = new model::table::HederaAccount(); @@ -140,11 +190,27 @@ namespace controller { printf("[HederaAccount::updateBalanceFromHedera] exception calling hedera request: %s\n", ex.displayText().data()); } - getErrors(&request); + if (0 == errorCount() && 0 == request.errorCount()) { + return true; + } + getErrors(&request); return false; } + bool HederaAccount::hederaAccountCreate(int autoRenewPeriodSeconds, double initialBalance) + { + auto account_model = getModel(); + auto new_key_pair = KeyPairHedera::create(); + auto transaction_body = createTransactionBody(); + //CryptoCreateTransaction(const unsigned char* publicKey, Poco::UInt64 initialBalance, int autoRenewPeriod); + model::hedera::CryptoCreateTransaction create_transaction(new_key_pair->getPublicKey(), initialBalance, autoRenewPeriodSeconds); + transaction_body->setCryptoCreate(create_transaction); + + + return false; + } + bool HederaAccount::changeEncryption(Poco::AutoPtr user) { assert(!user.isNull() && user->getModel()); @@ -166,6 +232,13 @@ namespace controller { } + std::unique_ptr HederaAccount::createTransactionBody() + { + auto account_model = getModel(); + auto hedera_node = NodeServer::pick(account_model->networkTypeToNodeServerType(account_model->getNetworkType())); + return std::make_unique(mHederaID, hedera_node); + } + std::string HederaAccount::toShortSelectOptionName() { diff --git a/src/cpp/controller/HederaAccount.h b/src/cpp/controller/HederaAccount.h index 77f34aa87..882800713 100644 --- a/src/cpp/controller/HederaAccount.h +++ b/src/cpp/controller/HederaAccount.h @@ -5,6 +5,8 @@ #include "User.h" #include "../model/table/HederaAccount.h" +#include "../model/hedera/TransactionBody.h" + #include "Poco/SharedPtr.h" #include "TableControllerBase.h" @@ -21,6 +23,8 @@ namespace controller { static std::vector> load(const std::string& fieldName, int fieldValue); static Poco::AutoPtr load(Poco::AutoPtr hederaId); static std::vector> listAll(); + //! \brief for picking a account for paying transaction, mostly consensusSendMessage + static Poco::AutoPtr pick(model::table::HederaNetworkType networkType, bool encrypted = false); inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } @@ -35,9 +39,14 @@ namespace controller { Poco::AutoPtr getCryptoKey() const; bool hederaAccountGetBalance(Poco::AutoPtr user); + bool hederaAccountCreate(int autoRenewPeriodSeconds, double initialBalance); bool changeEncryption(Poco::AutoPtr user); + //! \brief create Transaction body with this hedera account as operator + std::unique_ptr createTransactionBody(); + protected: + HederaAccount(model::table::HederaAccount* dbModel); Poco::AutoPtr mHederaID; diff --git a/src/cpp/controller/HederaId.cpp b/src/cpp/controller/HederaId.cpp index de2cf1dfa..3b9627c8b 100644 --- a/src/cpp/controller/HederaId.cpp +++ b/src/cpp/controller/HederaId.cpp @@ -1,4 +1,7 @@ #include "HederaId.h" +#include "../SingletonManager/ErrorManager.h" + +using namespace Poco::Data::Keywords; namespace controller { @@ -30,6 +33,42 @@ namespace controller { return nullptr; } + Poco::AutoPtr HederaId::find(int groupId, model::table::HederaNetworkType networkType) + { + auto cm = ConnectionManager::getInstance(); + auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + model::table::HederaIdTuple result_tuple; + + Poco::Data::Statement select(session); + select << "SELECT h.id, h.shardNum, h.realmNum, h.num FROM hedera_ids as h " + << "JOIN hedera_topics as topic ON(topic.topic_hedera_id = h.id) " + << "JOIN hedera_accounts as account ON(account.id = topic.auto_renew_account_hedera_id) " + << "WHERE topic.group_id = ? AND account.network_type = ?" + , into(result_tuple), use(groupId), use(networkType); + + try { + /*select.executeAsync(); + select.wait(); + auto result_count = select.rowsExtracted();*/ + auto result_count = select.execute(); + if (1 == result_count) { + return new HederaId(new model::table::HederaId(result_tuple)); + } + else { + printf("[HederaId::find] result_count other as expected: %d\n", result_count); + } + } + catch (Poco::Exception& ex) { + auto em = ErrorManager::getInstance(); + static const char* function_name = "HederaId::find"; + em->addError(new ParamError(function_name, "mysql error: ", ex.displayText())); + em->addError(new ParamError(function_name, "group id: ", groupId)); + em->addError(new ParamError(function_name, "network type: ", (int)networkType)); + em->sendErrorsAsEmail(); + } + return nullptr; + } + void HederaId::copyToProtoAccountId(proto::AccountID* protoAccountId) const { auto model = getModel(); @@ -38,6 +77,14 @@ namespace controller { protoAccountId->set_accountnum(model->getNum()); } + void HederaId::copyToProtoTopicId(proto::TopicID* protoTopicId) const + { + auto model = getModel(); + protoTopicId->set_shardnum(model->getShardNum()); + protoTopicId->set_realmnum(model->getRealmNum()); + protoTopicId->set_topicnum(model->getNum()); + } + bool HederaId::isExistInDB() { auto model = getModel(); diff --git a/src/cpp/controller/HederaId.h b/src/cpp/controller/HederaId.h index 1cf967927..0bfc1f691 100644 --- a/src/cpp/controller/HederaId.h +++ b/src/cpp/controller/HederaId.h @@ -2,6 +2,7 @@ #define GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_ID_INCLUDE #include "../model/table/HederaId.h" +#include "../model/table/HederaAccount.h" #include "Poco/SharedPtr.h" @@ -10,8 +11,10 @@ #include "../proto/hedera/BasicTypes.pb.h" namespace controller { + class HederaAccount; class HederaId : public TableControllerBase { + friend HederaAccount; public: ~HederaId(); @@ -19,6 +22,8 @@ namespace controller { static Poco::AutoPtr create(Poco::UInt64 shardNum, Poco::UInt64 realmNum, Poco::UInt64 num); static Poco::AutoPtr load(int id); + //! \return hedera topic id for group and network type (should exist only one) + static Poco::AutoPtr find(int groupId, model::table::HederaNetworkType networkType); bool isExistInDB(); @@ -28,6 +33,7 @@ namespace controller { inline const model::table::HederaId* getModel() const { return _getModel(); } void copyToProtoAccountId(proto::AccountID* protoAccountId) const; + void copyToProtoTopicId(proto::TopicID* protoTopicId) const; protected: diff --git a/src/cpp/controller/HederaRequest.cpp b/src/cpp/controller/HederaRequest.cpp index 64998fa6a..7ddb95800 100644 --- a/src/cpp/controller/HederaRequest.cpp +++ b/src/cpp/controller/HederaRequest.cpp @@ -1,5 +1,6 @@ #include "HederaRequest.h" #include "../proto/hedera/CryptoService.grpc.pb.h" +#include "../proto/hedera/ConsensusService.grpc.pb.h" #include "../lib/DataTypeConverter.h" @@ -71,6 +72,33 @@ HederaRequestReturn HederaRequest::request(model::hedera::Transaction* transacti return HEDERA_REQUEST_RETURN_OK; } +HederaRequestReturn HederaRequest::request(model::hedera::Transaction* transaction, HederaTask* task) +{ + assert(transaction && task); + auto channel = grpc::CreateChannel(transaction->getConnectionString(), grpc::InsecureChannelCredentials()); + + grpc::ClientContext context; + std::chrono::system_clock::time_point deadline = std::chrono::system_clock::now() + + std::chrono::milliseconds(5000); + context.set_deadline(deadline); + auto transaction_type = transaction->getType(); + if (model::hedera::TRANSACTION_CONSENSUS_SUBMIT_MESSAGE == transaction_type) { + auto stub = proto::ConsensusService::NewStub(channel); + + auto status = stub->submitMessage(&context, *transaction->getTransaction(), task->getTransactionResponse()->getProtoResponse()); + if (status.ok()) { + return HEDERA_REQUEST_RETURN_OK; + } + else { + addError(new ParamError("Hedera Request", "consensus service submit message error message:", status.error_message())); + addError(new ParamError("Hedera Request", "details: ", status.error_details())); + return HEDERA_REQUEST_RETURN_ERROR; + } + } + addError(new ParamError("Hedera Request", "not implemnetet or unknown transaction type", transaction_type)); + return HEDERA_REQUEST_UNKNOWN_TRANSACTION; +} + #include "Poco/JSON/Object.h" #include "../lib/JsonRequest.h" diff --git a/src/cpp/controller/HederaRequest.h b/src/cpp/controller/HederaRequest.h index 34bd304a1..56adf3c79 100644 --- a/src/cpp/controller/HederaRequest.h +++ b/src/cpp/controller/HederaRequest.h @@ -14,12 +14,16 @@ #include "../model/hedera/Query.h" #include "../model/hedera/Transaction.h" #include "../model/hedera/Response.h" +#include "../model/hedera/TransactionResponse.h" +#include "../tasks/HederaTask.h" enum HederaRequestReturn { HEDERA_REQUEST_RETURN_OK, HEDERA_REQUEST_RETURN_PARSE_ERROR, HEDERA_REQUEST_RETURN_ERROR, + HEDERA_REQUEST_UNKNOWN_TRANSACTION, + HEDERA_REQUEST_UNKNOWN_QUERY, HEDERA_REQUEST_CONNECT_ERROR }; @@ -32,6 +36,9 @@ public: HederaRequestReturn request(model::hedera::Query* query, model::hedera::Response* response, Poco::UInt64 fee = 0); HederaRequestReturn request(model::hedera::Transaction* transaction, model::hedera::Response* response); + //! + //! \param task goes into HederaTaskManager and will be run after transaction + HederaRequestReturn request(model::hedera::Transaction* transaction, HederaTask* task); //! for testing, didn't work server say invalid json :/ HederaRequestReturn requestViaPHPRelay(model::hedera::Query* query); diff --git a/src/cpp/controller/HederaTopic.cpp b/src/cpp/controller/HederaTopic.cpp index 31d18a94c..d852b57e7 100644 --- a/src/cpp/controller/HederaTopic.cpp +++ b/src/cpp/controller/HederaTopic.cpp @@ -19,6 +19,8 @@ namespace controller { return Poco::AutoPtr(hedera_topic); } + + Poco::UInt64 HederaTopic::hederaCreateTopic() { return 0; diff --git a/src/cpp/controller/HederaTopic.h b/src/cpp/controller/HederaTopic.h index 4c2ebefb6..c7b169b4b 100644 --- a/src/cpp/controller/HederaTopic.h +++ b/src/cpp/controller/HederaTopic.h @@ -13,6 +13,7 @@ #include "TableControllerBase.h" #include "../model/table/HederaTopic.h" + namespace controller { class HederaTopic : public TableControllerBase { @@ -27,6 +28,7 @@ namespace controller { inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } + inline Poco::AutoPtr getModel() { return _getModel(); } @@ -36,4 +38,4 @@ namespace controller { }; } -#endif //__GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_TOPIC_H \ No newline at end of file +#endif //__GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_TOPIC_H diff --git a/src/cpp/lib/DataTypeConverter.cpp b/src/cpp/lib/DataTypeConverter.cpp index 72e6aceb8..0e84b4be4 100644 --- a/src/cpp/lib/DataTypeConverter.cpp +++ b/src/cpp/lib/DataTypeConverter.cpp @@ -55,6 +55,34 @@ namespace DataTypeConverter } } + NumberParseState strToDouble(const std::string& input, double& result) + { + auto comma_position = input.find(','); + std::string input_filtered = input; + if (comma_position > 0 && comma_position != input.npos) { + input_filtered = input_filtered.replace(comma_position, 0, 1, '.'); + } + try { + result = stod(input_filtered); + return NUMBER_PARSE_OKAY; + } + catch (const std::invalid_argument& ia) + { + printf("[strToDouble] exception: invalid argument: %s\n", ia.what()); + return NUMBER_PARSE_INVALID_ARGUMENT; + } + catch (const std::out_of_range& oor) + { + printf("[strToDouble] exception: out or range: %s\n", oor.what()); + return NUMBER_PARSE_OUT_OF_RANGE; + } + catch (const std::logic_error & ler) + { + printf("[strToDouble] exception: logical error: %s\n", ler.what()); + return NUMBER_PARSE_LOGIC_ERROR; + } + } + const char* numberParseStateToString(NumberParseState state) { switch (state) { diff --git a/src/cpp/lib/DataTypeConverter.h b/src/cpp/lib/DataTypeConverter.h index d970d697d..933fdfb74 100644 --- a/src/cpp/lib/DataTypeConverter.h +++ b/src/cpp/lib/DataTypeConverter.h @@ -23,6 +23,7 @@ namespace DataTypeConverter { NumberParseState strToInt(const std::string& input, int& result); NumberParseState strToInt(const std::string& input, unsigned long long& result); + NumberParseState strToDouble(const std::string& input, double& result); MemoryBin* hexToBin(const std::string& hexString); MemoryBin* base64ToBin(const std::string& base64String); diff --git a/src/cpp/model/hedera/ConsensusSubmitMessage.cpp b/src/cpp/model/hedera/ConsensusSubmitMessage.cpp index e69de29bb..18da97c73 100644 --- a/src/cpp/model/hedera/ConsensusSubmitMessage.cpp +++ b/src/cpp/model/hedera/ConsensusSubmitMessage.cpp @@ -0,0 +1,42 @@ +#include "ConsensusSubmitMessage.h" + +namespace model { + namespace hedera { + ConsensusSubmitMessage::ConsensusSubmitMessage(Poco::AutoPtr topicID) + : mConsensusMessageBody(nullptr) + { + mConsensusMessageBody = new proto::ConsensusSubmitMessageTransactionBody; + topicID->copyToProtoTopicId(mConsensusMessageBody->mutable_topicid()); + } + + ConsensusSubmitMessage::~ConsensusSubmitMessage() + { + if (mConsensusMessageBody) { + delete mConsensusMessageBody; + mConsensusMessageBody = nullptr; + } + } + + bool ConsensusSubmitMessage::validate() + { + // TODO: unpack gradido transaction and make simple validation check + assert(mConsensusMessageBody); + if (0 == mConsensusMessageBody->message().size()) { + printf("[ConsensusSubmitMessage::validate] empty message\n"); + return false; + } + if (!mConsensusMessageBody->has_topicid()) { + printf("[ConsensusSubmitMessage::validate] empty topic id\n"); + return false; + } + + return true; + } + + void ConsensusSubmitMessage::setMessage(std::string byteString) + { + assert(mConsensusMessageBody); + mConsensusMessageBody->set_message(byteString); + } + } +} \ No newline at end of file diff --git a/src/cpp/model/hedera/ConsensusSubmitMessage.h b/src/cpp/model/hedera/ConsensusSubmitMessage.h index e69de29bb..d08b72279 100644 --- a/src/cpp/model/hedera/ConsensusSubmitMessage.h +++ b/src/cpp/model/hedera/ConsensusSubmitMessage.h @@ -0,0 +1,32 @@ +#ifndef __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_SUBMIT_MESSAGE_H +#define __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_SUBMIT_MESSAGE_H + +#include "../../proto/hedera/ConsensusSubmitMessage.pb.h" +#include "../../controller/HederaId.h" + +namespace model { + namespace hedera { + + class ConsensusSubmitMessage + { + public: + ConsensusSubmitMessage(Poco::AutoPtr topicID); + ~ConsensusSubmitMessage(); + + inline proto::ConsensusSubmitMessageTransactionBody* getProtoTransactionBody() { return mConsensusMessageBody; } + inline void resetPointer() { mConsensusMessageBody = nullptr; } + void setMessage(std::string byteString); + inline void setMessage(const MemoryBin* message) { setMessage(std::string((const char*)message->data(), message->size())); } + + bool validate(); + + + + protected: + proto::ConsensusSubmitMessageTransactionBody* mConsensusMessageBody; + + }; + } +} + +#endif //__GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_SUBMIT_MESSAGE_H \ No newline at end of file diff --git a/src/cpp/model/hedera/CryptoCreateTransaction.cpp b/src/cpp/model/hedera/CryptoCreateTransaction.cpp index 696a8d6e7..1c5d58e11 100644 --- a/src/cpp/model/hedera/CryptoCreateTransaction.cpp +++ b/src/cpp/model/hedera/CryptoCreateTransaction.cpp @@ -3,14 +3,32 @@ namespace model { namespace hedera { - CryptoCreateTransaction::CryptoCreateTransaction() + CryptoCreateTransaction::CryptoCreateTransaction(const unsigned char* publicKey, Poco::UInt64 initialBalance, int autoRenewPeriod) { + mCryptoCreateBody = new proto::CryptoCreateTransactionBody; + // public key + auto key = mCryptoCreateBody->mutable_key(); + auto public_key = new std::string((const char*)publicKey, KeyPairHedera::getPublicKeySize()); + key->set_allocated_ed25519(public_key); + + mCryptoCreateBody->set_initialbalance(initialBalance); + + auto auto_renew_period = mCryptoCreateBody->mutable_autorenewperiod(); + auto_renew_period->set_seconds(autoRenewPeriod); + } CryptoCreateTransaction::~CryptoCreateTransaction() { - + if (mCryptoCreateBody) { + delete mCryptoCreateBody; + mCryptoCreateBody = nullptr; + } } + bool CryptoCreateTransaction::validate() + { + return true; + } } } \ No newline at end of file diff --git a/src/cpp/model/hedera/CryptoCreateTransaction.h b/src/cpp/model/hedera/CryptoCreateTransaction.h index e1425ebf5..7182f3506 100644 --- a/src/cpp/model/hedera/CryptoCreateTransaction.h +++ b/src/cpp/model/hedera/CryptoCreateTransaction.h @@ -3,15 +3,23 @@ #include "../../proto/hedera/CryptoCreate.pb.h" +#include "../Crypto/KeyPairHedera.h" + namespace model { namespace hedera { class CryptoCreateTransaction { public: - CryptoCreateTransaction(); + //! \param publicKey newly created public key from ed25519 public-private key pair for hedera + CryptoCreateTransaction(const unsigned char* publicKey, Poco::UInt64 initialBalance, int autoRenewPeriod); ~CryptoCreateTransaction(); + proto::CryptoCreateTransactionBody* getProtoTransactionBody() { return mCryptoCreateBody; } + inline void resetPointer() { mCryptoCreateBody = nullptr; } + + bool validate(); + protected: proto::CryptoCreateTransactionBody* mCryptoCreateBody; }; diff --git a/src/cpp/model/hedera/CryptoTransferTransaction.cpp b/src/cpp/model/hedera/CryptoTransferTransaction.cpp index 828a85645..171e239f4 100644 --- a/src/cpp/model/hedera/CryptoTransferTransaction.cpp +++ b/src/cpp/model/hedera/CryptoTransferTransaction.cpp @@ -43,11 +43,6 @@ namespace model { } return 0 == sum && transfers->accountamounts_size() > 0; } - - void CryptoTransferTransaction::resetPointer() - { - mCryptoTransfer = nullptr; - } } } diff --git a/src/cpp/model/hedera/CryptoTransferTransaction.h b/src/cpp/model/hedera/CryptoTransferTransaction.h index 04aacafea..21d9bd3c3 100644 --- a/src/cpp/model/hedera/CryptoTransferTransaction.h +++ b/src/cpp/model/hedera/CryptoTransferTransaction.h @@ -26,7 +26,7 @@ namespace model { bool validate(); // set pointer to zero, after hand over pointer to transaction body - void resetPointer(); + inline void resetPointer() { mCryptoTransfer = nullptr; } inline proto::CryptoTransferTransactionBody* getProtoTransactionBody() { return mCryptoTransfer; } diff --git a/src/cpp/model/hedera/Transaction.cpp b/src/cpp/model/hedera/Transaction.cpp index 4699e71ea..ab786e44f 100644 --- a/src/cpp/model/hedera/Transaction.cpp +++ b/src/cpp/model/hedera/Transaction.cpp @@ -18,6 +18,8 @@ namespace model { bool Transaction::sign(std::unique_ptr keyPairHedera, const TransactionBody* transactionBody) { + mType = transactionBody->getType(); + auto mm = MemoryManager::getInstance(); mConnection = transactionBody->getConnection(); auto transaction_body_proto = transactionBody->getProtoTransactionBody(); @@ -40,5 +42,32 @@ namespace model { mm->releaseMemory(sign); return true; } + + bool Transaction::sign(std::unique_ptr keyPairHedera, std::unique_ptr transactionBody) + { + mType = transactionBody->getType(); + + auto mm = MemoryManager::getInstance(); + mConnection = transactionBody->getConnection(); + auto transaction_body_proto = transactionBody->getProtoTransactionBody(); + auto body_bytes = transaction_body_proto->SerializeAsString(); + mTransaction->set_bodybytes(body_bytes.data(), body_bytes.size()); + auto signature_map = mTransaction->mutable_sigmap(); + auto signature_pairs = signature_map->mutable_sigpair(); + signature_map->add_sigpair(); + auto signature_pair = signature_pairs->Mutable(0); + auto public_key = keyPairHedera->getPublicKey(); + + auto sign = keyPairHedera->sign(body_bytes); + if (!sign) { + printf("[Query::sign] error signing message\n"); + return false; + } + signature_pair->set_pubkeyprefix(public_key, keyPairHedera->getPublicKeySize()); + signature_pair->set_ed25519(*sign, sign->size()); + + mm->releaseMemory(sign); + return true; + } } } \ No newline at end of file diff --git a/src/cpp/model/hedera/Transaction.h b/src/cpp/model/hedera/Transaction.h index d5e9434bd..fe1bfed51 100644 --- a/src/cpp/model/hedera/Transaction.h +++ b/src/cpp/model/hedera/Transaction.h @@ -23,14 +23,17 @@ namespace model { ~Transaction(); bool sign(std::unique_ptr keyPairHedera, const TransactionBody* transactionBody); + bool sign(std::unique_ptr keyPairHedera, std::unique_ptr transactionBody); inline proto::Transaction* getTransaction() { return mTransaction; } inline std::string getConnectionString() const { return mConnection.getUriWithPort(); } void resetPointer() { mTransaction = nullptr; } + inline TransactionBodyType getType() const { return mType; } protected: proto::Transaction* mTransaction; controller::NodeServerConnection mConnection; + TransactionBodyType mType; }; } } diff --git a/src/cpp/model/hedera/TransactionBody.cpp b/src/cpp/model/hedera/TransactionBody.cpp index f215ada23..ea44915a8 100644 --- a/src/cpp/model/hedera/TransactionBody.cpp +++ b/src/cpp/model/hedera/TransactionBody.cpp @@ -3,7 +3,7 @@ namespace model { namespace hedera { TransactionBody::TransactionBody(Poco::AutoPtr operatorAccountId, const controller::NodeServerConnection& connection) - : mConnection(connection) + : mConnection(connection), mHasBody(false) { connection.hederaId->copyToProtoAccountId(mTransactionBody.mutable_nodeaccountid()); auto transaction_id = mTransactionBody.mutable_transactionid(); @@ -22,9 +22,15 @@ namespace model { bool TransactionBody::setCryptoTransfer(CryptoTransferTransaction& cryptoTransferTransaction) { + if (mHasBody) { + printf("[TransactionBody::setCryptoTransfer] has already a body\n"); + return false; + } if (cryptoTransferTransaction.validate()) { mTransactionBody.set_allocated_cryptotransfer(cryptoTransferTransaction.getProtoTransactionBody()); cryptoTransferTransaction.resetPointer(); + mHasBody = true; + mType = TRANSACTION_CRYPTO_TRANSFER; return true; } return false; @@ -32,9 +38,47 @@ namespace model { bool TransactionBody::setCreateTopic(ConsensusCreateTopic& consensusCreateTopicTransaction) { + if (mHasBody) { + printf("[TransactionBody::setCreateTopic] has already a body\n"); + return false; + } if (consensusCreateTopicTransaction.validate()) { mTransactionBody.set_allocated_consensuscreatetopic(consensusCreateTopicTransaction.getProtoTransactionBody()); consensusCreateTopicTransaction.resetPointer(); + mHasBody = true; + mType = TRANSACTION_CONSENSUS_CREATE_TOPIC; + return true; + } + return false; + } + + bool TransactionBody::setCryptoCreate(CryptoCreateTransaction& cryptoCreateTransaction) + { + if (mHasBody) { + printf("[TransactionBody::setCryptoCreate] has already a body\n"); + return false; + } + if (cryptoCreateTransaction.validate()) { + mTransactionBody.set_allocated_cryptocreateaccount(cryptoCreateTransaction.getProtoTransactionBody()); + cryptoCreateTransaction.resetPointer(); + mHasBody = true; + mType = TRANSACTION_CRYPTO_CREATE; + return true; + } + return false; + } + + bool TransactionBody::setConsensusSubmitMessage(ConsensusSubmitMessage& consensusSubmitMessageTransaction) + { + if (mHasBody) { + printf("[TransactionBody::setConsensusSubmitMessage] has already a body\n"); + return false; + } + if (consensusSubmitMessageTransaction.validate()) { + mTransactionBody.set_allocated_consensussubmitmessage(consensusSubmitMessageTransaction.getProtoTransactionBody()); + consensusSubmitMessageTransaction.resetPointer(); + mHasBody = true; + mType = TRANSACTION_CONSENSUS_SUBMIT_MESSAGE; return true; } return false; diff --git a/src/cpp/model/hedera/TransactionBody.h b/src/cpp/model/hedera/TransactionBody.h index 7be8d2105..9a5406af7 100644 --- a/src/cpp/model/hedera/TransactionBody.h +++ b/src/cpp/model/hedera/TransactionBody.h @@ -13,12 +13,23 @@ #include "../../controller/NodeServer.h" #include "CryptoTransferTransaction.h" +#include "CryptoCreateTransaction.h" #include "ConsensusCreateTopic.h" +#include "ConsensusSubmitMessage.h" #include "../../proto/hedera/TransactionBody.pb.h" namespace model { namespace hedera { + + enum TransactionBodyType + { + TRANSACTION_CRYPTO_TRANSFER, + TRANSACTION_CRYPTO_CREATE, + TRANSACTION_CONSENSUS_CREATE_TOPIC, + TRANSACTION_CONSENSUS_SUBMIT_MESSAGE + }; + class TransactionBody { public: @@ -29,17 +40,22 @@ namespace model { void setFee(Poco::UInt64 fee); bool setCryptoTransfer(CryptoTransferTransaction& cryptoTransferTransaction); + bool setCryptoCreate(CryptoCreateTransaction& cryptoCreateTransaction); bool setCreateTopic(ConsensusCreateTopic& consensusCreateTopicTransaction); + bool setConsensusSubmitMessage(ConsensusSubmitMessage& consensusSubmitMessageTransaction); //bool inline const proto::TransactionBody* getProtoTransactionBody() const { return &mTransactionBody; } inline std::string getConnectionString() const { return mConnection.getUriWithPort(); } inline controller::NodeServerConnection getConnection() const { return mConnection; } + inline TransactionBodyType getType() const { return mType; } protected: void updateTimestamp(); proto::TransactionBody mTransactionBody; controller::NodeServerConnection mConnection; + bool mHasBody; + TransactionBodyType mType; }; } } diff --git a/src/cpp/model/hedera/TransactionResponse.cpp b/src/cpp/model/hedera/TransactionResponse.cpp new file mode 100644 index 000000000..2e9a66ea1 --- /dev/null +++ b/src/cpp/model/hedera/TransactionResponse.cpp @@ -0,0 +1,18 @@ +#include "TransactionResponse.h" + +namespace model { + namespace hedera { + + TransactionResponse::TransactionResponse() + { + + } + + TransactionResponse::~TransactionResponse() + { + + } + + + } +} \ No newline at end of file diff --git a/src/cpp/model/hedera/TransactionResponse.h b/src/cpp/model/hedera/TransactionResponse.h new file mode 100644 index 000000000..325cbe73f --- /dev/null +++ b/src/cpp/model/hedera/TransactionResponse.h @@ -0,0 +1,30 @@ +#ifndef __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_RESPONSE_H +#define __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_RESPONSE_H + +#include "../../proto/hedera/TransactionResponse.pb.h" +#include "Poco/Types.h" + +namespace model { + namespace hedera { + + class TransactionResponse + { + public: + TransactionResponse(); + ~TransactionResponse(); + + inline proto::ResponseCodeEnum getPrecheckCode() const { return mProtoResponse.nodetransactionprecheckcode();} + inline std::string getPrecheckCodeString() const { return proto::ResponseCodeEnum_Name(mProtoResponse.nodetransactionprecheckcode()); } + inline Poco::UInt64 getCost() const { return mProtoResponse.cost(); } + + proto::TransactionResponse* getProtoResponse() { return &mProtoResponse; } + protected: + proto::TransactionResponse mProtoResponse; + + }; + } +} + + + +#endif //__GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_RESPONSE_H \ No newline at end of file diff --git a/src/cpp/model/table/HederaId.cpp b/src/cpp/model/table/HederaId.cpp index d6ceb8cb7..fce86a541 100644 --- a/src/cpp/model/table/HederaId.cpp +++ b/src/cpp/model/table/HederaId.cpp @@ -16,6 +16,13 @@ namespace model { } + HederaId::HederaId(const HederaIdTuple& tuple) + : ModelBase(tuple.get<0>()), + mShardNum(tuple.get<1>()), mRealmNum(tuple.get<2>()), mNum(tuple.get<3>()) + { + + } + HederaId::~HederaId() { diff --git a/src/cpp/model/table/HederaId.h b/src/cpp/model/table/HederaId.h index 9dc2029bc..bed00168f 100644 --- a/src/cpp/model/table/HederaId.h +++ b/src/cpp/model/table/HederaId.h @@ -7,11 +7,14 @@ namespace model { namespace table { + typedef Poco::Tuple HederaIdTuple; + class HederaId : public ModelBase { public: HederaId(); HederaId(Poco::UInt64 shardNum, Poco::UInt64 realmNum, Poco::UInt64 num); + HederaId(const HederaIdTuple& tuple); ~HederaId(); // generic db operations @@ -25,7 +28,6 @@ namespace model { inline Poco::UInt64 getRealmNum() const { return mRealmNum; } inline Poco::UInt64 getNum() const { return mNum; } - protected: Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session); diff --git a/src/cpp/tasks/HederaTask.cpp b/src/cpp/tasks/HederaTask.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/tasks/HederaTask.h b/src/cpp/tasks/HederaTask.h new file mode 100644 index 000000000..0c22da226 --- /dev/null +++ b/src/cpp/tasks/HederaTask.h @@ -0,0 +1,15 @@ +#ifndef __GRADIDO_LOGIN_TASKS_HEDERA_TASKS_H +#define __GRADIDO_LOGIN_TASKS_HEDERA_TASKS_H + +#include "../model/hedera/TransactionResponse.h" + +class HederaTask +{ +public: + inline model::hedera::TransactionResponse* getTransactionResponse() { return &mTransactionResponse; } + +protected: + model::hedera::TransactionResponse mTransactionResponse; +}; + +#endif //__GRADIDO_LOGIN_TASKS_HEDERA_TASKS_H \ No newline at end of file diff --git a/src/cpp/tasks/SigningTransaction.cpp b/src/cpp/tasks/SigningTransaction.cpp index df317a270..ab1196a54 100644 --- a/src/cpp/tasks/SigningTransaction.cpp +++ b/src/cpp/tasks/SigningTransaction.cpp @@ -20,6 +20,12 @@ #include "Poco/Net/HTTPRequest.h" #include "Poco/Net/HTTPResponse.h" +// stuff for hedera transaction +#include "../controller/HederaAccount.h" +#include "../controller/HederaRequest.h" +#include "../model/hedera/TransactionBody.h" +#include "../model/hedera/Transaction.h" + SigningTransaction::SigningTransaction(Poco::AutoPtr processingeTransaction, Poco::AutoPtr newUser) : mProcessingeTransaction(processingeTransaction), mNewUser(newUser) { @@ -152,6 +158,41 @@ int SigningTransaction::run() { return -6; } + auto network_type = model::table::HEDERA_TESTNET; + auto topic_id = controller::HederaId::find(1, network_type); + auto hedera_operator_account = controller::HederaAccount::pick(network_type, false); + + if (!topic_id.isNull() && !hedera_operator_account.isNull()) { + auto crypto_key = hedera_operator_account->getCryptoKey(); + if (!crypto_key.isNull()) { + model::hedera::ConsensusSubmitMessage consensus_submit_message(topic_id); + consensus_submit_message.setMessage(finalTransactionBin); + auto hedera_transaction_body = hedera_operator_account->createTransactionBody(); + hedera_transaction_body->setConsensusSubmitMessage(consensus_submit_message); + model::hedera::Transaction hedera_transaction; + hedera_transaction.sign(crypto_key->getKeyPair(), std::move(hedera_transaction_body)); + + HederaRequest hedera_request; + HederaTask hedera_task;// placeholder + if (HEDERA_REQUEST_RETURN_OK != hedera_request.request(&hedera_transaction, &hedera_task)) { + addError(new Error("SigningTransaction", "error send transaction to hedera")); + getErrors(&hedera_request); + sendErrorsAsEmail(); + } + else { + auto hedera_precheck_code_string = hedera_task.getTransactionResponse()->getPrecheckCodeString(); + printf("hedera response: %s\n", hedera_precheck_code_string.data()); + } + //model::hedera::TransactionBody hedera_transaction_body() + } + else { + printf("[SigningTransaction] crypto key not found\n"); + } + } + else { + printf("[SigningTransaction] hedera topic id or operator account not found\n"); + } + // finale to base64 auto finalBase64Size = sodium_base64_encoded_len(finalTransactionBin.size(), sodium_base64_VARIANT_URLSAFE_NO_PADDING); auto finalBase64Bin = mm->getFreeMemory(finalBase64Size); diff --git a/src/cpsp/adminHederaAccount.cpsp b/src/cpsp/adminHederaAccount.cpsp index b55701b1b..d3d68b82c 100644 --- a/src/cpsp/adminHederaAccount.cpsp +++ b/src/cpsp/adminHederaAccount.cpsp @@ -24,6 +24,9 @@ auto sm = SessionManager::getInstance(); auto mm = MemoryManager::getInstance(); auto user = mSession->getNewUser(); + int auto_renew_period = 604800; // 7 Tage + int auto_renew_account = 0; + double initial_balance = 0.0; Profiler hedera_time; std::string hedera_time_string; @@ -59,8 +62,11 @@ if(action == "updateBalance") { hedera_time.reset(); - query_hedera_account->hederaAccountGetBalance(user); - addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string())); + if(query_hedera_account->hederaAccountGetBalance(user)) { + addNotification(new ParamSuccess("Hedera", "crypto get balance success in ", hedera_time.string())); + } else { + addError(new ParamError("Hedera", "crypto get balance failed in ", hedera_time.string())); + } } else if(action == "changeEncryption") { @@ -69,113 +75,150 @@ } } } - else if(!form.empty()) // add + else if(!form.empty()) // add or create { - // collect - auto shardNumString = form.get("account-shard-num", "0"); - auto realmNumString = form.get("account-realm-num", "0"); - auto numString = form.get("account-num", "0"); - auto privateKeyString = form.get("account-private-key", ""); - auto privateKeyEncryptedString = form.get("account-private-key-encrypted", "false"); - auto publicKeyString = form.get("account-public-key", ""); - auto networkTypeString = form.get("account-network-type", "0"); + auto creationButton = form.get("create",""); + if(creationButton != "") { - //printf("private key encrypted: %s\n", privateKeyEncryptedString.data()); - - int shardNum = 0; - int realmNum = 0; - int num = 0; - int networkType = 0; - - MemoryBin* private_key = nullptr; - MemoryBin* public_key = nullptr; - - // validate - if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) { - addError(new Error("Account ID", "shard num not integer")); - } else { - if(DataTypeConverter::strToInt(shardNumString, shardNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting shardNumString to int")); - } - } - if(!sm->isValid(realmNumString, VALIDATE_ONLY_INTEGER)) { - addError(new Error("Account ID", "realm num not integer")); - } else { - if(DataTypeConverter::strToInt(realmNumString, realmNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting realmNumString to int")); - } - } - if(!sm->isValid(numString, VALIDATE_ONLY_INTEGER)) { - addError(new Error("Account ID", "num not integer")); - } else { - if(DataTypeConverter::strToInt(numString, num) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting num to int")); - } - } - if(!sm->isValid(privateKeyString, VALIDATE_ONLY_HEX)) { - addError(new Error("Account Keys", "private key not hex")); - } - if(!sm->isValid(publicKeyString, VALIDATE_ONLY_HEX)) { - addError(new Error("Account Keys", "public key not hex")); - } - if(!sm->isValid(networkTypeString, VALIDATE_ONLY_INTEGER)) { - addError(new Error("Network Type", "not integer")); - } else { - if(DataTypeConverter::strToInt(networkTypeString, networkType) != DataTypeConverter::NUMBER_PARSE_OKAY) { - addError(new Error("Int Convert Error", "Error converting network type to int")); - } - if(networkType < 0 || networkType >= (int)model::table::HEDERA_NET_COUNT) { - addError(new Error("Network Type", "invalid value")); - } - } - - if(0 == errorCount()) { - - auto hedera_id = controller::HederaId::create(shardNum, realmNum, num); + // collect + auto auto_renew_account_string = form.get("account-auto-renew-account", "0"); + auto auto_renew_period_string = form.get("account-auto-renew-period", "604800"); + auto account_initial_balance_string = form.get("account-initial-balance", "0"); - private_key = DataTypeConverter::hexToBin(privateKeyString); - public_key = DataTypeConverter::hexToBin(publicKeyString); - - - KeyPairHedera key_pair(private_key, public_key); - auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE); - - if(crypto_key.isNull()) { - crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true"); - if(!crypto_key->getModel()->insertIntoDB(true)) { - addError(new Error("DB Error", "Error saving crypto key in DB")); - } + if(!sm->isValid(auto_renew_account_string, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account", "auto renew account id not an integer")); } else { - printf("crypto key found in db\n"); - } - if(0 == errorCount()) { - - if(hedera_id->isExistInDB()) { - auto hedera_account = controller::HederaAccount::load(hedera_id); - if(hedera_account.isNull()) { - addError(new Error("DB Error", "Couldn't load hedera account from db, but it should exist")); - } else { - addError(new Error("Hedera Account", "Account already exist (same account id")); - } - - } else { - auto hedera_account = controller::HederaAccount::create( - user->getModel()->getID(), - hedera_id->getModel()->getID(), - crypto_key->getModel()->getID(), - 0, - (model::table::HederaNetworkType)networkType - ); - if(!hedera_account->getModel()->insertIntoDB(false)) { - addError(new Error("DB Error", "Error saving hedera account into DB")); - } + if(DataTypeConverter::strToInt(auto_renew_account_string, auto_renew_account) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int convert error", "Error converting auto renew account id to int")); } } - mm->releaseMemory(private_key); - mm->releaseMemory(public_key); - } + if(!sm->isValid(auto_renew_period_string, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account", "auto renew period not an integer")); + } else { + if(DataTypeConverter::strToInt(auto_renew_period_string, auto_renew_period) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int convert error", "Error converting auto renew period to int")); + } + } + + if(!sm->isValid(account_initial_balance_string, VALIDATE_ONLY_DECIMAL)) { + addError(new Error("Account", "initial balance not an decimal")); + } else { + if(DataTypeConverter::strToDouble(account_initial_balance_string, initial_balance) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Double convert error", "Error converting initial balance to double")); + } + } + if(0 == errorCount()) + { + } + + } else { + // collect + auto shardNumString = form.get("account-shard-num", "0"); + auto realmNumString = form.get("account-realm-num", "0"); + auto numString = form.get("account-num", "0"); + auto privateKeyString = form.get("account-private-key", ""); + auto privateKeyEncryptedString = form.get("account-private-key-encrypted", "false"); + auto publicKeyString = form.get("account-public-key", ""); + auto networkTypeString = form.get("account-network-type", "0"); + + //printf("private key encrypted: %s\n", privateKeyEncryptedString.data()); + + int shardNum = 0; + int realmNum = 0; + int num = 0; + int networkType = 0; + + MemoryBin* private_key = nullptr; + MemoryBin* public_key = nullptr; + + // validate + if(!sm->isValid(shardNumString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "shard num not integer")); + } else { + if(DataTypeConverter::strToInt(shardNumString, shardNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting shardNumString to int")); + } + } + if(!sm->isValid(realmNumString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "realm num not integer")); + } else { + if(DataTypeConverter::strToInt(realmNumString, realmNum) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting realmNumString to int")); + } + } + if(!sm->isValid(numString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Account ID", "num not integer")); + } else { + if(DataTypeConverter::strToInt(numString, num) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting num to int")); + } + } + if(!sm->isValid(privateKeyString, VALIDATE_ONLY_HEX)) { + addError(new Error("Account Keys", "private key not hex")); + } + if(!sm->isValid(publicKeyString, VALIDATE_ONLY_HEX)) { + addError(new Error("Account Keys", "public key not hex")); + } + if(!sm->isValid(networkTypeString, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Network Type", "not integer")); + } else { + if(DataTypeConverter::strToInt(networkTypeString, networkType) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting network type to int")); + } + if(networkType < 0 || networkType >= (int)model::table::HEDERA_NET_COUNT) { + addError(new Error("Network Type", "invalid value")); + } + } + + if(0 == errorCount()) { + + auto hedera_id = controller::HederaId::create(shardNum, realmNum, num); + + private_key = DataTypeConverter::hexToBin(privateKeyString); + public_key = DataTypeConverter::hexToBin(publicKeyString); + + + KeyPairHedera key_pair(private_key, public_key); + auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE); + + if(crypto_key.isNull()) { + crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true"); + if(!crypto_key->getModel()->insertIntoDB(true)) { + addError(new Error("DB Error", "Error saving crypto key in DB")); + } + } else { + printf("crypto key found in db\n"); + } + if(0 == errorCount()) { + + if(hedera_id->isExistInDB()) { + auto hedera_account = controller::HederaAccount::load(hedera_id); + if(hedera_account.isNull()) { + addError(new Error("DB Error", "Couldn't load hedera account from db, but it should exist")); + } else { + addError(new Error("Hedera Account", "Account already exist (same account id")); + } + + } else { + auto hedera_account = controller::HederaAccount::create( + user->getModel()->getID(), + hedera_id->getModel()->getID(), + crypto_key->getModel()->getID(), + 0, + (model::table::HederaNetworkType)networkType + ); + if(!hedera_account->getModel()->insertIntoDB(false)) { + addError(new Error("DB Error", "Error saving hedera account into DB")); + } + } + } + + mm->releaseMemory(private_key); + mm->releaseMemory(public_key); + } + } } if(!query_hedera_account.isNull()) { getErrors(query_hedera_account); @@ -184,6 +227,14 @@ auto hedera_accounts = controller::HederaAccount::load("user_id", user->getModel()->getID()); %><%@ include file="header_large.cpsp" %> + <%= getErrorsHtml() %>
    @@ -207,13 +258,14 @@ if(hedera_account_model->getUserId() == user->getModel()->getID()) { changeEncryption = ServerConfig::g_serverPath + "/hedera_account?action=changeEncryption&account_id=" + std::to_string(hedera_account_model->getID()); } + auto isEncrypted = (*it)->getCryptoKey()->getModel()->isEncrypted(); //printf("change encryption: %s\n", changeEncryption.data()); %>
    <%= (*it)->getHederaId()->getModel()->toString() %>
    <%= hedera_account_model->getBalanceDouble() %> hbar
    <%= model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) %>
    -
    <%= (*it)->getCryptoKey()->getModel()->isEncrypted() ? "Ja": "Nein" %>
    +
    "><%= isEncrypted ? "Ja": "Nein" %>
    <%= hedera_account_model->getUpdatedString() %>
    -

    Einen neuen Account anlegen

    +

    Ein existierenden Account eintragen

    @@ -248,8 +300,39 @@ <% } %> - "> + "> +
    +
    +
    +

    Ein neuen Account anlegen

    +

    Bei Hedera einen neuen Account anlegen und zum Start Hashbars von einem existierenden Account überweisen.

    +
    +
    +
    + + + +
    + + + ">
    <%@ include file="footer.cpsp" %> + + From 4cd082bc944f86254d0333db7104ec3e4cbf29eb Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 15 Sep 2020 14:34:13 +0200 Subject: [PATCH 033/293] add tests for hedera account and hedera id for faster fixing mysql error --- CMakeLists.txt | 3 +- src/cpp/test/controller/TestHederaAccount.cpp | 14 ++ src/cpp/test/controller/TestHederaAccount.h | 13 ++ src/cpp/test/controller/TestHederaId.cpp | 14 ++ src/cpp/test/controller/TestHederaId.h | 13 ++ src/cpp/test/controller/TestHederaTopic.cpp | 0 src/cpp/test/controller/TestHederaTopic.h | 0 src/cpp/test/main.cpp | 196 ++++++++++++++++++ 8 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 src/cpp/test/controller/TestHederaAccount.cpp create mode 100644 src/cpp/test/controller/TestHederaAccount.h create mode 100644 src/cpp/test/controller/TestHederaId.cpp create mode 100644 src/cpp/test/controller/TestHederaId.h create mode 100644 src/cpp/test/controller/TestHederaTopic.cpp create mode 100644 src/cpp/test/controller/TestHederaTopic.h diff --git a/CMakeLists.txt b/CMakeLists.txt index fc2eb1771..c8cbe2e74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -213,11 +213,12 @@ enable_testing() add_executable(Gradido_LoginServer_Test ${LOCAL_SRCS} ${LOCAL_TEST_SRC}) target_compile_definitions(Gradido_LoginServer_Test PUBLIC "_TEST_BUILD") -target_link_libraries(Gradido_LoginServer_Test ${CONAN_LIBS} ${IROHA_ED25519}) +target_link_libraries(Gradido_LoginServer_Test absl::base absl::flat_hash_map absl::flags absl::memory absl::meta absl::numeric absl::strings ${CONAN_LIBS} ${IROHA_ED25519}) if(WIN32) TARGET_LINK_LIBRARIES(Gradido_LoginServer_Test optimized ${MYSQL_LIBRARIES} Shlwapi) TARGET_LINK_LIBRARIES(Gradido_LoginServer_Test debug ${COMPILED_MARIADB_CLIENT_DEBUG} Shlwapi) + TARGET_LINK_LIBRARIES(Gradido_LoginServer_Test debug ${GRPC_LIBS} ${PROTOBUF_DEBUG_LIBS}) else(WIN32) target_link_libraries(Gradido_LoginServer_Test libmariadb protoc protobuf -pthread) endif(WIN32) diff --git a/src/cpp/test/controller/TestHederaAccount.cpp b/src/cpp/test/controller/TestHederaAccount.cpp new file mode 100644 index 000000000..2300dc60b --- /dev/null +++ b/src/cpp/test/controller/TestHederaAccount.cpp @@ -0,0 +1,14 @@ +#include "TestHederaAccount.h" +#include "../SingletonManager/ConnectionManager.h" +namespace controller { + + void TestHederaAccount::SetUp() + { + + } + + TEST_F(TestHederaAccount, TestPick) { + auto hedera_account = controller::HederaAccount::pick(model::table::HEDERA_TESTNET, false); + EXPECT_FALSE(hedera_account.isNull()); + } +} \ No newline at end of file diff --git a/src/cpp/test/controller/TestHederaAccount.h b/src/cpp/test/controller/TestHederaAccount.h new file mode 100644 index 000000000..7e8e7843a --- /dev/null +++ b/src/cpp/test/controller/TestHederaAccount.h @@ -0,0 +1,13 @@ +#include "gtest/gtest.h" + +#include "../controller/HederaAccount.h" + + +namespace controller { + + class TestHederaAccount : public ::testing::Test { + protected: + void SetUp() override; + }; + +} \ No newline at end of file diff --git a/src/cpp/test/controller/TestHederaId.cpp b/src/cpp/test/controller/TestHederaId.cpp new file mode 100644 index 000000000..ad17e0933 --- /dev/null +++ b/src/cpp/test/controller/TestHederaId.cpp @@ -0,0 +1,14 @@ +#include "TestHederaId.h" +#include "../SingletonManager/ConnectionManager.h" +namespace controller { + + void TestHederaId::SetUp() + { + + } + + TEST_F(TestHederaId, TestFindTopicId) { + auto hedera_topic_id = controller::HederaId::find(1, model::table::HEDERA_TESTNET); + EXPECT_FALSE(hedera_topic_id.isNull()); + } +} \ No newline at end of file diff --git a/src/cpp/test/controller/TestHederaId.h b/src/cpp/test/controller/TestHederaId.h new file mode 100644 index 000000000..b6e4b574e --- /dev/null +++ b/src/cpp/test/controller/TestHederaId.h @@ -0,0 +1,13 @@ +#include "gtest/gtest.h" + +#include "../controller/HederaId.h" + + +namespace controller { + + class TestHederaId : public ::testing::Test { + protected: + void SetUp() override; + }; + +} \ No newline at end of file diff --git a/src/cpp/test/controller/TestHederaTopic.cpp b/src/cpp/test/controller/TestHederaTopic.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/test/controller/TestHederaTopic.h b/src/cpp/test/controller/TestHederaTopic.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/test/main.cpp b/src/cpp/test/main.cpp index 5fcab4163..62482c664 100644 --- a/src/cpp/test/main.cpp +++ b/src/cpp/test/main.cpp @@ -8,6 +8,8 @@ #include "../SingletonManager/ConnectionManager.h" +#include "../lib/Profiler.h" + std::list gTests; @@ -20,6 +22,21 @@ void fillTests() // gTests.push_back(new LoginTest()); } +void runMysql(std::string sqlQuery) +{ + auto cm = ConnectionManager::getInstance(); + auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + Poco::Data::Statement mysqlStatement(session); + mysqlStatement << sqlQuery; + + try { + mysqlStatement.execute(true); + } + catch (Poco::Exception& ex) { + printf("exception in runMysql: %s\n", ex.displayText().data()); + } +} + int load() { // init server config, init seed array @@ -54,7 +71,186 @@ int load() { //printf("try connect php server mysql \n"); conn->setConnectionsFromConfig(*test_config, CONNECTION_MYSQL_PHP_SERVER); + Profiler timeUsed; + // clean up and fill db + std::string tables[] = { + "hedera_accounts", + "hedera_ids", + "crypto_keys", + "hedera_topics", + "groups", + "node_servers", + "users" + }; + for (int i = 0; i < 7; i++) { + runMysql("TRUNCATE " + tables[i]); + runMysql("ALTER TABLE " + tables[i] + " AUTO_INCREMENT = 1"); + } + + std::stringstream ss; + ss << "INSERT INTO `users` (`id`, `email`, `first_name`, `last_name`, `password`, `pubkey`, `privkey`, `created`, `email_checked`, `passphrase_shown`, `language`, `disabled`) VALUES " + << "(1, 'einhorn_silas@ist-allein.info', 'DDD', 'Schultz', 13134558453895551556, 0x146d3fb9e88abc0fca0b0091c1ab1b32b399be037436f340befa8bf004461889, 0x0dcc08960f45f631fe23bc7ddee0724cedc9ec0c861ce30f5091d20ffd96062d08ca215726fb9bd64860c754772e945eea4cc872ed0a36c7b640e8b0bf7a873ec6765fa510711622341347ce2307b5ce, '2020-02-20 16:05:44', 1, 0, 'de', 0), " + << "(2, 'Dario.Rekowski@buerotiger.de', 'Darios', 'Bruder', 12910944485867375321, 0x952e215a21d4376b4ac252c4bf41e156e1498e1b6b8ccf2a6826d96712f4f461, 0x4d40bf0860655f728312140dc3741e897bc2d13d00ea80a63e2961046a5a7bd8315397dfb488b89377087bc1a5f4f3af8ffdcf203329ae23ba04be7d38ad3852699d90ff1fc00e5b1ca92b64cc59c01f, '2020-02-20 16:05:44', 1, 0, 'de', 0), " + << "(3, 'morgenstern175@es-ist-liebe.de', 'Dieter', 'Schultz', 13528673707291575501, 0xb539944bf6444a2bfc988244f0c0c9dc326452be9b8a2a43fcd90663719f4f6d, 0x5461fda60b719b65ba00bd6298e48410c4cbf0e89deb13cc784ba8978cf047454e8556ee3eddc8487ee835c33a83163bc8d8babbf2a5c431876bc0a0c114ff0a0d6b57baa12cf8f23c64fb642c862db5, '2020-02-20 16:05:45', 1, 0, 'de', 0), " + << "(4, 'spaceteam@gmx.de', 'Bernd', 'Hückstädt', 15522411320147607375, 0x476b059744f08b0995522b484c90f8d2f47d9b59f4b3c96d9dc0ae6ab7b84979, 0x5277bf044cba4fec64e6f4d38da132755b029161231daefc9a7b4692ad37e05cdd88e0a2c2215baf854dd3a813578c214167af1113607e9f999ca848a7598ba5068e38f2a1afb097e4752a88024d79c8, '2020-02-20 16:05:46', 1, 0, 'de', 0), " + << "(5, 'em741@gmx.de', 'Thomas', 'Markuk', 7022671043835614958, 0xb1584e169d60a7e771d3a348235dfd7b5f9e8235fcc26090761a0264b0daa6ff, 0xb46fb7110bf91e28f367aa80f84d1bbd639b6f689f4b0aa28c0f71529232df9bf9ee0fb02fa4c1b9f5a6799c82d119e5646f7231d011517379faaacf6513d973ac3043d4c786490ba62d56d75b86164d, '2020-02-20 16:05:46', 1, 0, 'de', 0), " + << "(6, 'coin-info12@gradido.net', 'coin-info12', 'Test', 1548398919826089202, 0x4046ae49c1b620f2a321aba0c874fa2bc7ba844ab808bb0eeb18a908d468db14, 0x9522657ecd7456eedf86d065aa087ba7a94a8961a8e4950d044136155d38fe0840f2c0a2876ce055b3eaa6e9ab95c5feba89e535e0434fb2648d94d6e6ec68211aa2ea9e42d1ccd40b6b3c31e41f848e, '2020-02-20 16:05:47', 1, 0, 'de', 0), " + << "(7, 'info@einhornimmond.de', 'Alex', 'Wesper', 5822761891727948301, 0xb13ede3402abb8f29722b14fec0a2006ae7a3a51fb677cd6a2bbd797ac6905a5, 0x6aa39d7670c64a31639c7d89b874ad929b2eaeb2e5992dbad71b6cea700bf9e3c6cf866d0f0fdc22b44a0ebf51a860799e880ef86266199931dd0a301e5552db44b9b7fa99ed5945652bc7b31eff767c, '2020-02-20 16:05:47', 1, 0, 'de', 0); "; + runMysql(ss.str()); + ss.str(std::string()); + + ss << "INSERT INTO `groups` (`id`, `alias`, `name`, `url`, `description`) VALUES " + << "(1, 'gdd1', 'Gradido1', 'gdd1.gradido.com', 'Der erste offizielle Gradido Server (zum Testen)'); "; + runMysql(ss.str()); + ss.str(std::string()); + + ss << "INSERT INTO `hedera_accounts` (`id`, `user_id`, `account_hedera_id`, `account_key_id`, `balance`, `network_type`, `updated`) VALUES " + << "(1, 2, 15, 1, 1000000000000, 1, '2020-09-03 11:13:52'), " + << "(2, 2, 17, 2, 22787166159, 0, '2020-09-03 11:13:56'); "; + runMysql(ss.str()); + ss.str(std::string()); + + ss << "INSERT INTO `hedera_ids` (`id`, `shardNum`, `realmNum`, `num`) VALUES " + << "(1, 0, 0, 3), " + << "(2, 0, 0, 4)," + << "(3, 0, 0, 5)," + << "(4, 0, 0, 6)," + << "(6, 0, 0, 3)," + << "(10, 0, 0, 7)," + << "(11, 0, 0, 8)," + << "(12, 0, 0, 9)," + << "(13, 0, 0, 10)," + << "(14, 0, 0, 12)," + << "(15, 0, 0, 3327)," + << "(16, 0, 0, 3323)," + << "(17, 0, 0, 8707)," + << "(18, 0, 0, 39446);"; + runMysql(ss.str()); + ss.str(std::string()); + + ss << "INSERT INTO `crypto_keys` (`id`, `private_key`, `public_key`, `crypto_key_type_id`) VALUES " + << "(1, 0xd2d4735174e6d2577573a0ec2767fba6511b1e37cd1cd98674912797fd37e12373d6b4d771034cc114f80b2afb2956b6b3e020ddea2db1142c61f3fa87c72a6c, 0x73d6b4d771034cc114f80b2afb2956b6b3e020ddea2db1142c61f3fa87c72a6c, 3), " + << "(2, 0xf1c3285be6ef869a2a8deef6caee56a5a7c2660e2bce24f39e420dd8d42fe8894bd027b2799e46dc7111a4fdd0eac3848054331f844a358de15c5b0ed3eb1740fab13ecb5a271d480e040c9266bcd584, 0xd6f6d29fb277f86ac7c3098dc799028974223e8dce6b1dd57b03940bf35fae7f, 1); "; + runMysql(ss.str()); + ss.str(std::string()); + + ss << "INSERT INTO `hedera_topics` (`id`, `topic_hedera_id`, `name`, `auto_renew_account_hedera_id`, `auto_renew_period`, `group_id`, `admin_key_id`, `submit_key_id`, `current_timeout`, `sequence_number`, `updated`) VALUES " + << "(1, 18, 'from Pauls created with his python script', 1, 0, 1, NULL, NULL, '1999-12-31 23:00:00', 0, '2020-09-14 18:29:04'); "; + runMysql(ss.str()); + ss.str(std::string()); + + ss << "INSERT INTO `node_servers` (`id`, `url`, `port`, `group_id`, `server_type`, `node_hedera_id`, `last_live_sign`) VALUES " + << "(1, 'http://0.testnet.hedera.com', 50211, 0, 4, 1, '2000-01-01 00:00:00'), " + << "(2, 'http://1.testnet.hedera.com', 50211, 0, 4, 2, '2000-01-01 00:00:00'), " + << "(3, 'http://2.testnet.hedera.com', 50211, 0, 4, 3, '2000-01-01 00:00:00'), " + << "(4, 'http://3.testnet.hedera.com', 50211, 0, 4, 4, '2000-01-01 00:00:00'), " + << "(5, 'http://35.237.200.180', 50211, 0, 3, 6, '2000-01-01 00:00:00'), " + << "(6, 'http://35.186.191.247', 50211, 0, 3, 2, '2000-01-01 00:00:00'), " + << "(7, 'http://35.192.2.25', 50211, 0, 3, 3, '2000-01-01 00:00:00'), " + << "(8, 'http://35.199.161.108', 50211, 0, 3, 4, '2000-01-01 00:00:00'), " + << "(9, 'http://35.203.82.240', 50211, 0, 3, 10, '2000-01-01 00:00:00'), " + << "(10, 'http://35.236.5.219', 50211, 0, 3, 11, '2000-01-01 00:00:00'), " + << "(11, 'http://35.197.192.225', 50211, 0, 3, 12, '2000-01-01 00:00:00'), " + << "(12, 'http://35.242.233.154', 50211, 0, 3, 13, '2000-01-01 00:00:00'), " + << "(13, 'http://35.240.118.96', 50211, 0, 3, 12, '2000-01-01 00:00:00'), " + << "(14, 'http://35.204.86.32', 50211, 0, 3, 14, '2000-01-01 00:00:00'), " + << "(15, 'https://gradido.dario-rekowski.de/', 443, 1, 2, 0, '2000-01-01 00:00:00'), " + << "(16, 'http://192.168.178.232', 8340, 1, 1, 0, '2000-01-01 00:00:00'); "; + runMysql(ss.str()); + + printf("init db in : %s\n", timeUsed.string().data()); + + /*mysqlStatement + << "TRUNCATE hedera_accounts; " + << "ALTER TABLE hedera_accounts AUTO_INCREMENT = 1; " + << "TRUNCATE hedera_ids; " + << "ALTER TABLE hedera_ids AUTO_INCREMENT = 1; " + << "TRUNCATE crypto_keys; " + << "ALTER TABLE crypto_keys AUTO_INCREMENT = 1; " + << "TRUNCATE hedera_topics; " + << "ALTER TABLE hedera_topics AUTO_INCREMENT = 1; " + << "TRUNCATE groups; " + << "ALTER TABLE groups AUTO_INCREMENT = 1; " + << "TRUNCATE node_servers; " + << "ALTER TABLE node_servers AUTO_INCREMENT = 1; " + << "TRUNCATE users; " + << "ALTER TABLE users AUTO_INCREMENT = 1; " + ; + + try { + mysqlStatement.execute(true); + } + catch (Poco::Exception& ex) { + printf("exception by cleaning up db: %s\n", ex.displayText().data()); + } + mysqlStatement.reset(session); + mysqlStatement + << "INSERT INTO `users` (`id`, `email`, `first_name`, `last_name`, `password`, `pubkey`, `privkey`, `created`, `email_checked`, `passphrase_shown`, `language`, `disabled`) VALUES " + << "(1, 'einhorn_silas@ist-allein.info', 'DDD', 'Schultz', 13134558453895551556, 0x146d3fb9e88abc0fca0b0091c1ab1b32b399be037436f340befa8bf004461889, 0x0dcc08960f45f631fe23bc7ddee0724cedc9ec0c861ce30f5091d20ffd96062d08ca215726fb9bd64860c754772e945eea4cc872ed0a36c7b640e8b0bf7a873ec6765fa510711622341347ce2307b5ce, '2020-02-20 16:05:44', 1, 0, 'de', 0), " + << "(2, 'Dario.Rekowski@buerotiger.de', 'Darios', 'Bruder', 12910944485867375321, 0x952e215a21d4376b4ac252c4bf41e156e1498e1b6b8ccf2a6826d96712f4f461, 0x4d40bf0860655f728312140dc3741e897bc2d13d00ea80a63e2961046a5a7bd8315397dfb488b89377087bc1a5f4f3af8ffdcf203329ae23ba04be7d38ad3852699d90ff1fc00e5b1ca92b64cc59c01f, '2020-02-20 16:05:44', 1, 0, 'de', 0), " + << "(3, 'morgenstern175@es-ist-liebe.de', 'Dieter', 'Schultz', 13528673707291575501, 0xb539944bf6444a2bfc988244f0c0c9dc326452be9b8a2a43fcd90663719f4f6d, 0x5461fda60b719b65ba00bd6298e48410c4cbf0e89deb13cc784ba8978cf047454e8556ee3eddc8487ee835c33a83163bc8d8babbf2a5c431876bc0a0c114ff0a0d6b57baa12cf8f23c64fb642c862db5, '2020-02-20 16:05:45', 1, 0, 'de', 0), " + << "(4, 'spaceteam@gmx.de', 'Bernd', 'Hückstädt', 15522411320147607375, 0x476b059744f08b0995522b484c90f8d2f47d9b59f4b3c96d9dc0ae6ab7b84979, 0x5277bf044cba4fec64e6f4d38da132755b029161231daefc9a7b4692ad37e05cdd88e0a2c2215baf854dd3a813578c214167af1113607e9f999ca848a7598ba5068e38f2a1afb097e4752a88024d79c8, '2020-02-20 16:05:46', 1, 0, 'de', 0), " + << "(5, 'em741@gmx.de', 'Thomas', 'Markuk', 7022671043835614958, 0xb1584e169d60a7e771d3a348235dfd7b5f9e8235fcc26090761a0264b0daa6ff, 0xb46fb7110bf91e28f367aa80f84d1bbd639b6f689f4b0aa28c0f71529232df9bf9ee0fb02fa4c1b9f5a6799c82d119e5646f7231d011517379faaacf6513d973ac3043d4c786490ba62d56d75b86164d, '2020-02-20 16:05:46', 1, 0, 'de', 0), " + << "(6, 'coin-info12@gradido.net', 'coin-info12', 'Test', 1548398919826089202, 0x4046ae49c1b620f2a321aba0c874fa2bc7ba844ab808bb0eeb18a908d468db14, 0x9522657ecd7456eedf86d065aa087ba7a94a8961a8e4950d044136155d38fe0840f2c0a2876ce055b3eaa6e9ab95c5feba89e535e0434fb2648d94d6e6ec68211aa2ea9e42d1ccd40b6b3c31e41f848e, '2020-02-20 16:05:47', 1, 0, 'de', 0), " + << "(7, 'info@einhornimmond.de', 'Alex', 'Wesper', 5822761891727948301, 0xb13ede3402abb8f29722b14fec0a2006ae7a3a51fb677cd6a2bbd797ac6905a5, 0x6aa39d7670c64a31639c7d89b874ad929b2eaeb2e5992dbad71b6cea700bf9e3c6cf866d0f0fdc22b44a0ebf51a860799e880ef86266199931dd0a301e5552db44b9b7fa99ed5945652bc7b31eff767c, '2020-02-20 16:05:47', 1, 0, 'de', 0); " + + << "INSERT INTO `groups` (`id`, `alias`, `name`, `url`, `description`) VALUES " + << "(1, 'gdd1', 'Gradido1', 'gdd1.gradido.com', 'Der erste offizielle Gradido Server (zum Testen)'); " + + << "INSERT INTO `hedera_accounts` (`id`, `user_id`, `account_hedera_id`, `account_key_id`, `balance`, `network_type`, `updated`) VALUES " + << "(1, 2, 15, 1, 1000000000000, 1, '2020-09-03 11:13:52'), " + << "(2, 2, 17, 2, 22787166159, 0, '2020-09-03 11:13:56'); " + + << "INSERT INTO `hedera_ids` (`id`, `shardNum`, `realmNum`, `num`) VALUES " + << "(1, 0, 0, 3), " + << "(2, 0, 0, 4)," + << "(3, 0, 0, 5)," + << "(4, 0, 0, 6)," + << "(6, 0, 0, 3)," + << "(10, 0, 0, 7)," + << "(11, 0, 0, 8)," + << "(12, 0, 0, 9)," + << "(13, 0, 0, 10)," + << "(14, 0, 0, 12)," + << "(15, 0, 0, 3327)," + << "(16, 0, 0, 3323)," + << "(17, 0, 0, 8707)," + << "(18, 0, 0, 39446);" + + << "INSERT INTO `crypto_keys` (`id`, `private_key`, `public_key`, `crypto_key_type_id`) VALUES " + << "(1, 0xd2d4735174e6d2577573a0ec2767fba6511b1e37cd1cd98674912797fd37e12373d6b4d771034cc114f80b2afb2956b6b3e020ddea2db1142c61f3fa87c72a6c, 0x73d6b4d771034cc114f80b2afb2956b6b3e020ddea2db1142c61f3fa87c72a6c, 3), " + << "(2, 0xf1c3285be6ef869a2a8deef6caee56a5a7c2660e2bce24f39e420dd8d42fe8894bd027b2799e46dc7111a4fdd0eac3848054331f844a358de15c5b0ed3eb1740fab13ecb5a271d480e040c9266bcd584, 0xd6f6d29fb277f86ac7c3098dc799028974223e8dce6b1dd57b03940bf35fae7f, 1); " + + << "INSERT INTO `hedera_topics` (`id`, `topic_hedera_id`, `name`, `auto_renew_account_hedera_id`, `auto_renew_period`, `group_id`, `admin_key_id`, `submit_key_id`, `current_timeout`, `sequence_number`, `updated`) VALUES " + << "(1, 18, 'from Pauls created with his python script', 1, 0, 1, NULL, NULL, '1999-12-31 23:00:00', 0, '2020-09-14 18:29:04'); " + + << "INSERT INTO `node_servers` (`id`, `url`, `port`, `group_id`, `server_type`, `node_hedera_id`, `last_live_sign`) VALUES " + << "(1, 'http://0.testnet.hedera.com', 50211, 0, 4, 1, '2000-01-01 00:00:00'), " + << "(2, 'http://1.testnet.hedera.com', 50211, 0, 4, 2, '2000-01-01 00:00:00'), " + << "(3, 'http://2.testnet.hedera.com', 50211, 0, 4, 3, '2000-01-01 00:00:00'), " + << "(4, 'http://3.testnet.hedera.com', 50211, 0, 4, 4, '2000-01-01 00:00:00'), " + << "(5, 'http://35.237.200.180', 50211, 0, 3, 6, '2000-01-01 00:00:00'), " + << "(6, 'http://35.186.191.247', 50211, 0, 3, 2, '2000-01-01 00:00:00'), " + << "(7, 'http://35.192.2.25', 50211, 0, 3, 3, '2000-01-01 00:00:00'), " + << "(8, 'http://35.199.161.108', 50211, 0, 3, 4, '2000-01-01 00:00:00'), " + << "(9, 'http://35.203.82.240', 50211, 0, 3, 10, '2000-01-01 00:00:00'), " + << "(10, 'http://35.236.5.219', 50211, 0, 3, 11, '2000-01-01 00:00:00'), " + << "(11, 'http://35.197.192.225', 50211, 0, 3, 12, '2000-01-01 00:00:00'), " + << "(12, 'http://35.242.233.154', 50211, 0, 3, 13, '2000-01-01 00:00:00'), " + << "(13, 'http://35.240.118.96', 50211, 0, 3, 12, '2000-01-01 00:00:00'), " + << "(14, 'http://35.204.86.32', 50211, 0, 3, 14, '2000-01-01 00:00:00'), " + << "(15, 'https://gradido.dario-rekowski.de/', 443, 1, 2, 0, '2000-01-01 00:00:00'), " + << "(16, 'http://192.168.178.232', 8340, 1, 1, 0, '2000-01-01 00:00:00'); " + ; + + try { + mysqlStatement.execute(); + } + catch (Poco::Exception& ex) { + printf("exception by init db with data: %s\n", ex.displayText().data()); + } + */ fillTests(); for (std::list::iterator it = gTests.begin(); it != gTests.end(); it++) { From 01bf8a3870111cca21af86101925d310e6eb974e Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 15 Sep 2020 14:35:12 +0200 Subject: [PATCH 034/293] fix mysql error, cast enum to int before using in poco data use --- src/cpp/controller/HederaAccount.cpp | 21 +++++++++++++++------ src/cpp/controller/HederaId.cpp | 10 +++++----- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/cpp/controller/HederaAccount.cpp b/src/cpp/controller/HederaAccount.cpp index 25f3c7245..4a1c45c7c 100644 --- a/src/cpp/controller/HederaAccount.cpp +++ b/src/cpp/controller/HederaAccount.cpp @@ -67,18 +67,23 @@ namespace controller { Poco::Tuple result_tuple; int crypto_key_type = encrypted ? model::table::KEY_TYPE_ED25519_HEDERA_ENCRYPTED : model::table::KEY_TYPE_ED25519_HEDERA_CLEAR; - //id, user_id, account_hedera_id, account_key_id, balance, network_type, updated + int network_type_int = (int)networkType; - select << "SELECT account.id, account.user_id, account.account_hedera_id, account.account_key_id, account.balance, i.shardNum, i.realmNum, i.num FROM hedera_accounts as account " - << "JOIN hedera_ids as i ON(i.id = account.account_hedera_id) " + select + << "SELECT account.id, account.user_id, account.account_hedera_id, account.account_key_id, account.balance, i.shardNum, i.realmNum, i.num " + << "FROM hedera_accounts as account " + << "JOIN hedera_ids as i ON(i.id = account_hedera_id) " << "JOIN crypto_keys as k ON(k.id = account.account_key_id) " - << "WHERE account.network_type = ? AND k.crypto_key_type_id = ? ORDER BY RAND() LIMIT 1 ", - into(result_tuple), use(networkType), use(crypto_key_type); + << "WHERE account.network_type = ? " + << "AND k.crypto_key_type_id = ? " + << "ORDER BY RAND() LIMIT 1 " + , into(result_tuple), use(network_type_int) , use(crypto_key_type); try { select.executeAsync(); select.wait(); - if (1 == select.rowsExtracted()) { + auto result_count = select.rowsExtracted(); + if (1 == result_count) { auto db = new model::table::HederaAccount( result_tuple.get<1>(), result_tuple.get<2>(), result_tuple.get<3>(), result_tuple.get<4>(), networkType @@ -90,10 +95,14 @@ namespace controller { hedera_account->setHederaId(hedera_id); return hedera_account; } + else if(result_count > 1) { + printf("[HederaAccount::pick] extracted rows not like expected\n"); + } } catch (Poco::Exception& ex) { auto em = ErrorManager::getInstance(); static const char* function_name = "HederaAccount::pick"; + printf("exception: %s\n", ex.displayText().data()); em->addError(new ParamError(function_name, "mysql error: ", ex.displayText())); em->addError(new ParamError(function_name, "network type: ", networkType)); em->addError(new ParamError(function_name, "encrypted: ", (int)encrypted)); diff --git a/src/cpp/controller/HederaId.cpp b/src/cpp/controller/HederaId.cpp index 3b9627c8b..9e39cd84b 100644 --- a/src/cpp/controller/HederaId.cpp +++ b/src/cpp/controller/HederaId.cpp @@ -38,23 +38,23 @@ namespace controller { auto cm = ConnectionManager::getInstance(); auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); model::table::HederaIdTuple result_tuple; + int network_type_int = (int)networkType; Poco::Data::Statement select(session); select << "SELECT h.id, h.shardNum, h.realmNum, h.num FROM hedera_ids as h " << "JOIN hedera_topics as topic ON(topic.topic_hedera_id = h.id) " << "JOIN hedera_accounts as account ON(account.id = topic.auto_renew_account_hedera_id) " << "WHERE topic.group_id = ? AND account.network_type = ?" - , into(result_tuple), use(groupId), use(networkType); + , into(result_tuple), use(groupId), use(network_type_int); try { - /*select.executeAsync(); + select.executeAsync(); select.wait(); - auto result_count = select.rowsExtracted();*/ - auto result_count = select.execute(); + auto result_count = select.rowsExtracted(); if (1 == result_count) { return new HederaId(new model::table::HederaId(result_tuple)); } - else { + else if(result_count > 1) { printf("[HederaId::find] result_count other as expected: %d\n", result_count); } } From 69e7897fddb9451f73e6c653a4d91c03f0ec9662 Mon Sep 17 00:00:00 2001 From: team-devstage Date: Tue, 15 Sep 2020 14:57:29 +0200 Subject: [PATCH 035/293] git checkout work of samir --- src/Controller/AppController.php | 1 - src/Controller/ServerUsersController.php | 2 +- src/Template/Dashboard/index.ctp | 21 +++++++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php index 94b99da73..97da257b3 100644 --- a/src/Controller/AppController.php +++ b/src/Controller/AppController.php @@ -129,7 +129,6 @@ class AppController extends Controller if ($this->Auth->user('id')) { $GLOBALS['ServerUser'] = $this->Auth->user(); } - // login server url $loginServer = Configure::read('LoginServer'); if ($loginServer && isset($loginServer['url'])) { diff --git a/src/Controller/ServerUsersController.php b/src/Controller/ServerUsersController.php index 52165bb3b..236e35b7f 100644 --- a/src/Controller/ServerUsersController.php +++ b/src/Controller/ServerUsersController.php @@ -15,7 +15,7 @@ class ServerUsersController extends AppController public function initialize() { parent::initialize(); - //$this->Auth->allow(['add', 'edit']); + $this->Auth->allow(['add', 'edit']); $this->Auth->deny('index'); } diff --git a/src/Template/Dashboard/index.ctp b/src/Template/Dashboard/index.ctp index 3e93e968a..095234222 100644 --- a/src/Template/Dashboard/index.ctp +++ b/src/Template/Dashboard/index.ctp @@ -111,4 +111,25 @@ $this->assign(
    +
    +

    Roles ...

    +
    +
    + roles + Html->link( + __('View'), + ['controller' => 'Roles', 'action' => 'index'], + ['class' => 'info-item-link'] + ); ?> +
    +
    + assign_roles + Html->link( + __('Assign Roles'), + ['controller' => 'StateUserRoles', 'action' => 'search'], + ['class' => 'info-item-link'] + ); ?> +
    +
    +
    From 8c4a354d92801b5c37d3d31a69886769ddd07c42 Mon Sep 17 00:00:00 2001 From: Dario Date: Wed, 16 Sep 2020 13:22:17 +0200 Subject: [PATCH 036/293] work on hedera task for hedera transactions async --- src/cpp/model/hedera/Transaction.cpp | 2 + src/cpp/model/hedera/Transaction.h | 2 + src/cpp/model/hedera/TransactionReceipt.cpp | 16 ++++++++ src/cpp/model/hedera/TransactionReceipt.h | 23 +++++++++++ src/cpp/model/hedera/TransactionRecord.cpp | 0 src/cpp/model/hedera/TransactionRecord.h | 0 src/cpp/tasks/HederaTask.cpp | 45 +++++++++++++++++++++ src/cpp/tasks/HederaTask.h | 36 ++++++++++++++++- src/cpp/tasks/SigningTransaction.cpp | 6 ++- 9 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 src/cpp/model/hedera/TransactionReceipt.cpp create mode 100644 src/cpp/model/hedera/TransactionReceipt.h create mode 100644 src/cpp/model/hedera/TransactionRecord.cpp create mode 100644 src/cpp/model/hedera/TransactionRecord.h diff --git a/src/cpp/model/hedera/Transaction.cpp b/src/cpp/model/hedera/Transaction.cpp index ab786e44f..779488630 100644 --- a/src/cpp/model/hedera/Transaction.cpp +++ b/src/cpp/model/hedera/Transaction.cpp @@ -58,6 +58,8 @@ namespace model { auto signature_pair = signature_pairs->Mutable(0); auto public_key = keyPairHedera->getPublicKey(); + mTransactionId = transactionBody->getProtoTransactionBody()->transactionid(); + auto sign = keyPairHedera->sign(body_bytes); if (!sign) { printf("[Query::sign] error signing message\n"); diff --git a/src/cpp/model/hedera/Transaction.h b/src/cpp/model/hedera/Transaction.h index fe1bfed51..5938a0f1e 100644 --- a/src/cpp/model/hedera/Transaction.h +++ b/src/cpp/model/hedera/Transaction.h @@ -29,11 +29,13 @@ namespace model { inline std::string getConnectionString() const { return mConnection.getUriWithPort(); } void resetPointer() { mTransaction = nullptr; } inline TransactionBodyType getType() const { return mType; } + inline proto::TransactionID getTransactionId() const { return mTransactionId; } protected: proto::Transaction* mTransaction; controller::NodeServerConnection mConnection; TransactionBodyType mType; + proto::TransactionID mTransactionId; }; } } diff --git a/src/cpp/model/hedera/TransactionReceipt.cpp b/src/cpp/model/hedera/TransactionReceipt.cpp new file mode 100644 index 000000000..46966814d --- /dev/null +++ b/src/cpp/model/hedera/TransactionReceipt.cpp @@ -0,0 +1,16 @@ +#include "TransactionReceipt.h" + +namespace model { + namespace hedera { + + TransactionReceipt::TransactionReceipt() + { + + } + + TransactionReceipt::~TransactionReceipt() + { + + } + } +} \ No newline at end of file diff --git a/src/cpp/model/hedera/TransactionReceipt.h b/src/cpp/model/hedera/TransactionReceipt.h new file mode 100644 index 000000000..ed1036857 --- /dev/null +++ b/src/cpp/model/hedera/TransactionReceipt.h @@ -0,0 +1,23 @@ +#ifndef __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_RECEIPT_H +#define __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_RECEIPT_H + +#include "../proto/hedera/TransactionReceipt.pb.h" + +namespace model { + namespace hedera { + class TransactionReceipt + { + public: + TransactionReceipt(); + ~TransactionReceipt(); + + inline proto::TransactionReceipt* getProto() { return &mProtoReceipt; } + + protected: + proto::TransactionReceipt mProtoReceipt; + + }; + } +} + +#endif //__GRADIDO_LOGIN_SERVER_MODEL_HEDERA_TRANSACTION_RECEIPT_H \ No newline at end of file diff --git a/src/cpp/model/hedera/TransactionRecord.cpp b/src/cpp/model/hedera/TransactionRecord.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/model/hedera/TransactionRecord.h b/src/cpp/model/hedera/TransactionRecord.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/cpp/tasks/HederaTask.cpp b/src/cpp/tasks/HederaTask.cpp index e69de29bb..9cd152d27 100644 --- a/src/cpp/tasks/HederaTask.cpp +++ b/src/cpp/tasks/HederaTask.cpp @@ -0,0 +1,45 @@ +#include "HederaTask.h" +#include "../lib/DataTypeConverter.h" + +#include "../proto/hedera/TransactionGetReceipt.pb.h" + +HederaTask::HederaTask() + : mTransactionReceipt(nullptr) +{ + +} + +HederaTask::~HederaTask() +{ + if (mTransactionReceipt) { + delete mTransactionReceipt; + mTransactionReceipt = nullptr; + } +} + +bool HederaTask::isTimeout() +{ + std::shared_lock _lock(mWorkingMutex); + auto valid_start = mTransactionID.transactionvalidstart(); + auto poco_timestamp = DataTypeConverter::convertFromProtoTimestamp(valid_start); + auto poco_duration = DataTypeConverter::convertFromProtoDuration(mValidDuration); + return (poco_timestamp + poco_duration) > Poco::Timestamp(); +} + +void HederaTask::setTransactionReceipt(model::hedera::TransactionReceipt* transactionReceipt) +{ + assert(transactionReceipt); + + std::unique_lock _lock(mWorkingMutex); + if (mTransactionReceipt) { + printf("[HederaTask::setTransactionReceipt] warning, receipt already set\n"); + delete mTransactionReceipt; + } + mTransactionReceipt = transactionReceipt; +} + +bool HederaTask::tryQueryReceipt() +{ + proto::TransactionGetReceiptQuery get_receipt_query; + return true; +} \ No newline at end of file diff --git a/src/cpp/tasks/HederaTask.h b/src/cpp/tasks/HederaTask.h index 0c22da226..3576ca7b6 100644 --- a/src/cpp/tasks/HederaTask.h +++ b/src/cpp/tasks/HederaTask.h @@ -2,14 +2,48 @@ #define __GRADIDO_LOGIN_TASKS_HEDERA_TASKS_H #include "../model/hedera/TransactionResponse.h" +#include "../model/hedera/TransactionReceipt.h" +#include "../proto/hedera/BasicTypes.pb.h" +#include "../proto/hedera/Duration.pb.h" + +#include "Poco/Timestamp.h" + +#include class HederaTask { public: - inline model::hedera::TransactionResponse* getTransactionResponse() { return &mTransactionResponse; } + + HederaTask(); + ~HederaTask(); + + inline model::hedera::TransactionResponse* getTransactionResponse() { std::shared_lock _lock(mWorkingMutex); return &mTransactionResponse; } + inline void setTransactionId(const proto::TransactionID& transactionId) { std::unique_lock _lock(mWorkingMutex); mTransactionID = transactionId; } + inline void setValidDuration(const proto::Duration& validDuration) { std::unique_lock _lock(mWorkingMutex); mValidDuration = validDuration; } + //! \param transactionReceipt take ownership and call delete if done + void setTransactionReceipt(model::hedera::TransactionReceipt* transactionReceipt); + + inline const proto::TransactionID& getTransactionId() const { std::shared_lock _lock(mWorkingMutex); return mTransactionID; } + inline const proto::Duration& getDuration() const { std::shared_lock _lock(mWorkingMutex); return mValidDuration; } + inline const model::hedera::TransactionReceipt* getTransactionReceipt() const{ std::shared_lock _lock(mWorkingMutex); return mTransactionReceipt; } + + //! \ brief return true if transactionValidStart + validDuration > now + bool isTimeout(); + + bool tryQueryReceipt(); + protected: model::hedera::TransactionResponse mTransactionResponse; + model::hedera::TransactionReceipt* mTransactionReceipt; + + proto::TransactionID mTransactionID; + proto::Duration mValidDuration; + + // last time checked if transaction receipt is available + Poco::Timestamp mLastCheck; + + mutable std::shared_mutex mWorkingMutex; }; #endif //__GRADIDO_LOGIN_TASKS_HEDERA_TASKS_H \ No newline at end of file diff --git a/src/cpp/tasks/SigningTransaction.cpp b/src/cpp/tasks/SigningTransaction.cpp index ab1196a54..50e5953b3 100644 --- a/src/cpp/tasks/SigningTransaction.cpp +++ b/src/cpp/tasks/SigningTransaction.cpp @@ -1,5 +1,8 @@ +#include + #include "SigningTransaction.h" + #include #include "../SingletonManager/ErrorManager.h" @@ -181,7 +184,8 @@ int SigningTransaction::run() { } else { auto hedera_precheck_code_string = hedera_task.getTransactionResponse()->getPrecheckCodeString(); - printf("hedera response: %s\n", hedera_precheck_code_string.data()); + auto cost = hedera_task.getTransactionResponse()->getCost(); + printf("hedera response: %s, cost: %" PRIu64 "\n", hedera_precheck_code_string.data(), cost); } //model::hedera::TransactionBody hedera_transaction_body() } From 48e732b897f352dc4c85e1a353565c06b0e861f9 Mon Sep 17 00:00:00 2001 From: Dario Date: Wed, 16 Sep 2020 13:25:15 +0200 Subject: [PATCH 037/293] prepare for hedera get topic info query --- .../hedera/ConsensusGetTopicInfoResponse.cpp | 15 ++++++++++ .../hedera/ConsensusGetTopicInfoResponse.h | 22 ++++++++++++++ src/cpp/model/hedera/Query.cpp | 25 ++++++++++++++++ src/cpp/model/hedera/Query.h | 2 ++ src/cpp/model/hedera/QueryHeader.cpp | 16 ++++++++++ src/cpp/model/hedera/QueryHeader.h | 25 ++++++++++++++++ src/cpp/model/hedera/Response.cpp | 15 ++++++++++ src/cpp/model/hedera/Response.h | 4 +++ src/cpp/model/hedera/TransactionBody.cpp | 30 ++++++++++++++++++- src/cpp/model/hedera/TransactionBody.h | 1 + 10 files changed, 154 insertions(+), 1 deletion(-) diff --git a/src/cpp/model/hedera/ConsensusGetTopicInfoResponse.cpp b/src/cpp/model/hedera/ConsensusGetTopicInfoResponse.cpp index e69de29bb..f99d82934 100644 --- a/src/cpp/model/hedera/ConsensusGetTopicInfoResponse.cpp +++ b/src/cpp/model/hedera/ConsensusGetTopicInfoResponse.cpp @@ -0,0 +1,15 @@ +#include "ConsensusGetTopicInfoResponse.h" + +namespace model { + namespace hedera { + ConsensusGetTopicInfoResponse::ConsensusGetTopicInfoResponse() + { + + } + + ConsensusGetTopicInfoResponse::~ConsensusGetTopicInfoResponse() + { + + } + } +} \ No newline at end of file diff --git a/src/cpp/model/hedera/ConsensusGetTopicInfoResponse.h b/src/cpp/model/hedera/ConsensusGetTopicInfoResponse.h index e69de29bb..63b837101 100644 --- a/src/cpp/model/hedera/ConsensusGetTopicInfoResponse.h +++ b/src/cpp/model/hedera/ConsensusGetTopicInfoResponse.h @@ -0,0 +1,22 @@ +#ifndef __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_GET_TOPIC_INFO_RESPONSE_H +#define __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_GET_TOPIC_INFO_RESPONSE_H + +#include "../proto/hedera/ConsensusGetTopicInfo.pb.h" + +namespace model +{ + namespace hedera + { + class ConsensusGetTopicInfoResponse + { + public: + ConsensusGetTopicInfoResponse(); + ~ConsensusGetTopicInfoResponse(); + + protected: + proto::ConsensusGetTopicInfoResponse mProto; + }; + } +} + +#endif //__GRADIDO_LOGIN_SERVER_MODEL_HEDERA_CONSENSUS_GET_TOPIC_INFO_RESPONSE_H \ No newline at end of file diff --git a/src/cpp/model/hedera/Query.cpp b/src/cpp/model/hedera/Query.cpp index 11a8eb735..c478a96ff 100644 --- a/src/cpp/model/hedera/Query.cpp +++ b/src/cpp/model/hedera/Query.cpp @@ -48,6 +48,29 @@ namespace model { return query; } + Query* Query::getTopicInfo(Poco::AutoPtr topicId, Poco::AutoPtr payerAccountId, const controller::NodeServerConnection& connection) + { + assert(!topicId.isNull() && topicId->getModel()); + assert(!payerAccountId.isNull() && payerAccountId->getModel()); + + auto query = new Query; + auto get_topic_info = query->mQueryProto.mutable_consensusgettopicinfo(); + topicId->copyToProtoTopicId(get_topic_info->mutable_topicid()); + + auto query_header = get_topic_info->mutable_header(); + query_header->set_responsetype(proto::ANSWER_ONLY); + + query->mTransactionBody = new TransactionBody(payerAccountId, connection); + CryptoTransferTransaction crypto_transaction; + // 0.002809 Hashbars + // fee from https://www.hedera.com/fees + crypto_transaction.addSender(payerAccountId, -2809); + crypto_transaction.addReceiver(connection.hederaId, 2809); + query->mTransactionBody->setCryptoTransfer(crypto_transaction); + + return query; + } + bool Query::sign(std::unique_ptr keyPairHedera) { Transaction transaction; @@ -73,5 +96,7 @@ namespace model { auto query_header = get_account_balance->mutable_header(); return query_header->responsetype(); } + + } } \ No newline at end of file diff --git a/src/cpp/model/hedera/Query.h b/src/cpp/model/hedera/Query.h index 376528314..5c633e66c 100644 --- a/src/cpp/model/hedera/Query.h +++ b/src/cpp/model/hedera/Query.h @@ -22,10 +22,12 @@ namespace model { public: ~Query(); static Query* getBalance(Poco::AutoPtr accountId, const controller::NodeServerConnection& connection); + static Query* getTopicInfo(Poco::AutoPtr topicId, Poco::AutoPtr payerAccountId, const controller::NodeServerConnection& connection); bool sign(std::unique_ptr keyPairHedera); void setResponseType(proto::ResponseType type); proto::ResponseType getResponseType(); + inline bool setTransactionFee(Poco::UInt64 fee) { return mTransactionBody->updateCryptoTransferAmount(fee);} inline const proto::Query* getProtoQuery() const { return &mQueryProto; } inline std::string getConnectionString() const { return mTransactionBody->getConnectionString(); } diff --git a/src/cpp/model/hedera/QueryHeader.cpp b/src/cpp/model/hedera/QueryHeader.cpp index e69de29bb..c622841ec 100644 --- a/src/cpp/model/hedera/QueryHeader.cpp +++ b/src/cpp/model/hedera/QueryHeader.cpp @@ -0,0 +1,16 @@ +#include "QueryHeader.h" + +namespace model { + namespace hedera { + QueryHeader::QueryHeader(Transaction* paymentTransaction) + { + mProtoQueryHeader.set_responsetype(proto::ANSWER_ONLY); + } + + QueryHeader::~QueryHeader() + { + + } + + } +} \ No newline at end of file diff --git a/src/cpp/model/hedera/QueryHeader.h b/src/cpp/model/hedera/QueryHeader.h index e69de29bb..47261e24a 100644 --- a/src/cpp/model/hedera/QueryHeader.h +++ b/src/cpp/model/hedera/QueryHeader.h @@ -0,0 +1,25 @@ +#ifndef __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_QUERY_HEADER_H +#define __GRADIDO_LOGIN_SERVER_MODEL_HEDERA_QUERY_HEADER_H + +#include "../proto/hedera/QueryHeader.pb.h" +#include "Transaction.h" + +namespace model { + namespace hedera { + class QueryHeader + { + public: + QueryHeader(Transaction* paymentTransaction); + ~QueryHeader(); + + void setResponseType(proto::ResponseType type) { mProtoQueryHeader.set_responsetype(type); }; + proto::ResponseType getResponseType() const { return mProtoQueryHeader.responsetype(); } + + protected: + proto::QueryHeader mProtoQueryHeader; + + }; + } +} + +#endif //__GRADIDO_LOGIN_SERVER_MODEL_HEDERA_QUERY_HEADER_H \ No newline at end of file diff --git a/src/cpp/model/hedera/Response.cpp b/src/cpp/model/hedera/Response.cpp index a39c5364e..d0a88ad94 100644 --- a/src/cpp/model/hedera/Response.cpp +++ b/src/cpp/model/hedera/Response.cpp @@ -20,6 +20,21 @@ namespace model { return 0; } + Poco::UInt64 Response::getQueryCost() + { + proto::ResponseHeader* response_header = nullptr; + if (mResponseProto.has_consensusgettopicinfo()) { + response_header = mResponseProto.mutable_consensusgettopicinfo()->mutable_header(); + } + else if (mResponseProto.has_cryptogetaccountbalance()) { + response_header = mResponseProto.mutable_cryptogetaccountbalance()->mutable_header(); + } + if (response_header) { + return response_header->cost(); + } + return 0; + } + proto::ResponseCodeEnum Response::getResponseCode() { if (isCryptoGetAccountBalanceResponse()) { diff --git a/src/cpp/model/hedera/Response.h b/src/cpp/model/hedera/Response.h index 779f5e982..89599b8c4 100644 --- a/src/cpp/model/hedera/Response.h +++ b/src/cpp/model/hedera/Response.h @@ -11,6 +11,7 @@ */ #include "../../proto/hedera/Response.pb.h" +#include "ConsensusGetTopicInfoResponse.h" #include "Poco/Types.h" namespace model { @@ -23,9 +24,12 @@ namespace model { inline proto::Response* getResponsePtr() { return &mResponseProto; } Poco::UInt64 getAccountBalance(); + Poco::UInt64 getQueryCost(); proto::ResponseCodeEnum getResponseCode(); + inline bool isCryptoGetAccountBalanceResponse() { return mResponseProto.has_cryptogetaccountbalance(); } + inline bool isConsensusGetTopicInfoResponse() { return mResponseProto.has_consensusgettopicinfo(); } protected: proto::Response mResponseProto; diff --git a/src/cpp/model/hedera/TransactionBody.cpp b/src/cpp/model/hedera/TransactionBody.cpp index ea44915a8..4ecae0fb9 100644 --- a/src/cpp/model/hedera/TransactionBody.cpp +++ b/src/cpp/model/hedera/TransactionBody.cpp @@ -8,7 +8,7 @@ namespace model { connection.hederaId->copyToProtoAccountId(mTransactionBody.mutable_nodeaccountid()); auto transaction_id = mTransactionBody.mutable_transactionid(); operatorAccountId->copyToProtoAccountId(transaction_id->mutable_accountid()); - mTransactionBody.set_transactionfee(10000); + mTransactionBody.set_transactionfee(1000000); auto transaction_valid_duration = mTransactionBody.mutable_transactionvalidduration(); transaction_valid_duration->set_seconds(120); @@ -36,6 +36,34 @@ namespace model { return false; } + bool TransactionBody::updateCryptoTransferAmount(Poco::UInt64 newAmount) + { + assert(mHasBody); + + if (!mTransactionBody.has_cryptotransfer()) { + printf("[TransactionBody::updateCryptoTransferAmount] hasn't crypto transfer\n"); + return false; + } + + auto crypto_transfer = mTransactionBody.mutable_cryptotransfer(); + auto transfers = crypto_transfer->mutable_transfers(); + if (transfers->accountamounts_size() != 2) { + printf("[TransactionBody::updateCryptoTransferAmount] structure not like expected, transfers has %d accountamounts\n", transfers->accountamounts_size()); + return false; + } + proto::AccountAmount* account_amounts[] = { transfers->mutable_accountamounts(0), transfers->mutable_accountamounts(1) }; + for (int i = 0; i < 2; i++) { + if (account_amounts[i]->amount() > 0) { + account_amounts[i]->set_amount(newAmount); + } + else if (account_amounts[i]->amount() < 0) { + account_amounts[i]->set_amount(-newAmount); + } + } + return true; + + } + bool TransactionBody::setCreateTopic(ConsensusCreateTopic& consensusCreateTopicTransaction) { if (mHasBody) { diff --git a/src/cpp/model/hedera/TransactionBody.h b/src/cpp/model/hedera/TransactionBody.h index 9a5406af7..c05f419ff 100644 --- a/src/cpp/model/hedera/TransactionBody.h +++ b/src/cpp/model/hedera/TransactionBody.h @@ -40,6 +40,7 @@ namespace model { void setFee(Poco::UInt64 fee); bool setCryptoTransfer(CryptoTransferTransaction& cryptoTransferTransaction); + bool updateCryptoTransferAmount(Poco::UInt64 newAmount); bool setCryptoCreate(CryptoCreateTransaction& cryptoCreateTransaction); bool setCreateTopic(ConsensusCreateTopic& consensusCreateTopicTransaction); bool setConsensusSubmitMessage(ConsensusSubmitMessage& consensusSubmitMessageTransaction); From d9122ad0be4cc87670e0c571a8b3025ada3c5086 Mon Sep 17 00:00:00 2001 From: Dario Date: Wed, 16 Sep 2020 13:26:05 +0200 Subject: [PATCH 038/293] update Hedera Topics Page to show existing topics --- skeema/gradido_login/hedera_topics.sql | 4 +- .../HTTPInterface/AdminHederaAccountPage.cpp | 68 ++--- src/cpp/HTTPInterface/AdminTopicPage.cpp | 245 ++++++++++++++---- src/cpp/controller/HederaAccount.cpp | 24 +- src/cpp/controller/HederaAccount.h | 6 +- src/cpp/controller/HederaRequest.cpp | 38 ++- src/cpp/controller/HederaTopic.cpp | 34 ++- src/cpp/controller/HederaTopic.h | 9 +- src/cpp/lib/DataTypeConverter.cpp | 11 + src/cpp/lib/DataTypeConverter.h | 6 + src/cpp/model/table/HederaAccount.cpp | 20 +- src/cpp/model/table/HederaAccount.h | 1 + src/cpp/model/table/HederaTopic.cpp | 37 ++- src/cpp/model/table/HederaTopic.h | 10 +- src/cpp/model/table/ModelBase.cpp | 24 ++ src/cpp/model/table/ModelBase.h | 26 +- src/cpsp/adminHederaAccount.cpsp | 18 +- src/cpsp/adminTopic.cpsp | 55 +++- 18 files changed, 500 insertions(+), 136 deletions(-) diff --git a/skeema/gradido_login/hedera_topics.sql b/skeema/gradido_login/hedera_topics.sql index b9adaefc2..8bf279f3b 100644 --- a/skeema/gradido_login/hedera_topics.sql +++ b/skeema/gradido_login/hedera_topics.sql @@ -7,9 +7,9 @@ CREATE TABLE `hedera_topics` ( `group_id` int unsigned NOT NULL, `admin_key_id` int unsigned DEFAULT NULL, `submit_key_id` int unsigned DEFAULT NULL, - `current_timeout` timestamp NOT NULL DEFAULT '2000-01-01 00:00:00', + `current_timeout` DATETIME NOT NULL DEFAULT '2000-01-01 00:00:00', `sequence_number` bigint unsigned DEFAULT '0', - `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `updated` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `topic_hedera_id` (`topic_hedera_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp index 5ff4f7218..4bcf9b614 100644 --- a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp +++ b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp @@ -349,8 +349,8 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "
    \n"; responseStream << "\t\t\t\t\t
    "; #line 266 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" - responseStream << ( hedera_account_model->getBalanceDouble() ); - responseStream << " hbar
    \n"; + responseStream << ( hedera_account_model->getBalanceString() ); + responseStream << "
    \n"; responseStream << "\t\t\t\t\t
    "; #line 267 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( model::table::HederaAccount::hederaNetworkTypeToString(hedera_account_model->getNetworkType()) ); @@ -366,27 +366,29 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request #line 269 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" responseStream << ( hedera_account_model->getUpdatedString() ); responseStream << "
    \n"; - responseStream << "\t\t\t\t\t\n"; - responseStream << "\t\t\t\t\t"; -#line 273 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" - if(changeEncryption != "") { responseStream << "\n"; - responseStream << "\t\t\t\t\t\t\n"; - responseStream << "\t\t\t\t\t"; -#line 277 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" + responseStream << "\t\t\t\t\t\t\t\tChange Encryption\n"; + responseStream << "\t\t\t\t\t\t\t\n"; + responseStream << "\t\t\t\t\t\t"; +#line 278 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" } responseStream << "\n"; + responseStream << "\t\t\t\t\t
    \n"; responseStream << "\t\t\t\t
    \n"; responseStream << "\t\t\t"; -#line 279 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" +#line 281 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminHederaAccount.cpsp" } responseStream << "\n"; responseStream << "\t\t
    \n"; responseStream << "\t
    \n"; @@ -395,7 +397,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t
    \n"; responseStream << "\t
    \n"; responseStream << "\t\t
    \n"; responseStream << "\t\t\t\n"; @@ -411,21 +413,21 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t
    \n"; @@ -436,46 +438,46 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t
    \n"; responseStream << "\t
    \n"; responseStream << "\t\t
    \n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t
    \n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\n"; @@ -506,7 +508,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request // end include footer.cpsp responseStream << "\n"; responseStream << "\n"; responseStream << "\n"; responseStream << "\n"; responseStream << "\n"; responseStream << "\t\t\n"; responseStream << "\t "; -#line 219 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\passphrase.cpsp" +#line 222 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\passphrase.cpsp" } else if(state == PAGE_ASK_PASSPHRASE) { responseStream << "\n"; responseStream << "\t \n"; - responseStream << "\n"; - responseStream << "\n"; - responseStream << "
    \n"; - responseStream << "\t

    Login Server in Entwicklung

    \n"; - responseStream << "\t

    Alpha "; -#line 53 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_old.cpsp" - responseStream << ( ServerConfig::g_versionString ); - responseStream << "

    \n"; - responseStream << "
    \n"; - // end include header_old.cpsp - responseStream << "\n"; - responseStream << "
    \n"; - responseStream << "\t

    Einen neuen Account anlegen

    \n"; - responseStream << "\t"; -#line 45 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\register.cpsp" - responseStream << ( getErrorsHtml() ); - responseStream << "\n"; - responseStream << "\t"; -#line 46 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\register.cpsp" - if(!form.empty() && userReturned) { responseStream << "\n"; - responseStream << "\t\t
    \n"; - responseStream << "\t\t\t
    \n"; - responseStream << "\t\t\t\tDeine Anmeldung wird verarbeitet und es wird dir eine E-Mail zugeschickt. \n"; - responseStream << "\t\t\t\tWenn sie da ist, befolge ihren Anweisungen. \n"; - responseStream << "\t\t\t
    \n"; - responseStream << "\t\t
    \n"; - responseStream << "\t"; -#line 53 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\register.cpsp" - } else { responseStream << "\n"; - responseStream << "\t
    \n"; - responseStream << "\t\t\n"; - responseStream << "\t\t
    \n"; - responseStream << "\t\t\tAccount anlegen\n"; - responseStream << "\t\t\t

    Bitte gebe deine Daten um einen Account anzulegen

    \n"; - responseStream << "\t\t\t

    \n"; - responseStream << "\t\t\t\t\n"; - responseStream << "\t\t\t\t\n"; - responseStream << "\t\t\t

    \n"; - responseStream << "\t\t\t

    \n"; - responseStream << "\t\t\t\t\n"; - responseStream << "\t\t\t\t\n"; - responseStream << "\t\t\t

    \n"; - responseStream << "\t\t\t

    \n"; - responseStream << "\t\t\t\t\n"; - responseStream << "\t\t\t\t\n"; - responseStream << "\t\t\t

    \n"; - responseStream << "\t\t\t

    \n"; - responseStream << "\t\t\t\t\n"; - responseStream << "\t\t\t\t\n"; - responseStream << "\t\t\t

    \n"; - responseStream << "\t\t\t

    \n"; - responseStream << "\t\t\t\t\n"; - responseStream << "\t\t\t\t\n"; - responseStream << "\t\t\t

    \n"; - responseStream << "\t\t
    \n"; - responseStream << "\t\t\n"; - responseStream << "\t\t\n"; - responseStream << "\t
    \n"; - responseStream << "\t"; -#line 83 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\register.cpsp" - } responseStream << "\n"; - responseStream << "
    \n"; - // begin include footer.cpsp - responseStream << "
    \n"; - responseStream << "

    Copyright © Gradido 2020

    \n"; - responseStream << "
    \n"; - responseStream << "
    \n"; - responseStream << "
    \n"; - responseStream << " "; -#line 6 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp" - responseStream << ( mTimeProfiler.string() ); - responseStream << "\n"; - responseStream << "
    \n"; - responseStream << "
    \n"; - responseStream << "

    Login Server in Entwicklung

    \n"; - responseStream << "

    Alpha "; -#line 10 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp" - responseStream << ( ServerConfig::g_versionString ); - responseStream << "

    \n"; - responseStream << "
    \n"; - responseStream << "
    \n"; - responseStream << "\n"; - responseStream << "\n"; - responseStream << ""; - // end include footer.cpsp - responseStream << "\n"; - if (_compressResponse) _gzipStream.close(); -} diff --git a/src/cpp/HTTPInterface/RegisterPage.h b/src/cpp/HTTPInterface/RegisterPage.h deleted file mode 100644 index 7dc16970a..000000000 --- a/src/cpp/HTTPInterface/RegisterPage.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef RegisterPage_INCLUDED -#define RegisterPage_INCLUDED - - -#include "Poco/Net/HTTPRequestHandler.h" - - -#include "PageRequestMessagedHandler.h" - - -class RegisterPage: public PageRequestMessagedHandler -{ -public: - void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response); -}; - - -#endif // RegisterPage_INCLUDED diff --git a/src/cpp/HTTPInterface/SaveKeysPage.cpp b/src/cpp/HTTPInterface/SaveKeysPage.cpp index 12064f812..3d8d79b67 100644 --- a/src/cpp/HTTPInterface/SaveKeysPage.cpp +++ b/src/cpp/HTTPInterface/SaveKeysPage.cpp @@ -40,7 +40,8 @@ void SaveKeysPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Ne const char* pageName = "Daten auf Server speichern?"; bool hasErrors = mSession->errorCount() > 0; // crypto key only in memory, if user has tipped in his passwort in this session - bool hasPassword = mSession->getUser()->hasCryptoKey(); + auto user = mSession->getNewUser(); + bool hasPassword = user->getModel()->hasPrivateKeyEncrypted(); PageState state = PAGE_ASK; auto uri_start = ServerConfig::g_php_serverPath;//request.serverParams().getServerName(); @@ -161,11 +162,11 @@ void SaveKeysPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Ne responseStream << "
    \n"; responseStream << "\t

    Daten speichern

    \n"; responseStream << "\t"; -#line 75 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" +#line 76 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" responseStream << ( getErrorsHtml() ); responseStream << "\n"; responseStream << "\t"; -#line 76 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" +#line 77 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" if(state == PAGE_ASK) { responseStream << "\n"; responseStream << "\t
    \n"; responseStream << "\t\t
    \n"; @@ -180,7 +181,7 @@ void SaveKeysPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Ne responseStream << "\t\t\t\t\n"; responseStream << "\t\t\t

    \n"; responseStream << "\t\t\t"; -#line 89 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" +#line 90 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" if(!hasPassword) { responseStream << "\n"; responseStream << "\t\t\t\t

    Ich brauche nochmal dein Passwort wenn du dich für ja entscheidest.

    \n"; responseStream << "\t\t\t\t

    \n"; @@ -188,7 +189,7 @@ void SaveKeysPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Ne responseStream << "\t\t\t\t\t\n"; responseStream << "\t\t\t\t

    \n"; responseStream << "\t\t\t"; -#line 95 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" +#line 96 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" } responseStream << "\n"; responseStream << "\t\t\t

    \n"; responseStream << "\t\t\t\t\n"; @@ -213,15 +214,15 @@ void SaveKeysPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Ne responseStream << "\t\t\n"; responseStream << "\t

    \n"; responseStream << "\t"; -#line 118 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" +#line 119 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" } else if(state == PAGE_SHOW_PUBKEY) { responseStream << "\n"; responseStream << "\t\t
    \n"; responseStream << "\t\t\t

    "; -#line 120 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" +#line 121 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" responseStream << ( gettext("Daten gespeichert!") ); responseStream << "

    \n"; responseStream << "\t\t\t

    "; -#line 121 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" +#line 122 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" responseStream << ( gettext("Deine Daten wurden verschlüsselt und gespeichert.") ); responseStream << "

    \n"; responseStream << "\t\t\t\n"; @@ -229,27 +230,27 @@ void SaveKeysPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Ne responseStream << "\t\t\t\n"; responseStream << "\t\t\tZurück zur Startseite\n"; responseStream << "\t\t
    \n"; responseStream << "\t"; -#line 130 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" +#line 131 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" } else if(state == PAGE_ERROR) { responseStream << "\n"; responseStream << "\t\t
    \n"; responseStream << "\t\t\t

    Ein Fehler trat auf, bitte versuche es erneut oder wende dich an den Server-Admin

    \n"; responseStream << "\t\t\t"; -#line 133 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" +#line 134 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" responseStream << ( mSession->getSessionStateString() ); responseStream << "\n"; responseStream << "\t\t
    \n"; responseStream << "\t"; -#line 135 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" +#line 136 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\saveKeys.cpsp" } responseStream << "\n"; responseStream << "
    \n"; // begin include footer.cpsp diff --git a/src/cpp/HTTPInterface/TranslatePassphrase.cpp b/src/cpp/HTTPInterface/TranslatePassphrase.cpp index 512383518..3b14f9a2c 100644 --- a/src/cpp/HTTPInterface/TranslatePassphrase.cpp +++ b/src/cpp/HTTPInterface/TranslatePassphrase.cpp @@ -7,7 +7,7 @@ #line 7 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" -#include "../Crypto/KeyPair.h" +#include "../Crypto/KeyPairEd25519.h" #include "../ServerConfig.h" #line 1 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp" @@ -50,16 +50,17 @@ void TranslatePassphrase::handleRequest(Poco::Net::HTTPServerRequest& request, P { inputPassphrase = form.get("inputPassphrase", ""); - auto localPassphrase = KeyPair::filterPassphrase(inputPassphrase); + auto localPassphrase = Passphrase::filter(inputPassphrase); auto btnGenerate = form.get("btnGenerate", ""); if("" != btnGenerate) { - mSession->generatePassphrase(); - localPassphrase = mSession->getOldPassphrase(); + auto passphrase_gen = Passphrase::generate(wordSource); + + localPassphrase = passphrase_gen->getString(); inputPassphrase = localPassphrase; } - - if(localPassphrase != "" && !User::validatePassphrase(localPassphrase, &wordSource)) { + auto passphrase_object = Passphrase::create(localPassphrase, wordSource); + if(localPassphrase != "" && passphrase_object.isNull() || !passphrase_object->checkIfValid()) { addError(new Error( gettext("Fehler"), gettext("Diese Passphrase ist ungültig, bitte überprüfen oder neu generieren (lassen).") @@ -70,7 +71,8 @@ void TranslatePassphrase::handleRequest(Poco::Net::HTTPServerRequest& request, P } else { targetSource = &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]; } - passphrase = KeyPair::passphraseTransform(localPassphrase, wordSource, targetSource); + auto transformed_passphrase_obj = passphrase_object->transform(targetSource); + passphrase = transformed_passphrase_obj->getString(); } @@ -197,7 +199,7 @@ void TranslatePassphrase::handleRequest(Poco::Net::HTTPServerRequest& request, P responseStream << "\n"; responseStream << "
    \n"; responseStream << "\t

    "; -#line 59 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" +#line 61 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" responseStream << ( gettext("Passphrase umwandeln") ); responseStream << "

    \n"; responseStream << "
    \n"; @@ -208,57 +210,57 @@ void TranslatePassphrase::handleRequest(Poco::Net::HTTPServerRequest& request, P responseStream << "\t
    \n"; responseStream << "\t\t
    \n"; responseStream << "\t\t
    "; -#line 67 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" +#line 69 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" responseStream << ( gettext("Was zu tun ist:") ); responseStream << "
    \n"; responseStream << "\t\t

    "; -#line 68 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" +#line 70 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" responseStream << ( gettext("Kopiere/schreibe deine Passphrase in die Textbox und du bekommst sie in die jeweils andere Sprache umgewandelt.") ); responseStream << "

    \n"; responseStream << "\t\t

    "; -#line 69 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" +#line 71 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" responseStream << ( gettext("Du kannst mit beiden Varianten dein Konto wiederherstellen oder dein Passwort ändern.") ); responseStream << "

    \n"; responseStream << "\t\t
    \n"; responseStream << "\t
    \n"; responseStream << "\t
    \n"; responseStream << "\t\t
    \n"; responseStream << "\t\t
    \n"; responseStream << "\t\t\t\n"; responseStream << "\t\t
    \n"; responseStream << "\t\t \n"; responseStream << "\t\t "; -#line 78 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" +#line 80 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" if(model::table::ROLE_ADMIN == role) { responseStream << "\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t "; -#line 80 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" +#line 82 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" } responseStream << "\n"; responseStream << "\t\t
    \n"; responseStream << "\t
    \n"; responseStream << "\t "; -#line 83 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" +#line 85 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" if(passphrase != "") { responseStream << "\n"; responseStream << "\t\t
    \n"; responseStream << "\t\t\t
    \n"; responseStream << "\t\t\t\t
    Umgewandelte Passphrase:
    \n"; responseStream << "\t\t\t\t

    "; -#line 87 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" +#line 89 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" responseStream << ( passphrase ); responseStream << "

    \n"; responseStream << "\t\t\t
    \n"; responseStream << "\t\t
    \n"; responseStream << "\t "; -#line 90 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" +#line 92 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\translatePassphrase.cpsp" } responseStream << "\n"; responseStream << "\t
    \n"; responseStream << "\t
    \n"; diff --git a/src/cpp/HTTPInterface/UserUpdateGroupPage.cpp b/src/cpp/HTTPInterface/UserUpdateGroupPage.cpp new file mode 100644 index 000000000..f41928116 --- /dev/null +++ b/src/cpp/HTTPInterface/UserUpdateGroupPage.cpp @@ -0,0 +1,209 @@ +#include "UserUpdateGroupPage.h" +#include "Poco/Net/HTTPServerRequest.h" +#include "Poco/Net/HTTPServerResponse.h" +#include "Poco/Net/HTMLForm.h" +#include "Poco/DeflatingStream.h" + + +#line 6 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\userUpdateGroup.cpsp" + + +#include "../controller/Group.h" +#include "../SingletonManager/SessionManager.h" + +enum PageState { + PAGE_STATE_OVERVIEW, + PAGE_STATE_REQUEST_IS_RUNNING +}; + +#line 1 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + +#include "../ServerConfig.h" + + +UserUpdateGroupPage::UserUpdateGroupPage(Session* arg): + SessionHTTPRequestHandler(arg) +{ +} + + +void UserUpdateGroupPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) +{ + response.setChunkedTransferEncoding(true); + response.setContentType("text/html"); + bool _compressResponse(request.hasToken("Accept-Encoding", "gzip")); + if (_compressResponse) response.set("Content-Encoding", "gzip"); + + Poco::Net::HTMLForm form(request, request.stream()); +#line 17 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\userUpdateGroup.cpsp" + + const char* pageName = gettext("Gruppe wählen"); + auto user = mSession->getNewUser(); + auto sm = SessionManager::getInstance(); + PageState state = PAGE_STATE_OVERVIEW; + + if(!form.empty()) { + } + + auto groups = controller::Group::listAll(); + + +#line 3 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + + bool withMaterialIcons = false; + std::ostream& _responseStream = response.send(); + Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1); + std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream; + responseStream << "\n"; + // begin include header_large.cpsp + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "Gradido Login Server: "; +#line 11 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + responseStream << ( pageName ); + responseStream << "\n"; + responseStream << "\n"; +#line 13 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + if(withMaterialIcons) { responseStream << "\n"; + responseStream << "\n"; +#line 15 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_large.cpsp" + } responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "
    \n"; + responseStream << "\t\t
    \n"; + responseStream << "\t\t\t
    \n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t
    \n"; + responseStream << "\t\t
    \n"; + responseStream << "\t\t
    "; + // end include header_large.cpsp + responseStream << "\n"; +#line 30 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\userUpdateGroup.cpsp" + responseStream << ( getErrorsHtml() ); + responseStream << "\n"; + responseStream << "
    \n"; + responseStream << "\t"; +#line 32 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\userUpdateGroup.cpsp" + if(PAGE_STATE_OVERVIEW == state ) { responseStream << "\n"; + responseStream << "
    \n"; + responseStream << "

    "; +#line 34 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\userUpdateGroup.cpsp" + responseStream << ( gettext("Gruppe wählen") ); + responseStream << "

    \n"; + responseStream << "
    \n"; + responseStream << "\t

    "; +#line 36 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\userUpdateGroup.cpsp" + responseStream << ( gettext("Bitte wähle die Gruppe/Gemeinschaft aus, zu der du gehörst.") ); + responseStream << "

    \n"; + responseStream << "\t

    "; +#line 37 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\userUpdateGroup.cpsp" + responseStream << ( gettext("Du bekommst eine Bestätigungsmail, nachdem dein Beitritt bestätigt wurde.") ); + responseStream << "

    \n"; + responseStream << "\t
    \n"; + responseStream << "\t\t
    \n"; + responseStream << "\t\t\t
    \n"; + responseStream << "\t\t\t\t
    "; +#line 41 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\userUpdateGroup.cpsp" + responseStream << ( gettext("Auswahl") ); + responseStream << "
    \n"; + responseStream << "\t\t\t\t
    Name
    \n"; + responseStream << "\t\t\t\t
    Alias
    \n"; + responseStream << "\t\t\t\t
    Url
    \n"; + responseStream << "\t\t\t\t
    "; +#line 45 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\userUpdateGroup.cpsp" + responseStream << ( gettext("Description") ); + responseStream << "
    \n"; + responseStream << "\t\t\t
    \n"; + responseStream << "\t\t\t"; +#line 47 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\userUpdateGroup.cpsp" + for(auto it = groups.begin(); it != groups.end(); it++) { + auto group_model = (*it)->getModel(); responseStream << "\n"; + responseStream << "\t\t\t\t
    \n"; + responseStream << "\t\t\t\t\t
    getID()); + responseStream << "\" />
    \n"; + responseStream << "\t\t\t\t\t
    "; +#line 51 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\userUpdateGroup.cpsp" + responseStream << ( group_model->getName() ); + responseStream << "
    \n"; + responseStream << "\t\t\t\t\t
    "; +#line 52 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\userUpdateGroup.cpsp" + responseStream << ( group_model->getAlias() ); + responseStream << "
    \n"; + responseStream << "\t\t\t\t\t
    "; +#line 53 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\userUpdateGroup.cpsp" + responseStream << ( group_model->getUrl() ); + responseStream << "
    \n"; + responseStream << "\t\t\t\t\t
    "; +#line 54 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\userUpdateGroup.cpsp" + responseStream << ( group_model->getDescription()); + responseStream << "
    \n"; + responseStream << "\t\t\t\t
    \n"; + responseStream << "\t\t\t"; +#line 56 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\userUpdateGroup.cpsp" + } responseStream << "\n"; + responseStream << "\t\t\t\n"; + responseStream << "\t\t
    \n"; + responseStream << "\t
    \n"; + responseStream << "\t"; +#line 60 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\userUpdateGroup.cpsp" + } responseStream << "\n"; + responseStream << "
    \n"; + // begin include footer.cpsp + responseStream << "
    \n"; + responseStream << "

    Copyright © Gradido 2020

    \n"; + responseStream << "
    \n"; + responseStream << "
    \n"; + responseStream << "
    \n"; + responseStream << " "; +#line 6 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp" + responseStream << ( mTimeProfiler.string() ); + responseStream << "\n"; + responseStream << "
    \n"; + responseStream << "
    \n"; + responseStream << "

    Login Server in Entwicklung

    \n"; + responseStream << "

    Alpha "; +#line 10 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp" + responseStream << ( ServerConfig::g_versionString ); + responseStream << "

    \n"; + responseStream << "
    \n"; + responseStream << "
    \n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << ""; + // end include footer.cpsp + responseStream << "\n"; + if (_compressResponse) _gzipStream.close(); +} diff --git a/src/cpp/HTTPInterface/UserUpdateGroupPage.h b/src/cpp/HTTPInterface/UserUpdateGroupPage.h new file mode 100644 index 000000000..5b1e9a7d1 --- /dev/null +++ b/src/cpp/HTTPInterface/UserUpdateGroupPage.h @@ -0,0 +1,20 @@ +#ifndef UserUpdateGroupPage_INCLUDED +#define UserUpdateGroupPage_INCLUDED + + +#include "Poco/Net/HTTPRequestHandler.h" + + +#include "SessionHTTPRequestHandler.h" + + +class UserUpdateGroupPage: public SessionHTTPRequestHandler +{ +public: + UserUpdateGroupPage(Session*); + + void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response); +}; + + +#endif // UserUpdateGroupPage_INCLUDED diff --git a/src/cpp/ImportantTests.cpp b/src/cpp/ImportantTests.cpp index d321bab5f..33c7d0f26 100644 --- a/src/cpp/ImportantTests.cpp +++ b/src/cpp/ImportantTests.cpp @@ -2,7 +2,7 @@ #include #include "ServerConfig.h" -#include "Crypto/KeyPair.h" +//#include "Crypto/KeyPair.h" #include "Crypto/KeyPairEd25519.h" #include "lib/DataTypeConverter.h" @@ -38,27 +38,36 @@ namespace ImportantTests { // test old key pair implementation - KeyPair keys; + //KeyPair keys; bool errorsOccured = false; - std::string filtered_1_de = KeyPair::filterPassphrase(passphrase_1_de); - keys.generateFromPassphrase(filtered_1_de.data(), de_words); - if (keys.getPubkeyHex() != passphrase_1_pubkey_hex) { + std::string filtered_1_de = Passphrase::filter(passphrase_1_de); + KeyPairEd25519* keys = nullptr; + keys = KeyPairEd25519::create(Passphrase::create(filtered_1_de, de_words)); + std::string public_key_hex = keys->getPublicKeyHex(); + + if (std::string(public_key_hex.data(), public_key_hex.size() - 1) != passphrase_1_pubkey_hex) { printf("1 de incorrect\n"); errorsOccured = true; } - keys.generateFromPassphrase(passphrase_1_en.data(), en_words); - if (keys.getPubkeyHex() != passphrase_1_pubkey_hex) { + delete keys; + keys = KeyPairEd25519::create(Passphrase::create(passphrase_1_en, en_words)); + public_key_hex = keys->getPublicKeyHex(); + if (std::string(public_key_hex.data(), public_key_hex.size() - 1) != passphrase_1_pubkey_hex) { printf("1 en incorrect\n"); errorsOccured = true; } - std::string filtered_2_de = KeyPair::filterPassphrase(passphrase_2_de); - keys.generateFromPassphrase(filtered_2_de.data(), de_words); - if (keys.getPubkeyHex() != passphrase_2_pubkey_hex) { + std::string filtered_2_de = Passphrase::filter(passphrase_2_de); + delete keys; + keys = KeyPairEd25519::create(Passphrase::create(filtered_2_de, de_words)); + public_key_hex = keys->getPublicKeyHex(); + if (std::string(public_key_hex.data(), public_key_hex.size() - 1) != passphrase_2_pubkey_hex) { printf("2 de incorrect\n"); errorsOccured = true; } - keys.generateFromPassphrase(passphrase_2_en.data(), en_words); - if (keys.getPubkeyHex() != passphrase_2_pubkey_hex) { + delete keys; + keys = KeyPairEd25519::create(Passphrase::create(passphrase_2_en, en_words)); + public_key_hex = keys->getPublicKeyHex(); + if (std::string(public_key_hex.data(), public_key_hex.size() - 1) != passphrase_2_pubkey_hex) { printf("2 en incorrect\n"); errorsOccured = true; } diff --git a/src/cpp/JSONInterface/JsonCreateUser.cpp b/src/cpp/JSONInterface/JsonCreateUser.cpp index 63d1cf1f4..a13832853 100644 --- a/src/cpp/JSONInterface/JsonCreateUser.cpp +++ b/src/cpp/JSONInterface/JsonCreateUser.cpp @@ -12,6 +12,7 @@ Poco::JSON::Object* JsonCreateUser::handle(Poco::Dynamic::Var params) std::string first_name; std::string last_name; int emailType; + int group_id; auto em = EmailManager::getInstance(); // if is json object @@ -27,6 +28,7 @@ Poco::JSON::Object* JsonCreateUser::handle(Poco::Dynamic::Var params) paramJsonObject->get("first_name").convert(first_name); paramJsonObject->get("last_name").convert(last_name); paramJsonObject->get("emailType").convert(emailType); + paramJsonObject->get("group_id").convert(group_id); } catch (Poco::Exception& ex) { return stateError("json exception", ex.displayText()); @@ -45,7 +47,7 @@ Poco::JSON::Object* JsonCreateUser::handle(Poco::Dynamic::Var params) } // create user - user = controller::User::create(email, first_name, last_name); + user = controller::User::create(email, first_name, last_name, group_id); auto userModel = user->getModel(); if (!userModel->insertIntoDB(true)) { userModel->sendErrorsAsEmail(); diff --git a/src/cpp/JSONInterface/JsonTransaction.cpp b/src/cpp/JSONInterface/JsonTransaction.cpp index 777fca295..7e09dd55d 100644 --- a/src/cpp/JSONInterface/JsonTransaction.cpp +++ b/src/cpp/JSONInterface/JsonTransaction.cpp @@ -33,10 +33,6 @@ Poco::JSON::Object* JsonTransaction::handle(Poco::Dynamic::Var params) if (!paramJsonObject->isNull("balance")) { paramJsonObject->get("balance").convert(balance); if (balance) { - auto u = session->getUser(); - if (u) { - u->setBalance(balance); - } auto nu = session->getNewUser(); if (!nu.isNull()) { nu->setBalance(balance); diff --git a/src/cpp/controller/User.cpp b/src/cpp/controller/User.cpp index ba07a066c..95549687a 100644 --- a/src/cpp/controller/User.cpp +++ b/src/cpp/controller/User.cpp @@ -21,6 +21,7 @@ namespace controller { : mPassword(nullptr), mGradidoKeyPair(nullptr), mCanDecryptPrivateKey(false), mGradidoCurrentBalance(0) { mDBModel = dbModel; + } User::~User() @@ -39,9 +40,9 @@ namespace controller { return Poco::AutoPtr(user); } - Poco::AutoPtr User::create(const std::string& email, const std::string& first_name, const std::string& last_name, Poco::UInt64 passwordHashed/* = 0*/, std::string languageKey/* = "de"*/) + Poco::AutoPtr User::create(const std::string& email, const std::string& first_name, const std::string& last_name, int group_id, Poco::UInt64 passwordHashed/* = 0*/, std::string languageKey/* = "de"*/) { - auto db = new model::table::User(email, first_name, last_name, passwordHashed, languageKey); + auto db = new model::table::User(email, first_name, last_name, group_id, passwordHashed, languageKey); auto user = new User(db); return Poco::AutoPtr(user); } @@ -327,6 +328,41 @@ namespace controller { return -1; } + /* + USER_EMPTY, + USER_LOADED_FROM_DB, + USER_PASSWORD_INCORRECT, + USER_PASSWORD_ENCRYPTION_IN_PROCESS, + USER_EMAIL_NOT_ACTIVATED, + USER_NO_KEYS, + USER_NO_PRIVATE_KEY, + USER_NO_GROUP, + USER_KEYS_DONT_MATCH, + USER_COMPLETE, + USER_DISABLED + */ + UserState User::getUserState() + { + std::unique_lock _lock(mSharedMutex); + auto model = getModel(); + if (!model->getID() && model->getEmail() == "") { + return USER_EMPTY; + } + if (!model->hasPrivateKeyEncrypted() && !model->hasPublicKey()) { + return USER_NO_KEYS; + } + if (!model->hasPrivateKeyEncrypted()) { + return USER_NO_PRIVATE_KEY; + } + if (!model->getGroupId()) { + return USER_NO_GROUP; + } + if (!model->isEmailChecked()) { + return USER_EMAIL_NOT_ACTIVATED; + } + return USER_COMPLETE; + } + int User::checkIfVerificationEmailsShouldBeResend(const Poco::Util::Timer& timer) { diff --git a/src/cpp/controller/User.h b/src/cpp/controller/User.h index a400d2ff5..1b60852b5 100644 --- a/src/cpp/controller/User.h +++ b/src/cpp/controller/User.h @@ -9,6 +9,21 @@ #include "TableControllerBase.h" +enum UserState +{ + USER_EMPTY, + USER_LOADED_FROM_DB, + USER_PASSWORD_INCORRECT, + USER_PASSWORD_ENCRYPTION_IN_PROCESS, + USER_EMAIL_NOT_ACTIVATED, + USER_NO_KEYS, + USER_NO_PRIVATE_KEY, + USER_NO_GROUP, + USER_KEYS_DONT_MATCH, + USER_COMPLETE, + USER_DISABLED +}; + namespace controller { @@ -26,7 +41,7 @@ namespace controller { ~User(); static Poco::AutoPtr create(); - static Poco::AutoPtr create(const std::string& email, const std::string& first_name, const std::string& last_name, Poco::UInt64 passwordHashed = 0, std::string languageKey = "de"); + static Poco::AutoPtr create(const std::string& email, const std::string& first_name, const std::string& last_name, int group_id, Poco::UInt64 passwordHashed = 0, std::string languageKey = "de"); static std::vector search(const std::string& searchString); @@ -96,6 +111,9 @@ namespace controller { //! \return -1 = stored pubkey and private key didn't match int setNewPassword(const std::string& password); + //! \brief calculate user state + UserState getUserState(); + //! \brief return AuthenticatedEncryption Auto Pointer inline const Poco::AutoPtr getPassword() { std::shared_lock _lock(mSharedMutex); diff --git a/src/cpp/controller/UserBackup.cpp b/src/cpp/controller/UserBackup.cpp index 9a152592f..88bc3f682 100644 --- a/src/cpp/controller/UserBackup.cpp +++ b/src/cpp/controller/UserBackup.cpp @@ -48,17 +48,12 @@ namespace controller { } - Poco::SharedPtr UserBackup::getKeyPair() + Poco::SharedPtr UserBackup::getKeyPair() { if (!mKeyPair.isNull()) { return mKeyPair; } - mKeyPair = new KeyPair; - auto model = getModel(); - auto passphrase = model->getPassphrase(); - - mKeyPair->generateFromPassphrase(passphrase); - return mKeyPair; + mKeyPair = createGradidoKeyPair(); } KeyPairEd25519* UserBackup::createGradidoKeyPair() @@ -77,17 +72,17 @@ namespace controller { return ""; } auto passphrase = getModel()->getPassphrase(); - Mnemonic* wordSource = nullptr; - if (KeyPair::validatePassphrase(passphrase, &wordSource)) { - for (int i = 0; i < ServerConfig::Mnemonic_Types::MNEMONIC_MAX; i++) { - Mnemonic* m = &ServerConfig::g_Mnemonic_WordLists[i]; - if (m == wordSource) { - if (type == i) { - return passphrase; - } - else { - return KeyPair::passphraseTransform(passphrase, m, &ServerConfig::g_Mnemonic_WordLists[type]); - } + auto wordSource = Passphrase::detectMnemonic(passphrase); + for (int i = 0; i < ServerConfig::Mnemonic_Types::MNEMONIC_MAX; i++) { + Mnemonic* m = &ServerConfig::g_Mnemonic_WordLists[i]; + if (m == wordSource) { + if (type == i) { + return passphrase; + } + else { + //return KeyPair::passphraseTransform(passphrase, m, &ServerConfig::g_Mnemonic_WordLists[type]); + auto passphrase_obj = Passphrase::create(passphrase, wordSource); + return passphrase_obj->transform(&ServerConfig::g_Mnemonic_WordLists[type])->getString(); } } } diff --git a/src/cpp/controller/UserBackup.h b/src/cpp/controller/UserBackup.h index a21d1c3ab..f1ab2f95a 100644 --- a/src/cpp/controller/UserBackup.h +++ b/src/cpp/controller/UserBackup.h @@ -2,7 +2,6 @@ #define GRADIDO_LOGIN_SERVER_CONTROLLER_USER_BACKUPS_INCLUDE #include "../model/table/UserBackup.h" -#include "../Crypto/KeyPair.h" #include "../Crypto/KeyPairEd25519.h" #include "Poco/SharedPtr.h" @@ -26,7 +25,7 @@ namespace controller { //! depracted //! \return create keyPair from passphrase if not exist, else return existing pointer - Poco::SharedPtr getKeyPair(); + Poco::SharedPtr getKeyPair(); //! \return newly created key pair from passphrase or nullptr if not possible, caller becomes owner of pointer KeyPairEd25519* createGradidoKeyPair(); @@ -38,7 +37,7 @@ namespace controller { protected: UserBackup(model::table::UserBackup* dbModel); - Poco::SharedPtr mKeyPair; + Poco::SharedPtr mKeyPair; }; } diff --git a/src/cpp/model/Session.cpp b/src/cpp/model/Session.cpp index 2e24e8610..ae3138233 100644 --- a/src/cpp/model/Session.cpp +++ b/src/cpp/model/Session.cpp @@ -34,59 +34,12 @@ using namespace Poco::Data::Keywords; -int WriteEmailVerification::run() -{ - auto em = ErrorManager::getInstance(); - - mEmailVerificationCode->getModel()->setUserId(mUser->getDBId()); - auto emailVerificationModel = mEmailVerificationCode->getModel(); - emailVerificationModel->setUserId(mUser->getDBId()); - if (!emailVerificationModel->insertIntoDB(true) || emailVerificationModel->errorCount() > 0) { - emailVerificationModel->sendErrorsAsEmail(); - return -1; - } - - return 0; -} - -// --------------------------------------------------------------------------------------------------------------- - -int WritePassphraseIntoDB::run() -{ - Profiler timeUsed; - - // TODO: encrypt passphrase, need server admin crypto box pubkey - //int crypto_box_seal(unsigned char *c, const unsigned char *m, - //unsigned long long mlen, const unsigned char *pk); - size_t mlen = mPassphrase.size(); - size_t crypto_size = crypto_box_SEALBYTES + mlen; - - auto em = ErrorManager::getInstance(); - - auto dbSession = ConnectionManager::getInstance()->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); - Poco::Data::Statement insert(dbSession); - insert << "INSERT INTO user_backups (user_id, passphrase) VALUES(?,?)", - use(mUserId), use(mPassphrase); - try { - if (insert.execute() != 1) { - em->addError(new ParamError("WritePassphraseIntoDB::run", "inserting passphrase for user failed", std::to_string(mUserId))); - em->sendErrorsAsEmail(); - } - } - catch (Poco::Exception& ex) { - em->addError(new ParamError("WritePassphraseIntoDB::run", "insert passphrase mysql error", ex.displayText().data())); - em->sendErrorsAsEmail(); - } - - //printf("[WritePassphraseIntoDB] timeUsed: %s\n", timeUsed.string().data()); - return 0; -} // -------------------------------------------------------------------------------------------------------------- Session::Session(int handle) - : mHandleId(handle), mSessionUser(nullptr), mState(SESSION_STATE_EMPTY), mActive(false) + : mHandleId(handle), mState(SESSION_STATE_EMPTY), mActive(false) { } @@ -109,7 +62,6 @@ void Session::reset() //printf("[Session::reset]\n"); lock("Session::reset"); std::unique_lock _lock(mSharedMutex); - mSessionUser.assign(nullptr); mNewUser.assign(nullptr); mEmailVerificationCodeObject.assign(nullptr); @@ -147,7 +99,7 @@ Poco::AutoPtr Session::getEmailVerificationCo return ret; } -bool Session::adminCreateUser(const std::string& first_name, const std::string& last_name, const std::string& email) +bool Session::adminCreateUser(const std::string& first_name, const std::string& last_name, const std::string& email, int group_id) { Profiler usedTime; @@ -177,7 +129,7 @@ bool Session::adminCreateUser(const std::string& first_name, const std::string& return false; } - auto newUser = controller::User::create(email, first_name, last_name); + auto newUser = controller::User::create(email, first_name, last_name, group_id); updateTimeout(); @@ -201,128 +153,9 @@ bool Session::adminCreateUser(const std::string& first_name, const std::string& return true; } -// -bool Session::createUser(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password) -{ - Profiler usedTime; - auto sm = SessionManager::getInstance(); - if (!sm->isValid(first_name, VALIDATE_NAME)) { - addError(new Error(gettext("Vorname"), gettext("Bitte gebe einen Namen an. Mindestens 3 Zeichen, keines folgender Zeichen <>&;")), false); - return false; - } - if (!sm->isValid(last_name, VALIDATE_NAME)) { - addError(new Error(gettext("Nachname"), gettext("Bitte gebe einen Namen an. Mindestens 3 Zeichen, keines folgender Zeichen <>&;")), false); - return false; - } - if (!sm->isValid(email, VALIDATE_EMAIL)) { - addError(new Error(gettext("E-Mail"), gettext("Bitte gebe eine gültige E-Mail Adresse an.")), false); - return false; - } - if (!sm->checkPwdValidation(password, this)) { - return false; - } - /*if (passphrase.size() > 0 && !sm->isValid(passphrase, VALIDATE_PASSPHRASE)) { - addError(new Error("Merkspruch", "Der Merkspruch ist nicht gültig, er besteht aus 24 Wörtern, mit Komma getrennt.")); - return false; - } - if (passphrase.size() == 0) { - //mPassphrase = User::generateNewPassphrase(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]); - mPassphrase = User::generateNewPassphrase(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]); - } - else { - //mPassphrase = passphrase; - }*/ - // check if user with that email already exist - auto dbConnection = ConnectionManager::getInstance()->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); - Poco::Data::Statement select(dbConnection); - select << "SELECT email from users where email = ?;", useRef(email); - try { - if (select.execute() > 0) { - addError(new Error(gettext("E-Mail"), gettext("Für diese E-Mail Adresse gibt es bereits einen Account")), false); - return false; - } - } - catch (Poco::Exception& exc) { - printf("mysql exception: %s\n", exc.displayText().data()); - } - - mSessionUser = new User(email.data(), first_name.data(), last_name.data()); - mNewUser = controller::User::create(email, first_name, last_name); - updateTimeout(); - - // Prepare E-Mail - //UniLib::controller::TaskPtr prepareEmail(new PrepareEmailTask(ServerConfig::g_CPUScheduler)); - //prepareEmail->scheduleTask(prepareEmail); - - // create user crypto key - UniLib::controller::TaskPtr cryptoKeyTask(new UserCreateCryptoKey(mSessionUser, mNewUser, password, ServerConfig::g_CryptoCPUScheduler)); - cryptoKeyTask->setFinishCommand(new SessionStateUpdateCommand(SESSION_STATE_CRYPTO_KEY_GENERATED, this)); - cryptoKeyTask->scheduleTask(cryptoKeyTask); - - // depends on crypto key, write user record into db - UniLib::controller::TaskPtr writeUserIntoDB(new UserWriteIntoDB(mSessionUser, ServerConfig::g_CPUScheduler, 1)); - writeUserIntoDB->setParentTaskPtrInArray(cryptoKeyTask, 0); - writeUserIntoDB->setFinishCommand(new SessionStateUpdateCommand(SESSION_STATE_USER_WRITTEN, this)); - writeUserIntoDB->scheduleTask(writeUserIntoDB); - - std::unique_lock _lock(mSharedMutex); - mEmailVerificationCodeObject = controller::EmailVerificationCode::create(model::table::EMAIL_OPT_IN_REGISTER); - UniLib::controller::TaskPtr writeEmailVerification(new WriteEmailVerification(mSessionUser, mEmailVerificationCodeObject, ServerConfig::g_CPUScheduler, 1)); - - writeEmailVerification->setParentTaskPtrInArray(writeUserIntoDB, 0); - writeEmailVerification->setFinishCommand(new SessionStateUpdateCommand(SESSION_STATE_EMAIL_VERIFICATION_WRITTEN, this)); - writeEmailVerification->scheduleTask(writeEmailVerification); - - - /*printf("LastName: %s\n", last_name.data()); - for (int i = 0; i < last_name.size(); i++) { - char c = last_name.data()[i]; - //printf("%d ", c); - } - //printf("\n\n"); - */ - - // depends on writeUser because need user_id, write email verification into db - /*auto message = new Poco::Net::MailMessage; - Poco::Net::MediaType mt("text", "plain"); - mt.setParameter("charset", "utf-8"); - message->setContentType(mt); - - message->addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, email)); - message->setSubject(gettext("Gradido: E-Mail Verification")); - std::stringstream ss; - ss << "Hallo " << first_name << " " << last_name << "," << std::endl << std::endl; - ss << "Du oder jemand anderes hat sich soeben mit dieser E-Mail Adresse bei Gradido registriert. " << std::endl; - ss << "Wenn du es warst, klicke bitte auf den Link: " << ServerConfig::g_serverPath << "/checkEmail/" << mEmailVerificationCode << std::endl; - //ss << "oder kopiere den Code: " << mEmailVerificationCode << " selbst dort hinein." << std::endl; - ss << "oder kopiere den obigen Link in Dein Browserfenster." << std::endl; - ss << std::endl; - ss << "Mit freundlichen " << u8"Grüßen" << std::endl; - ss << "Dario, Gradido Server Admin" << std::endl; - - - message->addContent(new Poco::Net::StringPartSource(ss.str())); - */ - //UniLib::controller::TaskPtr sendEmail(new SendEmailTask(message, ServerConfig::g_CPUScheduler, 1)); - //Email(AutoPtr emailVerification, AutoPtr user, EmailType type); - UniLib::controller::TaskPtr sendEmail(new SendEmailTask(new model::Email(mEmailVerificationCodeObject, mNewUser, model::EMAIL_USER_VERIFICATION_CODE), ServerConfig::g_CPUScheduler, 1)); - //sendEmail->setParentTaskPtrInArray(prepareEmail, 0); - sendEmail->setParentTaskPtrInArray(writeEmailVerification, 0); - sendEmail->setFinishCommand(new SessionStateUpdateCommand(SESSION_STATE_EMAIL_VERIFICATION_SEND, this)); - sendEmail->scheduleTask(sendEmail); - - // write user into db - // generate and write email verification into db - // send email - - //printf("[Session::createUser] time: %s\n", usedTime.string().data()); - - return true; -} - -bool Session::createUserDirect(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password) +bool Session::createUserDirect(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password, int groupId) { std::unique_lock _lock(mSharedMutex); static const char* function_name = "Session::createUserDirect"; @@ -354,7 +187,7 @@ bool Session::createUserDirect(const std::string& first_name, const std::string& } // user - mNewUser = controller::User::create(email, first_name, last_name); + mNewUser = controller::User::create(email, first_name, last_name, groupId); auto user_model = mNewUser->getModel(); user_model->insertIntoDB(true); auto user_id = user_model->getID(); @@ -429,16 +262,8 @@ int Session::updateEmailVerification(Poco::UInt64 emailVerificationCode) } auto email_verification_code_model = mEmailVerificationCodeObject->getModel(); assert(email_verification_code_model); - if(email_verification_code_model->getCode() == emailVerificationCode) { - if (mSessionUser && mSessionUser->getDBId() == 0) { - //addError(new Error("E-Mail Verification", "Benutzer wurde nicht richtig gespeichert, bitte wende dich an den Server-Admin")); - em->addError(new Error(funcName, "user exist with 0 as id")); - em->sendErrorsAsEmail(); - - //return false; - return -2; - } - + if(email_verification_code_model->getCode() == emailVerificationCode) + { // load correct user from db if (mNewUser.isNull() || !mNewUser->getModel() || mNewUser->getModel()->getID() != email_verification_code_model->getUserId()) { mNewUser = controller::User::create(); @@ -460,7 +285,6 @@ int Session::updateEmailVerification(Poco::UInt64 emailVerificationCode) first_email_activation = true; } if (first_email_activation && user_model->isEmailChecked()) { - mSessionUser = new User(mNewUser); addError(new Error(gettext("E-Mail Verification"), gettext("Du hast dein Konto bereits aktiviert!")), false); return 1; @@ -499,28 +323,6 @@ int Session::updateEmailVerification(Poco::UInt64 emailVerificationCode) return -2; - /*if (updated_rows == 1) { - Poco::Data::Statement delete_row(dbConnection); - delete_row << "DELETE FROM email_opt_in where verification_code = ?", use(emailVerificationCode); - if (delete_row.execute() != 1) { - em->addError(new Error(funcName, "delete from email_opt_in entry didn't work as expected, please check db")); - em->sendErrorsAsEmail(); - } - if (mSessionUser) { - mSessionUser->setEmailChecked(); - mSessionUser->setLanguage(getLanguage()); - } - updateState(SESSION_STATE_EMAIL_VERIFICATION_CODE_CHECKED); - //printf("[%s] time: %s\n", funcName, usedTime.string().data()); - unlock(); - return true; - } - else { - em->addError(new ParamError(funcName, "update user work not like expected, updated row count", updated_rows)); - em->sendErrorsAsEmail(); - }*/ - - } else { addError(new Error(gettext("E-Mail Verification"), gettext("Falscher Code für aktiven Login"))); @@ -537,7 +339,6 @@ int Session::updateEmailVerification(Poco::UInt64 emailVerificationCode) int Session::sendResetPasswordEmail(Poco::AutoPtr user, bool passphraseMemorized) { mNewUser = user; - mSessionUser = new User(user); auto em = EmailManager::getInstance(); std::unique_lock _lock(mSharedMutex); @@ -579,16 +380,17 @@ int Session::sendResetPasswordEmail(Poco::AutoPtr user, bool p return 0; } -int Session::comparePassphraseWithSavedKeys(const std::string& inputPassphrase, Mnemonic* wordSource) +int Session::comparePassphraseWithSavedKeys(const std::string& inputPassphrase, const Mnemonic* wordSource) { - KeyPair keys; + static const char* functionName = "Session::comparePassphraseWithSavedKeys"; if (!wordSource) { addError(new Error(functionName, "wordSource is empty")); sendErrorsAsEmail(); return -2; } - if (!keys.generateFromPassphrase(inputPassphrase.data(), wordSource)) { + auto passphrase = Passphrase::create(inputPassphrase, wordSource); + if (passphrase.isNull() || !passphrase->checkIfValid()) { addError(new ParamError(functionName, "invalid passphrase", inputPassphrase)); if (!mNewUser.isNull() && mNewUser->getModel()) { addError(new ParamError(functionName, "user email", mNewUser->getModel()->getEmail())); @@ -610,9 +412,15 @@ int Session::comparePassphraseWithSavedKeys(const std::string& inputPassphrase, return -1; } } - if (0 == memcmp(userModel->getPublicKey(), keys.getPublicKey(), crypto_sign_PUBLICKEYBYTES)) { - mPassphrase = inputPassphrase; - return 1; + auto keys = KeyPairEd25519::create(passphrase); + if (keys) { + auto cmp_result = memcmp(userModel->getPublicKey(), keys->getPublicKey(), crypto_sign_PUBLICKEYBYTES); + delete keys; + keys = nullptr; + if (0 == cmp_result) { + mPassphrase = inputPassphrase; + return 1; + } } addError(new Error(gettext("Passphrase"), gettext("Das ist nicht die richtige Passphrase.")), false); return 0; @@ -634,13 +442,8 @@ bool Session::startProcessingTransaction(const std::string& proto_message_base64 return false; } } - if (mSessionUser.isNull() || !mSessionUser->getEmail()) { - addError(new Error(funcName, "user is zero")); - unlock(); - return false; - } - Poco::AutoPtr processorTask(new ProcessingTransaction(proto_message_base64, DRMakeStringHash(mSessionUser->getEmail()))); + Poco::AutoPtr processorTask(new ProcessingTransaction(proto_message_base64, DRMakeStringHash(mNewUser->getModel()->getEmail().data()))); processorTask->scheduleTask(processorTask); mProcessingTransactions.push_back(processorTask); unlock(); @@ -723,15 +526,7 @@ size_t Session::getProcessingTransactionCount() return count; } -bool Session::isPwdValid(const std::string& pwd) -{ - if (mSessionUser) { - return mSessionUser->validatePwd(pwd, this); - } - return false; -} - -UserStates Session::loadUser(const std::string& email, const std::string& password) +UserState Session::loadUser(const std::string& email, const std::string& password) { static const char* functionName = "Session::loadUser"; auto observer = SingletonTaskObserver::getInstance(); @@ -742,24 +537,20 @@ UserStates Session::loadUser(const std::string& email, const std::string& passwo } //Profiler usedTime; lock(functionName); - if (mSessionUser && mSessionUser->getEmail() != email) { - mSessionUser.assign(nullptr); - mNewUser.assign(nullptr); - } + //if (!mSessionUser) { if (mNewUser.isNull()) { mNewUser = controller::User::create(); // load user for email only once from db mNewUser->load(email); - mSessionUser = new User(mNewUser); - //mSessionUser = new User(email.data()); + } auto user_model = mNewUser->getModel(); if (user_model && user_model->isDisabled()) { return USER_DISABLED; } - if (mSessionUser->getUserState() >= USER_LOADED_FROM_DB) { + if (mNewUser->getUserState() >= USER_LOADED_FROM_DB) { int loginResult = mNewUser->login(password); if (-1 == loginResult) { @@ -798,42 +589,30 @@ UserStates Session::loadUser(const std::string& email, const std::string& passwo } } } - // can be removed if session user isn't used any more - // don't calculate password two times anymore - mSessionUser->login(mNewUser); - /*if (mNewUser->getModel()->getPasswordHashed() && !mSessionUser->validatePwd(password, this)) { - unlock(); - return USER_PASSWORD_INCORRECT; - }*/ + } else { - User::fakeCreateCryptoKey(); + Poco::Thread::sleep(ServerConfig::g_FakeLoginSleepTime); } - /*if (!mSessionUser->validatePwd(password, this)) { - addError(new Error("Login", "E-Mail oder Passwort nicht korrekt, bitte versuche es erneut!")); - unlock(); - return false; - } - if (!mSessionUser->isEmailChecked()) { - addError(new Error("Account", "E-Mail Adresse wurde noch nicht bestätigt, hast du schon eine E-Mail erhalten?")); - unlock(); - return false; - }*/ detectSessionState(); unlock(); + if (0 == mNewUser->getModel()->getGroupId()) { + return USER_NO_GROUP; + } - return mSessionUser->getUserState(); + return mNewUser->getUserState(); } bool Session::deleteUser() { lock("Session::deleteUser"); bool bResult = false; - if(mSessionUser) { + if(!mNewUser.isNull()) { JsonRequest phpServerRequest(ServerConfig::g_php_serverHost, 443); Poco::Net::NameValueCollection payload; - payload.add("user", std::string(mSessionUser->getPublicKeyHex())); + auto user_model = mNewUser->getModel(); + payload.add("user", user_model->getPublicKeyHex()); //auto ret = phpServerRequest.request("userDelete", payload); JsonRequestReturn ret = JSON_REQUEST_RETURN_OK; if (ret == JSON_REQUEST_RETURN_ERROR) { @@ -842,7 +621,7 @@ bool Session::deleteUser() sendErrorsAsEmail(); } else if (ret == JSON_REQUEST_RETURN_OK) { - bResult = mSessionUser->deleteFromDB(); + bResult = user_model->deleteFromDB(); } else { addError(new Error(gettext("Benutzer"), gettext("Konnte Community Server nicht erreichen. E-Mail an den Admin ist raus."))); @@ -895,14 +674,14 @@ SESSION_STATE_COUNT */ void Session::detectSessionState() { - if (!mSessionUser || !mSessionUser->hasCryptoKey()) { + if (mNewUser.isNull() || !mNewUser->getModel() || mNewUser->getPassword().isNull()) { return; } - UserStates userState = mSessionUser->getUserState(); + UserState userState = mNewUser->getUserState(); int checkEmail = -1, resetPasswd = -1; try { - auto emailVerificationCodeObjects = controller::EmailVerificationCode::load(mSessionUser->getDBId()); + auto emailVerificationCodeObjects = controller::EmailVerificationCode::load(mNewUser->getModel()->getID()); for (int i = 0; i < emailVerificationCodeObjects.size(); i++) { auto type = emailVerificationCodeObjects[i]->getModel()->getType(); @@ -940,7 +719,7 @@ void Session::detectSessionState() if (USER_NO_KEYS == userState) { - auto user_id = mSessionUser->getDBId(); + auto user_id = mNewUser->getModel()->getID(); auto userBackups = controller::UserBackup::load(user_id); // check passphrase, only possible while passphrase isn't crypted in db @@ -948,15 +727,20 @@ void Session::detectSessionState() // always trigger SESSION_STATE_PASSPHRASE_WRITTEN, else lost of data possible bool cryptedPassphrase = userBackups.size() > 0; for (auto it = userBackups.begin(); it != userBackups.end(); it++) { - KeyPair keys; auto passphrase = (*it)->getModel()->getPassphrase(); Mnemonic* wordSource = nullptr; - if (User::validatePassphrase(passphrase, &wordSource)) { - if (keys.generateFromPassphrase((*it)->getModel()->getPassphrase().data(), wordSource)) { - if (sodium_memcmp(mSessionUser->getPublicKey(), keys.getPublicKey(), ed25519_pubkey_SIZE) == 0) { - correctPassphraseFound = true; - break; - } + auto passphrase_obj = Passphrase::create(passphrase, wordSource); + if (!passphrase_obj.isNull() && passphrase_obj->checkIfValid()) { + auto key_pair = KeyPairEd25519::create(passphrase_obj); + if (key_pair && key_pair->isTheSame(mNewUser->getModel()->getPublicKey())) { + correctPassphraseFound = true; + //break; + } + if (key_pair) { + delete key_pair; + } + if (correctPassphraseFound) { + break; } } else { @@ -1038,8 +822,7 @@ bool Session::loadFromEmailVerificationCode(Poco::UInt64 emailVerificationCode) addError(new Error(gettext("E-Mail Verification"), gettext("Fehler beim laden des Benutzers."))); return false; } - mSessionUser = new User(mNewUser); - mSessionUser->setLanguage(getLanguage()); + // TODO: Maybe update language key by user, is session has another, or update only with options-menu auto verificationType = mEmailVerificationCodeObject->getModel()->getType(); if (verificationType == model::table::EMAIL_OPT_IN_RESET_PASSWORD) { @@ -1117,21 +900,7 @@ bool Session::useOrGeneratePassphrase(const std::string& passphase) } } */ -bool Session::generatePassphrase() -{ - if (mNewUser.isNull()) return false; - - auto lang = getLanguage(); - if (lang == LANG_EN) { - mPassphrase = User::generateNewPassphrase(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]); - } - else { - mPassphrase = User::generateNewPassphrase(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]); - } - //mPassphrase = User::generateNewPassphrase(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]); - updateState(SESSION_STATE_PASSPHRASE_GENERATED); - return true; -} + bool Session::generateKeys(bool savePrivkey, bool savePassphrase) { diff --git a/src/cpp/model/Session.h b/src/cpp/model/Session.h index 6557ef30e..8834b63fd 100644 --- a/src/cpp/model/Session.h +++ b/src/cpp/model/Session.h @@ -11,7 +11,6 @@ #define DR_LUA_WEB_MODULE_SESSION_SESSION_H #include "../lib/NotificationList.h" -#include "User.h" #include "../controller/User.h" #include "../lib/MultithreadContainer.h" @@ -73,29 +72,20 @@ public: inline Poco::AutoPtr getNewUser() { return mNewUser; } // ---------------- User functions ---------------------------- - // TODO: register state: written into db, mails sended, update state only if new state is higher as old state - // create User send e-mail activation link - bool createUser(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password); //! \brief new register function, without showing user pubkeys, using controller/user - bool createUserDirect(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password); + bool createUserDirect(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password, int groupId); // adminRegister without passwort - bool adminCreateUser(const std::string& first_name, const std::string& last_name, const std::string& email); + bool adminCreateUser(const std::string& first_name, const std::string& last_name, const std::string& email, int group_id); // TODO: check if email exist and if not, fake waiting on password hashing with profiled times of real password hashing - UserStates loadUser(const std::string& email, const std::string& password); + UserState loadUser(const std::string& email, const std::string& password); bool ifUserExist(const std::string& email); - - inline void setUser(Poco::AutoPtr user) { mSessionUser = user; } - bool deleteUser(); - Poco::AutoPtr getUser() { - return mSessionUser; - } // ------------------------- Email Verification Code functions ------------------------------- @@ -117,7 +107,7 @@ public: //! \return 1 = same //! \return -1 = error //! \return -2 = critical error - int comparePassphraseWithSavedKeys(const std::string& inputPassphrase, Mnemonic* wordSource); + int comparePassphraseWithSavedKeys(const std::string& inputPassphrase, const Mnemonic* wordSource); Poco::Net::HTTPCookie getLoginCookie(); @@ -132,14 +122,13 @@ public: inline void setPassphrase(const std::string& passphrase) { mPassphrase = passphrase; } inline const std::string& getOldPassphrase() { return mPassphrase; } - bool generatePassphrase(); + bool generateKeys(bool savePrivkey, bool savePassphrase); inline void setClientIp(Poco::Net::IPAddress ip) { mClientLoginIP = ip; } inline Poco::Net::IPAddress getClientIp() { return mClientLoginIP; } inline bool isIPValid(Poco::Net::IPAddress ip) { return mClientLoginIP == ip; } - bool isPwdValid(const std::string& pwd); void reset(); void updateState(SessionStates newState); @@ -198,7 +187,6 @@ protected: private: int mHandleId; - Poco::AutoPtr mSessionUser; Poco::AutoPtr mNewUser; std::string mPassphrase; Poco::AutoPtr mNewPassphrase; @@ -219,44 +207,6 @@ private: }; -class WriteEmailVerification : public UniLib::controller::CPUTask -{ -public: - WriteEmailVerification(Poco::AutoPtr user, Poco::AutoPtr emailVerificationCode, UniLib::controller::CPUSheduler* cpuScheduler, size_t taskDependenceCount = 0) - : UniLib::controller::CPUTask(cpuScheduler, taskDependenceCount), mUser(user), mEmailVerificationCode(emailVerificationCode) { -#ifdef _UNI_LIB_DEBUG - setName(user->getEmail()); -#endif - } - - virtual const char* getResourceType() const { return "WriteEmailVerification"; }; - virtual int run(); - -private: - Poco::AutoPtr mUser; - Poco::AutoPtr mEmailVerificationCode; - -}; - -class WritePassphraseIntoDB : public UniLib::controller::CPUTask -{ -public: - WritePassphraseIntoDB(int userId, const std::string& passphrase) - : mUserId(userId), mPassphrase(passphrase) { -#ifdef _UNI_LIB_DEBUG - setName(std::to_string(userId).data()); -#endif - } - - - virtual int run(); - virtual const char* getResourceType() const { return "WritePassphraseIntoDB"; }; - -protected: - int mUserId; - std::string mPassphrase; -}; - class SessionStateUpdateCommand : public UniLib::controller::Command { public: diff --git a/src/cpp/model/TransactionCreation.cpp b/src/cpp/model/TransactionCreation.cpp index 499aef61d..fd80660d8 100644 --- a/src/cpp/model/TransactionCreation.cpp +++ b/src/cpp/model/TransactionCreation.cpp @@ -3,17 +3,14 @@ #include TransactionCreation::TransactionCreation(const std::string& memo, const proto::gradido::GradidoCreation& protoCreation) - : TransactionBase(memo), mProtoCreation(protoCreation), mReceiverUser(nullptr) + : TransactionBase(memo), mProtoCreation(protoCreation) { memset(mReceiverPublicHex, 0, 65); } TransactionCreation::~TransactionCreation() { - if (mReceiverUser) { - delete mReceiverUser; - mReceiverUser = nullptr; - } + } int TransactionCreation::prepare() @@ -30,15 +27,17 @@ int TransactionCreation::prepare() addError(new Error(functionName, "receiver public invalid (size not 32)")); return -2; } - mReceiverUser = new User((const unsigned char*)receiverPublic.data()); - getErrors(mReceiverUser); + mReceiverUser = controller::User::create(); + //mReceiverUser = new User((const unsigned char*)receiverPublic.data()); + mReceiverUser->load((const unsigned char*)receiverPublic.data()); + getErrors(mReceiverUser->getModel()); if (mReceiverUser->getUserState() == USER_EMPTY) { sodium_bin2hex(mReceiverPublicHex, 65, (const unsigned char*)receiverPublic.data(), receiverPublic.size()); delete mReceiverUser; mReceiverUser = nullptr; } else { - memcpy(mReceiverPublicHex, mReceiverUser->getPublicKeyHex().data(), 64); + memcpy(mReceiverPublicHex, mReceiverUser->getModel()->getPublicKeyHex().data(), 64); // uncomment because not correctly working /*if (!mReceiverUser->validateIdentHash(mProtoCreation.ident_hash())) { addError(new Error(functionName, "ident hash isn't the same")); diff --git a/src/cpp/model/TransactionCreation.h b/src/cpp/model/TransactionCreation.h index ff1fd62a8..fe695b89b 100644 --- a/src/cpp/model/TransactionCreation.h +++ b/src/cpp/model/TransactionCreation.h @@ -13,7 +13,7 @@ #include "TransactionBase.h" #include "../proto/gradido/GradidoCreation.pb.h" -#include "User.h" +#include "../controller/User.h" class TransactionCreation : public TransactionBase { @@ -23,7 +23,7 @@ public: int prepare(); - inline User* getUser() { return mReceiverUser; } + inline Poco::AutoPtr getUser() { return mReceiverUser; } inline google::protobuf::int64 getAmount() { return mProtoCreation.receiver().amount(); } inline char* getPublicHex() { return mReceiverPublicHex; } @@ -33,7 +33,7 @@ public: protected: const proto::gradido::GradidoCreation& mProtoCreation; char mReceiverPublicHex[65]; - User* mReceiverUser; + Poco::AutoPtr mReceiverUser; }; #endif //GRADIDO_LOGIN_SERVER_MODEL_TRANSACTION_CREATION_INCLUDE \ No newline at end of file diff --git a/src/cpp/model/User.cpp b/src/cpp/model/User.cpp deleted file mode 100644 index a57324cf8..000000000 --- a/src/cpp/model/User.cpp +++ /dev/null @@ -1,1323 +0,0 @@ -#include "User.h" -#include "Session.h" -#include -#include "ed25519/ed25519.h" -#include "Poco/Util/Application.h" -#include "Poco/RegularExpression.h" -#include "../ServerConfig.h" - -#include "../SingletonManager/ConnectionManager.h" -#include "../SingletonManager/ErrorManager.h" -#include "../SingletonManager/SessionManager.h" -#include "../SingletonManager/LanguageManager.h" -#include "../SingletonManager/SingletonTaskObserver.h" - -#include "../controller/UserBackup.h" - - -#include "Poco/Data/Binding.h" - -using namespace Poco::Data::Keywords; - -//#define DEBUG_USER_DELETE_ENV - - -// ------------------------------------------------------------------------------------------------- - -UserCreateCryptoKey::UserCreateCryptoKey(Poco::AutoPtr user, Poco::AutoPtr newUser, const std::string& password, UniLib::controller::CPUSheduler* cpuScheduler) - : UniLib::controller::CPUTask(cpuScheduler), mUser(user), mNewUser(newUser), mPassword(password) { -#ifdef _UNI_LIB_DEBUG - setName(user->getEmail()); -#endif - -} - -int UserCreateCryptoKey::run() -{ - auto cryptoKey = mUser->createCryptoKey(mPassword); - mUser->setCryptoKey(cryptoKey); - - if (sizeof(User::passwordHashed) != crypto_shorthash_BYTES) { - printf("[UserCreateCryptoKey] crypto_shorthash_BYTES != sizeof(mPasswordHashed)\n"); - throw Poco::Exception("crypto_shorthash_BYTES != sizeof(mPasswordHashed)"); - } - - auto pwdHashed = mUser->createPasswordHashed(cryptoKey); - mUser->setPwdHashed(pwdHashed); - mNewUser->getModel()->setPasswordHashed(pwdHashed); - - //printf("crypto key created\n"); - setTaskFinished(); - // must poke cpu scheduler manually because another task is waiting for this task, but in the other scheduler - ServerConfig::g_CPUScheduler->checkPendingTasks(); - return 0; -} - -// ------------------------------------------------------------------------------------------------------------- - -int UserGenerateKeys::run() -{ - - Mnemonic* wordList = nullptr; - if (!User::validatePassphrase(mPassphrase, &wordList)) { - mUser->addError(new Error(mUser->gettext("User generate Keys"), mUser->gettext("invalid passphrase, please notice the server admin coin@gradido.net"))); - return -2; - } - - // always return true, cannot fail (only if low on memory) - // !!! update: now can fail, if passphrase is invalid, for example if memory is corrupted - if (!mKeys.generateFromPassphrase(mPassphrase.data(), wordList)) { - mUser->addError(new Error(mUser->gettext("User generate Keys"), mUser->gettext("invalid passphrase2, please notice the server admin coin@gradido.net"))); - return -1; - } - - mUser->setPublicKeyHex(mKeys.getPubkeyHex()); - mUser->setPublicKey(mKeys.getPublicKey()); - - auto newUserModel = mNewUser->getModel(); - - newUserModel->setPublicKey(mKeys.getPublicKey()); - if (mUser->hasCryptoKey()) { - mUser->setPrivKey(mKeys.getPrivateKey()); - newUserModel->setPrivateKey(mUser->getPrivKey()); - } - - //printf("[UserGenerateKeys::run] controller::User: %d\n", (int)mNewUser.get()); - - return 0; -} - -// ----------------------------------------------------------------------------------------------------- - -int UserWriteIntoDB::run() -{ - auto cm = ConnectionManager::getInstance(); - auto em = ErrorManager::getInstance(); - auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); - Poco::Data::Statement insert = mUser->insertIntoDB(session); - try { - if (1 != insert.execute()) { - mUser->addError(new Error("User::insertIntoDB", "error by inserting data tuple to db")); - return -1; - } - } catch (Poco::Exception& ex) { - em->addError(new ParamError("[UserWriteIntoDB]", "error writing into db", ex.displayText().data())); - em->sendErrorsAsEmail(); - return -3; - } - if (!mUser->loadEntryDBId(session)) { - return -2; - } - return 0; -} - -// -------------------------------------------------------------------------------------------------------- - -UserWriteKeysIntoDB::UserWriteKeysIntoDB(std::vector parents, Poco::AutoPtr user, bool savePrivKey) - : UniLib::controller::CPUTask(parents.size()), mUser(user), mSavePrivKey(savePrivKey) -{ -#ifdef _UNI_LIB_DEBUG - setName(user->getEmail()); -#endif - if (parents.size() < 1 || strcmp(parents[0]->getResourceType(), "UserGenerateKeys") != 0) { - throw Poco::Exception("given TaskPtr isn't UserGenerateKeys"); - } - for (int i = 0; i < parents.size(); i++) { - setParentTaskPtrInArray(parents[i], i); - } - //setParentTaskPtrInArray(parents[0], 0); - -} - -int UserWriteKeysIntoDB::run() -{ - auto cm = ConnectionManager::getInstance(); - auto em = ErrorManager::getInstance(); - auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); - auto keyPairs = getParent(0).cast()->getKeyPairs(); - auto pubKey = keyPairs->getPublicKey(); - static const char* functionName = "UserWritePrivKeyIntoDB::run"; - - //printf("[UserWriteKeysIntoDB] after init\n"); - - Poco::Data::BLOB pubkey_blob(pubKey, crypto_sign_PUBLICKEYBYTES); - Poco::Data::Statement update(session); - Poco::Data::BLOB* pprivkey_blob = nullptr; - if (mSavePrivKey) { - //printf("[UserWriteKeysIntoDB] save privkey\n"); - // TODO: encrypt privkey - auto privKey = keyPairs->getPrivateKey(); - //printf("[UserWriteKeysIntoDB] privKey hex: %s\n", KeyPair::getHex(*privKey, privKey->size()).data()); - auto encryptedPrivKey = mUser->encrypt(privKey); - //pprivkey_blob = mUser->encrypt(privKey); - if (!encryptedPrivKey) { - em->addError(new Error(functionName, "no privkey found")); - em->sendErrorsAsEmail(); - return -1; - } - pprivkey_blob = new Poco::Data::BLOB(*encryptedPrivKey, encryptedPrivKey->size()); - //printf("[UserWriteKeysIntoDB] privkey encrypted\n"); - //Poco::Data::BLOB privkey_blob(*privKey, privKey->size()); - - update << "UPDATE users SET pubkey=?, privkey=? where id=?", - use(pubkey_blob), use(*pprivkey_blob), bind(mUser->getDBId()); - } - else { - update << "UPDATE users SET pubkey=? where id=?", - use(pubkey_blob), bind(mUser->getDBId()); - } - - try { - if (update.execute() != 1) { - em->addError(new ParamError(functionName, "error writing keys into db for user", std::to_string(mUser->getDBId()))); - em->sendErrorsAsEmail(); - if (pprivkey_blob) { - delete pprivkey_blob; - } - return -1; - } - } - catch (Poco::Exception& ex) { - em->addError(new ParamError(functionName, "mysql error updating", ex.displayText().data())); - em->sendErrorsAsEmail(); - if (pprivkey_blob) { - delete pprivkey_blob; - } - return -1; - } - - //printf("[UserWriteKeysIntoDB] after saving into db\n"); - if (pprivkey_blob) { - delete pprivkey_blob; - } - - return 0; -} - -// -------------------------------------------------------------------------------------------------------- - -UserWriteCryptoKeyHashIntoDB::UserWriteCryptoKeyHashIntoDB(Poco::AutoPtr user, int dependencieCount/* = 0*/) - : UniLib::controller::CPUTask(ServerConfig::g_CPUScheduler, dependencieCount), mUser(user) -{ -#ifdef _UNI_LIB_DEBUG - setName(user->getEmail()); -#endif -} - -int UserWriteCryptoKeyHashIntoDB::run() -{ - mUser->updateIntoDB(USER_FIELDS_PASSWORD); - return 0; -} - -// ******************************************************************************* -// new user -User::User(const char* email, const char* first_name, const char* last_name) - : mState(USER_EMPTY), mDBId(0), mEmail(email), mFirstName(first_name), mLastName(last_name), mPasswordHashed(0), mPrivateKey(nullptr), mEmailChecked(false), - mLanguage(LANG_DE), mGradidoCurrentBalance(0), mCryptoKey(nullptr), mReferenceCount(1) -{ - memset(mPublicKey, 0, crypto_sign_PUBLICKEYBYTES); - mLanguageCatalog = LanguageManager::getInstance()->getFreeCatalog(mLanguage); -} -// load from db -User::User(const char* email) - : mState(USER_EMPTY), mDBId(0), mEmail(email), mPasswordHashed(0), mPrivateKey(nullptr), mEmailChecked(false), - mLanguage(LANG_DE), mGradidoCurrentBalance(0), mCryptoKey(nullptr), mReferenceCount(1) -{ - //crypto_shorthash(mPasswordHashed, (const unsigned char*)password, strlen(password), *ServerConfig::g_ServerCryptoKey); - //memset(mPasswordHashed, 0, crypto_shorthash_BYTES); - auto cm = ConnectionManager::getInstance(); - auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); - - memset(mPublicKey, 0, crypto_sign_PUBLICKEYBYTES); - - Poco::Nullable pubkey; - Poco::Nullable privkey; - - Poco::Data::Statement select(session); - int email_checked = 0; - std::string language_key; - select << "SELECT id, first_name, last_name, password, pubkey, privkey, email_checked, language from users where email = ?", - into(mDBId), into(mFirstName), into(mLastName), into(mPasswordHashed), into(pubkey), into(privkey), into(email_checked), into(language_key), - use(mEmail); - try { - auto result = select.execute(); - if (result == 1) { - mState = USER_LOADED_FROM_DB; - mLanguage = LanguageManager::languageFromString(language_key); - mLanguageCatalog = LanguageManager::getInstance()->getFreeCatalog(mLanguage); - - if (email_checked == 0) { mState = USER_EMAIL_NOT_ACTIVATED;} - else if (pubkey.isNull()) { mState = USER_NO_KEYS;} - else if (privkey.isNull()) { mState = USER_NO_PRIVATE_KEY; } - else { mState = USER_COMPLETE;} - - mEmailChecked = email_checked == 1; - - if (!pubkey.isNull()) { - auto pubkey_value = pubkey.value(); - if (pubkey_value.size() == crypto_sign_PUBLICKEYBYTES) { - memcpy(mPublicKey, pubkey_value.content().data(), crypto_sign_PUBLICKEYBYTES); - } - else { - addError(new Error("User", "pubkey from db has other size as expected")); - } - size_t hexSize = pubkey_value.size() * 2 + 1; - char* hexString = (char*)malloc(hexSize); - memset(hexString, 0, hexSize); - sodium_bin2hex(hexString, hexSize, pubkey_value.content().data(), pubkey_value.size()); - mPublicHex = hexString; - free(hexString); - } - if (!privkey.isNull()) { - auto privkey_value = privkey.value(); - auto privkey_size = privkey_value.size(); - //mPrivateKey = new ObfusArray(privkey_value.size(), privkey_value.content().data()); - mPrivateKey = MemoryManager::getInstance()->getFreeMemory(privkey_size); - memcpy(*mPrivateKey, privkey_value.content().data(), privkey_size); - } - - } - } catch(Poco::Exception& ex) { - addError(new ParamError("User::User", "mysql error", ex.displayText().data())); - } -} - -User::User(int user_id) - : mState(USER_EMPTY), mDBId(user_id), mPasswordHashed(0), mPrivateKey(nullptr), mEmailChecked(false), - mLanguage(LANG_DE), mGradidoCurrentBalance(0), mCryptoKey(nullptr), mReferenceCount(1) -{ - auto cm = ConnectionManager::getInstance(); - auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); - - memset(mPublicKey, 0, crypto_sign_PUBLICKEYBYTES); - - Poco::Nullable pubkey; - Poco::Nullable privkey; - - Poco::Data::Statement select(session); - int email_checked = 0; - std::string language_key; - select << "SELECT email, first_name, last_name, password, pubkey, privkey, email_checked, language from users where id = ?", - into(mEmail), into(mFirstName), into(mLastName), into(mPasswordHashed), into(pubkey), into(privkey), into(email_checked), into(language_key), - use(user_id); - try { - auto result = select.execute(); - if (result == 1) { - mState = USER_LOADED_FROM_DB; - mLanguage = LanguageManager::languageFromString(language_key); - mLanguageCatalog = LanguageManager::getInstance()->getFreeCatalog(mLanguage); - - if (email_checked == 0) { mState = USER_EMAIL_NOT_ACTIVATED; } - else if (pubkey.isNull()) { mState = USER_NO_KEYS; } - else if (privkey.isNull()) { mState = USER_NO_PRIVATE_KEY; } - else { mState = USER_COMPLETE; } - - mEmailChecked = email_checked == 1; - - if (!pubkey.isNull()) { - auto pubkey_value = pubkey.value(); - if (pubkey_value.size() == crypto_sign_PUBLICKEYBYTES) { - memcpy(mPublicKey, pubkey_value.content().data(), crypto_sign_PUBLICKEYBYTES); - } - else { - addError(new Error("User", "pubkey from db has other size as expected")); - } - size_t hexSize = pubkey_value.size() * 2 + 1; - char* hexString = (char*)malloc(hexSize); - memset(hexString, 0, hexSize); - sodium_bin2hex(hexString, hexSize, pubkey_value.content().data(), pubkey_value.size()); - mPublicHex = hexString; - free(hexString); - } - if (!privkey.isNull()) { - auto privkey_value = privkey.value(); - auto privkey_size = privkey_value.size(); - //mPrivateKey = new ObfusArray(privkey_value.size(), privkey_value.content().data()); - mPrivateKey = MemoryManager::getInstance()->getFreeMemory(privkey_size); - memcpy(*mPrivateKey, privkey_value.content().data(), privkey_size); - } - } - } - catch (Poco::Exception& ex) { - addError(new ParamError("User::User", "mysql error", ex.displayText().data())); - } -} - -User::User(const unsigned char* pubkey_array) - : mState(USER_EMPTY), mDBId(0), mPasswordHashed(0), mPrivateKey(nullptr), mEmailChecked(false), - mLanguage(LANG_DE), mGradidoCurrentBalance(0), mCryptoKey(nullptr), mReferenceCount(1) -{ - //crypto_shorthash(mPasswordHashed, (const unsigned char*)password, strlen(password), *ServerConfig::g_ServerCryptoKey); - //memset(mPasswordHashed, 0, crypto_shorthash_BYTES); - auto cm = ConnectionManager::getInstance(); - auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); - - memcpy(mPublicKey, pubkey_array, crypto_sign_PUBLICKEYBYTES); - - Poco::Data::BLOB pubkey(pubkey_array, 32); - Poco::Nullable privkey; - - Poco::Data::Statement select(session); - int email_checked = 0; - std::string language_key; - select << "SELECT id, email, first_name, last_name, password, privkey, email_checked, language from users where pubkey = ?", - into(mDBId), into(mEmail), into(mFirstName), into(mLastName), into(mPasswordHashed), into(privkey), into(email_checked), into(language_key), - use(pubkey); - try { - auto result = select.execute(); - if (result == 1) { - mState = USER_LOADED_FROM_DB; - mLanguage = LanguageManager::languageFromString(language_key); - mLanguageCatalog = LanguageManager::getInstance()->getFreeCatalog(mLanguage); - - if (email_checked == 0) { mState = USER_EMAIL_NOT_ACTIVATED; } - else if (privkey.isNull()) { mState = USER_NO_PRIVATE_KEY; } - else { mState = USER_COMPLETE; } - - mEmailChecked = email_checked == 1; - - size_t hexSize = pubkey.size() * 2 + 1; - char* hexString = (char*)malloc(hexSize); - memset(hexString, 0, hexSize); - sodium_bin2hex(hexString, hexSize, pubkey.content().data(), pubkey.size()); - mPublicHex = hexString; - free(hexString); - - if (!privkey.isNull()) { - auto privkey_value = privkey.value(); - auto privkey_size = privkey_value.size(); - //mPrivateKey = new ObfusArray(privkey_value.size(), privkey_value.content().data()); - mPrivateKey = MemoryManager::getInstance()->getFreeMemory(privkey_size); - memcpy(*mPrivateKey, privkey_value.content().data(), privkey_size); - } - - } - - } - catch (Poco::Exception& ex) { - addError(new ParamError("User::User", "mysql error", ex.displayText().data())); - } -} - -User::User(Poco::AutoPtr ctrl_user) - : mUserCtrl(ctrl_user), mState(USER_EMPTY), mDBId(0), mPasswordHashed(0), mPrivateKey(nullptr), mEmailChecked(false), - mLanguage(LANG_DE), mGradidoCurrentBalance(0), mCryptoKey(nullptr), mReferenceCount(1) -{ - assert(!ctrl_user.isNull()); - auto model = ctrl_user->getModel(); - assert(model); - - auto mm = MemoryManager::getInstance(); - mDBId = model->getID(); - mEmail = model->getEmail(); - mFirstName = model->getFirstName(); - mLastName = model->getLastName(); - mPasswordHashed = model->getPasswordHashed(); - auto pubkey = model->getPublicKey(); - if (pubkey) { - memcpy(mPublicKey, pubkey, crypto_sign_PUBLICKEYBYTES); - - size_t hexSize = crypto_sign_PUBLICKEYBYTES * 2 + 1; - auto hexStringTemp = mm->getFreeMemory(hexSize); - //char* hexString = (char*)malloc(hexSize); - memset(*hexStringTemp, 0, hexSize); - sodium_bin2hex((char*)(*hexStringTemp), hexSize, pubkey, crypto_sign_PUBLICKEYBYTES); - mPublicHex = std::string((char*)(*hexStringTemp)); - mm->releaseMemory(hexStringTemp); - } - if (model->hasPrivateKeyEncrypted()) { - auto privKeyVetor = model->getPrivateKeyEncrypted(); - mPrivateKey = mm->getFreeMemory(privKeyVetor.size()); - memcpy(*mPrivateKey, privKeyVetor.data(), privKeyVetor.size()); - } - mEmailChecked = model->isEmailChecked(); - mLanguage = LanguageManager::languageFromString(model->getLanguageKey()); - mLanguageCatalog = LanguageManager::getInstance()->getFreeCatalog(mLanguage); - - /* - USER_EMPTY, - USER_LOADED_FROM_DB, - USER_PASSWORD_INCORRECT, - USER_PASSWORD_ENCRYPTION_IN_PROCESS, - USER_EMAIL_NOT_ACTIVATED, - USER_NO_KEYS, - USER_NO_PRIVATE_KEY, - USER_COMPLETE - */ - - if (mEmail != "") { - mState = USER_LOADED_FROM_DB; - - if (!mEmailChecked) { mState = USER_EMAIL_NOT_ACTIVATED; } - else if (!pubkey) { mState = USER_NO_KEYS; } - else if (!mPrivateKey) { mState = USER_NO_PRIVATE_KEY; } - else { mState = USER_COMPLETE; } - } -} - - -User::~User() -{ -#ifdef DEBUG_USER_DELETE_ENV - printf("[User::~User]\n"); -#endif - auto mm = MemoryManager::getInstance(); - if (mCryptoKey) { - //delete mCryptoKey; - mm->releaseMemory(mCryptoKey); - mCryptoKey = nullptr; - } - if (mPrivateKey) { - //delete mPrivateKey; - mm->releaseMemory(mPrivateKey); - mPrivateKey = nullptr; - } -} - -void User::setLanguage(Languages lang) -{ - lock("User::setLanguage"); - if (mLanguage != lang) { - mLanguageCatalog = LanguageManager::getInstance()->getFreeCatalog(lang); - } - mLanguage = lang; - unlock(); -} - - -std::string User::generateNewPassphrase(Mnemonic* word_source) -{ - auto em = ErrorManager::getInstance(); - static const char* errorMessageForUser = "Ein Fehler, bitte wende dich an den Server-Admin (coin@gradido.net). | An error occured, please ask the server admin (coin@gradido.net)."; - unsigned int random_indices[PHRASE_WORD_COUNT]; - unsigned int str_sizes[PHRASE_WORD_COUNT]; - unsigned int phrase_buffer_size = 0; - bool errorReloadingMnemonicWordList = false; - int loopTrys = 0; - Poco::RegularExpression checkValidWord("^[a-zA-ZÄÖÜäöüß&;]*$"); - - // TODO: make sure words didn't double - for (int i = 0; i < PHRASE_WORD_COUNT; i++) { - random_indices[i] = randombytes_random() % 2048; - auto word = word_source->getWord(random_indices[i]); - if (loopTrys > 10 || errorReloadingMnemonicWordList) { - return errorMessageForUser; - } - if (!word) { - em->addError(new ParamError("User::generateNewPassphrase", "empty word get for index", random_indices[i])); - em->sendErrorsAsEmail(); - - random_indices[i] = randombytes_random() % 2048; - word = word_source->getWord(random_indices[i]); - if (!word) return errorMessageForUser; - - } - else { - if (!checkValidWord.match(word, 0, Poco::RegularExpression::RE_NOTEMPTY)) { - em->addError(new ParamError("User::generateNewPassphrase", "invalid word", word)); - em->addError(new Error("User::generateNewPassphrase", "try to reload mnemonic word list, but this error is maybe evidence for a serious memory problem!!!")); - if (!ServerConfig::loadMnemonicWordLists()) { - em->addError(new Error("User::generateNewPassphrase", "error reloading mnemonic word lists")); - errorReloadingMnemonicWordList = true; - } - else { - i = 0; - loopTrys++; - } - em->sendErrorsAsEmail(); - //return "Server Fehler, bitte frage den Admin coin@gradido.net | Server error, please ask the admin coin@gradido.net"; - } - } - str_sizes[i] = strlen(word); - phrase_buffer_size += str_sizes[i]; - } - phrase_buffer_size += PHRASE_WORD_COUNT + 1; - - std::string phrase_buffer(phrase_buffer_size, '\0'); - int phrase_buffer_cursor = 0; - - for (int i = 0; i < PHRASE_WORD_COUNT; i++) { - memcpy(&phrase_buffer[phrase_buffer_cursor], word_source->getWord(random_indices[i]), str_sizes[i]); - - phrase_buffer_cursor += str_sizes[i]; - phrase_buffer[phrase_buffer_cursor++] = ' '; - } - - - return phrase_buffer; -} - -bool User::validatePassphrase(const std::string& passphrase, Mnemonic** wordSource/* = nullptr*/) -{ - return KeyPair::validatePassphrase(passphrase, wordSource); - -} - -bool User::isEmptyPassword() -{ - bool bRet = false; - lock("User::isEmptyPassword"); - //printf("[User::isEmptyPassword] pwd hashed: %d, running: %d, this: %d\n", -// mPasswordHashed, !mCreateCryptoKeyTask.isNull(), this); - bRet = mPasswordHashed == 0 && (mCreateCryptoKeyTask.isNull() || mCreateCryptoKeyTask->isTaskFinished()); - unlock(); - return bRet; -} - -UserStates User::getUserState() -{ - UserStates state; - lock("User::getUserState"); - state = mState; - unlock(); - return state; -} - -Poco::JSON::Object User::getJson() -{ - lock("User::getJson"); - Poco::JSON::Object userObj; - - userObj.set("first_name", mFirstName); - userObj.set("last_name", mLastName); - userObj.set("email", mEmail); - userObj.set("public_hex", mPublicHex); - userObj.set("state", userStateToString(mState)); - userObj.set("email_checked", mEmailChecked); - userObj.set("ident_hash", DRMakeStringHash(mEmail.data(), mEmail.size())); - unlock(); - return userObj; -} - -/* -// TODO: if a password and privkey already exist, load current private key and re encrypt with new crypto key -bool User::setNewPassword(const std::string& newPassword) -{ - //Profiler timeUsed; - if (newPassword == "") { - lock("User::setNewPassword"); - addError(new Error("Passwort", "Ist leer.")); - unlock(); - return false; - } - if (!mCreateCryptoKeyTask.isNull() && !mCreateCryptoKeyTask->isTaskFinished()) { - lock("User::setNewPassword"); - addError(new Error("Passwort", "Wird bereits erstellt, bitte in ca. 1 minute neuladen.")); - unlock(); - return false; - } - duplicate(); - lock("User::setNewPassword"); - //printf("[User::setNewPassword] start create crypto key task with this: %d\n", this); - mCreateCryptoKeyTask = new UserCreateCryptoKey(this, newPassword, ServerConfig::g_CPUScheduler); - mCreateCryptoKeyTask->scheduleTask(mCreateCryptoKeyTask); - unlock(); - - duplicate(); - - UniLib::controller::TaskPtr savePassword(new UserWriteCryptoKeyHashIntoDB(this, 1)); - savePassword->setParentTaskPtrInArray(mCreateCryptoKeyTask, 0); - savePassword->scheduleTask(savePassword); - - - //printf("[User::setNewPassword] timeUsed: %s\n", timeUsed.string().data()); - return true; -} -*/ -bool User::updatePassword(const std::string& newPassword, const std::string& passphrase, Poco::AutoPtr newUser) -{ - static const char* functionName("User::updatePassword"); - if (newPassword == "") { - lock(functionName); - addError(new Error(gettext("Passwort"), gettext("Ist leer."))); - unlock(); - return false; - } - if (!mCreateCryptoKeyTask.isNull() && !mCreateCryptoKeyTask->isTaskFinished()) { - lock(functionName); - addError(new Error(gettext("Passwort"), gettext("Wird bereits erstellt, bitte in ca. 1 minute neuladen."))); - unlock(); - return false; - } - //duplicate(); - //lock("User::setNewPassword"); - //printf("[User::setNewPassword] start create crypto key task with this: %d\n", this); - //mCreateCryptoKeyTask = new UserCreateCryptoKey(this, newPassword, ServerConfig::g_CPUScheduler); - //mCreateCryptoKeyTask->scheduleTask(mCreateCryptoKeyTask); - //unlock(); - - auto mm = MemoryManager::getInstance(); - - bool passwordHashedCalculated = false; - - // no previous password set - - //if (!mPasswordHashed) { - duplicate(); - lock(functionName); - //printf("[User::setNewPassword] start create crypto key task with this: %d\n", this); - mCreateCryptoKeyTask = new UserCreateCryptoKey(this, newUser, newPassword, ServerConfig::g_CPUScheduler); - mCreateCryptoKeyTask->scheduleTask(mCreateCryptoKeyTask); - unlock(); - //} - /*else { - // compare with previous password - auto cryptoKey = createCryptoKey(newPassword); - auto passwordHash = createPasswordHashed(cryptoKey); - lock(functionName); - if (mPasswordHashed == passwordHash) { - addError(new Error(gettext("Passwort"), gettext("Du hast dasselbe Passwort gewählt, bitte wähle ein anderes."))); - unlock(); - mm->releaseMemory(cryptoKey); - return false; - } - mPasswordHashed = passwordHash; - passwordHashedCalculated = true; - if (mCryptoKey) { - mm->releaseMemory(mCryptoKey); - } - mCryptoKey = cryptoKey; - unlock(); - }*/ - - duplicate(); - UniLib::controller::TaskPtr savePassword(nullptr); - UserWriteCryptoKeyHashIntoDB* writePWDHashedIntoDB = nullptr; - if (passwordHashedCalculated) { - savePassword = new UserWriteCryptoKeyHashIntoDB(this, 0); - } - else { - savePassword = new UserWriteCryptoKeyHashIntoDB(this, 1); - savePassword->setParentTaskPtrInArray(mCreateCryptoKeyTask, 0); - } - savePassword->scheduleTask(savePassword); - - if (passphrase != "") { - duplicate(); - UniLib::controller::TaskPtr genKeys(new UserGenerateKeys(this, newUser, passphrase)); - genKeys->scheduleTask(genKeys); - - - std::vector saveKeysParents; - saveKeysParents.reserve(2); // to prevent allocating more memory as ever needed - saveKeysParents.push_back(genKeys); - if (!passwordHashedCalculated) { - saveKeysParents.push_back(mCreateCryptoKeyTask); - } - duplicate(); - UniLib::controller::TaskPtr saveKeys(new UserWriteKeysIntoDB(saveKeysParents, this, true)); - saveKeys->scheduleTask(saveKeys); - } - - //printf("[User::setNewPassword] timeUsed: %s\n", timeUsed.string().data()); - return true; -} - -void User::setEmailChecked() -{ - lock("User::setEmailChecked"); - mEmailChecked = true; - if (mState <= USER_EMAIL_NOT_ACTIVATED) { - if (mPublicHex == "") { - mState = USER_NO_KEYS; - } - else if (!mPrivateKey) { - mState = USER_NO_PRIVATE_KEY; - } - else { - mState = USER_COMPLETE; - } - } - unlock(); -} - -bool User::validatePwd(const std::string& pwd, NotificationList* validationErrorsToPrint) -{ - auto mm = MemoryManager::getInstance(); - auto cmpCryptoKey = createCryptoKey(pwd); - if (sizeof(User::passwordHashed) != crypto_shorthash_BYTES) { - throw Poco::Exception("crypto_shorthash_BYTES != sizeof(User::passwordHashed)"); - } - if (nullptr == cmpCryptoKey) { - if (validationErrorsToPrint) { - validationErrorsToPrint->addError(new Error("User::validatePwd", "couldn't create crypto key")); - return false; - } - } - User::passwordHashed pwdHashed; - if (!ServerConfig::g_ServerCryptoKey) { - if (validationErrorsToPrint) { - validationErrorsToPrint->addError(new Error("User::validatePwd", "server crypto key not set")); - } - mm->releaseMemory(cmpCryptoKey); - return false; - } - crypto_shorthash((unsigned char*)&pwdHashed, *cmpCryptoKey, crypto_box_SEEDBYTES, *ServerConfig::g_ServerCryptoKey); - lock("User::validatePwd"); - if (pwdHashed == mPasswordHashed) { - if (!mCryptoKey) { - mCryptoKey = cmpCryptoKey; - } - else { - //delete cmpCryptoKey; - mm->releaseMemory(cmpCryptoKey); - } - unlock(); - return true; - } - //delete cmpCryptoKey; - mm->releaseMemory(cmpCryptoKey); - - unlock(); - return false; -} - -void User::login(Poco::AutoPtr newUser) -{ - assert(!newUser.isNull()); - assert(newUser->getModel()); - - lock("User::validatePwd"); - mPasswordHashed = newUser->getModel()->getPasswordHashed(); - auto mm = MemoryManager::getInstance(); - if (mCryptoKey) { - mm->releaseMemory(mCryptoKey); - mCryptoKey = nullptr; - } - auto keyPair = newUser->getGradidoKeyPair(); - if (keyPair) { - mCryptoKey = keyPair->getCryptedPrivKey(newUser->getPassword()); - } - unlock(); -} - -bool User::validateIdentHash(HASH hash) -{ - lock("User::validateIdentHash"); - HASH local_hash = DRMakeStringHash(mEmail.data(), mEmail.size()); - unlock(); - return local_hash == hash; -} - -bool User::deleteFromDB() -{ - auto cm = ConnectionManager::getInstance(); - auto em = ErrorManager::getInstance(); - auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); - - Poco::Data::Statement deleteFromDB(session); - //DELETE FROM `table_name` [WHERE condition]; - - std::string tables[] = { "users", "email_opt_in", "user_backups" }; - - /*deleteFromDB - << "DELETE from users where id = ?;" - "DELETE from email_opt_in where user_id = ?;" - "DELETE from user_backups where user_id = ?", - use(mDBId), use(mDBId), use(mDBId); - */ - for (int i = 0; i < 3; i++) { - if (i > 0) { - deleteFromDB.reset(session); - deleteFromDB << "DELETE from " << tables[i] << " where user_id = ?", use(mDBId); - } - else { - deleteFromDB << "DELETE from " << tables[i] << " where id = ?", use(mDBId); - } - - try { - lock("User::deleteFromDB"); - auto result = deleteFromDB.execute(); - unlock(); - //printf("[User::deleteFromDB] %s deleted: %d\n", tables[i].data(), result); - } - catch (Poco::Exception& ex) { - unlock(); - em->addError(new ParamError("[User::deleteFromDB]", "error deleting user tables", ex.displayText().data())); - em->sendErrorsAsEmail(); - //return false; - } - } - - - return true; -} - -void User::duplicate() -{ - Poco::Mutex::ScopedLock _lock(mReferenceMutex); - //mReferenceMutex.lock(); - mReferenceCount++; -#ifdef DEBUG_USER_DELETE_ENV - printf("[User::duplicate] new value: %d\n", mReferenceCount); -#endif - //mReferenceMutex.unlock(); -} - -void User::release() -{ - - Poco::Mutex::ScopedLock _lock(mReferenceMutex); - //mReferenceMutex.lock(); - mReferenceCount--; -#ifdef DEBUG_USER_DELETE_ENV - printf("[User::release] new value: %d, this: %d\n", mReferenceCount, this); -#endif - if (0 == mReferenceCount) { - //mReferenceMutex.unlock(); - delete this; - return; - } - //mReferenceMutex.unlock(); - -} - -MemoryBin* User::createCryptoKey(const std::string& password) -{ - - //Profiler timeUsed; - auto mm = MemoryManager::getInstance(); - auto observer = SingletonTaskObserver::getInstance(); - static const char* funcName = "User::createCryptoKey"; - if (mEmail == "") { - lock(funcName); - addError(new Error(funcName, "email is empty")); - unlock(); - return nullptr; - } - - - - // TODO: put it in secure location, or use value from server config - static const unsigned char app_secret[] = { 0x21, 0xff, 0xbb, 0xc6, 0x16, 0xfe }; - - sha_context context_sha512; - //unsigned char* hash512 = (unsigned char*)malloc(SHA_512_SIZE); - if (SHA_512_SIZE < crypto_pwhash_SALTBYTES) { - lock(funcName); - addError(new Error(funcName, "sha512 is to small for libsodium pwhash saltbytes")); - unlock(); - return nullptr; - } - - observer->addTask(mEmail, TASK_OBSERVER_PASSWORD_CREATION); - - unsigned char hash512_salt[SHA_512_SIZE]; // need at least crypto_pwhash_SALTBYTES 16U - sha512_init(&context_sha512); - sha512_update(&context_sha512, (const unsigned char*)mEmail.data(), mEmail.size()); - sha512_update(&context_sha512, app_secret, 6); - sha512_final(&context_sha512, hash512_salt); - - - //unsigned char* key = (unsigned char *)malloc(crypto_box_SEEDBYTES); // 32U - //ObfusArray* key = new ObfusArray(crypto_box_SEEDBYTES); - auto key = mm->getFreeMemory(crypto_box_SEEDBYTES); - //Bin32Bytes* key = mm->get32Bytes(); - if (crypto_pwhash(*key, key->size(), password.data(), password.size(), hash512_salt, 10U, 33554432, 2) != 0) { - lock(funcName); - addError(new ParamError(funcName, " error creating pwd hash, maybe to much memory requestet? error:", strerror(errno))); - unlock(); - observer->removeTask(mEmail, TASK_OBSERVER_PASSWORD_CREATION); - //printf("[User::%s] error creating pwd hash, maybe to much memory requestet? error: %s\n", __FUNCTION__, strerror(errno)); - //printf("pwd: %s\n", pwd); - return nullptr; - } - observer->removeTask(mEmail, TASK_OBSERVER_PASSWORD_CREATION); - -// lock(); -// auto cryptoKey = new ObfusArray(crypto_box_SEEDBYTES, key); -// unlock(); -// free(key); - - // mCryptoKey - //printf("[User::createCryptoKey] time used: %s\n", timeUsed.string().data()); - return key; -} - -User::passwordHashed User::createPasswordHashed(MemoryBin* cryptoKey, NotificationList* errorReceiver/* = nullptr*/) -{ - if (sizeof(User::passwordHashed) != crypto_shorthash_BYTES) { - throw Poco::Exception("crypto_shorthash_BYTES != sizeof(User::passwordHashed)"); - } - User::passwordHashed pwdHashed = 0; - if (!ServerConfig::g_ServerCryptoKey) { - if (errorReceiver) { - errorReceiver->addError(new Error("User::validatePwd", "server crypto key not set")); - } - return pwdHashed; - } - crypto_shorthash((unsigned char*)&pwdHashed, *cryptoKey, crypto_box_SEEDBYTES, *ServerConfig::g_ServerCryptoKey); - - return pwdHashed; -} - -void User::fakeCreateCryptoKey() -{ - Poco::Thread::sleep(ServerConfig::g_FakeLoginSleepTime); -} - -bool User::generateKeys(bool savePrivkey, const std::string& passphrase, Session* session) -{ - //Profiler timeUsed; - - duplicate(); - UniLib::controller::TaskPtr generateKeysTask(new UserGenerateKeys(this, session->getNewUser(), passphrase)); - //generateKeysTask->setFinishCommand(new SessionStateUpdateCommand(SESSION_STATE_KEY_PAIR_GENERATED, session)); - //generateKeysTask->scheduleTask(generateKeysTask); - // run directly because we like to show pubkey on interface, shouldn't last to long - generateKeysTask->run(); - session->updateState(SESSION_STATE_KEY_PAIR_GENERATED); - - if (mDBId == 0) { - //printf("[User::generateKeys] dbid is zero, load from db\n"); - loadEntryDBId(ConnectionManager::getInstance()->getConnection(CONNECTION_MYSQL_LOGIN_SERVER)); - if (mDBId == 0) { - auto em = ErrorManager::getInstance(); - em->addError(new ParamError("User::generateKeys", "user not found in db with email", mEmail.data())); - em->sendErrorsAsEmail(); - } - return false; - } - - duplicate(); - std::vector parentsForWriteKeys; - parentsForWriteKeys.reserve(2); - parentsForWriteKeys.push_back(generateKeysTask); - if (!mCreateCryptoKeyTask.isNull() && !mCreateCryptoKeyTask->isTaskFinished()) { - parentsForWriteKeys.push_back(mCreateCryptoKeyTask); - } - - UniLib::controller::TaskPtr saveKeysTask(new UserWriteKeysIntoDB(parentsForWriteKeys, this, savePrivkey)); - saveKeysTask->setFinishCommand(new SessionStateUpdateCommand(SESSION_STATE_KEY_PAIR_WRITTEN, session)); - saveKeysTask->scheduleTask(saveKeysTask); - - -// printf("[User::generateKeys] call two tasks, time used: %s\n", timeUsed.string().data()); - return true; - -} - -MemoryBin* User::encrypt(const MemoryBin* data) -{ - if (!hasCryptoKey()) { - addError(new Error("User::encrypt", "hasn't crypto key")); - return nullptr; - } - if (!data) { - addError(new Error("User::encrypt", "data is zero")); - return nullptr; - } - size_t message_len = data->size(); - size_t ciphertext_len = crypto_secretbox_MACBYTES + message_len; - - unsigned char nonce[crypto_secretbox_NONCEBYTES]; - // we use a hardcoded value for nonce - memset(nonce, 31, crypto_secretbox_NONCEBYTES); - - //unsigned char* ciphertext = (unsigned char*)malloc(ciphertext_len); - //ObfusArray* ciphertext = new ObfusArray(ciphertext_len); - auto mm = MemoryManager::getInstance(); - auto ciphertext = mm->getFreeMemory(ciphertext_len); - memset(*ciphertext, 0, ciphertext_len); - - if (0 != crypto_secretbox_easy(*ciphertext, *data, message_len, nonce, *mCryptoKey)) { - //printf("[%s] error encrypting message \n", __FUNCTION__); - addError(new Error("User::encrypt", "encrypting message failed")); - //free(ciphertext); - mm->releaseMemory(ciphertext); - - return nullptr; - } - - //printf("[User::encrypt] encrypted: %s, ciphertext len: %u\n", KeyPair::getHex(ciphertext, ciphertext_len).data(), ciphertext_len); - - //auto resultObfus = new ObfusArray(ciphertext_len, ciphertext); - //free(ciphertext); - - return ciphertext; -} - -MemoryBin* User::decrypt(const MemoryBin* encryptedData) -{ - if (!hasCryptoKey()) { - addError(new Error("User::decrypt", "hasn't crypto key")); - return nullptr; - } - //printf("[User::decrypt] decrypt: %s, ciphertext len: %u\n", KeyPair::getHex(*encryptedData, encryptedData->size()).data(), encryptedData->size()); - //ObfusArray* decrypetData = new ObfusArray(encryptedData->size() - crypto_secretbox_MACBYTES); - - size_t decryptSize = encryptedData->size() - crypto_secretbox_MACBYTES; - //unsigned char* decryptBuffer = (unsigned char*)malloc(decryptSize); - auto mm = MemoryManager::getInstance(); - //ObfusArray* decryptedData = new ObfusArray(decryptSize); - auto decryptedData = mm->getFreeMemory(decryptSize); - unsigned char nonce[crypto_secretbox_NONCEBYTES]; - // we use a hardcoded value for nonce - memset(nonce, 31, crypto_secretbox_NONCEBYTES); - - if (crypto_secretbox_open_easy(*decryptedData, *encryptedData, encryptedData->size(), nonce, *mCryptoKey)) { - mm->releaseMemory(decryptedData); - addError(new Error("User::decrypt", "error decrypting")); - return nullptr; - } - /*int crypto_secretbox_open_easy(unsigned char *m, const unsigned char *c, - unsigned long long clen, const unsigned char *n, - const unsigned char *k);*/ - - return decryptedData; -} - -MemoryBin* User::sign(const unsigned char* message, size_t messageSize) -{ - - if (!message || !messageSize) return nullptr; - if (!hasCryptoKey()) { - addError(new Error("User::sign", "hasn't crypto key")); - return nullptr; - } - if (!mPrivateKey) { - addError(new Error("User::sign", "hasn't privkey")); - return nullptr; - } - - //binArrayObj = new BinaryArray(crypto_sign_BYTES); - auto mm = MemoryManager::getInstance(); - //auto signBinBuffer = (unsigned char*)malloc(crypto_sign_BYTES); - auto privKey = getPrivKey(); - - if (!privKey) { - //addError(new Error("User::sign", "decrypt privkey failed")); - - - auto userBackups = controller::UserBackup::load(mDBId); - - // get privkey, only possible while passphrase isn't crypted in db - bool correctPassphraseFound = false; - KeyPair keys; - for (auto it = userBackups.begin(); it != userBackups.end(); it++) { - - auto passphrase = (*it)->getModel()->getPassphrase(); - Mnemonic* wordSource = nullptr; - if (User::validatePassphrase(passphrase, &wordSource)) { - if (keys.generateFromPassphrase((*it)->getModel()->getPassphrase().data(), wordSource)) { - if(keys.isPubkeysTheSame(getPublicKey())) - { - correctPassphraseFound = true; - break; - } - } - } - } - if (correctPassphraseFound) { - - // save corrected key into db - auto encyrptedPrivKey = encrypt(keys.getPrivateKey()); - auto newUser = controller::User::create(); - if (1 == newUser->load(mDBId)) { - auto userModel = newUser->getModel(); - if (encyrptedPrivKey) { - userModel->setPrivateKey(encyrptedPrivKey); - userModel->updatePrivkey(); - // remove unencrypt error from priv key to prevent error 404 forwarding - delete getLastError(); - } - - mm->releaseMemory(encyrptedPrivKey); - - } - - // sign with received key - auto const_privKey = keys.getPrivateKey(); - auto signBinBuffer = mm->getFreeMemory(crypto_sign_BYTES); - unsigned long long actualSignLength = 0; - - if (crypto_sign_detached(*signBinBuffer, &actualSignLength, message, messageSize, *const_privKey)) { - addError(new Error("User::sign 2", "sign failed")); - mm->releaseMemory(signBinBuffer); - return nullptr; - } - - if (crypto_sign_verify_detached(*signBinBuffer, message, messageSize, mPublicKey) != 0) { - // Incorrect signature! - //printf("c[KeyBuffer::%s] sign verify failed\n", __FUNCTION__); - addError(new Error("User::sign 2", "sign verify failed")); - mm->releaseMemory(privKey); - mm->releaseMemory(signBinBuffer); - return nullptr; - } - - return signBinBuffer; - } - - return nullptr; - } - - auto signBinBuffer = mm->getFreeMemory(crypto_sign_BYTES); - - unsigned long long actualSignLength = 0; - - if (crypto_sign_detached(*signBinBuffer, &actualSignLength, message, messageSize, *privKey)) { - addError(new Error("User::sign", "sign failed")); - mm->releaseMemory(privKey); - mm->releaseMemory(signBinBuffer); - return nullptr; - } - - if (crypto_sign_verify_detached(*signBinBuffer, message, messageSize, mPublicKey) != 0) { - // Incorrect signature! - //printf("c[KeyBuffer::%s] sign verify failed\n", __FUNCTION__); - addError(new Error("User::sign", "sign verify failed")); - mm->releaseMemory(privKey); - mm->releaseMemory(signBinBuffer); - return nullptr; - } - - // debug - const size_t hex_sig_size = crypto_sign_BYTES * 2 + 1; - char sig_hex[hex_sig_size]; - sodium_bin2hex(sig_hex, hex_sig_size, *signBinBuffer, crypto_sign_BYTES); - printf("[User::sign] signature hex: %s\n", sig_hex); - - mm->releaseMemory(privKey); - - return signBinBuffer; -} - -Poco::Data::Statement User::insertIntoDB(Poco::Data::Session session) -{ - - Poco::Data::Statement insert(session); - - //Poco::Data::BLOB pwd(&mPasswordHashed[0], crypto_shorthash_BYTES); - - //printf("[User::insertIntoDB] password hashed: %llu\n", mPasswordHashed); - std::string languageKey = LanguageManager::keyForLanguage(mLanguage); - if (mPasswordHashed) { - insert << "INSERT INTO users (email, first_name, last_name, password, language) VALUES(?, ?, ?, ?, ?);", - use(mEmail), use(mFirstName), use(mLastName), bind(mPasswordHashed), bind(languageKey); - } - else { - insert << "INSERT INTO users (email, first_name, last_name, language) VALUES(?, ?, ?, ?);", - use(mEmail), use(mFirstName), use(mLastName), bind(languageKey); - } - - - return insert; -} - -bool User::updateIntoDB(UserFields fieldType) -{ - - if (mDBId == 0) { - addError(new Error("User::updateIntoDB", "user id is zero")); - return false; - } - if (USER_FIELDS_PASSWORD == fieldType || USER_FIELDS_EMAIL_CHECKED == fieldType) { - auto session = ConnectionManager::getInstance()->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); - Poco::Data::Statement update(session); - if (USER_FIELDS_PASSWORD == fieldType) { - update << "UPDATE users SET password = ? where id = ?", - use(mPasswordHashed), use(mDBId); - } - else if (USER_FIELDS_EMAIL_CHECKED == fieldType) { - update << "UPDATE users SET email_checked = ? where id = ?", - use(mEmailChecked), use(mDBId); - } - else if (USER_FIELDS_LANGUAGE == fieldType) { - std::string languageKey = LanguageManager::keyForLanguage(mLanguage); - update << "UPDATE users SET language = ? where id = ?", - bind(languageKey), use(mDBId); - } - try { - if (update.execute() == 1) return true; - addError(new ParamError("User::updateIntoDB", "update not affected 1 rows", fieldType)); - } - catch (Poco::Exception& ex) { - auto em = ErrorManager::getInstance(); - em->addError(new ParamError("User::updateIntoDB", "mysql error", ex.displayText().data())); - em->sendErrorsAsEmail(); - } - } - - return false; - -} - -bool User::loadEntryDBId(Poco::Data::Session session) -{ - auto em = ErrorManager::getInstance(); - Poco::Data::Statement select(session); - - select << "SELECT id from users where email = ?;", - into(mDBId), use(mEmail); - try { - if (select.execute() != 1) { - addError(new Error("User::loadEntryDBId", "didn't get expectet row count (1)")); - return false; - } - } catch(Poco::Exception& ex) { - em->addError(new ParamError("[User::loadEntryDBId]", "error selecting from db", ex.displayText().data())); - em->sendErrorsAsEmail(); - } - - return true; -} - -const char* User::userStateToString(UserStates state) -{ - switch (state) { - case USER_EMPTY: return "empty"; - case USER_LOADED_FROM_DB: return "loaded from db"; - case USER_PASSWORD_INCORRECT: return "password incorrect"; - case USER_EMAIL_NOT_ACTIVATED: return "email not activated"; - case USER_NO_KEYS: return "no keys"; - case USER_NO_PRIVATE_KEY: return "no private key"; - case USER_COMPLETE: return "complete"; - } - return "- unknown -"; -} - -MemoryBin* User::getPrivKey() -{ - if (!mPrivateKey) { - addError(new Error("User::getPrivKey", "no private key saved")); - return nullptr; - } - if (!hasCryptoKey()) { - addError(new Error("User::getPrivKey", "no crypto key set for decrypting priv key")); - return nullptr; - } - return decrypt(mPrivateKey); -} - -bool User::setPrivKey(const MemoryBin* privKey) -{ - if (!hasCryptoKey()) { - lock("User::setPrivKey"); - addError(new Error("User::getPrivKey", "no crypto key set for encrypting priv key")); - unlock(); - return false; - } - auto encyrptedPrivKey = encrypt(privKey); - lock("User::setPrivKey"); - mState = USER_COMPLETE; - mPrivateKey = encyrptedPrivKey;// encrypt(privKey); - unlock(); - - return true; -} - -void User::lock(const char* stateInfos/* = nullptr*/) -{ - try { - mWorkingMutex.lock(500); - } - catch (Poco::TimeoutException& ex) { - addError(new ParamError("User::lock", "timeout exception", ex.displayText())); - if (stateInfos) { - addError(new ParamError("User::lock", "stateInfos", stateInfos)); - } - sendErrorsAsEmail(); - } -} \ No newline at end of file diff --git a/src/cpp/model/User.h b/src/cpp/model/User.h deleted file mode 100644 index cc1a8be86..000000000 --- a/src/cpp/model/User.h +++ /dev/null @@ -1,272 +0,0 @@ -#ifndef GRADIDO_LOGIN_SERVER_MODEL_USER_INCLUDE -#define GRADIDO_LOGIN_SERVER_MODEL_USER_INCLUDE - -#include "../Crypto/KeyPair.h" -#include -//#include "ModelBase.h" -#include "../lib/NotificationList.h" - -#include "Poco/Thread.h" -#include "Poco/Types.h" -#include "Poco/Data/Session.h" -#include "Poco/JSON/Object.h" -#include "../tasks/CPUTask.h" - -#include "../SingletonManager/MemoryManager.h" -#include "../SingletonManager/LanguageManager.h" - -#include "../controller/User.h" - -class UserCreateCryptoKey; -class UserWriteIntoDB; -class Session; -class UserWriteCryptoKeyHashIntoDB; -class SigningTransaction; -class UserGenerateKeys; -class DebugPassphrasePage; -class RepairDefectPassphrase; - -enum UserStates -{ - USER_EMPTY, - USER_LOADED_FROM_DB, - USER_PASSWORD_INCORRECT, - USER_PASSWORD_ENCRYPTION_IN_PROCESS, - USER_EMAIL_NOT_ACTIVATED, - USER_NO_KEYS, - USER_NO_PRIVATE_KEY, - USER_KEYS_DONT_MATCH, - USER_COMPLETE, - USER_DISABLED -}; - -enum UserFields -{ - USER_FIELDS_ID, - USER_FIELDS_FIRST_NAME, - USER_FIELDS_LAST_NAME, - USER_FIELDS_PASSWORD, - USER_FIELDS_EMAIL_CHECKED, - USER_FIELDS_LANGUAGE -}; - -class User : public NotificationList -{ - friend UserCreateCryptoKey; - friend UserWriteIntoDB; - friend UserWriteCryptoKeyHashIntoDB; - friend SigningTransaction; - friend UserGenerateKeys; - friend DebugPassphrasePage; - friend RepairDefectPassphrase; -public: - // new user - User(const char* email, const char* first_name, const char* last_name); - // existing user - User(const char* email); - - // existing user by public key - User(const unsigned char* pubkey_array); - - User(int user_id); - - // load from controller user - User(Poco::AutoPtr ctrl_user); - - // login - //User(const std::string& email, const std::string& password); - - ~User(); - - void login(Poco::AutoPtr newUser); - - static std::string generateNewPassphrase(Mnemonic* word_source); - static bool validatePassphrase(const std::string& passphrase, Mnemonic** wordSource = nullptr); - static const char* userStateToString(UserStates state); - //static User* login(const std::string& email, const std::string& password, ErrorList* errorContainer = nullptr); - - bool generateKeys(bool savePrivkey, const std::string& passphrase, Session* session); - - bool loadEntryDBId(Poco::Data::Session session); - - bool deleteFromDB(); - - inline bool hasCryptoKey() { lock(); bool bRet = mCryptoKey != nullptr; unlock(); return bRet; } - - inline const char* getEmail() const { return mEmail.data(); } - inline const char* getFirstName() const { return mFirstName.data(); } - inline const char* getLastName() const { return mLastName.data(); } - inline int getDBId() const { return mDBId; } - inline int getBalance() { lock(); int balance = mGradidoCurrentBalance; unlock(); return balance; } - inline std::string getPublicKeyHex() { lock(); std::string pubkeyHex = mPublicHex; unlock(); return pubkeyHex; } - inline const unsigned char* getPublicKey() { return mPublicKey; } - inline Languages getLanguage() { lock(); Languages lang = mLanguage; unlock(); return lang; } - - inline void setPublicKeyHex(const std::string& publicKeyHex) { lock(); mPublicHex = publicKeyHex; unlock(); } - inline void setPublicKey(const unsigned char* key) { lock(); memcpy(mPublicKey, key, crypto_sign_PUBLICKEYBYTES); unlock();} - - inline const char* gettext(const char* text) { if (mLanguageCatalog.isNull()) return text; return mLanguageCatalog->gettext(text); } - - UserStates getUserState(); - - void setLanguage(Languages lang); - inline void setBalance(int balance) { lock(); mGradidoCurrentBalance = balance; unlock(); } - void setEmailChecked(); - bool isEmptyPassword(); - //bool setNewPassword(const std::string& newPassword); - bool updatePassword(const std::string& newPassword, const std::string& passphrase, Poco::AutoPtr newUser); - bool validatePwd(const std::string& pwd, NotificationList* validationErrorsToPrint); - bool validateIdentHash(HASH hash); - - MemoryBin* encrypt(const MemoryBin* data); - MemoryBin* decrypt(const MemoryBin* encryptedData); - MemoryBin* sign(const unsigned char* message, size_t messageSize); - - Poco::JSON::Object getJson(); - - // for poco auto ptr - void duplicate(); - void release(); - - //! \brief wait time create crypto key is normally running - static void fakeCreateCryptoKey(); -protected: - typedef Poco::UInt64 passwordHashed; - - MemoryBin* createCryptoKey(const std::string& password); - static passwordHashed createPasswordHashed(MemoryBin* cryptoKey, NotificationList* errorReceiver = nullptr); - inline void setCryptoKey(MemoryBin* cryptoKey) { lock(); mCryptoKey = cryptoKey; unlock(); } - - //void detectState(); - - Poco::Data::Statement insertIntoDB(Poco::Data::Session session); - bool updateIntoDB(UserFields fieldType); - inline passwordHashed getPwdHashed() { lock(); auto ret = mPasswordHashed; unlock(); return ret; } - inline void setPwdHashed(passwordHashed pwdHashed) { lock(); mPasswordHashed = pwdHashed; unlock(); } - - void lock(const char* stateInfos = nullptr); - inline void unlock() { mWorkingMutex.unlock(); } - - MemoryBin* getPrivKey(); - inline bool hasPrivKey() { lock(); bool result = false; if (mPrivateKey && mCryptoKey) result = true; unlock(); return result; } - bool setPrivKey(const MemoryBin* privKey); - -private: - Poco::AutoPtr mUserCtrl; - UserStates mState; - - // ************************* DB FIELDS ****************************** - int mDBId; - std::string mEmail; - std::string mFirstName; - std::string mLastName; - - passwordHashed mPasswordHashed; - - std::string mPublicHex; - unsigned char mPublicKey[crypto_sign_PUBLICKEYBYTES]; - //! crypted private key - MemoryBin* mPrivateKey; - // TODO: insert created if necessary - - bool mEmailChecked; - Languages mLanguage; - - // ************************ DB FIELDS END ****************************** - - int mGradidoCurrentBalance; - Poco::AutoPtr mLanguageCatalog; - - // crypto key as obfus array - // only in memory, if user has typed in password - MemoryBin* mCryptoKey; - - Poco::Mutex mWorkingMutex; - Poco::Mutex mReferenceMutex; - - // for poco auto ptr - int mReferenceCount; - - UniLib::controller::TaskPtr mCreateCryptoKeyTask; -}; - -class UserCreateCryptoKey : public UniLib::controller::CPUTask -{ -public: - UserCreateCryptoKey(Poco::AutoPtr user, Poco::AutoPtr newUser, const std::string& password, UniLib::controller::CPUSheduler* cpuScheduler); - - virtual int run(); - virtual const char* getResourceType() const { return "UserCreateCryptoKey"; }; - -private: - Poco::AutoPtr mUser; - Poco::AutoPtr mNewUser; - std::string mPassword; -}; - -class UserGenerateKeys : public UniLib::controller::CPUTask -{ -public: - UserGenerateKeys(Poco::AutoPtr user, Poco::AutoPtr newUser, const std::string& passphrase) - : mUser(user), mNewUser(newUser), mPassphrase(passphrase) { -#ifdef _UNI_LIB_DEBUG - setName(user->getEmail()); -#endif - } - - ~UserGenerateKeys() { - - } - virtual int run(); - inline KeyPair* getKeyPairs() { return &mKeys; } - - virtual const char* getResourceType() const { return "UserGenerateKeys"; }; -protected: - Poco::AutoPtr mUser; - Poco::AutoPtr mNewUser; - std::string mPassphrase; - KeyPair mKeys; -}; - -class UserWriteIntoDB : public UniLib::controller::CPUTask -{ -public: - UserWriteIntoDB(Poco::AutoPtr user, UniLib::controller::CPUSheduler* cpuScheduler, size_t taskDependenceCount = 0) - : UniLib::controller::CPUTask(cpuScheduler, taskDependenceCount), mUser(user) { -#ifdef _UNI_LIB_DEBUG - setName(user->getEmail()); -#endif - } - - virtual int run(); - virtual const char* getResourceType() const { return "UserWriteIntoDB"; }; -private: - Poco::AutoPtr mUser; -}; - -class UserWriteKeysIntoDB : public UniLib::controller::CPUTask -{ -public: - UserWriteKeysIntoDB(std::vector parents, Poco::AutoPtr user, bool savePrivKey); - - virtual int run(); - - virtual const char* getResourceType() const { return "UserWriteKeysIntoDB"; }; -protected: - Poco::AutoPtr mUser; - bool mSavePrivKey; -}; - -class UserWriteCryptoKeyHashIntoDB : public UniLib::controller::CPUTask -{ -public: - UserWriteCryptoKeyHashIntoDB(Poco::AutoPtr user, int dependencieCount = 0); - - int run(); - const char* getResourceType() const { return "UserWriteCryptoKeyHashIntoDB"; }; - -protected: - Poco::AutoPtr mUser; -}; - -#endif //GRADIDO_LOGIN_SERVER_MODEL_USER_INCLUDE \ No newline at end of file diff --git a/src/cpp/model/table/User.cpp b/src/cpp/model/table/User.cpp index 11584659c..d45147532 100644 --- a/src/cpp/model/table/User.cpp +++ b/src/cpp/model/table/User.cpp @@ -17,8 +17,8 @@ namespace model { { } - User::User(const std::string& email, const std::string& first_name, const std::string& last_name, Poco::UInt64 passwordHashed/* = 0*/, std::string languageKey/* = "de"*/) - : mFirstName(first_name), mLastName(last_name), mPasswordHashed(passwordHashed), mEmailChecked(false), mLanguageKey(languageKey), mDisabled(false), mRole(ROLE_NOT_LOADED) + User::User(const std::string& email, const std::string& first_name, const std::string& last_name, int group_id, Poco::UInt64 passwordHashed/* = 0*/, std::string languageKey/* = "de"*/) + : mFirstName(first_name), mLastName(last_name), mPasswordHashed(passwordHashed), mEmailChecked(false), mLanguageKey(languageKey), mDisabled(false), mGroupId(group_id), mRole(ROLE_NOT_LOADED) { setEmail(email); @@ -27,7 +27,7 @@ namespace model { User::User(UserTuple tuple) : ModelBase(tuple.get<0>()), mFirstName(tuple.get<1>()), mLastName(tuple.get<2>()), mEmail(tuple.get<3>()), - mPublicKey(tuple.get<4>()), mCreated(tuple.get<5>()), mEmailChecked(tuple.get<6>()), mDisabled(tuple.get<7>()), + mPublicKey(tuple.get<4>()), mCreated(tuple.get<5>()), mEmailChecked(tuple.get<6>()), mDisabled(tuple.get<7>()), mGroupId(tuple.get<8>()), mPasswordHashed(0), mLanguageKey("de"), mRole(ROLE_NOT_LOADED) { @@ -80,12 +80,12 @@ namespace model { if (mPasswordHashed) { - insert << "INSERT INTO users (email, first_name, last_name, password, email_hash, language) VALUES(?,?,?,?,?,?);", - use(mEmail), use(mFirstName), use(mLastName), bind(mPasswordHashed), use(mEmailHash), use(mLanguageKey); + insert << "INSERT INTO users (email, first_name, last_name, password, email_hash, language, group_id) VALUES(?,?,?,?,?,?,?);", + use(mEmail), use(mFirstName), use(mLastName), bind(mPasswordHashed), use(mEmailHash), use(mLanguageKey), use(mGroupId); } else { - insert << "INSERT INTO users (email, first_name, last_name, email_hash, language) VALUES(?,?,?,?,?);", - use(mEmail), use(mFirstName), use(mLastName), use(mEmailHash), use(mLanguageKey); + insert << "INSERT INTO users (email, first_name, last_name, email_hash, language, group_id) VALUES(?,?,?,?,?,?);", + use(mEmail), use(mFirstName), use(mLastName), use(mEmailHash), use(mLanguageKey), use(mGroupId); } return insert; @@ -98,13 +98,13 @@ namespace model { _fieldName = getTableName() + std::string(".id"); } Poco::Data::Statement select(session); - select << "SELECT " << getTableName() << ".id, email, first_name, last_name, password, pubkey, privkey, email_hash, created, email_checked, language, disabled, user_roles.role_id " + select << "SELECT " << getTableName() << ".id, email, first_name, last_name, password, pubkey, privkey, email_hash, created, email_checked, language, disabled, group_id, user_roles.role_id " << " FROM " << getTableName() << " LEFT JOIN user_roles ON " << getTableName() << ".id = user_roles.user_id " << " WHERE " << _fieldName << " = ?" , into(mID), into(mEmail), into(mFirstName), into(mLastName), into(mPasswordHashed), into(mPublicKey), into(mPrivateKey), into(mEmailHash), into(mCreated), into(mEmailChecked), - into(mLanguageKey), into(mDisabled), into(mRole); + into(mLanguageKey), into(mDisabled), into(mGroupId), into(mRole); return select; @@ -114,7 +114,7 @@ namespace model { { Poco::Data::Statement select(session); // typedef Poco::Tuple, int> UserTuple; - select << "SELECT id, first_name, last_name, email, pubkey, created, email_checked, disabled FROM " << getTableName() + select << "SELECT id, first_name, last_name, email, pubkey, created, email_checked, disabled, group_id FROM " << getTableName() << " where " << fieldName << " LIKE ?"; @@ -130,7 +130,7 @@ namespace model { } // typedef Poco::Tuple, int> UserTuple; - select << "SELECT id, first_name, last_name, email, pubkey, created, email_checked, disabled FROM " << getTableName() + select << "SELECT id, first_name, last_name, email, pubkey, created, email_checked, disabled, group_id FROM " << getTableName() << " where " << fieldNames[0] << " LIKE ?"; if (conditionType == MYSQL_CONDITION_AND) { for (int i = 1; i < fieldNames.size(); i++) { @@ -311,6 +311,7 @@ namespace model { ss << "email checked: " << mEmailChecked << std::endl; ss << "language key: " << mLanguageKey << std::endl; ss << "disabled: " << mDisabled << std::endl; + ss << "group id: " << std::to_string(mGroupId) << std::endl; mm->releaseMemory(pubkeyHex); mm->releaseMemory(privkeyHex); @@ -346,6 +347,7 @@ namespace model { ss << "language key: " << mLanguageKey << "
    "; ss << "role: " << UserRole::typeToString(getRole()) << "
    "; ss << "disabled: " << mDisabled << "
    "; + ss << "group_id: " << std::to_string(mGroupId) << std::endl; mm->releaseMemory(pubkeyHex); mm->releaseMemory(email_hash); @@ -369,6 +371,25 @@ namespace model { return pubkeyHexString; } + std::string User::getPrivateKeyEncryptedHex() const + { + std::shared_lock _lock(mSharedMutex); + auto mm = MemoryManager::getInstance(); + std::string privkeyHexString; + + if (!mPrivateKey.isNull()) { + auto priv_key_size = mPrivateKey.value().content().size(); + auto privkeyHex = mm->getFreeMemory(priv_key_size+1); + + memset(*privkeyHex, 0, priv_key_size+1); + sodium_bin2hex(*privkeyHex, 65, mPrivateKey.value().content().data(), priv_key_size); + privkeyHexString = std::string((const char*)privkeyHex->data(), privkeyHex->size() - 1); + mm->releaseMemory(privkeyHex); + } + + return privkeyHexString; + } + Poco::JSON::Object User::getJson() { diff --git a/src/cpp/model/table/User.h b/src/cpp/model/table/User.h index 9d95a3223..d4fb2ea87 100644 --- a/src/cpp/model/table/User.h +++ b/src/cpp/model/table/User.h @@ -29,14 +29,16 @@ namespace model { USER_FIELDS_LANGUAGE }; - typedef Poco::Tuple, Poco::DateTime, int, int> UserTuple; + typedef Poco::Tuple, Poco::DateTime, int, int, int> UserTuple; class User : public ModelBase { public: +#define SHARED_LOCK std::shared_lock _lock(mSharedMutex) +#define UNIQUE_LOCK std::unique_lock _lock(mSharedMutex) User(); User(UserTuple tuple); - User(const std::string& email, const std::string& first_name, const std::string& last_name, Poco::UInt64 passwordHashed = 0, std::string languageKey = "de"); + User(const std::string& email, const std::string& first_name, const std::string& last_name, int group_id, Poco::UInt64 passwordHashed = 0, std::string languageKey = "de"); ~User(); // generic db operations @@ -54,35 +56,38 @@ namespace model { size_t updateFieldsFromCommunityServer(); // default getter unlocked - inline const std::string getEmail() const { std::shared_lock _lock(mSharedMutex); return mEmail; } - inline const std::string getFirstName() const { std::shared_lock _lock(mSharedMutex); return mFirstName; } - inline const std::string getLastName() const { std::shared_lock _lock(mSharedMutex); return mLastName; } - inline std::string getNameWithEmailHtml() const { std::shared_lock _lock(mSharedMutex); return mFirstName + " " + mLastName + " <" + mEmail + ">"; } - inline const Poco::UInt64 getPasswordHashed() const { std::shared_lock _lock(mSharedMutex); return mPasswordHashed; } - inline RoleType getRole() const { std::shared_lock _lock(mSharedMutex); if (mRole.isNull()) return ROLE_NONE; return static_cast(mRole.value()); } - inline const unsigned char* getPublicKey() const { std::shared_lock _lock(mSharedMutex); if (mPublicKey.isNull()) return nullptr; return mPublicKey.value().content().data(); } - inline size_t getPublicKeySize() const { std::shared_lock _lock(mSharedMutex); if (mPublicKey.isNull()) return 0; return mPublicKey.value().content().size(); } + inline const std::string getEmail() const { SHARED_LOCK; return mEmail; } + inline const std::string getFirstName() const { SHARED_LOCK; return mFirstName; } + inline const std::string getLastName() const { SHARED_LOCK; return mLastName; } + inline std::string getNameWithEmailHtml() const { SHARED_LOCK; return mFirstName + " " + mLastName + " <" + mEmail + ">"; } + inline const Poco::UInt64 getPasswordHashed() const { SHARED_LOCK; return mPasswordHashed; } + inline RoleType getRole() const { SHARED_LOCK; if (mRole.isNull()) return ROLE_NONE; return static_cast(mRole.value()); } + inline const unsigned char* getPublicKey() const { SHARED_LOCK; if (mPublicKey.isNull()) return nullptr; return mPublicKey.value().content().data(); } + inline size_t getPublicKeySize() const { SHARED_LOCK; if (mPublicKey.isNull()) return 0; return mPublicKey.value().content().size(); } std::string getPublicKeyHex() const; + std::string getPrivateKeyEncryptedHex() const; - inline bool hasPrivateKeyEncrypted() const { std::shared_lock _lock(mSharedMutex); return !mPrivateKey.isNull(); } - inline bool hasEmailHash() const { std::shared_lock _lock(mSharedMutex); return !mEmailHash.isNull(); } - inline const std::vector& getPrivateKeyEncrypted() const { return mPrivateKey.value().content(); } - inline bool isEmailChecked() const { std::shared_lock _lock(mSharedMutex); return mEmailChecked; } - inline const std::string getLanguageKey() const { std::shared_lock _lock(mSharedMutex); return mLanguageKey; } - inline bool isDisabled() const { std::shared_lock _lock(mSharedMutex); return mDisabled; } + inline bool hasPrivateKeyEncrypted() const { SHARED_LOCK; return !mPrivateKey.isNull(); } + inline bool hasPublicKey() const { SHARED_LOCK; return !mPublicKey.isNull(); } + inline bool hasEmailHash() const { SHARED_LOCK; return !mEmailHash.isNull(); } + inline const std::vector& getPrivateKeyEncrypted() const { SHARED_LOCK; return mPrivateKey.value().content(); } + inline bool isEmailChecked() const { SHARED_LOCK; return mEmailChecked; } + inline const std::string getLanguageKey() const { SHARED_LOCK; return mLanguageKey; } + inline bool isDisabled() const { SHARED_LOCK; return mDisabled; } + inline int getGroupId() const { SHARED_LOCK; return mGroupId; } // default setter unlocked void setEmail(const std::string& email); - inline void setFirstName(const std::string& first_name) { std::unique_lock _lock(mSharedMutex); mFirstName = first_name; } - inline void setLastName(const std::string& last_name) { std::unique_lock _lock(mSharedMutex); mLastName = last_name; } - inline void setPasswordHashed(const Poco::UInt64& passwordHashed) { std::unique_lock _lock(mSharedMutex); mPasswordHashed = passwordHashed; } + inline void setFirstName(const std::string& first_name) { UNIQUE_LOCK; mFirstName = first_name; } + inline void setLastName(const std::string& last_name) { UNIQUE_LOCK; mLastName = last_name; } + inline void setPasswordHashed(const Poco::UInt64& passwordHashed) { UNIQUE_LOCK; mPasswordHashed = passwordHashed; } void setPublicKey(const unsigned char* publicKey); //! \brief set encrypted private key //! \param privateKey copy data, didn't move memory bin void setPrivateKey(const MemoryBin* privateKey); - inline void setEmailChecked(bool emailChecked) { std::unique_lock _lock(mSharedMutex); mEmailChecked = emailChecked; } - inline void setLanguageKey(const std::string& languageKey) { std::unique_lock _lock(mSharedMutex); mLanguageKey = languageKey; } - inline void setDisabled(bool disabled) { std::unique_lock _lock(mSharedMutex); mDisabled = disabled; } + inline void setEmailChecked(bool emailChecked) { UNIQUE_LOCK; mEmailChecked = emailChecked; } + inline void setLanguageKey(const std::string& languageKey) { UNIQUE_LOCK; mLanguageKey = languageKey; } + inline void setDisabled(bool disabled) { UNIQUE_LOCK; mDisabled = disabled; } Poco::JSON::Object getJson(); @@ -113,6 +118,8 @@ namespace model { //! if set to true, prevent login bool mDisabled; + int mGroupId; + // from neighbor tables Poco::Nullable mRole; diff --git a/src/cpp/tasks/SigningTransaction.h b/src/cpp/tasks/SigningTransaction.h index aaaeb9253..e3b659edd 100644 --- a/src/cpp/tasks/SigningTransaction.h +++ b/src/cpp/tasks/SigningTransaction.h @@ -5,7 +5,6 @@ #include "../lib/NotificationList.h" #include "../model/TransactionBase.h" -#include "../model/User.h" #include "../controller/User.h" #include "../proto/gradido/GradidoTransaction.pb.h" diff --git a/src/cpsp/Error500.cpsp b/src/cpsp/Error500.cpsp index 7cea4f563..0cc255eed 100644 --- a/src/cpsp/Error500.cpsp +++ b/src/cpsp/Error500.cpsp @@ -10,18 +10,18 @@ <% const char* pageName = "Error"; response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR); - Poco::AutoPtr user; + Poco::AutoPtr user; if(mSession) { - auto user = mSession->getUser(); + auto user = mSession->getNewUser(); } %><%@ include file="header_old.cpsp" %>

    Ein Fehler auf dem Server trat ein, der Admin bekam eine E-Mail.

    <% if(mSession) { %> - <%= mSession->getErrorsHtml() %> + <%= mSession->getErrorsHtmlNewFormat() %> <% } %> <% if(!user.isNull()) {%> - <%= user->getErrorsHtml() %> + <%= user->getModel()->getErrorsHtmlNewFormat() %> <% } %>
    <%@ include file="footer.cpsp" %> diff --git a/src/cpsp/PassphrasedTransaction.cpsp b/src/cpsp/PassphrasedTransaction.cpsp index debc1f296..8c360da79 100644 --- a/src/cpsp/PassphrasedTransaction.cpsp +++ b/src/cpsp/PassphrasedTransaction.cpsp @@ -6,7 +6,7 @@ <%! #include "../SingletonManager/MemoryManager.h" #include "../SingletonManager/SessionManager.h" -#include "../Crypto/KeyPair.h" +#include "../Crypto/KeyPairEd25519.h" #include "../ServerConfig.h" #include "Poco/JSON/Object.h" @@ -23,29 +23,28 @@ enum PageState { <%% std::string pageName = "Gradidos mit Passphrase überweisen"; PageState state = PAGE_STATE_INPUT; - Mnemonic* wordSource = &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]; + Mnemonic* wordSource = &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER_FIXED_CASES]; auto sm = SessionManager::getInstance(); auto mm = MemoryManager::getInstance(); std::string errorString =""; if(!form.empty()) { auto passphrase = form.get("passphrase", ""); - bool passphraseValid = User::validatePassphrase(passphrase, &wordSource); + auto passphrase_obj = Passphrase::create(passphrase, wordSource); + bool keysGenerated = false; - KeyPair keys; - if(!passphraseValid) - { + KeyPairEd25519* keys = nullptr; + if(!passphrase_obj.isNull()) { addError(new Error("Passphrase", "Fehler beim validieren der Passphrase")); } - else - { - keysGenerated = keys.generateFromPassphrase(passphrase.data(), wordSource); - if(!keysGenerated) + else { + keys = KeyPairEd25519::create(passphrase_obj); + if(!keys) { addError(new Error("Passphrase", "Konnte keine Keys aus der Passphrase generieren")); } } - if(passphraseValid && keysGenerated) + if(keys) { // create session only for transaction int session_id = 0; @@ -53,7 +52,7 @@ enum PageState { // create payload Poco::JSON::Object requestJson; Poco::JSON::Object pubkeys; - pubkeys.set("sender", keys.getPubkeyHex()); + pubkeys.set("sender", keys->getPublicKeyHex()); pubkeys.set("receiver", form.get("recevier", "")); requestJson.set("method", "moveTransaction"); requestJson.set("pubkeys", pubkeys); @@ -129,6 +128,8 @@ enum PageState { if(session) { sm->releaseSession(session); } + delete keys; + keys = nullptr; } } diff --git a/src/cpsp/adminCheckUserBackup.cpsp b/src/cpsp/adminCheckUserBackup.cpsp index 35ac38ad4..66156796d 100644 --- a/src/cpsp/adminCheckUserBackup.cpsp +++ b/src/cpsp/adminCheckUserBackup.cpsp @@ -5,10 +5,11 @@ <%@ page ctorArg="Session*" %> <%@ header include="SessionHTTPRequestHandler.h" %> <%! -#include "../Crypto/KeyPair.h" +#include "../Crypto/KeyPairEd25519.h" +#include "../Crypto/Passphrase.h" #include "../SingletonManager/ConnectionManager.h" -#include "../controller/UserBackups.h" +#include "../controller/UserBackup.h" #include "Poco/Data/Binding.h" using namespace Poco::Data::Keywords; @@ -25,7 +26,7 @@ struct SListEntry <%% const char* pageName = "Admin Check User Backups"; auto cm = ConnectionManager::getInstance(); - KeyPair keys; + std::list notMatchingEntrys; auto con = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); @@ -44,21 +45,24 @@ struct SListEntry if(pubkey.isNull()) { continue; } - auto passphrase = KeyPair::filterPassphrase(tuple.get<2>()); + auto passphrase = Passphrase::filter(tuple.get<2>()); auto user_id = tuple.get<0>(); - Mnemonic* wordSource = nullptr; - if(!User::validatePassphrase(passphrase, &wordSource)) { + KeyPairEd25519 key_pair(pubkey.value().content().data()); + + auto wordSource = Passphrase::detectMnemonic(passphrase); + if(!wordSource) { addError(new Error("admin Check user backup", "invalid passphrase"), false); addError(new ParamError("admin Check user backup", "passphrase", passphrase.data()), false); addError(new ParamError("admin Check user backup", "user id", user_id), false); continue; - } else { - keys.generateFromPassphrase(passphrase.data(), wordSource); - } + } + auto passphrase_object = Passphrase::create(passphrase, wordSource); + auto key_pair_from_passhrase = KeyPairEd25519::create(passphrase_object); bool matching = false; - if(keys.isPubkeysTheSame(pubkey.value().content().data())) { + if(key_pair_from_passhrase->isTheSame(key_pair)) { matching = true; } + delete key_pair_from_passhrase; if(user_id != last_user_id) { last_user_id = user_id; if(matching) continue; diff --git a/src/cpsp/adminUserPasswordReset.cpsp b/src/cpsp/adminUserPasswordReset.cpsp index f534b8c4d..7022b42d9 100644 --- a/src/cpsp/adminUserPasswordReset.cpsp +++ b/src/cpsp/adminUserPasswordReset.cpsp @@ -8,7 +8,7 @@ // includes #include "../controller/User.h" #include "../controller/EmailVerificationCode.h" -#include "../controller/UserBackups.h" +#include "../controller/UserBackup.h" enum PageState @@ -47,11 +47,11 @@ enum PageState } } - auto backups = controller::UserBackups::load(userId); + auto backups = controller::UserBackup::load(userId); auto userPubkey = user->getModel()->getPublicKey(); for(auto it = backups.begin(); it != backups.end(); it++) { auto keys = (*it)->getKeyPair(); - if(keys->isPubkeysTheSame(userPubkey)) { + if(keys->isTheSame(userPubkey)) { userBackup = *it; break; } @@ -102,7 +102,7 @@ enum PageState hier findest du deine Passphrase mit dessen Hilfe du dir ein neues Passwort einstellen kannst. Bitte schreibe sie dir auf und packe sie gut weg. -<%= controller::UserBackups::formatPassphrase(userBackup->getPassphrase(ServerConfig::Mnemonic_Types::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER)) %> +<%= controller::UserBackup::formatPassphrase(userBackup->getPassphrase(ServerConfig::Mnemonic_Types::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER)) %> diff --git a/src/cpsp/checkTransaction.cpsp b/src/cpsp/checkTransaction.cpsp index 77d61a1ba..ef121dcb4 100644 --- a/src/cpsp/checkTransaction.cpsp +++ b/src/cpsp/checkTransaction.cpsp @@ -163,8 +163,10 @@ enum PageState { <%= gettext("Gradido") %>
    - <% if(transactionUser) { %> - <%= transactionUser->getFirstName() %> <%= transactionUser->getLastName() %> <<%= transactionUser->getEmail() %>> + <% if(!transactionUser.isNull()) { + auto user_model = transactionUser->getModel(); + %> + <%= user_model->getFirstName() %> <%= user_model->getLastName() %> <<%= user_model->getEmail() %>> <% } else { %> 0x<%= creationTransaction->getPublicHex() %> <% } %> diff --git a/src/cpsp/dashboard.cpsp b/src/cpsp/dashboard.cpsp index 687c6a709..654f7a4c3 100644 --- a/src/cpsp/dashboard.cpsp +++ b/src/cpsp/dashboard.cpsp @@ -10,6 +10,8 @@ %> <%% const char* pageName = "Dashboard"; + auto user = mSession->getNewUser(); + auto user_model = user->getModel(); //Poco::Net::NameValueCollection cookies; //request.getCookies(cookies); if(!form.empty()) { @@ -20,7 +22,7 @@ return; %><%@ include file="header_old.cpsp" %>
    -

    Willkommen <%= mSession->getUser()->getFirstName() %> <%= mSession->getUser()->getLastName() %>

    +

    Willkommen <%= user_model->getFirstName() %> <%= user_model->getLastName() %>

    <%= mSession->getErrorsHtml() %>

    Status

    <%= mSession->getSessionStateString() %>

    diff --git a/src/cpsp/debugMnemonic.cpsp b/src/cpsp/debugMnemonic.cpsp index 06f0c5f86..aa52d4561 100644 --- a/src/cpsp/debugMnemonic.cpsp +++ b/src/cpsp/debugMnemonic.cpsp @@ -6,7 +6,7 @@ <%@ header include="SessionHTTPRequestHandler.h" %> <%! #include "../ServerConfig.h" -#include "../Crypto/KeyPair.h" +#include "../Crypto/Passphrase.h" struct WordChecked { WordChecked() : index(0), bSet(false) {}; @@ -48,7 +48,7 @@ { if("" != form.get("check_word", "")) { - auto word = KeyPair::filterPassphrase(form.get("word", "")); + auto word = Passphrase::filter(form.get("word", "")); if("" != word) { checkedWord.bSet = true; checkedWord.word = word; diff --git a/src/cpsp/debugPassphrase.cpsp b/src/cpsp/debugPassphrase.cpsp index 936a4629f..416bdf0a3 100644 --- a/src/cpsp/debugPassphrase.cpsp +++ b/src/cpsp/debugPassphrase.cpsp @@ -5,45 +5,36 @@ <%@ page ctorArg="Session*" %> <%@ header include="SessionHTTPRequestHandler.h" %> <%! -#include "../Crypto/KeyPair.h" +#include "../Crypto/KeyPairEd25519.h" +#include "../controller/User.h" %> <%% const char* pageName = "Debug Passphrase"; - auto mm = MemoryManager::getInstance(); - KeyPair keys; - std::string privKeyHex = ""; + + KeyPairEd25519* keys = nullptr; std::string privKeyCryptedHex = ""; - User::passwordHashed pwdHashed = 0; + Poco::UInt64 pwdHashed = 0; Poco::AutoPtr existingUser; if(!form.empty()) { - auto passphrase = KeyPair::filterPassphrase(form.get("passphrase", "")); - Mnemonic* wordSource = nullptr; - if(!User::validatePassphrase(passphrase, &wordSource)) { + auto passphrase_string = form.get("passphrase", ""); + auto wordSource = Passphrase::detectMnemonic(passphrase_string); + if(!wordSource) { addError(new Error("debug Passphrase", "invalid passphrase"), false); } else { - keys.generateFromPassphrase(passphrase.data(), wordSource); + keys = KeyPairEd25519::create(Passphrase::create(passphrase_string, wordSource)); } auto email = form.get("email", ""); - auto newUser = new User(email.data(), "first_name", "last_name"); - if(email != "") { existingUser = controller::User::create(); - existingUser->load(email); - } - newUser->validatePwd(form.get("password", ""), this); - pwdHashed = newUser->getPwdHashed(); - auto privKey = keys.getPrivateKey(); - if(privKey) { - privKeyHex = KeyPair::getHex(privKey); - auto privKeyCrypted = newUser->encrypt(privKey); - if(privKeyCrypted) { - privKeyCryptedHex = KeyPair::getHex(privKeyCrypted); - mm->releaseMemory(privKeyCrypted); + if(1 == existingUser->load(email)) { + auto user_model = existingUser->getModel(); + pwdHashed = user_model->getPasswordHashed(); + if(user_model->hasPrivateKeyEncrypted()) { + privKeyCryptedHex = user_model->getPrivateKeyEncryptedHex(); + } } } - getErrors(newUser); - delete newUser; } @@ -58,23 +49,21 @@ "/>

    -

    - - -

    -

    Public key:
    <%= keys.getPubkeyHex() %>

    -

    Private Key:
    <%= privKeyHex %>

    -

    Passwort Hashed:
    <%= std::to_string(pwdHashed) %>

    -

    Private key crypted:
    <%= privKeyCryptedHex %>

    - <% if(!existingUser.isNull()) { - auto userModel = existingUser->getModel(); - auto dbPubkey = userModel->getPublicKey(); - %> -

    user Public:
    <%= KeyPair::getHex(dbPubkey, ed25519_pubkey_SIZE) %>

    + <% if(keys) { %> +

    Public key:
    <%= keys->getPublicKeyHex() %>

    +

    Private key crypted:
    <%= privKeyCryptedHex %>

    +

    Passwort Hashed:
    <%= std::to_string(pwdHashed) %>

    + <% if(!existingUser.isNull()) { + auto userModel = existingUser->getModel(); + auto dbPubkey = userModel->getPublicKey(); + %> +

    user Public:
    <%= keys->getPublicKeyHex() %>

    + <% } %> <% } %>
    +<% if(keys) delete keys; %> <%@ include file="footer.cpsp" %> diff --git a/src/cpsp/login.cpsp b/src/cpsp/login.cpsp index 70018bc79..fa9b4258b 100644 --- a/src/cpsp/login.cpsp +++ b/src/cpsp/login.cpsp @@ -26,8 +26,8 @@ auto langCatalog = lm->getFreeCatalog(lang); std::string presetEmail(""); - if(mSession && mSession->getUser()) { - presetEmail = mSession->getUser()->getEmail(); + if(mSession && mSession->getNewUser()) { + presetEmail = mSession->getNewUser()->getModel()->getEmail(); } if(!form.empty()) { @@ -114,6 +114,9 @@ } sm->deleteLoginCookies(request, response); break; + case USER_NO_GROUP: + response.redirect(ServerConfig::g_serverPath + "/userUpdateGroup"); + return; case USER_NO_PRIVATE_KEY: case USER_COMPLETE: case USER_EMAIL_NOT_ACTIVATED: diff --git a/src/cpsp/passphrase.cpsp b/src/cpsp/passphrase.cpsp index d941bffcd..e8079fec9 100644 --- a/src/cpsp/passphrase.cpsp +++ b/src/cpsp/passphrase.cpsp @@ -7,7 +7,7 @@ <%! #include "../SingletonManager/SessionManager.h" #include "../SingletonManager/LanguageManager.h" -#include "../Crypto/KeyPair.h" +#include "../Crypto/KeyPairEd25519.h" #include "../ServerConfig.h" //#include "Poco/Net/HTTPServerParams.h" @@ -68,13 +68,15 @@ enum PageState auto registerKeyChoice = form.get("passphrase", "no"); std::string oldPassphrase = ""; if (registerKeyChoice == "no") { - auto oldPassphrase = KeyPair::filterPassphrase(form.get("passphrase-existing", "")); + auto oldPassphrase = Passphrase::filter(form.get("passphrase-existing", "")); if(oldPassphrase != "") { - if (User::validatePassphrase(oldPassphrase, &wordSource)) { + auto word_source = Passphrase::detectMnemonic(oldPassphrase); + if (word_source) { // passphrase is valid if(PAGE_FORCE_ASK_PASSPHRASE == state) { - auto compareResult = mSession->comparePassphraseWithSavedKeys(oldPassphrase, wordSource); + + auto compareResult = mSession->comparePassphraseWithSavedKeys(oldPassphrase, word_source); if(-2 == compareResult) { response.redirect(ServerConfig::g_serverPath + "/error500"); return; @@ -96,7 +98,8 @@ enum PageState } } else if (registerKeyChoice == "yes") { - mSession->generatePassphrase(); + auto passphrase = Passphrase::generate(wordSource); + mSession->setPassphrase(passphrase); } } } @@ -104,7 +107,7 @@ enum PageState // double check passphrase auto passphrase = mSession->getOldPassphrase(); auto langWordSource = wordSource; - if("" != passphrase && !User::validatePassphrase(passphrase, &wordSource)) { + if("" != passphrase && !Passphrase::detectMnemonic(passphrase)) { addError(new Error("PassphrasePage", "Invalid Passphrase after double check")); addError(new ParamError("PassphrasePage", "passphrase", passphrase.data())); if(!mSession->getNewUser().isNull()) { @@ -117,8 +120,8 @@ enum PageState } //printf("wordSource: %d, langWordSource: %d\n", (int)wordSource, (int)langWordSource); if(wordSource != langWordSource) { - mSession->generatePassphrase(); - User::validatePassphrase(passphrase, &wordSource); + //mSession->generatePassphrase(); + mSession->setPassphrase(Passphrase::generate(wordSource)); } if(mSession->getSessionState() == SESSION_STATE_PASSPHRASE_GENERATED && state != PAGE_ASK_ENSURE_PASSPHRASE) { @@ -160,7 +163,7 @@ enum PageState
    <%= gettext("Deine Passphrase (Groß/Kleinschreibung beachten)") %>:
    -

    <%= mSession->getPassphrase() %>

    +

    <%= mSession->getPassphrase()->getString() %>

    <%= gettext("Was zu tun ist:") %>
    @@ -212,7 +215,7 @@ enum PageState
    diff --git a/src/cpsp/registerAdmin.cpsp b/src/cpsp/registerAdmin.cpsp index 6f1db5b76..495de5a14 100644 --- a/src/cpsp/registerAdmin.cpsp +++ b/src/cpsp/registerAdmin.cpsp @@ -6,22 +6,41 @@ <%@ header include="SessionHTTPRequestHandler.h" %> <%! #include "../SingletonManager/SessionManager.h" +#include "../controller/Group.h" +#include "../lib/DataTypeConverter.h" + #include "Poco/Net/HTTPCookie.h" + %> <%% const char* pageName = "Admin Registrieren"; - //auto sm = SessionManager::getInstance(); + auto sm = SessionManager::getInstance(); bool userReturned = false; if(!form.empty()) { - userReturned = mSession->adminCreateUser( - form.get("register-first-name", ""), - form.get("register-last-name", ""), - form.get("register-email", "") - ); - getErrors(mSession); + auto group_id_string = form.get("register-group", "0"); + int group_id = 0; + if(!sm->isValid(group_id_string, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Group id", "group_id not integer")); + } else { + if(DataTypeConverter::strToInt(group_id_string, group_id) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting group_id to int")); + } + } + if(!errorCount()) { + userReturned = mSession->adminCreateUser( + form.get("register-first-name", ""), + form.get("register-last-name", ""), + form.get("register-email", ""), + group_id + ); + getErrors(mSession); + } + } + + auto groups = controller::Group::listAll(); %><%@ include file="header_old.cpsp" %> @@ -52,6 +71,12 @@ "/>

    + diff --git a/src/cpsp/registerDirect.cpsp b/src/cpsp/registerDirect.cpsp index 6eadb19dc..f6c3dc49a 100644 --- a/src/cpsp/registerDirect.cpsp +++ b/src/cpsp/registerDirect.cpsp @@ -5,7 +5,10 @@ <%@ header include="PageRequestMessagedHandler.h" %> <%! #include "../SingletonManager/SessionManager.h" +#include "../controller/Group.h" +#include "../lib/DataTypeConverter.h" #include "Poco/Net/HTTPCookie.h" + %> <%% const char* pageName = "Registrieren"; @@ -24,12 +27,22 @@ session->setClientIp(user_host); response.addCookie(session->getLoginCookie()); } + auto group_id_string = form.get("register-group", "0"); + int group_id = 0; + if(!sm->isValid(group_id_string, VALIDATE_ONLY_INTEGER)) { + addError(new Error("Group id", "group_id not integer")); + } else { + if(DataTypeConverter::strToInt(group_id_string, group_id) != DataTypeConverter::NUMBER_PARSE_OKAY) { + addError(new Error("Int Convert Error", "Error converting group_id to int")); + } + } userReturned = session->createUserDirect( form.get("register-first-name", ""), form.get("register-last-name", ""), form.get("register-email", ""), - form.get("register-password", "") + form.get("register-password", ""), + group_id ); getErrors(session); @@ -48,6 +61,9 @@ // remove old cookies if exist sm->deleteLoginCookies(request, response); } + + auto groups = controller::Group::listAll(); + %><%@ include file="header.cpsp" %> <%= getErrorsHtml() %>
    @@ -67,6 +83,13 @@ +
    diff --git a/src/cpsp/saveKeys.cpsp b/src/cpsp/saveKeys.cpsp index 03fe1b763..d157ceaed 100644 --- a/src/cpsp/saveKeys.cpsp +++ b/src/cpsp/saveKeys.cpsp @@ -19,7 +19,8 @@ enum PageState const char* pageName = "Daten auf Server speichern?"; bool hasErrors = mSession->errorCount() > 0; // crypto key only in memory, if user has tipped in his passwort in this session - bool hasPassword = mSession->getUser()->hasCryptoKey(); + auto user = mSession->getNewUser(); + bool hasPassword = user->getModel()->hasPrivateKeyEncrypted(); PageState state = PAGE_ASK; auto uri_start = ServerConfig::g_php_serverPath;//request.serverParams().getServerName(); @@ -123,7 +124,7 @@ enum PageState Zurück zur Startseite
    diff --git a/src/cpsp/translatePassphrase.cpsp b/src/cpsp/translatePassphrase.cpsp index ad22a8e90..f8dd20a6a 100644 --- a/src/cpsp/translatePassphrase.cpsp +++ b/src/cpsp/translatePassphrase.cpsp @@ -5,7 +5,7 @@ <%@ page form="true" %> <%@ page compressed="true" %> <%! -#include "../Crypto/KeyPair.h" +#include "../Crypto/KeyPairEd25519.h" #include "../ServerConfig.h" %> <%% @@ -29,16 +29,17 @@ { inputPassphrase = form.get("inputPassphrase", ""); - auto localPassphrase = KeyPair::filterPassphrase(inputPassphrase); + auto localPassphrase = Passphrase::filter(inputPassphrase); auto btnGenerate = form.get("btnGenerate", ""); if("" != btnGenerate) { - mSession->generatePassphrase(); - localPassphrase = mSession->getOldPassphrase(); + auto passphrase_gen = Passphrase::generate(wordSource); + + localPassphrase = passphrase_gen->getString(); inputPassphrase = localPassphrase; } - - if(localPassphrase != "" && !User::validatePassphrase(localPassphrase, &wordSource)) { + auto passphrase_object = Passphrase::create(localPassphrase, wordSource); + if(localPassphrase != "" && passphrase_object.isNull() || !passphrase_object->checkIfValid()) { addError(new Error( gettext("Fehler"), gettext("Diese Passphrase ist ungültig, bitte überprüfen oder neu generieren (lassen).") @@ -49,7 +50,8 @@ } else { targetSource = &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]; } - passphrase = KeyPair::passphraseTransform(localPassphrase, wordSource, targetSource); + auto transformed_passphrase_obj = passphrase_object->transform(targetSource); + passphrase = transformed_passphrase_obj->getString(); } diff --git a/src/cpsp/updateUser.cpsp b/src/cpsp/updateUser.cpsp deleted file mode 100644 index 43e3a311a..000000000 --- a/src/cpsp/updateUser.cpsp +++ /dev/null @@ -1,69 +0,0 @@ -<%@ page class="UpdateUserPage" %> -<%@ page form="true" %> -<%@ page baseClass="SessionHTTPRequestHandler" %> -<%@ page ctorArg="Session*" %> -<%@ header include="SessionHTTPRequestHandler.h" %> -<%@ page compressed="true" %> -<%! -#include "../SingletonManager/SessionManager.h" -#include "Poco/Net/HTTPCookie.h" -#include "../model/Profiler.h" -%> -<%% - const char* pageName = "Update"; - Profiler timeUsed; - auto user = mSession->getUser(); - - if(!form.empty()) { - auto pwd = form.get("update-password", ""); - if(pwd != "") { - if(pwd != form.get("update-password", "")) { - session->addError(new Error("Passwort", "Passwörter sind nicht identisch.")); - } else { - userReturned = session->getUser()->setNewPassword( - form.get("update-password") - ); - } - } - } -%><%@ include file="header.cpsp" %> -
    -

    Einen neuen Account anlegen

    - <% if(!form.empty()) {%> -
    -
    - .. -
    -
    - <% } else { %> -
    - - <% if(!form.empty() && !userReturned) {%> - <%= session->getErrorsHtml() %> - <%} %> -
    - Account anlegen -

    Bitte gebe deine Daten um einen Account anzulegen

    -

    - - "/> -

    -

    - - "/> -

    -

    - - -

    -

    - - -

    -
    - - -
    - <% } %> -
    -<%@ include file="footer.cpsp" %> diff --git a/src/cpsp/userUpdateGroup.cpsp b/src/cpsp/userUpdateGroup.cpsp new file mode 100644 index 000000000..1fb1c4105 --- /dev/null +++ b/src/cpsp/userUpdateGroup.cpsp @@ -0,0 +1,62 @@ +<%@ page class="UserUpdateGroupPage" %> +<%@ page baseClass="SessionHTTPRequestHandler" %> +<%@ page ctorArg="Session*" %> +<%@ header include="SessionHTTPRequestHandler.h" %> +<%@ page compressed="true" %> +<%! + +#include "../controller/Group.h" +#include "../SingletonManager/SessionManager.h" + +enum PageState { + PAGE_STATE_OVERVIEW, + PAGE_STATE_REQUEST_IS_RUNNING +}; + +%> +<%% + const char* pageName = gettext("Gruppe wählen"); + auto user = mSession->getNewUser(); + auto sm = SessionManager::getInstance(); + PageState state = PAGE_STATE_OVERVIEW; + + if(!form.empty()) { + } + + auto groups = controller::Group::listAll(); + + +%><%@ include file="header_large.cpsp" %> +<%= getErrorsHtml() %> +
    + <% if(PAGE_STATE_OVERVIEW == state ) { %> +
    +

    <%= gettext("Gruppe wählen") %>

    +
    +

    <%= gettext("Bitte wähle die Gruppe/Gemeinschaft aus, zu der du gehörst.") %>

    +

    <%= gettext("Du bekommst eine Bestätigungsmail, nachdem dein Beitritt bestätigt wurde.") %>

    +
    +
    +
    +
    <%= gettext("Auswahl") %>
    +
    Name
    +
    Alias
    +
    Url
    +
    <%= gettext("Description") %>
    +
    + <% for(auto it = groups.begin(); it != groups.end(); it++) { + auto group_model = (*it)->getModel(); %> +
    +
    +
    <%= group_model->getName() %>
    +
    <%= group_model->getAlias() %>
    +
    <%= group_model->getUrl() %>
    +
    <%= group_model->getDescription()%>
    +
    + <% } %> + "/> +
    +
    + <% } %> +
    +<%@ include file="footer.cpsp" %> diff --git a/src/cpsp/updateUserPassword.cpsp b/src/cpsp/userUpdatePassword.cpsp similarity index 98% rename from src/cpsp/updateUserPassword.cpsp rename to src/cpsp/userUpdatePassword.cpsp index 364b21c7f..0bb915a52 100644 --- a/src/cpsp/updateUserPassword.cpsp +++ b/src/cpsp/userUpdatePassword.cpsp @@ -1,4 +1,4 @@ -<%@ page class="UpdateUserPasswordPage" %> +<%@ page class="UserUpdatePasswordPage" %> <%@ page baseClass="SessionHTTPRequestHandler" %> <%@ page ctorArg="Session*" %> <%@ header include="SessionHTTPRequestHandler.h" %> From 3f66cee0c9f3f731e11ee8106f75b6ff54b4e4f4 Mon Sep 17 00:00:00 2001 From: Dario via Pythagoras Date: Tue, 6 Oct 2020 11:46:39 +0200 Subject: [PATCH 049/293] changes in cmake, working in progess --- .gitmodules | 3 ++ CMakeLists.txt | 46 ++++++++++++++++++++++++++++-- dependencies/poco | 1 + src/cpp/Crypto/KeyPair.cpp | 12 ++++---- src/cpp/Crypto/KeyPairHedera.cpp | 6 ++-- src/cpp/controller/HederaAccount.h | 4 +-- src/proto | 2 +- 7 files changed, 59 insertions(+), 15 deletions(-) create mode 160000 dependencies/poco diff --git a/.gitmodules b/.gitmodules index 94115f227..7500d3d77 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "dependencies/grpc"] path = dependencies/grpc url = https://github.com/grpc/grpc.git +[submodule "dependencies/poco"] + path = dependencies/poco + url = https://github.com/pocoproject/poco.git diff --git a/CMakeLists.txt b/CMakeLists.txt index c8cbe2e74..ac13fb891 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ include_directories( "dependencies/spirit-po/include" "dependencies/grpc/include" "dependencies/grpc/third_party/protobuf/src" + #"dependencies/grpc/third_party/boringssl-with-bazel/src/include" "src/cpp/proto" #"dependencies/mariadb-connector-c/build/include" #"dependencies/mariadb-connector-c/include" @@ -22,6 +23,7 @@ include_directories( ) + FILE(GLOB CONTROLLER "src/cpp/controller/*.cpp" "src/cpp/controller/*.h") FILE(GLOB TINF "dependencies/tinf/src/*.c" "dependencies/tinf/src/*.h") FILE(GLOB HTTPInterface "src/cpp/HTTPInterface/*.h" "src/cpp/HTTPInterface/*.cpp") @@ -81,6 +83,7 @@ source_group("Test\\controller" FILES ${TEST_CONTROLLER}) source_group("Test" FILES ${TEST}) endif(MSVC) + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() @@ -165,16 +168,38 @@ set(CMAKE_CXX_FLAGS "/MP /EHsc") #set(CMAKE_CXX_FLAGS_RELEASE "-O3") else(WIN32) +set(GRPC_BORING_SSL_PATH "dependencies/grpc/build/third_party/boringssl-with-bazel") +find_library(GRPC_BORING_SSL_CRYPTO crypto ${GRPC_BORING_SSL_PATH} REQUIRED) +find_library(GRPC_BORING_SSL_SSL ssl ${GRPC_BORING_SSL_PATH} REQUIRED) +set(GRPC_LIBS + #${GRPC_BORING_SSL_CRYPTO} + #${GRPC_BORING_SSL_SSL} +) +#find_package(OpenSSL REQUIRED) +find_package(PROTOBUF PATHS "dependencies/grpc/build/third_party/protobuf" REQUIRED) +set(gRPC_SSL_PROVIDER "module") +find_package(gRPC PATHS "dependencies/grpc/build" REQUIRED) +find_package(Threads REQUIRED) +set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}) + +#find_package(Poco REQUIRED) +#find_package(libsodium REQUIRED) +#find_package(gtest REQUIRED) find_library(IROHA_ED25519 ed25519 PATHS "dependencies/iroha-ed25519/build" REQUIRED) # set vars for mariadb cmake files set(INSTALL_BINDIR "bin") set(INSTALL_PLUGINDIR "bin") +OPTION(WITH_SSL "" OFF) add_subdirectory("dependencies/mariadb-connector-c") include_directories( "dependencies/mariadb-connector-c/include" "build/dependencies/mariadb-connector-c/include" + #${OpenSSL_INCLUDE_DIR} + #${Poco_INCLUDE_DIR} + #${libsodium_INCLUDE_DIR} + #${gtest_INCLUDE_DIR} ) @@ -183,13 +208,28 @@ endif(WIN32) add_subdirectory("dependencies/grpc/third_party/abseil-cpp") -target_link_libraries(Gradido_LoginServer absl::base absl::flat_hash_map absl::flags absl::memory absl::meta absl::numeric absl::strings ${CONAN_LIBS} ${IROHA_ED25519}) +#target_link_libraries(Gradido_LoginServer absl::base absl::flat_hash_map absl::flags absl::memory absl::meta absl::numeric absl::strings)# ${CONAN_LIBS} ${IROHA_ED25519}) +message(STATUS "Conan libs: ") +list(REMOVE_ITEM CONAN_LIBS "ssl") +list(REMOVE_ITEM CONAN_LIBS "crypto") +foreach(i ${CONAN_LIBS}) + +message(STATUS ${i}) + +endforeach(i) + if(WIN32) TARGET_LINK_LIBRARIES(Gradido_LoginServer optimized ${MYSQL_LIBRARIES} Shlwapi) TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${COMPILED_MARIADB_CLIENT_DEBUG} Shlwapi) TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${GRPC_LIBS} ${PROTOBUF_DEBUG_LIBS}) else(WIN32) -target_link_libraries(Gradido_LoginServer libmariadb protoc protobuf -pthread) +target_link_libraries(Gradido_LoginServer gRPC::grpc++) +target_link_libraries(Gradido_LoginServer ${CONAN_LIBS}) +target_link_libraries(Gradido_LoginServer libmariadb )# ${GRPC_LIBS} protoc protobuf pthread) +#target_link_libraries(Gradido_LoginServer ${OpenSSL_LIBS} ${Poco_LIBS} ${libsodium_LIBS} ) + + + endif(WIN32) # install @@ -220,7 +260,7 @@ if(WIN32) TARGET_LINK_LIBRARIES(Gradido_LoginServer_Test debug ${COMPILED_MARIADB_CLIENT_DEBUG} Shlwapi) TARGET_LINK_LIBRARIES(Gradido_LoginServer_Test debug ${GRPC_LIBS} ${PROTOBUF_DEBUG_LIBS}) else(WIN32) - target_link_libraries(Gradido_LoginServer_Test libmariadb protoc protobuf -pthread) + target_link_libraries(Gradido_LoginServer_Test libmariadb protoc protobuf pthread) endif(WIN32) add_test(NAME main COMMAND Gradido_LoginServer_Test) diff --git a/dependencies/poco b/dependencies/poco new file mode 160000 index 000000000..3fc3e5f5b --- /dev/null +++ b/dependencies/poco @@ -0,0 +1 @@ +Subproject commit 3fc3e5f5b8462f7666952b43381383a79b8b5d92 diff --git a/src/cpp/Crypto/KeyPair.cpp b/src/cpp/Crypto/KeyPair.cpp index 770f3dedf..9c6e3a22e 100644 --- a/src/cpp/Crypto/KeyPair.cpp +++ b/src/cpp/Crypto/KeyPair.cpp @@ -76,18 +76,18 @@ bool KeyPair::generateFromPassphrase(const char* passphrase, const Mnemonic* wor createClearPassphraseFromWordIndices(word_indices, &ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]); // printf("clear passphrase: %s\n", clearPassphrase.data()); - sha_context state; + crypto_hash_sha512_state state; - unsigned char hash[SHA_512_SIZE]; + unsigned char hash[crypto_hash_sha512_BYTES]; //crypto_auth_hmacsha512_state state; size_t word_index_size = sizeof(word_indices); //crypto_auth_hmacsha512_init(&state, (unsigned char*)word_indices, sizeof(word_indices)); - sha512_init(&state); - sha512_update(&state, *word_indices, word_indices->size()); - sha512_update(&state, (unsigned char*)clearPassphrase.data(), clearPassphrase.size()); + crypto_hash_sha512_init(&state); + crypto_hash_sha512_update(&state, *word_indices, word_indices->size()); + crypto_hash_sha512_update(&state, (unsigned char*)clearPassphrase.data(), clearPassphrase.size()); //crypto_auth_hmacsha512_update(&state, (unsigned char*)passphrase, pass_phrase_size); - sha512_final(&state, hash); + crypto_hash_sha512_final(&state, hash); //crypto_auth_hmacsha512_final(&state, hash); /* diff --git a/src/cpp/Crypto/KeyPairHedera.cpp b/src/cpp/Crypto/KeyPairHedera.cpp index c2738e886..e16b76e05 100644 --- a/src/cpp/Crypto/KeyPairHedera.cpp +++ b/src/cpp/Crypto/KeyPairHedera.cpp @@ -44,7 +44,7 @@ KeyPairHedera::KeyPairHedera(const unsigned char* privateKey, size_t privateKeyS } break; default: - throw std::exception("[KeyPairHedera] invalid private key"); + throw Poco::Exception("[KeyPairHedera] invalid private key"); } // check public @@ -62,7 +62,7 @@ KeyPairHedera::KeyPairHedera(const unsigned char* privateKey, size_t privateKeyS } break; default: - throw std::exception("[KeyPairHedera] invalid public key"); + throw Poco::Exception("[KeyPairHedera] invalid public key"); } } auto public_key_2 = mm->getFreeMemory(ed25519_pubkey_SIZE); @@ -218,4 +218,4 @@ MemoryBin* KeyPairHedera::getPublicKeyCopy() const auto public_key = mm->getFreeMemory(ed25519_pubkey_SIZE); memcpy(*public_key, mPublicKey, ed25519_pubkey_SIZE); return public_key; -} \ No newline at end of file +} diff --git a/src/cpp/controller/HederaAccount.h b/src/cpp/controller/HederaAccount.h index 709e84c7a..94e21a597 100644 --- a/src/cpp/controller/HederaAccount.h +++ b/src/cpp/controller/HederaAccount.h @@ -29,7 +29,7 @@ namespace controller { inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } - std::string HederaAccount::toShortSelectOptionName(); + std::string toShortSelectOptionName(); inline Poco::AutoPtr getModel() { return _getModel(); } inline const model::table::HederaAccount* getModel() const { return _getModel(); } @@ -53,4 +53,4 @@ namespace controller { }; } -#endif //GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_ACCOUNT_INCLUDE \ No newline at end of file +#endif //GRADIDO_LOGIN_SERVER_CONTROLLER_HEDERA_ACCOUNT_INCLUDE diff --git a/src/proto b/src/proto index 72e8fe7b7..81a461566 160000 --- a/src/proto +++ b/src/proto @@ -1 +1 @@ -Subproject commit 72e8fe7b73a1aaf2d057d2fef59ade9268830008 +Subproject commit 81a461566e46d71533dc3e284fa075d7d68fd020 From fdf15bb94825ccec3d52cfa2d5a4ddefb599f397 Mon Sep 17 00:00:00 2001 From: Dario via Pythagoras Date: Tue, 6 Oct 2020 12:03:25 +0200 Subject: [PATCH 050/293] add linux parse file --- unix_parse_proto.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100755 unix_parse_proto.sh diff --git a/unix_parse_proto.sh b/unix_parse_proto.sh new file mode 100755 index 000000000..3727cc985 --- /dev/null +++ b/unix_parse_proto.sh @@ -0,0 +1,19 @@ +#!/bin/bash +if [ ! -d "./src/cpp/proto" ] ; then + mkdir ./src/cpp/proto +fi +if [ ! -d "./src/cpp/proto/gradido" ] ; then + mkdir ./src/cpp/proto/gradido +fi +PROTOC_PATH=./dependencies/grpc/build/third_party/protobuf +CPP_PLUGIN_PATH=./dependencies/grpc/build +$PROTOC_PATH/protoc --cpp_out=./src/cpp/proto --proto_path=./src/proto ./src/proto/gradido/*.proto + +if [ ! -d "./src/cpp/proto/hedera" ] ; then + mkdir ./src/cpp/proto/hedera +fi + +GOOGLE_PROTOBUF_INCLUDES=./dependencies/grpc/third_party/protobuf/src +$PROTOC_PATH/protoc --plugin=protoc-gen-grpc=$CPP_PLUGIN_PATH/grpc_cpp_plugin --cpp_out=./src/cpp/proto/hedera --grpc_out=./src/cpp/proto/hedera --proto_path=$GOOGLE_PROTOBUF_INCLUDES --proto_path=./src/proto/hedera/hedera-protobuf/src/main/proto ./src/proto/hedera/hedera-protobuf/src/main/proto/*.proto + + From 2239d3c21b0e8f642e1276fbfc68e257c61a3222 Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 6 Oct 2020 15:41:34 +0200 Subject: [PATCH 051/293] update code because irohe-ed25519 was removed --- src/cpp/Crypto/KeyPairHedera.cpp | 10 +++--- src/cpp/Crypto/KeyPairHedera.h | 5 ++- .../HTTPInterface/AdminHederaAccountPage.cpp | 2 +- .../HTTPInterface/RepairDefectPassphrase.cpp | 33 +++++++++---------- src/cpp/main.cpp | 4 +-- src/cpsp/adminHederaAccount.cpsp | 2 +- src/cpsp/repairDefectPassphrase.cpsp | 3 +- 7 files changed, 28 insertions(+), 31 deletions(-) diff --git a/src/cpp/Crypto/KeyPairHedera.cpp b/src/cpp/Crypto/KeyPairHedera.cpp index c2738e886..4a9220600 100644 --- a/src/cpp/Crypto/KeyPairHedera.cpp +++ b/src/cpp/Crypto/KeyPairHedera.cpp @@ -58,16 +58,16 @@ KeyPairHedera::KeyPairHedera(const unsigned char* privateKey, size_t privateKeyS } case 44: // DER encoded public key if (0 == sodium_memcmp(publicKey, *derPrefixPub, derPrefixPub->size())) { - memcpy(mPublicKey, &publicKey[derPrefixPub->size()], ed25519_pubkey_SIZE); + memcpy(mPublicKey, &publicKey[derPrefixPub->size()], crypto_sign_PUBLICKEYBYTES); } break; default: throw std::exception("[KeyPairHedera] invalid public key"); } } - auto public_key_2 = mm->getFreeMemory(ed25519_pubkey_SIZE); + auto public_key_2 = mm->getFreeMemory(crypto_sign_PUBLICKEYBYTES); crypto_sign_ed25519_sk_to_pk(*public_key_2, *mPrivateKey); - if (sodium_memcmp(*public_key_2, mPublicKey, ed25519_pubkey_SIZE) != 0) { + if (sodium_memcmp(*public_key_2, mPublicKey, crypto_sign_PUBLICKEYBYTES) != 0) { throw "public keys not match"; } @@ -215,7 +215,7 @@ MemoryBin* KeyPairHedera::getPrivateKeyCopy() const MemoryBin* KeyPairHedera::getPublicKeyCopy() const { auto mm = MemoryManager::getInstance(); - auto public_key = mm->getFreeMemory(ed25519_pubkey_SIZE); - memcpy(*public_key, mPublicKey, ed25519_pubkey_SIZE); + auto public_key = mm->getFreeMemory(crypto_sign_PUBLICKEYBYTES); + memcpy(*public_key, mPublicKey, crypto_sign_PUBLICKEYBYTES); return public_key; } \ No newline at end of file diff --git a/src/cpp/Crypto/KeyPairHedera.h b/src/cpp/Crypto/KeyPairHedera.h index 769f29af6..b8dba9024 100644 --- a/src/cpp/Crypto/KeyPairHedera.h +++ b/src/cpp/Crypto/KeyPairHedera.h @@ -14,7 +14,6 @@ #include "sodium.h" #include "SecretKeyCryptography.h" -#include "iroha-ed25519/include/ed25519/ed25519.h" #include "../lib/DataTypeConverter.h" class KeyPairHedera : public IKeyPair @@ -43,7 +42,7 @@ public: inline const unsigned char* getPublicKey() const { return mPublicKey; } MemoryBin* getPublicKeyCopy() const; inline std::string getPublicKeyHex() const { return DataTypeConverter::binToHex(mPublicKey, getPublicKeySize()); } - const static size_t getPublicKeySize() {return ed25519_pubkey_SIZE;} + const static size_t getPublicKeySize() {return crypto_sign_PUBLICKEYBYTES;} inline bool isTheSame(const KeyPairHedera& b) const { return 0 == sodium_memcmp(mPublicKey, b.mPublicKey, getPublicKeySize()); @@ -90,7 +89,7 @@ private: // 32 Byte //! \brief ed25519 libsodium public key - unsigned char mPublicKey[ed25519_pubkey_SIZE]; + unsigned char mPublicKey[crypto_sign_PUBLICKEYBYTES]; }; #endif //__GRADIDO_LOGIN_SERVER_CRYPTO_HEDERA_KEYS_H \ No newline at end of file diff --git a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp index 4bcf9b614..28c99c26a 100644 --- a/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp +++ b/src/cpp/HTTPInterface/AdminHederaAccountPage.cpp @@ -202,7 +202,7 @@ void AdminHederaAccountPage::handleRequest(Poco::Net::HTTPServerRequest& request KeyPairHedera key_pair(private_key, public_key); - auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE); + auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), crypto_sign_PUBLICKEYBYTES); if(crypto_key.isNull()) { crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true"); diff --git a/src/cpp/HTTPInterface/RepairDefectPassphrase.cpp b/src/cpp/HTTPInterface/RepairDefectPassphrase.cpp index 77fd06514..e089a38e2 100644 --- a/src/cpp/HTTPInterface/RepairDefectPassphrase.cpp +++ b/src/cpp/HTTPInterface/RepairDefectPassphrase.cpp @@ -9,7 +9,6 @@ #include "../SingletonManager/MemoryManager.h" #include "../SingletonManager/EmailManager.h" -#include "../Crypto/KeyPair.h" #include "../Crypto/Passphrase.h" #include "../Crypto/KeyPairEd25519.h" #include "../lib/DataTypeConverter.h" @@ -53,7 +52,7 @@ void RepairDefectPassphrase::handleRequest(Poco::Net::HTTPServerRequest& request if (_compressResponse) response.set("Content-Encoding", "gzip"); Poco::Net::HTMLForm form(request, request.stream()); -#line 36 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" +#line 35 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" auto mm = MemoryManager::getInstance(); auto em = EmailManager::getInstance(); @@ -270,26 +269,26 @@ void RepairDefectPassphrase::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "
\n"; // end include header_old.cpsp responseStream << "\n"; -#line 185 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" +#line 184 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" if("" != errorString) { responseStream << "\n"; responseStream << "\t"; -#line 186 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" +#line 185 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" responseStream << ( errorString ); responseStream << "\n"; -#line 187 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" +#line 186 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" } responseStream << "\n"; responseStream << "
\n"; responseStream << "\t"; -#line 189 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" +#line 188 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" responseStream << ( getErrorsHtml() ); responseStream << "\n"; responseStream << "\t

Konto reparieren

\n"; responseStream << "\t

Der Login-Server hat festgestellt das die gespeicherte Passphrase nicht zu deinem Konto passt.

\n"; responseStream << "\t"; -#line 192 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" +#line 191 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" if(GENERATE_PASSPHRASE == state) { responseStream << "\n"; responseStream << "\t\t"; -#line 193 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" +#line 192 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" if(new_user->canDecryptPrivateKey()) { responseStream << "\n"; responseStream << "\t\t\t

Dein Privat Key konnte noch entschlüsselt werden. Es könnte also eine neue Passphrase generiert werden und dein aktueller Kontostand\n"; responseStream << "\t\t\tauf die neue Adresse transferiert werden.

\n"; @@ -297,27 +296,27 @@ void RepairDefectPassphrase::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t\t\n"; responseStream << "\t\t\t\n"; responseStream << "\t\t"; -#line 199 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" +#line 198 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" } else { responseStream << "\n"; responseStream << "\t\t\t

Dein Privat Key konnte nicht entschlüsselt werden. Bitte wende dich an den Admin: "; -#line 200 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" +#line 199 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" responseStream << ( adminEmail ); responseStream << "

\n"; responseStream << "\t\t"; -#line 201 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" +#line 200 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" } responseStream << "\n"; responseStream << "\t"; -#line 202 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" +#line 201 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" } else if(SHOW_PASSPHRASE == state) { responseStream << "\n"; responseStream << "\t\t

Deine neue Passphrase, bitte schreibe sie dir auf (am besten auf einen Zettel) und hebe sie gut auf. \n"; responseStream << "\t\tDu brauchst sie wenn du dein Passwort vergessen hast oder dein Konto umziehen möchtest:

\n"; responseStream << "\t\t
Deine neue Passphrase:\n"; responseStream << "\t\t\t
\n"; responseStream << "\t\t\t\t"; -#line 207 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" +#line 206 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" responseStream << ( mSession->getPassphrase()->getString() ); responseStream << "\n"; responseStream << "\t\t\t
\n"; @@ -328,15 +327,15 @@ void RepairDefectPassphrase::handleRequest(Poco::Net::HTTPServerRequest& request responseStream << "\t\t\t

\n"; responseStream << "\t\t\n"; responseStream << "\t"; -#line 215 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" +#line 214 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" } else if(FINISH == state) { responseStream << "\n"; responseStream << "\t\t

Neue Daten erfolgreich gespeichert, bitte logge dich nun aus. Danach kannst du dich gerne wieder einloggen und müsstest dein Guthaben wieder auf deinem Konto haben.

\n"; responseStream << "\t\tAusloggen\n"; responseStream << "\t"; -#line 218 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" +#line 217 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\repairDefectPassphrase.cpsp" } responseStream << "\n"; responseStream << "
\n"; // begin include footer.cpsp diff --git a/src/cpp/main.cpp b/src/cpp/main.cpp index 899779fef..2f3a9a802 100644 --- a/src/cpp/main.cpp +++ b/src/cpp/main.cpp @@ -3,7 +3,7 @@ #include "proto/gradido/TransactionBody.pb.h" -#include "model/User.h" +//#include "model/User.h" #include "model/Session.h" #include "lib/Profiler.h" #include "ServerConfig.h" @@ -36,7 +36,7 @@ int main(int argc, char** argv) ServerConfig::g_versionString = Poco::DateTimeFormatter::format(buildDateTime, "0.%y.%m.%d"); //ServerConfig::g_versionString = "0.20.KW13.02"; printf("Version: %s\n", ServerConfig::g_versionString.data()); - printf("User size: %d Bytes, Session size: %d Bytes\n", (int)sizeof(User), (int)sizeof(Session)); + printf("User size: %d Bytes, Session size: %d Bytes\n", (int)sizeof(controller::User), (int)sizeof(Session)); printf("model sizes: User: %d Bytes, EmailOptIn: %d Bytes\n", (int)sizeof(model::table::User), (int)sizeof(model::table::EmailOptIn)); // load word lists diff --git a/src/cpsp/adminHederaAccount.cpsp b/src/cpsp/adminHederaAccount.cpsp index c7ec76f98..45f2c65ae 100644 --- a/src/cpsp/adminHederaAccount.cpsp +++ b/src/cpsp/adminHederaAccount.cpsp @@ -181,7 +181,7 @@ KeyPairHedera key_pair(private_key, public_key); - auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), ed25519_pubkey_SIZE); + auto crypto_key = controller::CryptoKey::load(key_pair.getPublicKey(), crypto_sign_PUBLICKEYBYTES); if(crypto_key.isNull()) { crypto_key = controller::CryptoKey::create(&key_pair, user, privateKeyEncryptedString == "true"); diff --git a/src/cpsp/repairDefectPassphrase.cpsp b/src/cpsp/repairDefectPassphrase.cpsp index 0e8c82e64..960466cd5 100644 --- a/src/cpsp/repairDefectPassphrase.cpsp +++ b/src/cpsp/repairDefectPassphrase.cpsp @@ -7,11 +7,10 @@ <%! #include "../SingletonManager/MemoryManager.h" #include "../SingletonManager/EmailManager.h" -#include "../Crypto/KeyPair.h" #include "../Crypto/Passphrase.h" #include "../Crypto/KeyPairEd25519.h" #include "../lib/DataTypeConverter.h" -#include "../controller/UserBackups.h" +#include "../controller/UserBackup.h" #include "../tasks/SigningTransaction.h" #include "../ServerConfig.h" From be4d2e87cd4cd01d667aa7851c0f9bbcb2dc94a4 Mon Sep 17 00:00:00 2001 From: dario Linux Date: Tue, 6 Oct 2020 15:44:11 +0200 Subject: [PATCH 052/293] update cmake for unix --- CMakeLists.txt | 247 ++++++++++++++++----------------- compile_pot.sh | 0 src/cpp/Crypto/KeyPairHedera.h | 1 - src/cpp/main.cpp | 1 - src/proto | 2 +- 5 files changed, 123 insertions(+), 128 deletions(-) mode change 100644 => 100755 compile_pot.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f442c87e..42b3410bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.18.2) project(Gradido_LoginServer C CXX) SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin" ) @@ -16,11 +16,10 @@ include_directories( "dependencies/grpc/third_party/protobuf/src" #"dependencies/grpc/third_party/boringssl-with-bazel/src/include" "src/cpp/proto" - #"dependencies/mariadb-connector-c/build/include" - #"dependencies/mariadb-connector-c/include" - #"import/mariadb/include" ) +set(MYSQL_INCLUDE_DIR "dependencies/mariadb-connector-c/include") + FILE(GLOB CONTROLLER "src/cpp/controller/*.cpp" "src/cpp/controller/*.h") @@ -59,51 +58,84 @@ SET(LOCAL_TEST_SRC aux_source_directory("src/cpp" LOCAL_SRCS) if(MSVC) -# src -source_group("controller" FILES ${CONTROLLER}) -source_group("proto\\gradido" FILES ${PROTO_GRADIDO}) -source_group("proto\\hedera" FILES ${PROTO_HEDERA}) -source_group("tinf" FILES ${TINF}) -source_group("Crypto" FILES ${CRYPTO}) -source_group("tasks" FILES ${TASKS}) -source_group("model\\table" FILES ${MODEL_TABLE}) -source_group("model\\email" FILES ${MODEL_EMAIL}) -source_group("model\\hedera" FILES ${MODEL_HEDERA}) -source_group("model" FILES ${MODEL}) -source_group("mysql" FILES ${MYSQL}) -source_group("SingletonManager" FILES ${SINGLETON_MANAGER}) -source_group("lib" FILES ${LIB_SRC}) -source_group("HTTP-Interface" FILES ${HTTPInterface}) -source_group("Json-Interface" FILES ${JSONInterface}) -source_group("Test\\crypto" FILES ${TEST_CRYPTO}) -source_group("Test\\model\\table" FILES ${TEST_MODEL_TABLE}) -source_group("Test\\model" FILES ${TEST_MODEL}) -source_group("Test\\controller" FILES ${TEST_CONTROLLER}) -source_group("Test" FILES ${TEST}) + # src + source_group("controller" FILES ${CONTROLLER}) + source_group("proto\\gradido" FILES ${PROTO_GRADIDO}) + source_group("proto\\hedera" FILES ${PROTO_HEDERA}) + source_group("tinf" FILES ${TINF}) + source_group("Crypto" FILES ${CRYPTO}) + source_group("tasks" FILES ${TASKS}) + source_group("model\\table" FILES ${MODEL_TABLE}) + source_group("model\\email" FILES ${MODEL_EMAIL}) + source_group("model\\hedera" FILES ${MODEL_HEDERA}) + source_group("model" FILES ${MODEL}) + source_group("mysql" FILES ${MYSQL}) + source_group("SingletonManager" FILES ${SINGLETON_MANAGER}) + source_group("lib" FILES ${LIB_SRC}) + source_group("HTTP-Interface" FILES ${HTTPInterface}) + source_group("Json-Interface" FILES ${JSONInterface}) + source_group("Test\\crypto" FILES ${TEST_CRYPTO}) + source_group("Test\\model\\table" FILES ${TEST_MODEL_TABLE}) + source_group("Test\\model" FILES ${TEST_MODEL}) + source_group("Test\\controller" FILES ${TEST_CONTROLLER}) + source_group("Test" FILES ${TEST}) endif(MSVC) include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() -#add_subdirectory("dependencies/curl") -#add_subdirectory("dependencies/mariadb-connector-c") - add_executable(Gradido_LoginServer ${LOCAL_SRCS}) -#SUBDIRS("src/test") + + +set(DEP_PATH "dependencies") +set(MARIADB_CONNECTOR_PATH "${DEP_PATH}/mariadb-connector-c/build/libmariadb") +set(GRPC_PATH "${DEP_PATH}/grpc/build") +set(GRPC_ABSL_PATH "${GRPC_PATH}/third_party/abseil-cpp/absl/types") +set(GRPC_CARES_PATH "${GRPC_PATH}/third_party/cares/cares/lib") +set(GRPC_BORING_SSL_PATH "${GRPC_PATH}/third_party/boringssl-with-bazel") +set(GRPC_RE2_PATH "${GRPC_PATH}/third_party/re2") +set(GRPC_PROTOBUF_PATH "${GRPC_PATH}/third_party/protobuf") if(WIN32) -find_library(MYSQL_LIBRARIES mariadbclient.lib PATHS "dependencies/mariadb-connector-c/build/libmariadb/Release" REQUIRED) -#find_library(MYSQL_LIBRARIES_DEBUG mariadbclient.lib PATHS "import/mariadb/lib/debug") -find_library(COMPILED_MARIADB_CLIENT_DEBUG mariadbclient PATHS "dependencies/mariadb-connector-c/build/libmariadb/Debug" REQUIRED) -set(GRPC_PATH "dependencies/grpc/_build/Debug") -set(GRPC_ABSL_PATH "dependencies/grpc/_build/third_party/abseil-cpp/absl/types/Debug") -set(GRPC_CARES_PATH "dependencies/grpc/_build/third_party/cares/cares/lib/Debug") -set(GRPC_BORING_SSL_PATH "dependencies/grpc/_build/third_party/boringssl-with-bazel/Debug") -set(GRPC_RE2_PATH "dependencies/grpc/_build/third_party/re2/Debug") -set(GRPC_PROTOBUF_DEBUG_PATH "dependencies/grpc/_build/third_party/protobuf/Debug") + find_library(MYSQL_LIBRARIES mariadbclient.lib PATHS "${MARIADB_CONNECTOR_PATH}/Release" REQUIRED) + find_library(COMPILED_MARIADB_CLIENT_DEBUG mariadbclient PATHS "${MARIADB_CONNECTOR_PATH}/Debug" REQUIRED) + + set(GRPC_PATH "${GRPC_PATH}/Debug") + set(GRPC_ABSL_PATH "${GRPC_ABSL_PATH}/Debug") + set(GRPC_CARES_PATH "${GRPC_CARES_PATH}/Debug") + set(GRPC_BORING_SSL_PATH "${GRPC_CGRPC_BORING_SSL_PATHARES_PATH}/Debug") + set(GRPC_RE2_PATH "${GRPC_RE2_PATH}/Debug") + set(GRPC_PROTOBUF_DEBUG_PATH "${GRPC_PROTOBUF_PATH}/Debug") + + find_library(PROTOBUF_LIB_DEBUG libprotobufd PATHS ${GRPC_PROTOBUF_DEBUG_PATH} REQUIRED) + find_library(PROTOBUF_LIB_LITE_DEBUG libprotobuf-lited PATHS ${GRPC_PROTOBUF_DEBUG_PATH} REQUIRED) + find_library(PROTOBUF_LIBC_DEBUG libprotocd PATHS ${GRPC_PROTOBUF_DEBUG_PATH} REQUIRED) + + set(PROTOBUF_DEBUG_LIBS + ${PROTOBUF_LIB_DEBUG} + ${PROTOBUF_LIB_LITE_DEBUG} + ${PROTOBUF_LIBC_DEBUG} + ) + + list(REMOVE_ITEM CONAN_LIBS "libeay32.lib") + list(REMOVE_ITEM CONAN_LIBS "ssleay32.lib") + + +else (WIN32) +# message(STATUS ${MARIADB_CONNECTOR_PATH}) + find_library(MYSQL_LIBRARIES libmariadb.so PATHS ${MARIADB_CONNECTOR_PATH} REQUIRED) + set(GRPC_PROTOBUF_DEBUG_PATH "${GRPC_PROTOBUF_PATH}") + + list(REMOVE_ITEM CONAN_LIBS "ssl") + list(REMOVE_ITEM CONAN_LIBS "crypto") + + +endif(WIN32) + +# grpc libs find_library(GRPC_PLUSPLUS grpc++ PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_UNSECURE grpc++_unsecure PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_REFLECTION grpc++_reflection PATHS ${GRPC_PATH} REQUIRED) @@ -113,15 +145,18 @@ find_library(GRPC_RLIB gpr PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_UPB upb PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_ALTS grpc++_alts PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_ADDRESS_SORTING address_sorting PATHS ${GRPC_PATH} REQUIRED) +# grpc third party libs find_library(GRPC_CARES cares PATHS ${GRPC_CARES_PATH} REQUIRED) -find_library(GRPC_BORING_SSL_CRYPTO crypto ${GRPC_BORING_SSL_PATH} REQUIRED) -find_library(GRPC_BORING_SSL_SSL ssl ${GRPC_BORING_SSL_PATH} REQUIRED) -find_library(GRPC_RE2 re2 ${GRPC_RE2_PATH} REQUIRED) -find_library(PROTOBUF_LIB_DEBUG libprotobufd ${GRPC_PROTOBUF_DEBUG_PATH} REQUIRED) -find_library(PROTOBUF_LIB_LITE_DEBUG libprotobuf-lited ${GRPC_PROTOBUF_DEBUG_PATH} REQUIRED) -find_library(PROTOBUF_LIBC_DEBUG libprotocd ${GRPC_PROTOBUF_DEBUG_PATH} REQUIRED) +find_library(GRPC_BORING_SSL_CRYPTO crypto PATHS ${GRPC_BORING_SSL_PATH} REQUIRED) +find_library(GRPC_BORING_SSL_SSL ssl PATHS ${GRPC_BORING_SSL_PATH} REQUIRED) +find_library(GRPC_RE2 re2 PATHS ${GRPC_RE2_PATH} REQUIRED) + +find_library(PROTOBUF_LIB libprotobuf.a PATHS ${GRPC_PROTOBUF_PATH} REQUIRED) +find_library(PROTOBUF_LIB_LITE libprotobuf-lite.a PATHS ${GRPC_PROTOBUF_PATH} REQUIRED) +find_library(PROTOBUF_LIBC libprotoc.a PATHS ${GRPC_PROTOBUF_PATH} REQUIRED) + +find_library(GRPC_ABSL_BAD_OPTIONAL_ACCESS absl_bad_optional_access PATHS ${GRPC_ABSL_PATH} REQUIRED) -find_library(GRPC_ABSL_BAD_OPTIONAL_ACCESS absl_bad_optional_access ${GRPC_ABSL_PATH} REQUIRED) set(GRPC_LIBS ${GRPC_PLUSPLUS} ${GRPC_REFLECTION} ${GRPC_UNSECURE} ${GRPC_LIB} ${GRPC_ERROR_DETAILS} ${GRPC_RLIB} ${GRPC_UPB} ${GRPC_ALTS} @@ -131,74 +166,49 @@ set(GRPC_LIBS ${GRPC_BORING_SSL_SSL} ${GRPC_RE2} ) -set(PROTOBUF_DEBUG_LIBS - ${PROTOBUF_LIB_DEBUG} - ${PROTOBUF_LIB_LITE_DEBUG} - ${PROTOBUF_LIBC_DEBUG} + +set(PROTOBUF_LIBS + ${PROTOBUF_LIB} + ${PROTOBUF_LIB_LITE} + ${PROTOBUF_LIBC} ) -set(MYSQL_INCLUDE_DIR "dependencies/mariadb-connector-c/include") +if(WIN32) -#set(POCO_DEBUG_PATH "I:/FremdCode/C++/poco/win64/lib/Debug") -#find_library(POCO_DEBUG_FOUNDATION PocoFoundationd PocoFoundation PATHS ${POCO_DEBUG_PATH} REQUIRED) -#find_library(POCO_DEBUG_DATA PocoDatad PocoData PATHS ${POCO_DEBUG_PATH} REQUIRED) -#find_library(POCO_DEBUG_NET PocoNetd PocoNet PATHS ${POCO_DEBUG_PATH} REQUIRED) -#find_library(POCO_DEBUG_NET_SSL PocoNetSSLd PocoNetSSL PATHS ${POCO_DEBUG_PATH} REQUIRED) -#find_library(POCO_DEBUG_UTIL PocoUtild PocoUtil PATHS ${POCO_DEBUG_PATH} REQUIRED) -#find_library(POCO_DEBUG_CRYPTO PocoCryptod PocoCrypto PATHS ${POCO_DEBUG_PATH} REQUIRED) - -#set(POCO_DEBUG_LIBS ${POCO_DEBUG_FOUNDATION} ${POCO_DEBUG_UTIL} ${POCO_DEBUG_DATA} ${POCO_DEBUG_NET} ${POCO_DEBUG_NET_SSL} ${POCO_DEBUG_CRYPTO}) -#include_directories( -# "I:/FremdCode/C++/poco/Foundation/include" -# "I:/FremdCode/C++/poco/Data/include" -# "I:/FremdCode/C++/poco/Net/include" - #"I:/FremdCode/C++/poco/NetSSL_Win/include" -# "I:/FremdCode/C++/poco/NetSSL_OpenSSL/include" -# "I:/FremdCode/C++/poco/Crypto/include" -# "I:/FremdCode/C++/poco/Util/include" -# "I:/FremdCode/C++/ssl/include" -#) - -set(CMAKE_CXX_FLAGS "/MP /EHsc") -#set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3") -#set(CMAKE_CXX_FLAGS_RELEASE "-O3") + set(CMAKE_CXX_FLAGS "/MP /EHsc") + #set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3") + #set(CMAKE_CXX_FLAGS_RELEASE "-O3") else(WIN32) -set(GRPC_BORING_SSL_PATH "dependencies/grpc/build/third_party/boringssl-with-bazel") -find_library(GRPC_BORING_SSL_CRYPTO crypto ${GRPC_BORING_SSL_PATH} REQUIRED) -find_library(GRPC_BORING_SSL_SSL ssl ${GRPC_BORING_SSL_PATH} REQUIRED) -set(GRPC_LIBS - #${GRPC_BORING_SSL_CRYPTO} - #${GRPC_BORING_SSL_SSL} -) -#find_package(OpenSSL REQUIRED) -find_package(PROTOBUF PATHS "dependencies/grpc/build/third_party/protobuf" REQUIRED) -set(gRPC_SSL_PROVIDER "module") -find_package(gRPC PATHS "dependencies/grpc/build" REQUIRED) -find_package(Threads REQUIRED) -set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}) -#find_package(Poco REQUIRED) -#find_package(libsodium REQUIRED) -#find_package(gtest REQUIRED) -find_library(IROHA_ED25519 ed25519 PATHS "dependencies/iroha-ed25519/build" REQUIRED) -# set vars for mariadb cmake files -set(INSTALL_BINDIR "bin") -set(INSTALL_PLUGINDIR "bin") -OPTION(WITH_SSL "" OFF) -add_subdirectory("dependencies/mariadb-connector-c") + #find_package(OpenSSL REQUIRED) + #find_package(PROTOBUF PATHS "dependencies/grpc/build/third_party/protobuf" REQUIRED) + #set(gRPC_SSL_PROVIDER "module") + #find_package(gRPC PATHS "dependencies/grpc/build" REQUIRED) + find_package(Threads REQUIRED) + set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}) + + #find_package(Poco REQUIRED) + #find_package(libsodium REQUIRED) + #find_package(gtest REQUIRED) + #find_library(IROHA_ED25519 ed25519 PATHS "dependencies/iroha-ed25519/build" REQUIRED) + # set vars for mariadb cmake files + set(INSTALL_BINDIR "bin") + set(INSTALL_PLUGINDIR "bin") +# OPTION(WITH_SSL "" OFF) +# add_subdirectory("dependencies/mariadb-connector-c") -include_directories( - "dependencies/mariadb-connector-c/include" - "build/dependencies/mariadb-connector-c/include" - #${OpenSSL_INCLUDE_DIR} - #${Poco_INCLUDE_DIR} - #${libsodium_INCLUDE_DIR} - #${gtest_INCLUDE_DIR} -) + include_directories( + # "dependencies/mariadb-connector-c/include" +# "build/dependencies/mariadb-connector-c/include" + #${OpenSSL_INCLUDE_DIR} + #${Poco_INCLUDE_DIR} + #${libsodium_INCLUDE_DIR} + #${gtest_INCLUDE_DIR} + ) @@ -207,30 +217,17 @@ endif(WIN32) add_subdirectory("dependencies/grpc/third_party/abseil-cpp") -#target_link_libraries(Gradido_LoginServer absl::base absl::flat_hash_map absl::flags absl::memory absl::meta absl::numeric absl::strings)# ${CONAN_LIBS} ${IROHA_ED25519}) -message(STATUS "Conan libs: ") -list(REMOVE_ITEM CONAN_LIBS "ssl") -list(REMOVE_ITEM CONAN_LIBS "crypto") -foreach(i ${CONAN_LIBS}) - -message(STATUS ${i}) - -endforeach(i) - - target_link_libraries(Gradido_LoginServer absl::base absl::flat_hash_map absl::flags absl::memory absl::meta absl::numeric absl::strings ${CONAN_LIBS}) if(WIN32) -TARGET_LINK_LIBRARIES(Gradido_LoginServer optimized ${MYSQL_LIBRARIES} Shlwapi) -TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${COMPILED_MARIADB_CLIENT_DEBUG} Shlwapi) -TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${GRPC_LIBS} ${PROTOBUF_DEBUG_LIBS}) -else(WIN32) -target_link_libraries(Gradido_LoginServer gRPC::grpc++) -target_link_libraries(Gradido_LoginServer ${CONAN_LIBS}) -target_link_libraries(Gradido_LoginServer libmariadb )# ${GRPC_LIBS} protoc protobuf pthread) -#target_link_libraries(Gradido_LoginServer ${OpenSSL_LIBS} ${Poco_LIBS} ${libsodium_LIBS} ) - - + TARGET_LINK_LIBRARIES(Gradido_LoginServer optimized ${MYSQL_LIBRARIES} Shlwapi) + TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${COMPILED_MARIADB_CLIENT_DEBUG} Shlwapi) + TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${GRPC_LIBS} ${PROTOBUF_DEBUG_LIBS}) +else(WIN32) # unix +# target_link_libraries(Gradido_LoginServer gRPC::grpc++) +# target_link_libraries(Gradido_LoginServer ) + target_link_libraries(Gradido_LoginServer ${MYSQL_LIBRARIES} ${GRPC_LIBS} ${PROTOBUF_LIBS} )# ${GRPC_LIBS} protoc protobuf pthread) + #target_link_libraries(Gradido_LoginServer ${OpenSSL_LIBS} ${Poco_LIBS} ${libsodium_LIBS} ) endif(WIN32) @@ -255,7 +252,7 @@ enable_testing() add_executable(Gradido_LoginServer_Test ${LOCAL_SRCS} ${LOCAL_TEST_SRC}) target_compile_definitions(Gradido_LoginServer_Test PUBLIC "_TEST_BUILD") -target_link_libraries(Gradido_LoginServer_Test absl::base absl::flat_hash_map absl::flags absl::memory absl::meta absl::numeric absl::strings ${CONAN_LIBS} ${IROHA_ED25519}) +target_link_libraries(Gradido_LoginServer_Test absl::base absl::flat_hash_map absl::flags absl::memory absl::meta absl::numeric absl::strings ${CONAN_LIBS} ) if(WIN32) TARGET_LINK_LIBRARIES(Gradido_LoginServer_Test optimized ${MYSQL_LIBRARIES} Shlwapi) diff --git a/compile_pot.sh b/compile_pot.sh old mode 100644 new mode 100755 diff --git a/src/cpp/Crypto/KeyPairHedera.h b/src/cpp/Crypto/KeyPairHedera.h index 769f29af6..f342164d6 100644 --- a/src/cpp/Crypto/KeyPairHedera.h +++ b/src/cpp/Crypto/KeyPairHedera.h @@ -14,7 +14,6 @@ #include "sodium.h" #include "SecretKeyCryptography.h" -#include "iroha-ed25519/include/ed25519/ed25519.h" #include "../lib/DataTypeConverter.h" class KeyPairHedera : public IKeyPair diff --git a/src/cpp/main.cpp b/src/cpp/main.cpp index 899779fef..8d3858923 100644 --- a/src/cpp/main.cpp +++ b/src/cpp/main.cpp @@ -3,7 +3,6 @@ #include "proto/gradido/TransactionBody.pb.h" -#include "model/User.h" #include "model/Session.h" #include "lib/Profiler.h" #include "ServerConfig.h" diff --git a/src/proto b/src/proto index 81a461566..72e8fe7b7 160000 --- a/src/proto +++ b/src/proto @@ -1 +1 @@ -Subproject commit 81a461566e46d71533dc3e284fa075d7d68fd020 +Subproject commit 72e8fe7b73a1aaf2d057d2fef59ade9268830008 From d170cf5e270d80e249933f13710ab475bcfea31c Mon Sep 17 00:00:00 2001 From: dario Linux Date: Wed, 7 Oct 2020 12:39:55 +0200 Subject: [PATCH 053/293] more experiments with cmake --- CMakeLists.txt | 54 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1546672f8..7b1c3e7d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,8 +129,9 @@ else (WIN32) find_library(MYSQL_LIBRARIES libmariadb.so PATHS ${MARIADB_CONNECTOR_PATH} REQUIRED) set(GRPC_PROTOBUF_DEBUG_PATH "${GRPC_PROTOBUF_PATH}") -# list(REMOVE_ITEM CONAN_LIBS "ssl") -# list(REMOVE_ITEM CONAN_LIBS "crypto") + list(REMOVE_ITEM CONAN_LIBS "ssl") + list(REMOVE_ITEM CONAN_LIBS "crypto") + list(REMOVE_ITEM CONAN_LIBS "dl") endif(WIN32) @@ -142,6 +143,7 @@ find_library(GRPC_PLUSPLUS grpc++ PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_UNSECURE grpc++_unsecure PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_REFLECTION grpc++_reflection PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_LIB grpc PATHS ${GRPC_PATH} REQUIRED) +find_library(GRPC_LIB_UNSECURE grpc_unsecure PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_ERROR_DETAILS grpc++_error_details PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_RLIB gpr PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_UPB upb PATHS ${GRPC_PATH} REQUIRED) @@ -149,8 +151,8 @@ find_library(GRPC_ALTS grpc++_alts PATHS ${GRPC_PATH} REQUIRED) find_library(GRPC_ADDRESS_SORTING address_sorting PATHS ${GRPC_PATH} REQUIRED) # grpc third party libs find_library(GRPC_CARES cares PATHS ${GRPC_CARES_PATH} REQUIRED) -find_library(GRPC_BORING_SSL_CRYPTO crypto PATHS ${GRPC_BORING_SSL_PATH} REQUIRED) -find_library(GRPC_BORING_SSL_SSL ssl PATHS ${GRPC_BORING_SSL_PATH} REQUIRED) +#find_library(GRPC_BORING_SSL_CRYPTO crypto PATHS ${GRPC_BORING_SSL_PATH} REQUIRED) +#find_library(GRPC_BORING_SSL_SSL ssl PATHS ${GRPC_BORING_SSL_PATH} REQUIRED) find_library(GRPC_RE2 re2 PATHS ${GRPC_RE2_PATH} REQUIRED) find_library(PROTOBUF_LIB libprotobuf.a PATHS ${GRPC_PROTOBUF_PATH} REQUIRED) @@ -159,13 +161,35 @@ find_library(PROTOBUF_LIBC libprotoc.a PATHS ${GRPC_PROTOBUF_PATH} REQUIRED) find_library(GRPC_ABSL_BAD_OPTIONAL_ACCESS absl_bad_optional_access PATHS ${GRPC_ABSL_PATH} REQUIRED) +# load same ssl version like used from poco +find_library(CONAN_OPENSSL_SSL ssl PATHS ${CONAN_LIB_DIRS_OPENSSL} REQUIRED NO_DEFAULT_PATH ) +find_library(CONAN_OPENSSL_CRYPTO crypto PATHS ${CONAN_LIB_DIRS_OPENSSL} REQUIRED NO_DEFAULT_PATH ) +#find_library(CONAN_OPENSSL_DL dl PATHS ${CONAN_LIB_DIRS_OPENSSL} REQUIRED NO_DEFAULT_PATH ) +#find_library(CONAN_OPENSSL_PTHREAD pthread PATHS ${CONAN_LIB_DIRS_OPENSSL} REQUIRED NO_DEFAULT_PATH ) + +set(CONAN_OPENSSL_CUSTOM_LIBS + ${CONAN_OPENSSL_SSL} + ${CONAN_OPENSSL_CRYPTO} + #${CONAN_OPENSSL_DL} +# ${CONAN_OPENSSL_PTHREAD} + ) +#foreach(i ${CONAN_LIBS_OPENSSL}) +# find_library(_LIB_${i} ${i} PATHS ${CONAN_LIB_DIRS_OPENSSL} NO_DEFAULT_PATH) + #set(CONAN_POCO_OPENSSL_LIBS ${CONAN_POCO_OPENSSL_LIBS} ${_LIB_${i}}) +#endforeach(i) + +#${CONAN_LIB_DIRS_OPENSSL} +#${CONAN_LIBS_OPENSSL} +#find_library(CONAN_POCO_OPENSSL_LIBS NAMES ${CONAN_LIBS_OPENSSL} PATHS ${CONAN_LIB_DIRS_OPENSSL} NO_DEFAULT_PATH) + set(GRPC_LIBS - ${GRPC_PLUSPLUS} ${GRPC_REFLECTION} ${GRPC_UNSECURE} ${GRPC_LIB} + ${GRPC_PLUSPLUS} + ${GRPC_REFLECTION} ${GRPC_UNSECURE} ${GRPC_LIB} ${GRPC_ERROR_DETAILS} ${GRPC_RLIB} ${GRPC_UPB} ${GRPC_ALTS} ${GRPC_ABSL_BAD_OPTIONAL_ACCESS} ${GRPC_ADDRESS_SORTING} ${GRPC_CARES} - ${GRPC_BORING_SSL_CRYPTO} - ${GRPC_BORING_SSL_SSL} +# ${GRPC_BORING_SSL_CRYPTO} +# ${GRPC_BORING_SSL_SSL} ${GRPC_RE2} ) @@ -229,10 +253,24 @@ if(WIN32) else(WIN32) # unix # target_link_libraries(Gradido_LoginServer gRPC::grpc++) # target_link_libraries(Gradido_LoginServer ) - target_link_libraries(Gradido_LoginServer ${MYSQL_LIBRARIES} ${GRPC_LIBS} ${PROTOBUF_LIBS} ${CMAKE_DL_LIBS} )# ${GRPC_LIBS} protoc protobuf pthread) + target_link_libraries(Gradido_LoginServer ${MYSQL_LIBRARIES} ${CONAN_OPENSSL_CUSTOM_LIBS} ${GRPC_LIBS} ${CMAKE_DL_LIBS} ${PROTOBUF_LIBS})# ${GRPC_LIBS} protoc protobuf pthread) #target_link_libraries(Gradido_LoginServer ${OpenSSL_LIBS} ${Poco_LIBS} ${libsodium_LIBS} ) endif(WIN32) +message(STATUS "link libraries:" ) +get_target_property(OUT Gradido_LoginServer LINK_LIBRARIES) +foreach(i ${OUT}) +message(STATUS ${i}) +endforeach(i) +message(STATUS "grpc libs: ") +foreach(i ${GRPC_LIBS}) +message(STATUS ${i}) +endforeach(i) +message(STATUS "boring ssl:") +message(STATUS ${GRPC_BORING_SSL_SSL}) +message(STATUS ${GRPC_BORING_SSL_CRYPTO}) +message(STATUS "Conan OpenSSL") +message(STATUS ${CONAN_POCO_OPENSSL_LIBS}) # install if(UNIX) From 09f2ae27de59ba78b29e95bed2eae103e21e5824 Mon Sep 17 00:00:00 2001 From: dario Linux Date: Thu, 8 Oct 2020 08:23:09 +0200 Subject: [PATCH 054/293] build working under linux :) --- CMakeLists.txt | 121 +++------------------ FindOpenSSL.cmake | 109 +++++++++++++++++++ conanfile.txt | 1 - src/cpp/test/crypto/TestKeyPairEd25519.cpp | 10 +- src/cpp/test/crypto/TestPassphrase.cpp | 9 +- 5 files changed, 134 insertions(+), 116 deletions(-) create mode 100644 FindOpenSSL.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b1c3e7d4..1648b666e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,14 +14,12 @@ include_directories( "dependencies/spirit-po/include" "dependencies/grpc/include" "dependencies/grpc/third_party/protobuf/src" - #"dependencies/grpc/third_party/boringssl-with-bazel/src/include" "src/cpp/proto" ) set(MYSQL_INCLUDE_DIR "dependencies/mariadb-connector-c/include") - FILE(GLOB CONTROLLER "src/cpp/controller/*.cpp" "src/cpp/controller/*.h") FILE(GLOB TINF "dependencies/tinf/src/*.c" "dependencies/tinf/src/*.h") FILE(GLOB HTTPInterface "src/cpp/HTTPInterface/*.h" "src/cpp/HTTPInterface/*.cpp") @@ -91,6 +89,7 @@ add_executable(Gradido_LoginServer ${LOCAL_SRCS}) set(DEP_PATH "dependencies") set(MARIADB_CONNECTOR_PATH "${DEP_PATH}/mariadb-connector-c/build/libmariadb") + set(GRPC_PATH "${DEP_PATH}/grpc/build") set(GRPC_ABSL_PATH "${GRPC_PATH}/third_party/abseil-cpp/absl/types") set(GRPC_CARES_PATH "${GRPC_PATH}/third_party/cares/cares/lib") @@ -98,6 +97,8 @@ set(GRPC_BORING_SSL_PATH "${GRPC_PATH}/third_party/boringssl-with-bazel") set(GRPC_RE2_PATH "${GRPC_PATH}/third_party/re2") set(GRPC_PROTOBUF_PATH "${GRPC_PATH}/third_party/protobuf") + + if(WIN32) find_library(MYSQL_LIBRARIES mariadbclient.lib PATHS "${MARIADB_CONNECTOR_PATH}/Release" REQUIRED) @@ -125,7 +126,7 @@ if(WIN32) else (WIN32) -# message(STATUS ${MARIADB_CONNECTOR_PATH}) + find_library(MYSQL_LIBRARIES libmariadb.so PATHS ${MARIADB_CONNECTOR_PATH} REQUIRED) set(GRPC_PROTOBUF_DEBUG_PATH "${GRPC_PROTOBUF_PATH}") @@ -136,141 +137,51 @@ else (WIN32) endif(WIN32) -message(STATUS ${MARIADB_CONNECTOR_PATH}) - -# grpc libs -find_library(GRPC_PLUSPLUS grpc++ PATHS ${GRPC_PATH} REQUIRED) -find_library(GRPC_UNSECURE grpc++_unsecure PATHS ${GRPC_PATH} REQUIRED) -find_library(GRPC_REFLECTION grpc++_reflection PATHS ${GRPC_PATH} REQUIRED) -find_library(GRPC_LIB grpc PATHS ${GRPC_PATH} REQUIRED) -find_library(GRPC_LIB_UNSECURE grpc_unsecure PATHS ${GRPC_PATH} REQUIRED) -find_library(GRPC_ERROR_DETAILS grpc++_error_details PATHS ${GRPC_PATH} REQUIRED) -find_library(GRPC_RLIB gpr PATHS ${GRPC_PATH} REQUIRED) -find_library(GRPC_UPB upb PATHS ${GRPC_PATH} REQUIRED) -find_library(GRPC_ALTS grpc++_alts PATHS ${GRPC_PATH} REQUIRED) -find_library(GRPC_ADDRESS_SORTING address_sorting PATHS ${GRPC_PATH} REQUIRED) -# grpc third party libs -find_library(GRPC_CARES cares PATHS ${GRPC_CARES_PATH} REQUIRED) -#find_library(GRPC_BORING_SSL_CRYPTO crypto PATHS ${GRPC_BORING_SSL_PATH} REQUIRED) -#find_library(GRPC_BORING_SSL_SSL ssl PATHS ${GRPC_BORING_SSL_PATH} REQUIRED) -find_library(GRPC_RE2 re2 PATHS ${GRPC_RE2_PATH} REQUIRED) - -find_library(PROTOBUF_LIB libprotobuf.a PATHS ${GRPC_PROTOBUF_PATH} REQUIRED) -find_library(PROTOBUF_LIB_LITE libprotobuf-lite.a PATHS ${GRPC_PROTOBUF_PATH} REQUIRED) -find_library(PROTOBUF_LIBC libprotoc.a PATHS ${GRPC_PROTOBUF_PATH} REQUIRED) - -find_library(GRPC_ABSL_BAD_OPTIONAL_ACCESS absl_bad_optional_access PATHS ${GRPC_ABSL_PATH} REQUIRED) - # load same ssl version like used from poco +find_package(OpenSSL PATHS . NO_DEFAULT_PATH) + find_library(CONAN_OPENSSL_SSL ssl PATHS ${CONAN_LIB_DIRS_OPENSSL} REQUIRED NO_DEFAULT_PATH ) find_library(CONAN_OPENSSL_CRYPTO crypto PATHS ${CONAN_LIB_DIRS_OPENSSL} REQUIRED NO_DEFAULT_PATH ) -#find_library(CONAN_OPENSSL_DL dl PATHS ${CONAN_LIB_DIRS_OPENSSL} REQUIRED NO_DEFAULT_PATH ) -#find_library(CONAN_OPENSSL_PTHREAD pthread PATHS ${CONAN_LIB_DIRS_OPENSSL} REQUIRED NO_DEFAULT_PATH ) set(CONAN_OPENSSL_CUSTOM_LIBS ${CONAN_OPENSSL_SSL} ${CONAN_OPENSSL_CRYPTO} - #${CONAN_OPENSSL_DL} -# ${CONAN_OPENSSL_PTHREAD} - ) -#foreach(i ${CONAN_LIBS_OPENSSL}) -# find_library(_LIB_${i} ${i} PATHS ${CONAN_LIB_DIRS_OPENSSL} NO_DEFAULT_PATH) - #set(CONAN_POCO_OPENSSL_LIBS ${CONAN_POCO_OPENSSL_LIBS} ${_LIB_${i}}) -#endforeach(i) - -#${CONAN_LIB_DIRS_OPENSSL} -#${CONAN_LIBS_OPENSSL} -#find_library(CONAN_POCO_OPENSSL_LIBS NAMES ${CONAN_LIBS_OPENSSL} PATHS ${CONAN_LIB_DIRS_OPENSSL} NO_DEFAULT_PATH) - -set(GRPC_LIBS - ${GRPC_PLUSPLUS} - ${GRPC_REFLECTION} ${GRPC_UNSECURE} ${GRPC_LIB} - ${GRPC_ERROR_DETAILS} ${GRPC_RLIB} ${GRPC_UPB} ${GRPC_ALTS} - ${GRPC_ABSL_BAD_OPTIONAL_ACCESS} ${GRPC_ADDRESS_SORTING} - ${GRPC_CARES} -# ${GRPC_BORING_SSL_CRYPTO} -# ${GRPC_BORING_SSL_SSL} - ${GRPC_RE2} ) -set(PROTOBUF_LIBS - ${PROTOBUF_LIB} - ${PROTOBUF_LIB_LITE} - ${PROTOBUF_LIBC} -) +set(BUILD_TESTING OFF) +set(gRPC_SSL_PROVIDER "package") +add_subdirectory("dependencies/grpc/") +message(STATUS "Using gRPC via add_subdirectory.") if(WIN32) - set(CMAKE_CXX_FLAGS "/MP /EHsc") #set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3") #set(CMAKE_CXX_FLAGS_RELEASE "-O3") else(WIN32) - #find_package(OpenSSL REQUIRED) - #find_package(PROTOBUF PATHS "dependencies/grpc/build/third_party/protobuf" REQUIRED) - #set(gRPC_SSL_PROVIDER "module") - #find_package(gRPC PATHS "dependencies/grpc/build" REQUIRED) -# find_package(Threads REQUIRED) -# set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}) - - #find_package(Poco REQUIRED) - #find_package(libsodium REQUIRED) - #find_package(gtest REQUIRED) - #find_library(IROHA_ED25519 ed25519 PATHS "dependencies/iroha-ed25519/build" REQUIRED) - # set vars for mariadb cmake files set(INSTALL_BINDIR "bin") set(INSTALL_PLUGINDIR "bin") -# OPTION(WITH_SSL "" OFF) -# add_subdirectory("dependencies/mariadb-connector-c") - include_directories( - # "dependencies/mariadb-connector-c/include" -# "build/dependencies/mariadb-connector-c/include" ${CONAN_INCLUDE_DIRS_OPENSSL} - #${OpenSSL_INCLUDE_DIR} - #${Poco_INCLUDE_DIR} - #${libsodium_INCLUDE_DIR} - #${gtest_INCLUDE_DIR} ) - endif(WIN32) -add_subdirectory("dependencies/grpc/third_party/abseil-cpp") - - -target_link_libraries(Gradido_LoginServer absl::base absl::flat_hash_map absl::flags absl::memory absl::meta absl::numeric absl::strings ${CONAN_LIBS}) +set(GRPC_LIBS libprotobuf grpc++_reflection grpc++) +target_link_libraries(Gradido_LoginServer ${CONAN_LIBS}) if(WIN32) TARGET_LINK_LIBRARIES(Gradido_LoginServer optimized ${MYSQL_LIBRARIES} Shlwapi) TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${COMPILED_MARIADB_CLIENT_DEBUG} Shlwapi) TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${GRPC_LIBS} ${PROTOBUF_DEBUG_LIBS}) else(WIN32) # unix -# target_link_libraries(Gradido_LoginServer gRPC::grpc++) -# target_link_libraries(Gradido_LoginServer ) - target_link_libraries(Gradido_LoginServer ${MYSQL_LIBRARIES} ${CONAN_OPENSSL_CUSTOM_LIBS} ${GRPC_LIBS} ${CMAKE_DL_LIBS} ${PROTOBUF_LIBS})# ${GRPC_LIBS} protoc protobuf pthread) - #target_link_libraries(Gradido_LoginServer ${OpenSSL_LIBS} ${Poco_LIBS} ${libsodium_LIBS} ) - + target_link_libraries(Gradido_LoginServer ${MYSQL_LIBRARIES} ${CONAN_OPENSSL_CUSTOM_LIBS} ${GRPC_LIBS} ${CMAKE_DL_LIBS} ${PROTOBUF_LIBS}) endif(WIN32) -message(STATUS "link libraries:" ) -get_target_property(OUT Gradido_LoginServer LINK_LIBRARIES) -foreach(i ${OUT}) -message(STATUS ${i}) -endforeach(i) -message(STATUS "grpc libs: ") -foreach(i ${GRPC_LIBS}) -message(STATUS ${i}) -endforeach(i) -message(STATUS "boring ssl:") -message(STATUS ${GRPC_BORING_SSL_SSL}) -message(STATUS ${GRPC_BORING_SSL_CRYPTO}) -message(STATUS "Conan OpenSSL") -message(STATUS ${CONAN_POCO_OPENSSL_LIBS}) # install if(UNIX) @@ -288,19 +199,19 @@ enable_testing() # ---------------------- Test ----------------------------------------- #project(Gradido_LoginServer_Test C CXX) #_TEST_BUILD - +#find_package(gtest) add_executable(Gradido_LoginServer_Test ${LOCAL_SRCS} ${LOCAL_TEST_SRC}) target_compile_definitions(Gradido_LoginServer_Test PUBLIC "_TEST_BUILD") -target_link_libraries(Gradido_LoginServer_Test absl::base absl::flat_hash_map absl::flags absl::memory absl::meta absl::numeric absl::strings ${CONAN_LIBS} ) +target_link_libraries(Gradido_LoginServer_Test ${CONAN_LIBS} ) if(WIN32) TARGET_LINK_LIBRARIES(Gradido_LoginServer_Test optimized ${MYSQL_LIBRARIES} Shlwapi) TARGET_LINK_LIBRARIES(Gradido_LoginServer_Test debug ${COMPILED_MARIADB_CLIENT_DEBUG} Shlwapi) TARGET_LINK_LIBRARIES(Gradido_LoginServer_Test debug ${GRPC_LIBS} ${PROTOBUF_DEBUG_LIBS}) else(WIN32) - target_link_libraries(Gradido_LoginServer_Test libmariadb protoc protobuf pthread) + target_link_libraries(Gradido_LoginServer_Test ${MYSQL_LIBRARIES} ${CONAN_OPENSSL_CUSTOM_LIBS} ${GRPC_LIBS} ${CMAKE_DL_LIBS} ${PROTOBUF_LIBS}) endif(WIN32) add_test(NAME main COMMAND Gradido_LoginServer_Test) diff --git a/FindOpenSSL.cmake b/FindOpenSSL.cmake new file mode 100644 index 000000000..4a4fec7df --- /dev/null +++ b/FindOpenSSL.cmake @@ -0,0 +1,109 @@ + + +function(conan_message MESSAGE_OUTPUT) + if(NOT CONAN_CMAKE_SILENT_OUTPUT) + message(${ARGV${0}}) + endif() +endfunction() + + + + +include(FindPackageHandleStandardArgs) + +conan_message(STATUS "Conan: Using autogenerated FindOpenSSL.cmake") +# Global approach +set(OpenSSL_FOUND 1) +set(OpenSSL_VERSION "1.0.2o") + +find_package_handle_standard_args(OpenSSL REQUIRED_VARS + OpenSSL_VERSION VERSION_VAR OpenSSL_VERSION) +mark_as_advanced(OpenSSL_FOUND OpenSSL_VERSION) + + +set(OpenSSL_INCLUDE_DIRS "${CONAN_INCLUDE_DIRS_OPENSSL}") +set(OpenSSL_INCLUDE_DIR "${CONAN_INCLUDE_DIRS_OPENSSL}") +set(OpenSSL_INCLUDES "${CONAN_INCLUDE_DIRS_OPENSSL}") +set(OpenSSL_RES_DIRS "${CONAN_RES_DIRS_OPENSSL}") +set(OpenSSL_DEFINITIONS ) +set(OpenSSL_LINKER_FLAGS_LIST + "$<$,SHARED_LIBRARY>:>" + "$<$,MODULE_LIBRARY>:>" + "$<$,EXECUTABLE>:>" +) +set(OpenSSL_COMPILE_DEFINITIONS ) +set(OpenSSL_COMPILE_OPTIONS_LIST "" "") +set(OpenSSL_COMPILE_OPTIONS_C "") +set(OpenSSL_COMPILE_OPTIONS_CXX "") +set(OpenSSL_LIBRARIES_TARGETS "") # Will be filled later, if CMake 3 +set(OpenSSL_LIBRARIES "") # Will be filled later +set(OpenSSL_LIBS "") # Same as OpenSSL_LIBRARIES +set(OpenSSL_FRAMEWORKS_FOUND "") # Will be filled later +set(OpenSSL_BUILD_MODULES_PATHS ) + + +mark_as_advanced(OpenSSL_INCLUDE_DIRS + OpenSSL_INCLUDE_DIR + OpenSSL_INCLUDES + OpenSSL_DEFINITIONS + OpenSSL_LINKER_FLAGS_LIST + OpenSSL_COMPILE_DEFINITIONS + OpenSSL_COMPILE_OPTIONS_LIST + OpenSSL_LIBRARIES + OpenSSL_LIBS + OpenSSL_LIBRARIES_TARGETS) + +# Find the real .lib/.a and add them to OpenSSL_LIBS and OpenSSL_LIBRARY_LIST +set(OpenSSL_LIBRARY_LIST ssl crypto dl pthread) +set(OpenSSL_LIB_DIRS "${CONAN_LIB_DIRS_OPENSSL}") + +# Gather all the libraries that should be linked to the targets (do not touch existing variables): +set(_OpenSSL_DEPENDENCIES "zlib::zlib") + +conan_package_library_targets("${OpenSSL_LIBRARY_LIST}" # libraries + "${OpenSSL_LIB_DIRS}" # package_libdir + "${_OpenSSL_DEPENDENCIES}" # deps + OpenSSL_LIBRARIES # out_libraries + OpenSSL_LIBRARIES_TARGETS # out_libraries_targets + "" # build_type + "OpenSSL") # package_name + +set(OpenSSL_LIBS ${OpenSSL_LIBRARIES}) + +# We need to add our requirements too +set(OpenSSL_LIBRARIES_TARGETS "${OpenSSL_LIBRARIES_TARGETS};zlib::zlib") +set(OpenSSL_LIBRARIES "${OpenSSL_LIBRARIES};zlib::zlib") + +set(CMAKE_MODULE_PATH "/home/dario/.conan/data/OpenSSL/1.0.2o/conan/stable/package/b781af3f476d0aa5070a0a35b544db7a3c193cc8/" ${CMAKE_MODULE_PATH}) +set(CMAKE_PREFIX_PATH "/home/dario/.conan/data/OpenSSL/1.0.2o/conan/stable/package/b781af3f476d0aa5070a0a35b544db7a3c193cc8/" ${CMAKE_PREFIX_PATH}) + +foreach(_BUILD_MODULE_PATH ${OpenSSL_BUILD_MODULES_PATHS}) + include(${_BUILD_MODULE_PATH}) +endforeach() + +if(NOT ${CMAKE_VERSION} VERSION_LESS "3.0") + # Target approach + if(NOT TARGET OpenSSL::OpenSSL) + add_library(OpenSSL::OpenSSL INTERFACE IMPORTED) + if(OpenSSL_INCLUDE_DIRS) + set_target_properties(OpenSSL::OpenSSL PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${OpenSSL_INCLUDE_DIRS}") + endif() + set_property(TARGET OpenSSL::OpenSSL PROPERTY INTERFACE_LINK_LIBRARIES + "${OpenSSL_LIBRARIES_TARGETS};${OpenSSL_LINKER_FLAGS_LIST}") + set_property(TARGET OpenSSL::OpenSSL PROPERTY INTERFACE_COMPILE_DEFINITIONS + ${OpenSSL_COMPILE_DEFINITIONS}) + set_property(TARGET OpenSSL::OpenSSL PROPERTY INTERFACE_COMPILE_OPTIONS + "${OpenSSL_COMPILE_OPTIONS_LIST}") + + # Library dependencies + include(CMakeFindDependencyMacro) + + if(NOT zlib_FOUND) + find_dependency(zlib REQUIRED) + else() + message(STATUS "Dependency zlib already found") + endif() + + endif() +endif() diff --git a/conanfile.txt b/conanfile.txt index a6c09d9fa..703260a39 100644 --- a/conanfile.txt +++ b/conanfile.txt @@ -6,4 +6,3 @@ gtest/1.8.1@bincrafters/stable [generators] cmake - diff --git a/src/cpp/test/crypto/TestKeyPairEd25519.cpp b/src/cpp/test/crypto/TestKeyPairEd25519.cpp index 314fb9cdc..51f714776 100644 --- a/src/cpp/test/crypto/TestKeyPairEd25519.cpp +++ b/src/cpp/test/crypto/TestKeyPairEd25519.cpp @@ -1,6 +1,6 @@ #include "TestPassphrase.h" -#include "../../Crypto/KeyPair.h" + #include "../../Crypto/KeyPairEd25519.h" #include "../../Crypto/Passphrase.h" #include "../../lib/DataTypeConverter.h" @@ -14,12 +14,12 @@ TEST_F(PassphraseTest, TestEd25519KeyPair) { auto word_indices = tr->getWordIndices(); auto key_pair_ed25519 = KeyPairEd25519::create(tr); - KeyPair key_pair; + //KeyPair key_pair; - key_pair.generateFromPassphrase(test_data_set.passphrases[test_data_set.mnemonicType].data(), mnemonic); + //key_pair.generateFromPassphrase(test_data_set.passphrases[test_data_set.mnemonicType].data(), mnemonic); - EXPECT_EQ(key_pair.getPubkeyHex(), test_data_set.pubkeyHex); - EXPECT_EQ(DataTypeConverter::pubkeyToHex(key_pair_ed25519->getPublicKey()), key_pair.getPubkeyHex()); + //EXPECT_EQ(key_pair.getPubkeyHex(), test_data_set.pubkeyHex); + //EXPECT_EQ(DataTypeConverter::pubkeyToHex(key_pair_ed25519->getPublicKey()), key_pair.getPubkeyHex()); //auto key_pair_old delete key_pair_ed25519; diff --git a/src/cpp/test/crypto/TestPassphrase.cpp b/src/cpp/test/crypto/TestPassphrase.cpp index 128a461f6..010353e17 100644 --- a/src/cpp/test/crypto/TestPassphrase.cpp +++ b/src/cpp/test/crypto/TestPassphrase.cpp @@ -10,7 +10,6 @@ #include "../../lib/DataTypeConverter.h" #include "../../Crypto/KeyPairEd25519.h" -#include "../../Crypto/KeyPair.h" @@ -170,10 +169,10 @@ TEST_F(PassphraseTest, createAndTransform) { EXPECT_EQ(word_indices[i], test_data_set.wordIndices[i]); } auto key_pair_ed25519 = KeyPairEd25519::create(tr); - KeyPair key_pair; - key_pair.generateFromPassphrase(test_data_set.passphrases[test_data_set.mnemonicType].data(), mnemonic); - //EXPECT_EQ(DataTypeConverter::pubkeyToHex(key_pair_ed25519->getPublicKey()), test_data_set.pubkeyHex); - EXPECT_EQ(key_pair.getPubkeyHex(), test_data_set.pubkeyHex); + //KeyPair key_pair; + //key_pair.generateFromPassphrase(test_data_set.passphrases[test_data_set.mnemonicType].data(), mnemonic); + EXPECT_EQ(DataTypeConverter::pubkeyToHex(key_pair_ed25519->getPublicKey()), test_data_set.pubkeyHex); + //EXPECT_EQ(key_pair.getPubkeyHex(), test_data_set.pubkeyHex); //auto key_pair_old delete key_pair_ed25519; From 6a53b19a4230f6ed731eca40f4583e9f7fd54bf8 Mon Sep 17 00:00:00 2001 From: Dario Date: Thu, 8 Oct 2020 11:40:03 +0200 Subject: [PATCH 055/293] adding PendingTask model and controller --- src/cpp/controller/PendingTask.cpp | 36 +++++++++++ src/cpp/controller/PendingTask.h | 37 ++++++++++++ src/cpp/model/table/PendingTask.cpp | 94 +++++++++++++++++++++++++++++ src/cpp/model/table/PendingTask.h | 61 +++++++++++++++++++ 4 files changed, 228 insertions(+) create mode 100644 src/cpp/controller/PendingTask.cpp create mode 100644 src/cpp/controller/PendingTask.h create mode 100644 src/cpp/model/table/PendingTask.cpp create mode 100644 src/cpp/model/table/PendingTask.h diff --git a/src/cpp/controller/PendingTask.cpp b/src/cpp/controller/PendingTask.cpp new file mode 100644 index 000000000..417813762 --- /dev/null +++ b/src/cpp/controller/PendingTask.cpp @@ -0,0 +1,36 @@ +#include "PendingTask.h" + +namespace controller { + + PendingTask::PendingTask(model::table::PendingTask* dbModel) + { + mDBModel = dbModel; + } + + PendingTask::~PendingTask() + { + + } + + Poco::AutoPtr PendingTask::create(int userId, std::string serializedProtoRequest, model::table::TaskType type) + { + auto db = new model::table::PendingTask(userId, serializedProtoRequest, type); + auto pending_task = new PendingTask(db); + return Poco::AutoPtr(pending_task); + } + + std::vector> PendingTask::load(int userId) + { + auto db = new model::table::PendingTask(); + auto pending_task_list = db->loadFromDB("user_id", userId, 3); + std::vector> resultVector; + resultVector.reserve(pending_task_list.size()); + for (auto it = pending_task_list.begin(); it != pending_task_list.end(); it++) { + resultVector.push_back(new PendingTask(new model::table::PendingTask(*it))); + } + return resultVector; + + + } + +} \ No newline at end of file diff --git a/src/cpp/controller/PendingTask.h b/src/cpp/controller/PendingTask.h new file mode 100644 index 000000000..821f4a141 --- /dev/null +++ b/src/cpp/controller/PendingTask.h @@ -0,0 +1,37 @@ +#ifndef GRADIDO_LOGIN_SERVER_CONTROLLER_PENDING_TASK_INCLUDE +#define GRADIDO_LOGIN_SERVER_CONTROLLER_PENDING_TASK_INCLUDE + +#include "../model/table/PendingTask.h" + +#include "Poco/SharedPtr.h" + +#include "TableControllerBase.h" + +namespace controller { + + + typedef Poco::Tuple NodeServerFullTuple; + + class PendingTask : public TableControllerBase + { + public: + + ~PendingTask(); + + static Poco::AutoPtr create(int userId, std::string serializedProtoRequest, model::table::TaskType type); + + static std::vector> load(int userId); + + inline bool deleteFromDB() { return mDBModel->deleteFromDB(); } + + inline Poco::AutoPtr getModel() { return _getModel(); } + + + protected: + PendingTask(model::table::PendingTask* dbModel); + + + }; +} + +#endif //GRADIDO_LOGIN_SERVER_CONTROLLER_PENDING_TASK_INCLUDE \ No newline at end of file diff --git a/src/cpp/model/table/PendingTask.cpp b/src/cpp/model/table/PendingTask.cpp new file mode 100644 index 000000000..6248333f8 --- /dev/null +++ b/src/cpp/model/table/PendingTask.cpp @@ -0,0 +1,94 @@ +#include "PendingTask.h" + +//#include + +using namespace Poco::Data::Keywords; + +namespace model +{ + namespace table + { + PendingTask::PendingTask() + : mUserId(0), mTaskTypeId(TASK_TYPE_NONE) + { + + } + PendingTask::PendingTask(int userId, std::string serializedProtoRequest, TaskType type) + : mUserId(userId), mRequest((const unsigned char*)serializedProtoRequest.data(), serializedProtoRequest.size()), + mTaskTypeId(TASK_TYPE_NONE) + { + + } + PendingTask::PendingTask(const PendingTaskTuple& tuple) + : ModelBase(tuple.get<0>()), mUserId(tuple.get<1>()), mRequest(tuple.get<2>()), mCreated(tuple.get<3>()), mFinished(tuple.get<4>()), + mResultJsonString(tuple.get<5>()), mTaskTypeId(tuple.get<6>()) + { + + } + PendingTask::~PendingTask() + { + + } + + + + std::string PendingTask::toString() + { + std::stringstream ss; + std::shared_lock _lock(mSharedMutex); + return ss.str(); + } + + + const char* PendingTask::typeToString(TaskType type) + { + switch (type) { + case TASK_TYPE_GROUP_CREATE: return "group create"; + case TASK_TYPE_GROUP_ADD_MEMBER: return "group add member"; + case TASK_TYPE_CREATION: return "creation"; + case TASK_TYPE_TRANSFER: return "transfer"; + case TASK_TYPE_HEDERA_TOPIC_CREATE: return "hedera topic create"; + case TASK_TYPE_HEDERA_TOPIC_MESSAGE: return "hedera topic send message"; + case TASK_TYPE_HEDERA_ACCOUNT_CREATE: return "hedera account create"; + default: return ""; + } + return ""; + } + + Poco::Data::Statement PendingTask::_loadFromDB(Poco::Data::Session session, const std::string& fieldName) + { + Poco::Data::Statement select(session); + + select << "SELECT id, user_id, request, created, finished, result_json, task_type_id FROM " << getTableName() + << " where " << fieldName << " = ?" + , into(mID), into(mUserId), into(mRequest), into(mCreated), into(mFinished), into(mResultJsonString), into(mTaskTypeId); + + return select; + } + + Poco::Data::Statement PendingTask::_loadIdFromDB(Poco::Data::Session session) + { + Poco::Data::Statement select(session); + lock(); + select << "SELECT id FROM " << getTableName() + << " WHERE user_id = ? " + << " AND created = ? " + << " AND task_type_id = ? " + , into(mID), use(mUserId), use(mCreated), use(mTaskTypeId); + unlock(); + return select; + } + + + Poco::Data::Statement PendingTask::_insertIntoDB(Poco::Data::Session session) + { + Poco::Data::Statement insert(session); + lock(); + insert << "INSERT INTO " << getTableName() + << " (user_id, request, created, task_type_id) VALUES(?,?,?,?)" + , use(mUserId), use(mRequest), use(mCreated), use(mTaskTypeId); + unlock(); + return insert; + } + } +} \ No newline at end of file diff --git a/src/cpp/model/table/PendingTask.h b/src/cpp/model/table/PendingTask.h new file mode 100644 index 000000000..bab94448c --- /dev/null +++ b/src/cpp/model/table/PendingTask.h @@ -0,0 +1,61 @@ +#ifndef GRADIDO_LOGIN_SERVER_MODEL_TABLE_PENDING_TASKS_INCLUDE +#define GRADIDO_LOGIN_SERVER_MODEL_TABLE_PENDING_TASKS_INCLUDE + +#include "ModelBase.h" +#include "Poco/Types.h" + +#include + +namespace model { + namespace table { + + enum TaskType { + TASK_TYPE_NONE = 0, + TASK_TYPE_GROUP_CREATE = 1, + TASK_TYPE_GROUP_ADD_MEMBER = 2, + TASK_TYPE_CREATION = 10, + TASK_TYPE_TRANSFER = 11, + TASK_TYPE_HEDERA_TOPIC_CREATE = 20, + TASK_TYPE_HEDERA_TOPIC_MESSAGE = 21, + TASK_TYPE_HEDERA_ACCOUNT_CREATE = 25, + + }; + + typedef Poco::Tuple PendingTaskTuple; + + class PendingTask : public ModelBase + { + public: + PendingTask(); + PendingTask(int userId, std::string serializedProtoRequest, TaskType type); + PendingTask(const PendingTaskTuple& tuple); + + ~PendingTask(); + + // generic db operations + const char* getTableName() const { return "pending_tasks"; } + std::string toString(); + + + static const char* typeToString(TaskType type); + protected: + Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); + Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session); + Poco::Data::Statement _insertIntoDB(Poco::Data::Session session); + + int mUserId; + Poco::Data::BLOB mRequest; + Poco::DateTime mCreated; + Poco::DateTime mFinished; + std::string mResultJsonString; + int mTaskTypeId; + + std::shared_mutex mSharedMutex; + + }; + + } +} + + +#endif //GRADIDO_LOGIN_SERVER_MODEL_TABLE_PENDING_TASKS_INCLUDE \ No newline at end of file From a4ab74b5c6b156337ad11ee98df7ef07e14ce36b Mon Sep 17 00:00:00 2001 From: einhornimmond - MarkX Date: Thu, 8 Oct 2020 11:51:23 +0200 Subject: [PATCH 056/293] cmake update for windows --- CMakeLists.txt | 20 +++++++------------- README | 16 +++++++--------- windows_parse_proto.sh | 8 ++++---- 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1648b666e..aaea26b43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,8 +101,11 @@ set(GRPC_PROTOBUF_PATH "${GRPC_PATH}/third_party/protobuf") if(WIN32) - find_library(MYSQL_LIBRARIES mariadbclient.lib PATHS "${MARIADB_CONNECTOR_PATH}/Release" REQUIRED) + find_library(MYSQL_LIBRARIES mariadbclient PATHS "${MARIADB_CONNECTOR_PATH}/Release" REQUIRED) find_library(COMPILED_MARIADB_CLIENT_DEBUG mariadbclient PATHS "${MARIADB_CONNECTOR_PATH}/Debug" REQUIRED) + + find_library(CONAN_OPENSSL_SSL ssleay32 PATHS ${CONAN_LIB_DIRS_OPENSSL} REQUIRED NO_DEFAULT_PATH ) + find_library(CONAN_OPENSSL_CRYPTO libeay32 PATHS ${CONAN_LIB_DIRS_OPENSSL} REQUIRED NO_DEFAULT_PATH ) set(GRPC_PATH "${GRPC_PATH}/Debug") set(GRPC_ABSL_PATH "${GRPC_ABSL_PATH}/Debug") @@ -111,15 +114,6 @@ if(WIN32) set(GRPC_RE2_PATH "${GRPC_RE2_PATH}/Debug") set(GRPC_PROTOBUF_DEBUG_PATH "${GRPC_PROTOBUF_PATH}/Debug") - find_library(PROTOBUF_LIB_DEBUG libprotobufd PATHS ${GRPC_PROTOBUF_DEBUG_PATH} REQUIRED) - find_library(PROTOBUF_LIB_LITE_DEBUG libprotobuf-lited PATHS ${GRPC_PROTOBUF_DEBUG_PATH} REQUIRED) - find_library(PROTOBUF_LIBC_DEBUG libprotocd PATHS ${GRPC_PROTOBUF_DEBUG_PATH} REQUIRED) - - set(PROTOBUF_DEBUG_LIBS - ${PROTOBUF_LIB_DEBUG} - ${PROTOBUF_LIB_LITE_DEBUG} - ${PROTOBUF_LIBC_DEBUG} - ) list(REMOVE_ITEM CONAN_LIBS "libeay32.lib") list(REMOVE_ITEM CONAN_LIBS "ssleay32.lib") @@ -128,6 +122,8 @@ if(WIN32) else (WIN32) find_library(MYSQL_LIBRARIES libmariadb.so PATHS ${MARIADB_CONNECTOR_PATH} REQUIRED) + find_library(CONAN_OPENSSL_SSL ssl PATHS ${CONAN_LIB_DIRS_OPENSSL} REQUIRED NO_DEFAULT_PATH ) + find_library(CONAN_OPENSSL_CRYPTO crypto PATHS ${CONAN_LIB_DIRS_OPENSSL} REQUIRED NO_DEFAULT_PATH ) set(GRPC_PROTOBUF_DEBUG_PATH "${GRPC_PROTOBUF_PATH}") list(REMOVE_ITEM CONAN_LIBS "ssl") @@ -138,10 +134,8 @@ else (WIN32) endif(WIN32) # load same ssl version like used from poco -find_package(OpenSSL PATHS . NO_DEFAULT_PATH) +#find_package(OpenSSL PATHS . NO_DEFAULT_PATH) -find_library(CONAN_OPENSSL_SSL ssl PATHS ${CONAN_LIB_DIRS_OPENSSL} REQUIRED NO_DEFAULT_PATH ) -find_library(CONAN_OPENSSL_CRYPTO crypto PATHS ${CONAN_LIB_DIRS_OPENSSL} REQUIRED NO_DEFAULT_PATH ) set(CONAN_OPENSSL_CUSTOM_LIBS ${CONAN_OPENSSL_SSL} diff --git a/README b/README index c6419d014..85f15134c 100644 --- a/README +++ b/README @@ -9,15 +9,6 @@ cmake -DWITH_SSL=OFF .. cd ../../../ -cd dependencies/grpc -mkdir build -cd build -cmake .. -make -# under windows build at least release for protoc.exe and grpc c++ plugin -cd ../../../ -./unix_parse_proto.sh - # get more dependencies with conan (need conan from https://conan.io/) mkdir build && cd build # // not used anymore @@ -29,3 +20,10 @@ conan install .. # build Makefile with cmake cmake .. +make grpc +# under windows build at least release for protoc.exe and grpc c++ plugin +cd ../ +./unix_parse_proto.sh +cd build +make + diff --git a/windows_parse_proto.sh b/windows_parse_proto.sh index 4c5d56d47..90497e6b8 100644 --- a/windows_parse_proto.sh +++ b/windows_parse_proto.sh @@ -5,15 +5,15 @@ fi if [ ! -d "./src/cpp/proto/gradido" ] ; then mkdir ./src/cpp/proto/gradido fi -PROTOC_PATH=./dependencies/grpc/_build/third_party/protobuf/Release -CPP_PLUGIN_PATH=./dependencies/grpc/_build/Release -$PROTOC_PATH/protoc --cpp_out=./src/cpp/proto --proto_path=./src/proto ./src/proto/gradido/*.proto +PROTOC_PATH=build/bin +CPP_PLUGIN_PATH=build/bin +$PROTOC_PATH/protoc.exe --cpp_out=./src/cpp/proto --proto_path=./src/proto ./src/proto/gradido/*.proto if [ ! -d "./src/cpp/proto/hedera" ] ; then mkdir ./src/cpp/proto/hedera fi GOOGLE_PROTOBUF_INCLUDES=./dependencies/grpc/third_party/protobuf/src -$PROTOC_PATH/protoc --plugin=protoc-gen-grpc=$CPP_PLUGIN_PATH/grpc_cpp_plugin.exe --cpp_out=./src/cpp/proto/hedera --grpc_out=./src/cpp/proto/hedera --proto_path=$GOOGLE_PROTOBUF_INCLUDES --proto_path=./src/proto/hedera/hedera-protobuf/src/main/proto ./src/proto/hedera/hedera-protobuf/src/main/proto/*.proto +$PROTOC_PATH/protoc.exe --plugin=protoc-gen-grpc=$CPP_PLUGIN_PATH/grpc_cpp_plugin.exe --cpp_out=./src/cpp/proto/hedera --grpc_out=./src/cpp/proto/hedera --proto_path=$GOOGLE_PROTOBUF_INCLUDES --proto_path=./src/proto/hedera/hedera-protobuf/src/main/proto ./src/proto/hedera/hedera-protobuf/src/main/proto/*.proto From 5642805b7e2f4f0b253672e82b75b11abd990a5b Mon Sep 17 00:00:00 2001 From: dario Linux Date: Mon, 12 Oct 2020 11:19:55 +0200 Subject: [PATCH 057/293] finish unix makefile updates --- .gitmodules | 3 +++ CMakeLists.txt | 43 ++++++++++++++++++++------------- FindOpenSSL.cmake | 2 ++ dependencies/cmake-modules | 1 + src/cpp/Gradido_LoginServer.cpp | 25 +++++++++++-------- src/cpp/MySQL/Connector.cpp | 19 ++++++++++----- unix_parse_proto.sh | 4 +-- 7 files changed, 62 insertions(+), 35 deletions(-) create mode 160000 dependencies/cmake-modules diff --git a/.gitmodules b/.gitmodules index 7500d3d77..96fdb6a84 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "dependencies/poco"] path = dependencies/poco url = https://github.com/pocoproject/poco.git +[submodule "dependencies/cmake-modules"] + path = dependencies/cmake-modules + url = https://github.com/viaduck/cmake-modules.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 1648b666e..39de3c0c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,9 +16,11 @@ include_directories( "dependencies/grpc/third_party/protobuf/src" "src/cpp/proto" ) - +#if(WIN32) +#include_directories("dependencies/mariadb-connector-c/include", "dependencies/mariadb-connector-c/build/include") set(MYSQL_INCLUDE_DIR "dependencies/mariadb-connector-c/include") +#endif(WIN32) FILE(GLOB CONTROLLER "src/cpp/controller/*.cpp" "src/cpp/controller/*.h") FILE(GLOB TINF "dependencies/tinf/src/*.c" "dependencies/tinf/src/*.h") @@ -85,10 +87,15 @@ conan_basic_setup() add_executable(Gradido_LoginServer ${LOCAL_SRCS}) - +set(CLIENT_PLUGIN_DIALOG OFF) +set(CLIENT_PLUGIN_client_ed25519 OFF) +set(CLIENT_PLUGIN_MYSQL_CLEAR_PASSWORD OFF) +set(CLIENT_PLUGIN_REMOTE_IO OFF) +set(WITH_SSL OFF) +add_subdirectory("dependencies/mariadb-connector-c") set(DEP_PATH "dependencies") -set(MARIADB_CONNECTOR_PATH "${DEP_PATH}/mariadb-connector-c/build/libmariadb") +#set(MARIADB_CONNECTOR_PATH "${DEP_PATH}/mariadb-connector-c/build/libmariadb") set(GRPC_PATH "${DEP_PATH}/grpc/build") set(GRPC_ABSL_PATH "${GRPC_PATH}/third_party/abseil-cpp/absl/types") @@ -126,8 +133,8 @@ if(WIN32) else (WIN32) - - find_library(MYSQL_LIBRARIES libmariadb.so PATHS ${MARIADB_CONNECTOR_PATH} REQUIRED) + #find_package(MariaDBClient PATHS "dependencies/cmake-modules") + #find_library(MYSQL_LIBRARIES libmariadb.so PATHS ${MARIADB_CONNECTOR_PATH} REQUIRED) set(GRPC_PROTOBUF_DEBUG_PATH "${GRPC_PROTOBUF_PATH}") list(REMOVE_ITEM CONAN_LIBS "ssl") @@ -138,7 +145,7 @@ else (WIN32) endif(WIN32) # load same ssl version like used from poco -find_package(OpenSSL PATHS . NO_DEFAULT_PATH) +#find_package(OpenSSL PATHS "../" NO_DEFAULT_PATH) find_library(CONAN_OPENSSL_SSL ssl PATHS ${CONAN_LIB_DIRS_OPENSSL} REQUIRED NO_DEFAULT_PATH ) find_library(CONAN_OPENSSL_CRYPTO crypto PATHS ${CONAN_LIB_DIRS_OPENSSL} REQUIRED NO_DEFAULT_PATH ) @@ -147,11 +154,9 @@ set(CONAN_OPENSSL_CUSTOM_LIBS ${CONAN_OPENSSL_SSL} ${CONAN_OPENSSL_CRYPTO} ) +include_directories(${CONAN_INCLUDE_DIRS_OPENSSL}) +# build grpc -set(BUILD_TESTING OFF) -set(gRPC_SSL_PROVIDER "package") -add_subdirectory("dependencies/grpc/") -message(STATUS "Using gRPC via add_subdirectory.") if(WIN32) @@ -164,14 +169,16 @@ else(WIN32) set(INSTALL_BINDIR "bin") set(INSTALL_PLUGINDIR "bin") - - include_directories( - ${CONAN_INCLUDE_DIRS_OPENSSL} - ) - + target_link_libraries(Gradido_LoginServer ${CONAN_OPENSSL_CUSTOM_LIBS}) endif(WIN32) +set(BUILD_TESTING OFF) +set(gRPC_SSL_PROVIDER "package") +add_subdirectory("dependencies/grpc/") +set(gRPC_SSL_PROVIDER "package") +message(STATUS "Using gRPC via add_subdirectory.") + set(GRPC_LIBS libprotobuf grpc++_reflection grpc++) target_link_libraries(Gradido_LoginServer ${CONAN_LIBS}) @@ -180,12 +187,13 @@ if(WIN32) TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${COMPILED_MARIADB_CLIENT_DEBUG} Shlwapi) TARGET_LINK_LIBRARIES(Gradido_LoginServer debug ${GRPC_LIBS} ${PROTOBUF_DEBUG_LIBS}) else(WIN32) # unix - target_link_libraries(Gradido_LoginServer ${MYSQL_LIBRARIES} ${CONAN_OPENSSL_CUSTOM_LIBS} ${GRPC_LIBS} ${CMAKE_DL_LIBS} ${PROTOBUF_LIBS}) + target_link_libraries(Gradido_LoginServer libmariadb ${GRPC_LIBS} ${CMAKE_DL_LIBS} ${PROTOBUF_LIBS}) endif(WIN32) # install if(UNIX) install(TARGETS Gradido_LoginServer RUNTIME DESTINATION /usr/local/bin) +#install(LIBRARYS DESTINATION /usr/local/lib) #install(FILES lib/libmariadb /usr/local/lib) install(FILES DESTINATION lib COMPONENT libmariadb) install(DIRECTORY src/LOCALE DESTINATION /etc/grd_login/ @@ -206,12 +214,13 @@ target_compile_definitions(Gradido_LoginServer_Test PUBLIC "_TEST_BUILD") target_link_libraries(Gradido_LoginServer_Test ${CONAN_LIBS} ) + if(WIN32) TARGET_LINK_LIBRARIES(Gradido_LoginServer_Test optimized ${MYSQL_LIBRARIES} Shlwapi) TARGET_LINK_LIBRARIES(Gradido_LoginServer_Test debug ${COMPILED_MARIADB_CLIENT_DEBUG} Shlwapi) TARGET_LINK_LIBRARIES(Gradido_LoginServer_Test debug ${GRPC_LIBS} ${PROTOBUF_DEBUG_LIBS}) else(WIN32) - target_link_libraries(Gradido_LoginServer_Test ${MYSQL_LIBRARIES} ${CONAN_OPENSSL_CUSTOM_LIBS} ${GRPC_LIBS} ${CMAKE_DL_LIBS} ${PROTOBUF_LIBS}) + target_link_libraries(Gradido_LoginServer_Test libmariadb ${GRPC_LIBS} ${CMAKE_DL_LIBS} ${PROTOBUF_LIBS}) endif(WIN32) add_test(NAME main COMMAND Gradido_LoginServer_Test) diff --git a/FindOpenSSL.cmake b/FindOpenSSL.cmake index 4a4fec7df..64fefb4ec 100644 --- a/FindOpenSSL.cmake +++ b/FindOpenSSL.cmake @@ -25,6 +25,8 @@ set(OpenSSL_INCLUDE_DIRS "${CONAN_INCLUDE_DIRS_OPENSSL}") set(OpenSSL_INCLUDE_DIR "${CONAN_INCLUDE_DIRS_OPENSSL}") set(OpenSSL_INCLUDES "${CONAN_INCLUDE_DIRS_OPENSSL}") set(OpenSSL_RES_DIRS "${CONAN_RES_DIRS_OPENSSL}") +set(OPENSSL_ROOT_DIR "${CONAN_OPENSSL_ROOT}") +set(OPENSSL_DIR "${CONAN_OPENSSL_ROOT}") set(OpenSSL_DEFINITIONS ) set(OpenSSL_LINKER_FLAGS_LIST "$<$,SHARED_LIBRARY>:>" diff --git a/dependencies/cmake-modules b/dependencies/cmake-modules new file mode 160000 index 000000000..7304f680b --- /dev/null +++ b/dependencies/cmake-modules @@ -0,0 +1 @@ +Subproject commit 7304f680be32915e772466ebddc5b7d3b453abd9 diff --git a/src/cpp/Gradido_LoginServer.cpp b/src/cpp/Gradido_LoginServer.cpp index cf17a0fba..507212e4b 100644 --- a/src/cpp/Gradido_LoginServer.cpp +++ b/src/cpp/Gradido_LoginServer.cpp @@ -31,7 +31,7 @@ -Gradido_LoginServer::Gradido_LoginServer() +Gradido_LoginServer::Gradido_LoginServer() : _helpRequested(false) { } @@ -147,7 +147,7 @@ int Gradido_LoginServer::main(const std::vector& args) unsigned short port = (unsigned short)config().getInt("HTTPServer.port", 9980); unsigned short json_port = (unsigned short)config().getInt("JSONServer.port", 1201); - + //printf("show mnemonic list: \n"); //printf(ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER].getCompleteWordList().data()); if (!ServerConfig::initServerCrypto(config())) { @@ -156,7 +156,7 @@ int Gradido_LoginServer::main(const std::vector& args) return Application::EXIT_CONFIG; } - // first check time for crypto + // first check time for crypto SecretKeyCryptography test_crypto; Profiler timeUsed; if (test_crypto.createKey("email@google.de", "haz27Newpassword") != SecretKeyCryptography::AUTH_CREATE_ENCRYPTION_KEY_SUCCEED) { @@ -178,13 +178,18 @@ int Gradido_LoginServer::main(const std::vector& args) ServerConfig::g_CPUScheduler = new UniLib::controller::CPUSheduler(worker_count, "Default Worker"); ServerConfig::g_CryptoCPUScheduler = new UniLib::controller::CPUSheduler(2, "Crypto Worker"); + // load up connection configs // register MySQL connector - Poco::Data::MySQL::Connector::registerConnector(); - //Poco::Data::MySQL::Connector::KEY; + try { + Poco::Data::MySQL::Connector::registerConnector(); + } catch(Poco::Exception& ex) { + errorLog.error("[Gradido_LoginServer::main] Poco Exception by register MySQL Connector: %s", ex.displayText()); + return Application::EXIT_CONFIG; + } + auto conn = ConnectionManager::getInstance(); - //conn->setConnection() - //printf("try connect login server mysql db\n"); + conn->setConnectionsFromConfig(config(), CONNECTION_MYSQL_LOGIN_SERVER); //printf("try connect php server mysql \n"); //conn->setConnectionsFromConfig(config(), CONNECTION_MYSQL_PHP_SERVER); @@ -196,10 +201,10 @@ int Gradido_LoginServer::main(const std::vector& args) Poco::Net::initializeSSL(); if(!ServerConfig::initSSLClientContext()) { //printf("[Gradido_LoginServer::%s] error init server SSL Client\n", __FUNCTION__); - errorLog.error("[Gradido_LoginServer::main] error init server SSL Client\n"); + errorLog.error("[Gradido_LoginServer::main] error init server SSL Client"); return Application::EXIT_CONFIG; } - + // schedule email verification resend controller::User::checkIfVerificationEmailsShouldBeResend(ServerConfig::g_CronJobsTimer); controller::User::addMissingEmailHashes(); @@ -211,7 +216,7 @@ int Gradido_LoginServer::main(const std::vector& args) Poco::ThreadPool& pool = Poco::ThreadPool::defaultPool(); Poco::Net::HTTPServer srv(new PageRequestHandlerFactory, svs, new Poco::Net::HTTPServerParams); ServerConfig::g_ServerKeySeed->put(7, 918276611); - + // start the HTTPServer srv.start(); diff --git a/src/cpp/MySQL/Connector.cpp b/src/cpp/MySQL/Connector.cpp index dc170cacb..5b35ded21 100644 --- a/src/cpp/MySQL/Connector.cpp +++ b/src/cpp/MySQL/Connector.cpp @@ -48,18 +48,25 @@ const std::string& Connector::name() const Poco::AutoPtr Connector::createSession(const std::string& connectionString, std::size_t timeout) { - return Poco::AutoPtr(new SessionImpl(connectionString, timeout)); + return Poco::AutoPtr(new SessionImpl(connectionString, timeout)); } void Connector::registerConnector() { - if (mysql_library_init(0, 0, 0) != 0) - { - throw Exception("mysql_library_init error"); - } - ServerConfig::g_ServerKeySeed->put(4, DRRandom::r64()); + printf("function pointer address: %d\n", mysql_library_init); + try { + if (mysql_library_init(0, nullptr, nullptr) != 0) + { + throw Exception("mysql_library_init error"); + } + } catch(std::exception &ex) { + printf("mysql exception: \n"); + } + printf("after exception\n"); + ServerConfig::g_ServerKeySeed->put(4, DRRandom::r64()); + printf("instance add new\n"); Poco::Data::SessionFactory::instance().add(new Connector()); } diff --git a/unix_parse_proto.sh b/unix_parse_proto.sh index 3727cc985..43fdc3a14 100755 --- a/unix_parse_proto.sh +++ b/unix_parse_proto.sh @@ -5,8 +5,8 @@ fi if [ ! -d "./src/cpp/proto/gradido" ] ; then mkdir ./src/cpp/proto/gradido fi -PROTOC_PATH=./dependencies/grpc/build/third_party/protobuf -CPP_PLUGIN_PATH=./dependencies/grpc/build +PROTOC_PATH=./build/bin +CPP_PLUGIN_PATH=./build/bin $PROTOC_PATH/protoc --cpp_out=./src/cpp/proto --proto_path=./src/proto ./src/proto/gradido/*.proto if [ ! -d "./src/cpp/proto/hedera" ] ; then From 7af29888ee7621434b9096b18dd21f8215c31d12 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 21 Aug 2020 13:05:31 +0000 Subject: [PATCH 058/293] adding error transaction api endpoint, only empty function --- src/Controller/JsonRequestHandlerController.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Controller/JsonRequestHandlerController.php b/src/Controller/JsonRequestHandlerController.php index e5823397e..9395e1239 100644 --- a/src/Controller/JsonRequestHandlerController.php +++ b/src/Controller/JsonRequestHandlerController.php @@ -58,7 +58,11 @@ class JsonRequestHandlerController extends AppController { case 'checkUser': return $this->checkUser($jsonData->email, $jsonData->last_name); case 'getUsers' : return $this->getUsers($jsonData->page, $jsonData->limit); case 'getUserBalance': return $this->getUserBalance($jsonData->email, $jsonData->last_name); + case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionGenericHash, $jsonData->error, $jsonData->errorMessage); + + case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionSha256, $jsonData->error, $jsonData->errorMessage); + } return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for post', 'details' => $method]); } @@ -66,6 +70,7 @@ class JsonRequestHandlerController extends AppController { } //! \param $transactionCreated creation of transaction in timestamp in seconds + //! -1 if transaction couldn't decode //! \param $transactionBodyBase64Sha256 generic hash from transaction body serialized and converted to base64 //! using sodium_crypto_generichash to calculate @@ -80,6 +85,7 @@ class JsonRequestHandlerController extends AppController { * payload.set("error", error); * payload.set("errorMessage", errorDetails); */ + } private function putTransaction($transactionBase64) { From 8f62ad61154d46fa8c3eb5faa6ed7e88f6e6a6c8 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 21 Aug 2020 13:16:58 +0000 Subject: [PATCH 059/293] change to blake2 --- src/Controller/JsonRequestHandlerController.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Controller/JsonRequestHandlerController.php b/src/Controller/JsonRequestHandlerController.php index 9395e1239..54b6af782 100644 --- a/src/Controller/JsonRequestHandlerController.php +++ b/src/Controller/JsonRequestHandlerController.php @@ -58,11 +58,8 @@ class JsonRequestHandlerController extends AppController { case 'checkUser': return $this->checkUser($jsonData->email, $jsonData->last_name); case 'getUsers' : return $this->getUsers($jsonData->page, $jsonData->limit); case 'getUserBalance': return $this->getUserBalance($jsonData->email, $jsonData->last_name); - case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionGenericHash, $jsonData->error, $jsonData->errorMessage); - case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionSha256, $jsonData->error, $jsonData->errorMessage); - } return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for post', 'details' => $method]); } @@ -70,7 +67,6 @@ class JsonRequestHandlerController extends AppController { } //! \param $transactionCreated creation of transaction in timestamp in seconds - //! -1 if transaction couldn't decode //! \param $transactionBodyBase64Sha256 generic hash from transaction body serialized and converted to base64 //! using sodium_crypto_generichash to calculate From 2f2af7e96fa68cefd2e71e6e8451750ea75fc5b1 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 4 Sep 2020 14:40:44 +0000 Subject: [PATCH 060/293] js for login server --- .../TransactionSendCoinsController.php | 2 +- webroot/js/time_calculations.js | 68 +++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 webroot/js/time_calculations.js diff --git a/src/Controller/TransactionSendCoinsController.php b/src/Controller/TransactionSendCoinsController.php index 2f48de063..c5a738736 100644 --- a/src/Controller/TransactionSendCoinsController.php +++ b/src/Controller/TransactionSendCoinsController.php @@ -188,7 +188,7 @@ class TransactionSendCoinsController extends AppController $this->set('timeUsed', microtime(true) - $startTime); return; } - if($requestAnswear['data']['userData']['disabled']) { + if(isset($requestAnswear['data']['userData']['disabled']) && $requestAnswear['data']['userData']['disabled']) { $this->Flash->error(__('Der Empfänger ist deaktiviert, daher können ihm zurzeit keine Gradidos gesendet werden.')); $this->set('timeUsed', microtime(true) - $startTime); return; diff --git a/webroot/js/time_calculations.js b/webroot/js/time_calculations.js new file mode 100644 index 000000000..7ca61c492 --- /dev/null +++ b/webroot/js/time_calculations.js @@ -0,0 +1,68 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + + + +var SECONDS_TO_YEAR = 31536000; +var SECONDS_TO_DAY = 86400; +var SECONDS_TO_HOUR = 3600; +var SECONDS_TO_MINUTE = 60; +SECONDS_TO = { + YEAR: SECONDS_TO_YEAR, + DAY: SECONDS_TO_DAY, + HOUR: SECONDS_TO_HOUR, + MINUTE: SECONDS_TO_MINUTE +}; + + + +function getReadableAge(timestamp) { + if(timestamp === undefined) { + return "no timestamp" + } + var ageSeconds = ((new Date()).getTime()/1000) - timestamp; + if(ageSeconds < SECONDS_TO_MINUTE) { + return Math.round(ageSeconds) + " seconds"; + } else if(ageSeconds < SECONDS_TO_HOUR) { + return "~ " + Math.round(ageSeconds / SECONDS_TO_MINUTE) + " minutes"; + } else if(ageSeconds < SECONDS_TO_DAY) { + return "~ " + Math.round(ageSeconds / SECONDS_TO_HOUR) + " hours"; + } else if(ageSeconds < SECONDS_TO_YEAR) { + return "~ " + Math.round(ageSeconds / SECONDS_TO_DAY) + " days"; + } else { + return "~ " + Math.round(ageSeconds / SECONDS_TO_YEAR) + " years"; + } +} + +function getExactTimeDuration(durationSeconds) { + var parts = { + seconds: durationSeconds, + minutes: 0, + hours: 0, + days: 0, + years: 0 + }; + var durationString = ''; + for(var i in SECONDS_TO) { + if(parts.seconds > SECONDS_TO[i]) { + var partIndexName = i.toLowerCase() + 's'; + parts[partIndexName] = Math.floor(parts.seconds / SECONDS_TO[i]); + parts.seconds -= parts[partIndexName] * SECONDS_TO[i]; + if(durationString.length > 0) { + durationString += ', '; + } + var unitName = partIndexName; + if(parts[partIndexName] === 1) { + unitName = partIndexName.substring(0, partIndexName.length-1); + } + durationString += parts[partIndexName] + ' ' + unitName; + break; + } + + } + return durationString; + +} \ No newline at end of file From 9d8eee819f385ed67d1c8527c4a8be3413f37628 Mon Sep 17 00:00:00 2001 From: team-devstage Date: Tue, 15 Sep 2020 14:57:29 +0200 Subject: [PATCH 061/293] git checkout work of samir --- src/Controller/AppController.php | 1 - src/Template/Dashboard/index.ctp | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php index fb0577034..87ec7afb3 100644 --- a/src/Controller/AppController.php +++ b/src/Controller/AppController.php @@ -129,7 +129,6 @@ class AppController extends Controller if ($this->Auth->user('id')) { $GLOBALS['ServerUser'] = $this->Auth->user(); } - // login server url $loginServer = Configure::read('LoginServer'); if ($loginServer && isset($loginServer['url'])) { diff --git a/src/Template/Dashboard/index.ctp b/src/Template/Dashboard/index.ctp index 3e93e968a..095234222 100644 --- a/src/Template/Dashboard/index.ctp +++ b/src/Template/Dashboard/index.ctp @@ -111,4 +111,25 @@ $this->assign(
+
+

Roles ...

+
+
+ roles + Html->link( + __('View'), + ['controller' => 'Roles', 'action' => 'index'], + ['class' => 'info-item-link'] + ); ?> +
+
+ assign_roles + Html->link( + __('Assign Roles'), + ['controller' => 'StateUserRoles', 'action' => 'search'], + ['class' => 'info-item-link'] + ); ?> +
+
+
From 2d6950bc80f1ea74e2f06af67f555bb4ba062185 Mon Sep 17 00:00:00 2001 From: team-devstage Date: Fri, 18 Sep 2020 18:08:17 +0200 Subject: [PATCH 062/293] add files created from samir --- src/Form/AssignRoleForm.php | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/Form/AssignRoleForm.php diff --git a/src/Form/AssignRoleForm.php b/src/Form/AssignRoleForm.php new file mode 100644 index 000000000..158fa2296 --- /dev/null +++ b/src/Form/AssignRoleForm.php @@ -0,0 +1,30 @@ +addField('role_id', ['type' => 'string']); + } + + function validationDefault(Validator $validator) + { + $validator->setProvider('custom', 'App\Model\Validation\GenericValidation'); + + return $validator; + } + + + protected function _execute(array $data) + { + // Send an email. + return true; + } +} \ No newline at end of file From 46492a1778a55585dce51f4bbcf81e36dd80c6ae Mon Sep 17 00:00:00 2001 From: team-devstage Date: Thu, 24 Sep 2020 08:01:11 +0200 Subject: [PATCH 063/293] add new created files from samir --- src/Controller/RolesController.php | 108 ++++++ src/Controller/StateUserRolesController.php | 307 ++++++++++++++++++ src/Model/Entity/Role.php | 26 ++ src/Model/Entity/StateUserRole.php | 30 ++ src/Model/Table/RolesTable.php | 72 ++++ src/Model/Table/StateUserRolesTable.php | 86 +++++ src/Template/Roles/add.ctp | 23 ++ src/Template/Roles/edit.ctp | 29 ++ src/Template/Roles/index.ctp | 47 +++ src/Template/Roles/view.ctp | 28 ++ src/Template/StateUserRoles/assign_role.ctp | 49 +++ src/Template/StateUserRoles/index.ctp | 69 ++++ src/Template/StateUserRoles/search.ctp | 80 +++++ tests/Fixture/RolesFixture.php | 45 +++ .../Controller/RolesControllerTest.php | 75 +++++ tests/TestCase/Model/Table/RolesTableTest.php | 82 +++++ 16 files changed, 1156 insertions(+) create mode 100644 src/Controller/RolesController.php create mode 100644 src/Controller/StateUserRolesController.php create mode 100644 src/Model/Entity/Role.php create mode 100644 src/Model/Entity/StateUserRole.php create mode 100644 src/Model/Table/RolesTable.php create mode 100644 src/Model/Table/StateUserRolesTable.php create mode 100644 src/Template/Roles/add.ctp create mode 100644 src/Template/Roles/edit.ctp create mode 100644 src/Template/Roles/index.ctp create mode 100644 src/Template/Roles/view.ctp create mode 100644 src/Template/StateUserRoles/assign_role.ctp create mode 100644 src/Template/StateUserRoles/index.ctp create mode 100644 src/Template/StateUserRoles/search.ctp create mode 100644 tests/Fixture/RolesFixture.php create mode 100644 tests/TestCase/Controller/RolesControllerTest.php create mode 100644 tests/TestCase/Model/Table/RolesTableTest.php diff --git a/src/Controller/RolesController.php b/src/Controller/RolesController.php new file mode 100644 index 000000000..80aa493d3 --- /dev/null +++ b/src/Controller/RolesController.php @@ -0,0 +1,108 @@ +paginate($this->Roles); + + $this->set(compact('roles')); + } + + /** + * View method + * + * @param string|null $id Role id. + * @return \Cake\Http\Response|null + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function view($id = null) + { + $role = $this->Roles->get($id, [ + 'contain' => [], + ]); + + $this->set('role', $role); + } + + /** + * Add method + * + * @return \Cake\Http\Response|null Redirects on successful add, renders view otherwise. + */ + public function add() + { + $role = $this->Roles->newEntity(); + if ($this->request->is('post')) { + $role = $this->Roles->patchEntity($role, $this->request->getData()); + if ($this->Roles->save($role)) { + $this->Flash->success(__('The role has been saved.')); + + return $this->redirect(['action' => 'index']); + } + $this->Flash->error(__('The role could not be saved. Please, try again.')); + } + $this->set(compact('role')); + } + + /** + * Edit method + * + * @param string|null $id Role id. + * @return \Cake\Http\Response|null Redirects on successful edit, renders view otherwise. + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function edit($id = null) + { + $role = $this->Roles->get($id, [ + 'contain' => [], + ]); + if ($this->request->is(['patch', 'post', 'put'])) { + $role = $this->Roles->patchEntity($role, $this->request->getData()); + if ($this->Roles->save($role)) { + $this->Flash->success(__('The role has been saved.')); + + return $this->redirect(['action' => 'index']); + } + $this->Flash->error(__('The role could not be saved. Please, try again.')); + } + $this->set(compact('role')); + } + + /** + * Delete method + * + * @param string|null $id Role id. + * @return \Cake\Http\Response|null Redirects to index. + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function delete($id = null) + { + $this->request->allowMethod(['post', 'delete']); + $role = $this->Roles->get($id); + if ($this->Roles->delete($role)) { + $this->Flash->success(__('The role has been deleted.')); + } else { + $this->Flash->error(__('The role could not be deleted. Please, try again.')); + } + + return $this->redirect(['action' => 'index']); + } +} diff --git a/src/Controller/StateUserRolesController.php b/src/Controller/StateUserRolesController.php new file mode 100644 index 000000000..b61d6b82b --- /dev/null +++ b/src/Controller/StateUserRolesController.php @@ -0,0 +1,307 @@ +loadComponent('JsonRequestClient'); + $this->Auth->allow([ + 'search' + ]); + $this->set( + 'naviHierarchy', + (new NaviHierarchy())-> + add(new NaviHierarchyEntry(__('Startseite'), 'Dashboard', 'index', false))->add(new NaviHierarchyEntry(__('Benutzer suchen'), 'StateUsers', 'search', true)) + ); + } + + public function search() + { + $this->loadModel('StateUsers'); + $startTime = microtime(true); + I18n::setLocale('de_DE'); + $this->viewBuilder()->setLayout('frontend'); + $session = $this->getRequest()->getSession(); + $result = $this->requestLogin(); + if ($result !== true) { + return $result; + } + $user = $session->read('StateUser'); + if ($user['role'] != 'admin') { + return $this->redirect(['controller' => 'dashboard', 'action' => 'index']); + } + + $searchForm = new UserSearchForm(); + + $timeUsed = microtime(true) - $startTime; + //$this->set('timeUsed', $timeUsed); + $csfr_token = $this->request->getParam('_csrfToken'); + $this->set(compact('timeUsed', 'searchForm', 'csfr_token')); + + if ($this->request->is('post')) { + $requestData = $this->request->getData(); + + if ($searchForm->validate($requestData)) { + //var_dump($requestData); + $searchString = $requestData['search']; + $searchType = 'unknown'; + if (GenericValidation::email($searchString, [])) { + $searchType = 'email'; + } + // find users on login server + $resultJson = $this->JsonRequestClient->getUsers($session->read('session_id'), $searchString); + $loginServerUser = []; + if ($resultJson['state'] == 'success') { + $dataJson = $resultJson['data']; + if ($dataJson['state'] != 'success') { + if ($dataJson['msg'] == 'session not found') { + $session->destroy(); + return $this->redirect(Router::url('/', true) . 'account', 303); + } + } + //var_dump($dataJson); + if (isset($dataJson['users'])) { + $loginServerUser = $dataJson['users']; + } + } + $pubkeySorted = []; + $emptyPubkeys = []; + foreach ($loginServerUser as $u) { + if (!isset($u['public_hex']) || $u['public_hex'] == '') { + array_push($emptyPubkeys, $u); + } else { + if (!isset($pubkeySorted[$u['public_hex']])) { + $pubkeySorted[$u['public_hex']] = ['login' => [], 'community' => []]; + } + array_push($pubkeySorted[$u['public_hex']]['login'], $u); + } + } + // find user on community server db + $globalSearch = '%' . $searchString . '%'; + $communityUsers = $this->StateUsers + ->find('all') + ->contain(['StateBalances' => ['fields' => ['amount', 'state_user_id']]]); + + $communityUsers->where(['OR' => [ + 'first_name LIKE' => $globalSearch, + 'last_name LIKE' => $globalSearch, + //'username LIKE' => $globalSearch, + 'email LIKE' => $globalSearch + ]]); + + //var_dump($communityUsers->toArray()); + foreach ($communityUsers as $u) { + $pubkey_hex = bin2hex(stream_get_contents($u->public_key)); + $u->public_hex = $pubkey_hex; + if (!isset($pubkeySorted[$pubkey_hex])) { + $pubkeySorted[$pubkey_hex] = ['login' => [], 'community' => []]; + } + array_push($pubkeySorted[$pubkey_hex]['community'], $u); + } + $finalUserEntrys = []; + // detect states + foreach ($pubkeySorted as $pubhex => $user) { + $finalUser = []; + $state = 'account created'; + $color = 'secondary'; + $finalUser['balance'] = 0; + $finalUser['pubkeyhex'] = $pubhex; + $finalUser['created'] = null; + + if (count($user['community']) == 1) { + if (isset($user['community'][0]->state_balances) && + isset($user['community'][0]->state_balances[0]['amount'])) { + $finalUser['balance'] = $user['community'][0]->state_balances[0]->amount; + } + } + + if (count($user['login']) == 0) { + $state = 'account not on login-server'; + $color = 'danger'; + if (count($user['community']) == 1) { + $c_user = $user['community'][0]; + $finalUser['name'] = $c_user->first_name . ' ' . $c_user->last_name; + $finalUser['first_name'] = $c_user->first_name; + $finalUser['last_name'] = $c_user->last_name; + //$finalUser['username'] = $c_user->username; + $finalUser['email'] = $c_user->email; + } + } elseif (count($user['login']) == 1) { + if ($user['login'][0]['email_checked'] == true) { + $state = 'email activated'; + $color = 'primary'; + + if (count($user['community']) == 1) { + $state = 'account copied to community'; + $color = 'success'; + //var_dump($user['community'][0]->state_balances[0]['amount']); + } + } else { + $state = 'email not activated'; + $color = 'warning'; + } + + $l_user = $user['login'][0]; + $finalUser['name'] = $l_user['first_name'] . ' ' . $l_user['last_name']; + $finalUser['first_name'] = $l_user['first_name']; + $finalUser['last_name'] = $l_user['last_name']; + //$finalUser['username'] = $l_user['username']; + $finalUser['email'] = $l_user['email']; + $finalUser['created'] = new FrozenTime($l_user['created']); + } else { + $state = 'account multiple times on login-server'; + $color = 'danger'; + } + + $this->loadModel('Roles'); + $state_user_id = $user['community'][0]->id; + $stateUserRole = $this->StateUserRoles->find('all')->where(['state_user_id' => $state_user_id])->all(); + + $role_ids = ""; + foreach ($stateUserRole as $userRole) { + if($role_ids != "") + $role_ids .= ",".$userRole->role_id; + else + $role_ids = $userRole->role_id; + } + + $roles = $this->Roles->find('all')->where(['id IN' => explode(",",$role_ids)])->all(); + + $role_names = ""; + foreach($roles as $role) + { + if($role_names != "") + $role_names .= "
".$role->title; + else + $role_names = $role->title; + } + + $finalUser['role_name'] = $role_names; + + $finalUser['indicator'] = ['name' => $state, 'color' => $color]; + array_push($finalUserEntrys, $finalUser); + } + + foreach ($emptyPubkeys as $user) { + $finalUser = []; + $state = 'account not on community server'; + $color = 'secondary'; + if ($user['email_checked'] == false) { + $state = 'email not activated'; + $color = 'warning'; + } else { + $state = 'no keys'; + $color = 'warning'; + } + $finalUser['balance'] = 0; + $finalUser['pubkeyhex'] = ''; + $finalUser['name'] = $user['first_name'] . ' ' . $user['last_name']; + $finalUser['first_name'] = $user['first_name']; + $finalUser['last_name'] = $user['last_name']; + //$finalUser['username'] = $user['username']; + $finalUser['email'] = $user['email']; + + + $finalUser['created'] = new FrozenTime($user['created']); + $finalUser['indicator'] = ['name' => $state, 'color' => $color]; + array_push($finalUserEntrys, $finalUser); + } + //var_dump($pubkeySorted); + } else { + $this->Flash->error(__('Something was invalid, please try again!')); + } + $this->set('finalUserEntrys', $finalUserEntrys); + } + $timeUsed = microtime(true) - $startTime; + $this->set('timeUsed', $timeUsed); + } + + public function assignRole() + { + $this->loadModel('Roles'); + $this->loadModel('StateUsers'); + + if ($this->request->is('post')) { + $requestData = $this->request->getData(); + + $public_hex = hex2bin($requestData['public_hex']); + + $stateUser = $this->StateUsers->find('all')->where(['public_key' => $public_hex])->first(); + + foreach($requestData['role_id'] as $role_id) + { + $newStateUserRole = $this->StateUserRoles->newEntity(); + + $post_data = []; + $post_data['state_user_id'] = $stateUser->id; + $post_data['role_id'] = $role_id; + $this->StateUserRoles->patchEntity($newStateUserRole, $post_data); + $this->StateUserRoles->save($newStateUserRole); + + } + + $this->Flash->success(__('Role has been assigned to User.')); + + return $this->redirect(['controller' => 'state-user-roles', 'action' => 'search']); + + } + + $assignRoleForm = new AssignRoleForm(); + + $public_hex = $this->request->getParam('pass')[0]; + + $publichex = hex2bin($public_hex); + + $stateUser = $this->StateUsers->find('all')->where(['public_key' => $publichex])->first(); + + $stateUserRoles = $this->StateUserRoles->find('all')->where(['state_user_id' => $stateUser->id])->all(); + + $role_ids = ""; + foreach ($stateUserRoles as $userRole) { + if($role_ids != "") + $role_ids .= ",".$userRole->role_id; + else + $role_ids = $userRole->role_id; + } + + $role_ids = explode(",", $role_ids); + + $roles = $this->Roles->find('list', array('fields' => array('id', 'title'))); + + + $this->set('roles', $roles); + $this->set('stateUser', $stateUser); + $this->set('role_ids', $role_ids); + $this->set('assignRoleForm', $assignRoleForm); + $this->set('public_hex', $public_hex); + } + +} diff --git a/src/Model/Entity/Role.php b/src/Model/Entity/Role.php new file mode 100644 index 000000000..ae0ddd0ba --- /dev/null +++ b/src/Model/Entity/Role.php @@ -0,0 +1,26 @@ + true, + ]; +} diff --git a/src/Model/Entity/StateUserRole.php b/src/Model/Entity/StateUserRole.php new file mode 100644 index 000000000..d510bb025 --- /dev/null +++ b/src/Model/Entity/StateUserRole.php @@ -0,0 +1,30 @@ + true, + 'role_id' => true + ]; +} diff --git a/src/Model/Table/RolesTable.php b/src/Model/Table/RolesTable.php new file mode 100644 index 000000000..940b7f246 --- /dev/null +++ b/src/Model/Table/RolesTable.php @@ -0,0 +1,72 @@ +setTable('roles'); + $this->setDisplayField('title'); + $this->setPrimaryKey('id'); + } + + /** + * Default validation rules. + * + * @param \Cake\Validation\Validator $validator Validator instance. + * @return \Cake\Validation\Validator + */ + public function validationDefault(Validator $validator) + { + $validator + ->integer('id') + ->allowEmptyString('id', null, 'create') + ->add('id', 'unique', ['rule' => 'validateUnique', 'provider' => 'table']); + + $validator + ->scalar('title') + ->maxLength('title', 255) + ->allowEmptyString('title'); + + return $validator; + } + + /** + * Returns a rules checker object that will be used for validating + * application integrity. + * + * @param \Cake\ORM\RulesChecker $rules The rules object to be modified. + * @return \Cake\ORM\RulesChecker + */ + public function buildRules(RulesChecker $rules) + { + $rules->add($rules->isUnique(['id'])); + + return $rules; + } +} diff --git a/src/Model/Table/StateUserRolesTable.php b/src/Model/Table/StateUserRolesTable.php new file mode 100644 index 000000000..895e788b2 --- /dev/null +++ b/src/Model/Table/StateUserRolesTable.php @@ -0,0 +1,86 @@ +setTable('state_user_roles'); + $this->setPrimaryKey('id'); + + + $this->belongsTo('StateUser', [ + 'foreignKey' => 'state_user_id', + 'joinType' => 'INNER' + ]); + + $this->belongsTo('Role', [ + 'foreignKey' => 'role_id', + 'joinType' => 'INNER' + ]); + + + } + + /** + * Default validation rules. + * + * @param \Cake\Validation\Validator $validator Validator instance. + * @return \Cake\Validation\Validator + */ + public function validationDefault(Validator $validator) + { + $validator + ->integer('id') + ->allowEmptyString('id', null, 'create'); + + + + return $validator; + } + + /** + * Returns a rules checker object that will be used for validating + * application integrity. + * + * @param \Cake\ORM\RulesChecker $rules The rules object to be modified. + * @return \Cake\ORM\RulesChecker + */ + public function buildRules(RulesChecker $rules) + { + // $rules->add($rules->existsIn(['index_id'], 'Indices')); + //$rules->add($rules->existsIn(['state_group_id'], 'StateGroups')); + + return $rules; + } + + +} diff --git a/src/Template/Roles/add.ctp b/src/Template/Roles/add.ctp new file mode 100644 index 000000000..c671ed011 --- /dev/null +++ b/src/Template/Roles/add.ctp @@ -0,0 +1,23 @@ + + +
+ Form->create($role) ?> +
+ + Form->control('title'); + ?> +
+ Form->button(__('Submit')) ?> + Form->end() ?> +
diff --git a/src/Template/Roles/edit.ctp b/src/Template/Roles/edit.ctp new file mode 100644 index 000000000..8a7cd385f --- /dev/null +++ b/src/Template/Roles/edit.ctp @@ -0,0 +1,29 @@ + + +
+ Form->create($role) ?> +
+ + Form->control('title'); + ?> +
+ Form->button(__('Submit')) ?> + Form->end() ?> +
diff --git a/src/Template/Roles/index.ctp b/src/Template/Roles/index.ctp new file mode 100644 index 000000000..2637ef958 --- /dev/null +++ b/src/Template/Roles/index.ctp @@ -0,0 +1,47 @@ + + +
+

+ + + + + + + + + + + + + + + + + +
Paginator->sort('id') ?>Paginator->sort('title') ?>
Number->format($role->id) ?>title) ?> + Html->link(__('View'), ['action' => 'view', $role->id]) ?> + Html->link(__('Edit'), ['action' => 'edit', $role->id]) ?> + Form->postLink(__('Delete'), ['action' => 'delete', $role->id], ['confirm' => __('Are you sure you want to delete # {0}?', $role->id)]) ?> +
+
+ +

Paginator->counter(['format' => __('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')]) ?>

+
+
diff --git a/src/Template/Roles/view.ctp b/src/Template/Roles/view.ctp new file mode 100644 index 000000000..04e1dcec5 --- /dev/null +++ b/src/Template/Roles/view.ctp @@ -0,0 +1,28 @@ + + +
+

title) ?>

+ + + + + + + + + +
title) ?>
Number->format($role->id) ?>
+
diff --git a/src/Template/StateUserRoles/assign_role.ctp b/src/Template/StateUserRoles/assign_role.ctp new file mode 100644 index 000000000..64d3a1f8b --- /dev/null +++ b/src/Template/StateUserRoles/assign_role.ctp @@ -0,0 +1,49 @@ +assign('title', __('Assign Role')); +// In a View class +$this->loadHelper('Form', [ + 'templates' => 'horizontal_form', +]); +?> +Html->css([ + 'loginServer/style.css', + 'rippleUI/style.css', + 'materialdesignicons.min.css' +]) ?> + +
+

Assign Role

+
+ Form->create($assignRoleForm, []) ?> +
User:  first_name." ".$stateUser->last_name ?>
+
Select Role:
Form->select('role_id', $roles, ['label' => __('Role'), 'class' => 'form-control', 'id' => 'inlineFormInputGroup', 'placeholder' => __('Role'), "multiple" => "multiple", "value" => $role_ids]) ?>
+ Form->button(' ' . __('Assign Role'), ['class' => 'form-button']) ?> + Form->hidden('public_hex', ['id' => 'input-order-row', 'value' => $public_hex]) ?> +
+
diff --git a/src/Template/StateUserRoles/index.ctp b/src/Template/StateUserRoles/index.ctp new file mode 100644 index 000000000..4e6ea8cb1 --- /dev/null +++ b/src/Template/StateUserRoles/index.ctp @@ -0,0 +1,69 @@ + + +
+

+ + + + + + + + + + + + + + + + + + + + + + +
Paginator->sort('id') ?>Paginator->sort('first_name') ?> + Paginator->sort('last_name') ?> + Paginator->sort('username') ?> + Paginator->sort('email') ?> + Paginator->sort('disabled') ?> +
Number->format($stateUser->id) ?>first_name ?>last_name ?>username ?>email ?>disabled ?> + Html->link(__('View'), ['action' => 'view', $stateUser->id]) ?> + Html->link(__('Edit'), ['action' => 'edit', $stateUser->id]) ?> + Form->postLink(__('Delete'), ['action' => 'delete', $stateUser->id], ['confirm' => __('Are you sure you want to delete # {0}?', $stateUser->id)]) ?> +
+
+ +

Paginator->counter(['format' => __('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')]) ?>

+
+
diff --git a/src/Template/StateUserRoles/search.ctp b/src/Template/StateUserRoles/search.ctp new file mode 100644 index 000000000..c1234d245 --- /dev/null +++ b/src/Template/StateUserRoles/search.ctp @@ -0,0 +1,80 @@ +assign('title', __('Benutzer suchen')); +// In a View class +$this->loadHelper('Form', [ + 'templates' => 'horizontal_form', +]); +?> +Html->css([ + 'loginServer/style.css', + 'rippleUI/style.css', + 'materialdesignicons.min.css' +]) ?> + +
+

Benutzer suchen

+
+ Form->create($searchForm, []) ?> + Form->control('search', ['label' => __('Suchbegriff'), 'class' => 'form-control', 'id' => 'inlineFormInputGroup', 'placeholder' => __('Vorname/Nachname/E-Mail')]) ?> + Form->button('search ' . __('Suchen'), ['class' => 'form-button']) ?> + Form->hidden('order_row', ['id' => 'input-order-row']) ?> +
+
+
+

+ + + + + + + + + + + + + + + + + + + + + +
Paginator->sort('first_name') ?>Paginator->sort('last_name') ?>Paginator->sort('email') ?>
+ Html->link(__('Assign Role'), ['action' => 'assignRole', $stateUser['pubkeyhex']]) ?> +
+
+ + diff --git a/tests/Fixture/RolesFixture.php b/tests/Fixture/RolesFixture.php new file mode 100644 index 000000000..db2c7640f --- /dev/null +++ b/tests/Fixture/RolesFixture.php @@ -0,0 +1,45 @@ + ['type' => 'integer', 'length' => 11, 'unsigned' => false, 'null' => false, 'default' => null, 'comment' => '', 'autoIncrement' => true, 'precision' => null], + 'title' => ['type' => 'string', 'length' => 255, 'null' => true, 'default' => null, 'collate' => 'utf8mb4_unicode_ci', 'comment' => '', 'precision' => null, 'fixed' => null], + '_constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['id'], 'length' => []], + 'roles_id_IDX' => ['type' => 'unique', 'columns' => ['id'], 'length' => []], + ], + '_options' => [ + 'engine' => 'InnoDB', + 'collation' => 'utf8mb4_unicode_ci' + ], + ]; + // @codingStandardsIgnoreEnd + /** + * Init method + * + * @return void + */ + public function init() + { + $this->records = [ + [ + 'id' => 1, + 'title' => 'Lorem ipsum dolor sit amet', + ], + ]; + parent::init(); + } +} diff --git a/tests/TestCase/Controller/RolesControllerTest.php b/tests/TestCase/Controller/RolesControllerTest.php new file mode 100644 index 000000000..12b2868a2 --- /dev/null +++ b/tests/TestCase/Controller/RolesControllerTest.php @@ -0,0 +1,75 @@ +markTestIncomplete('Not implemented yet.'); + } + + /** + * Test view method + * + * @return void + */ + public function testView() + { + $this->markTestIncomplete('Not implemented yet.'); + } + + /** + * Test add method + * + * @return void + */ + public function testAdd() + { + $this->markTestIncomplete('Not implemented yet.'); + } + + /** + * Test edit method + * + * @return void + */ + public function testEdit() + { + $this->markTestIncomplete('Not implemented yet.'); + } + + /** + * Test delete method + * + * @return void + */ + public function testDelete() + { + $this->markTestIncomplete('Not implemented yet.'); + } +} diff --git a/tests/TestCase/Model/Table/RolesTableTest.php b/tests/TestCase/Model/Table/RolesTableTest.php new file mode 100644 index 000000000..b40a0ca9b --- /dev/null +++ b/tests/TestCase/Model/Table/RolesTableTest.php @@ -0,0 +1,82 @@ +exists('Roles') ? [] : ['className' => RolesTable::class]; + $this->Roles = TableRegistry::getTableLocator()->get('Roles', $config); + } + + /** + * tearDown method + * + * @return void + */ + public function tearDown() + { + unset($this->Roles); + + parent::tearDown(); + } + + /** + * Test initialize method + * + * @return void + */ + public function testInitialize() + { + $this->markTestIncomplete('Not implemented yet.'); + } + + /** + * Test validationDefault method + * + * @return void + */ + public function testValidationDefault() + { + $this->markTestIncomplete('Not implemented yet.'); + } + + /** + * Test buildRules method + * + * @return void + */ + public function testBuildRules() + { + $this->markTestIncomplete('Not implemented yet.'); + } +} From b9b724ad07aac2dd0194346651ca68c28d37d07c Mon Sep 17 00:00:00 2001 From: team-devstage Date: Fri, 25 Sep 2020 15:01:33 +0200 Subject: [PATCH 064/293] cleanup samirs code, remove not needed stuff from my old code -Dario --- src/Controller/StateUserRolesController.php | 142 ++------------------ src/Template/StateUserRoles/search.ctp | 27 ---- 2 files changed, 10 insertions(+), 159 deletions(-) diff --git a/src/Controller/StateUserRolesController.php b/src/Controller/StateUserRolesController.php index b61d6b82b..9f83dc0bc 100644 --- a/src/Controller/StateUserRolesController.php +++ b/src/Controller/StateUserRolesController.php @@ -34,7 +34,7 @@ class StateUserRolesController extends AppController parent::initialize(); $this->loadComponent('JsonRequestClient'); $this->Auth->allow([ - 'search' +// 'search' ]); $this->set( 'naviHierarchy', @@ -49,22 +49,12 @@ class StateUserRolesController extends AppController $startTime = microtime(true); I18n::setLocale('de_DE'); $this->viewBuilder()->setLayout('frontend'); - $session = $this->getRequest()->getSession(); - $result = $this->requestLogin(); - if ($result !== true) { - return $result; - } - $user = $session->read('StateUser'); - if ($user['role'] != 'admin') { - return $this->redirect(['controller' => 'dashboard', 'action' => 'index']); - } $searchForm = new UserSearchForm(); $timeUsed = microtime(true) - $startTime; //$this->set('timeUsed', $timeUsed); - $csfr_token = $this->request->getParam('_csrfToken'); - $this->set(compact('timeUsed', 'searchForm', 'csfr_token')); + $this->set(compact('timeUsed', 'searchForm')); if ($this->request->is('post')) { $requestData = $this->request->getData(); @@ -72,43 +62,12 @@ class StateUserRolesController extends AppController if ($searchForm->validate($requestData)) { //var_dump($requestData); $searchString = $requestData['search']; - $searchType = 'unknown'; - if (GenericValidation::email($searchString, [])) { - $searchType = 'email'; - } - // find users on login server - $resultJson = $this->JsonRequestClient->getUsers($session->read('session_id'), $searchString); - $loginServerUser = []; - if ($resultJson['state'] == 'success') { - $dataJson = $resultJson['data']; - if ($dataJson['state'] != 'success') { - if ($dataJson['msg'] == 'session not found') { - $session->destroy(); - return $this->redirect(Router::url('/', true) . 'account', 303); - } - } - //var_dump($dataJson); - if (isset($dataJson['users'])) { - $loginServerUser = $dataJson['users']; - } - } - $pubkeySorted = []; - $emptyPubkeys = []; - foreach ($loginServerUser as $u) { - if (!isset($u['public_hex']) || $u['public_hex'] == '') { - array_push($emptyPubkeys, $u); - } else { - if (!isset($pubkeySorted[$u['public_hex']])) { - $pubkeySorted[$u['public_hex']] = ['login' => [], 'community' => []]; - } - array_push($pubkeySorted[$u['public_hex']]['login'], $u); - } - } + // find user on community server db $globalSearch = '%' . $searchString . '%'; $communityUsers = $this->StateUsers ->find('all') - ->contain(['StateBalances' => ['fields' => ['amount', 'state_user_id']]]); + ->contain([]); $communityUsers->where(['OR' => [ 'first_name LIKE' => $globalSearch, @@ -118,71 +77,15 @@ class StateUserRolesController extends AppController ]]); //var_dump($communityUsers->toArray()); - foreach ($communityUsers as $u) { - $pubkey_hex = bin2hex(stream_get_contents($u->public_key)); - $u->public_hex = $pubkey_hex; - if (!isset($pubkeySorted[$pubkey_hex])) { - $pubkeySorted[$pubkey_hex] = ['login' => [], 'community' => []]; - } - array_push($pubkeySorted[$pubkey_hex]['community'], $u); - } $finalUserEntrys = []; // detect states - foreach ($pubkeySorted as $pubhex => $user) { - $finalUser = []; - $state = 'account created'; - $color = 'secondary'; - $finalUser['balance'] = 0; - $finalUser['pubkeyhex'] = $pubhex; - $finalUser['created'] = null; - - if (count($user['community']) == 1) { - if (isset($user['community'][0]->state_balances) && - isset($user['community'][0]->state_balances[0]['amount'])) { - $finalUser['balance'] = $user['community'][0]->state_balances[0]->amount; - } - } - - if (count($user['login']) == 0) { - $state = 'account not on login-server'; - $color = 'danger'; - if (count($user['community']) == 1) { - $c_user = $user['community'][0]; - $finalUser['name'] = $c_user->first_name . ' ' . $c_user->last_name; - $finalUser['first_name'] = $c_user->first_name; - $finalUser['last_name'] = $c_user->last_name; - //$finalUser['username'] = $c_user->username; - $finalUser['email'] = $c_user->email; - } - } elseif (count($user['login']) == 1) { - if ($user['login'][0]['email_checked'] == true) { - $state = 'email activated'; - $color = 'primary'; - - if (count($user['community']) == 1) { - $state = 'account copied to community'; - $color = 'success'; - //var_dump($user['community'][0]->state_balances[0]['amount']); - } - } else { - $state = 'email not activated'; - $color = 'warning'; - } - - $l_user = $user['login'][0]; - $finalUser['name'] = $l_user['first_name'] . ' ' . $l_user['last_name']; - $finalUser['first_name'] = $l_user['first_name']; - $finalUser['last_name'] = $l_user['last_name']; - //$finalUser['username'] = $l_user['username']; - $finalUser['email'] = $l_user['email']; - $finalUser['created'] = new FrozenTime($l_user['created']); - } else { - $state = 'account multiple times on login-server'; - $color = 'danger'; - } + $this->loadModel('Roles'); +// foreach ($pubkeySorted as $pubhex => $user) { + foreach($communityUsers as $communityUser) { + $finalUser = $communityUser; + $finalUser['pubkeyhex'] = bin2hex(stream_get_contents($communityUser->public_key)); - $this->loadModel('Roles'); - $state_user_id = $user['community'][0]->id; + $state_user_id = $communityUser->id; $stateUserRole = $this->StateUserRoles->find('all')->where(['state_user_id' => $state_user_id])->all(); $role_ids = ""; @@ -206,34 +109,9 @@ class StateUserRolesController extends AppController $finalUser['role_name'] = $role_names; - $finalUser['indicator'] = ['name' => $state, 'color' => $color]; array_push($finalUserEntrys, $finalUser); } - foreach ($emptyPubkeys as $user) { - $finalUser = []; - $state = 'account not on community server'; - $color = 'secondary'; - if ($user['email_checked'] == false) { - $state = 'email not activated'; - $color = 'warning'; - } else { - $state = 'no keys'; - $color = 'warning'; - } - $finalUser['balance'] = 0; - $finalUser['pubkeyhex'] = ''; - $finalUser['name'] = $user['first_name'] . ' ' . $user['last_name']; - $finalUser['first_name'] = $user['first_name']; - $finalUser['last_name'] = $user['last_name']; - //$finalUser['username'] = $user['username']; - $finalUser['email'] = $user['email']; - - - $finalUser['created'] = new FrozenTime($user['created']); - $finalUser['indicator'] = ['name' => $state, 'color' => $color]; - array_push($finalUserEntrys, $finalUser); - } //var_dump($pubkeySorted); } else { $this->Flash->error(__('Something was invalid, please try again!')); diff --git a/src/Template/StateUserRoles/search.ctp b/src/Template/StateUserRoles/search.ctp index c1234d245..aff7fbbcb 100644 --- a/src/Template/StateUserRoles/search.ctp +++ b/src/Template/StateUserRoles/search.ctp @@ -12,31 +12,6 @@ $this->loadHelper('Form', [ 'templates' => 'horizontal_form', ]); ?> -Html->css([ - 'loginServer/style.css', - 'rippleUI/style.css', - 'materialdesignicons.min.css' -]) ?> -

Benutzer suchen

@@ -76,5 +51,3 @@ $this->loadHelper('Form', [
- - From 7e23b36cbc6959289161ae733723db644206cefe Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 25 Sep 2020 13:56:16 +0000 Subject: [PATCH 065/293] add new gradido proto files and update parse proto script --- parse_proto.sh | 2 +- src/Controller/StateUserRolesController.php | 4 +- .../Proto/Gradido/CrossGroupTransfer.php | 146 +++++++++++++ .../Proto/Gradido/GradidoCreation.php | 102 +++++++++ .../Proto/Gradido/GradidoTransaction.php | 116 +++++++++++ .../Proto/Gradido/GradidoTransfer.php | 109 ++++++++++ .../Proto/Gradido/GroupFriendsUpdate.php | 92 +++++++++ .../Gradido/GroupFriendsUpdate/Action.php | 51 +++++ .../Gradido/GroupFriendsUpdate_Action.php | 16 ++ .../Proto/Gradido/GroupMemberUpdate.php | 146 +++++++++++++ .../GroupMemberUpdate/MemberUpdateType.php | 56 +++++ .../GroupMemberUpdate_MemberUpdateType.php | 16 ++ src/Model/Messages/Proto/Gradido/Key.php | 96 +++++++++ .../Messages/Proto/Gradido/LocalTransfer.php | 85 ++++++++ .../Messages/Proto/Gradido/SignatureMap.php | 65 ++++++ .../Messages/Proto/Gradido/SignaturePair.php | 123 +++++++++++ .../Messages/Proto/Gradido/Timestamp.php | 101 +++++++++ .../Proto/Gradido/TimestampSeconds.php | 67 ++++++ .../Proto/Gradido/TransactionBody.php | 193 ++++++++++++++++++ .../Messages/Proto/Gradido/TransferAmount.php | 85 ++++++++ 20 files changed, 1668 insertions(+), 3 deletions(-) create mode 100644 src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php create mode 100644 src/Model/Messages/Proto/Gradido/GradidoCreation.php create mode 100644 src/Model/Messages/Proto/Gradido/GradidoTransaction.php create mode 100644 src/Model/Messages/Proto/Gradido/GradidoTransfer.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupMemberUpdate.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php create mode 100644 src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php create mode 100644 src/Model/Messages/Proto/Gradido/Key.php create mode 100644 src/Model/Messages/Proto/Gradido/LocalTransfer.php create mode 100644 src/Model/Messages/Proto/Gradido/SignatureMap.php create mode 100644 src/Model/Messages/Proto/Gradido/SignaturePair.php create mode 100644 src/Model/Messages/Proto/Gradido/Timestamp.php create mode 100644 src/Model/Messages/Proto/Gradido/TimestampSeconds.php create mode 100644 src/Model/Messages/Proto/Gradido/TransactionBody.php create mode 100644 src/Model/Messages/Proto/Gradido/TransferAmount.php diff --git a/parse_proto.sh b/parse_proto.sh index 576b99691..e6ccb451f 100755 --- a/parse_proto.sh +++ b/parse_proto.sh @@ -16,5 +16,5 @@ #PHP_PLUGIN="$(which grpc_php_plugin)" #protoc --proto_path=./src/protobuf/gradido --php_out=./src/ --grpc_out=./src/ --plugin=protoc-gen-grpc=$PHP_PLUGIN ./src/protobuf/gradido/*.proto -protoc --proto_path=./src/protobuf/gradido --php_out=./src/ ./src/protobuf/gradido/*.proto +protoc --proto_path=./src/protobuf --php_out=./src/Model/Messages ./src/protobuf/gradido/*.proto diff --git a/src/Controller/StateUserRolesController.php b/src/Controller/StateUserRolesController.php index 9f83dc0bc..9238c7ad6 100644 --- a/src/Controller/StateUserRolesController.php +++ b/src/Controller/StateUserRolesController.php @@ -81,9 +81,9 @@ class StateUserRolesController extends AppController // detect states $this->loadModel('Roles'); // foreach ($pubkeySorted as $pubhex => $user) { - foreach($communityUsers as $communityUser) { + foreach($communityUsers as $communityUser) { $finalUser = $communityUser; - $finalUser['pubkeyhex'] = bin2hex(stream_get_contents($communityUser->public_key)); + $finalUser['pubkeyhex'] = bin2hex(stream_get_contents($communityUser->public_key)); $state_user_id = $communityUser->id; $stateUserRole = $this->StateUserRoles->find('all')->where(['state_user_id' => $state_user_id])->all(); diff --git a/src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php b/src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php new file mode 100644 index 000000000..781ac8f25 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/CrossGroupTransfer.php @@ -0,0 +1,146 @@ +proto.gradido.CrossGroupTransfer + */ +class CrossGroupTransfer extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + */ + private $sender = null; + /** + * Generated from protobuf field bytes receiver = 2; + */ + private $receiver = ''; + /** + * Generated from protobuf field string other_group = 3; + */ + private $other_group = ''; + /** + * this matches related OutboundTransfer.paired_transaction_id + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 4; + */ + private $paired_transaction_id = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\TransferAmount $sender + * @type string $receiver + * @type string $other_group + * @type \Proto\Gradido\Timestamp $paired_transaction_id + * this matches related OutboundTransfer.paired_transaction_id + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoTransfer::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + * @return \Proto\Gradido\TransferAmount + */ + public function getSender() + { + return $this->sender; + } + + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + * @param \Proto\Gradido\TransferAmount $var + * @return $this + */ + public function setSender($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TransferAmount::class); + $this->sender = $var; + + return $this; + } + + /** + * Generated from protobuf field bytes receiver = 2; + * @return string + */ + public function getReceiver() + { + return $this->receiver; + } + + /** + * Generated from protobuf field bytes receiver = 2; + * @param string $var + * @return $this + */ + public function setReceiver($var) + { + GPBUtil::checkString($var, False); + $this->receiver = $var; + + return $this; + } + + /** + * Generated from protobuf field string other_group = 3; + * @return string + */ + public function getOtherGroup() + { + return $this->other_group; + } + + /** + * Generated from protobuf field string other_group = 3; + * @param string $var + * @return $this + */ + public function setOtherGroup($var) + { + GPBUtil::checkString($var, True); + $this->other_group = $var; + + return $this; + } + + /** + * this matches related OutboundTransfer.paired_transaction_id + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 4; + * @return \Proto\Gradido\Timestamp + */ + public function getPairedTransactionId() + { + return $this->paired_transaction_id; + } + + /** + * this matches related OutboundTransfer.paired_transaction_id + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 4; + * @param \Proto\Gradido\Timestamp $var + * @return $this + */ + public function setPairedTransactionId($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\Timestamp::class); + $this->paired_transaction_id = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GradidoCreation.php b/src/Model/Messages/Proto/Gradido/GradidoCreation.php new file mode 100644 index 000000000..9b4c3208d --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GradidoCreation.php @@ -0,0 +1,102 @@ +proto.gradido.GradidoCreation + */ +class GradidoCreation extends \Google\Protobuf\Internal\Message +{ + /** + * 40 Byte + * + * Generated from protobuf field .proto.gradido.TransferAmount receiver = 1; + */ + private $receiver = null; + /** + * 8 Byte + * + * Generated from protobuf field .proto.gradido.TimestampSeconds target_date = 3; + */ + private $target_date = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\TransferAmount $receiver + * 40 Byte + * @type \Proto\Gradido\TimestampSeconds $target_date + * 8 Byte + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoCreation::initOnce(); + parent::__construct($data); + } + + /** + * 40 Byte + * + * Generated from protobuf field .proto.gradido.TransferAmount receiver = 1; + * @return \Proto\Gradido\TransferAmount + */ + public function getReceiver() + { + return $this->receiver; + } + + /** + * 40 Byte + * + * Generated from protobuf field .proto.gradido.TransferAmount receiver = 1; + * @param \Proto\Gradido\TransferAmount $var + * @return $this + */ + public function setReceiver($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TransferAmount::class); + $this->receiver = $var; + + return $this; + } + + /** + * 8 Byte + * + * Generated from protobuf field .proto.gradido.TimestampSeconds target_date = 3; + * @return \Proto\Gradido\TimestampSeconds + */ + public function getTargetDate() + { + return $this->target_date; + } + + /** + * 8 Byte + * + * Generated from protobuf field .proto.gradido.TimestampSeconds target_date = 3; + * @param \Proto\Gradido\TimestampSeconds $var + * @return $this + */ + public function setTargetDate($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TimestampSeconds::class); + $this->target_date = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GradidoTransaction.php b/src/Model/Messages/Proto/Gradido/GradidoTransaction.php new file mode 100644 index 000000000..b4b34c77e --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GradidoTransaction.php @@ -0,0 +1,116 @@ +proto.gradido.GradidoTransaction + */ +class GradidoTransaction extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field .proto.gradido.SignatureMap sig_map = 1; + */ + private $sig_map = null; + /** + * TODO: consider if having concrete type wouldn't be better; + * having bytes would better show what is signed, still for + * blockchain it doesn't matter, as it has to be serialized again + * when validating + * UNICORN ANSWER: + * Maybe but hedera has at first concrete type and has depracted that now, so is must + * be reason for that + * + * Generated from protobuf field bytes body_bytes = 2; + */ + private $body_bytes = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\SignatureMap $sig_map + * @type string $body_bytes + * TODO: consider if having concrete type wouldn't be better; + * having bytes would better show what is signed, still for + * blockchain it doesn't matter, as it has to be serialized again + * when validating + * UNICORN ANSWER: + * Maybe but hedera has at first concrete type and has depracted that now, so is must + * be reason for that + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoTransaction::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field .proto.gradido.SignatureMap sig_map = 1; + * @return \Proto\Gradido\SignatureMap + */ + public function getSigMap() + { + return $this->sig_map; + } + + /** + * Generated from protobuf field .proto.gradido.SignatureMap sig_map = 1; + * @param \Proto\Gradido\SignatureMap $var + * @return $this + */ + public function setSigMap($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\SignatureMap::class); + $this->sig_map = $var; + + return $this; + } + + /** + * TODO: consider if having concrete type wouldn't be better; + * having bytes would better show what is signed, still for + * blockchain it doesn't matter, as it has to be serialized again + * when validating + * UNICORN ANSWER: + * Maybe but hedera has at first concrete type and has depracted that now, so is must + * be reason for that + * + * Generated from protobuf field bytes body_bytes = 2; + * @return string + */ + public function getBodyBytes() + { + return $this->body_bytes; + } + + /** + * TODO: consider if having concrete type wouldn't be better; + * having bytes would better show what is signed, still for + * blockchain it doesn't matter, as it has to be serialized again + * when validating + * UNICORN ANSWER: + * Maybe but hedera has at first concrete type and has depracted that now, so is must + * be reason for that + * + * Generated from protobuf field bytes body_bytes = 2; + * @param string $var + * @return $this + */ + public function setBodyBytes($var) + { + GPBUtil::checkString($var, False); + $this->body_bytes = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GradidoTransfer.php b/src/Model/Messages/Proto/Gradido/GradidoTransfer.php new file mode 100644 index 000000000..a76954c2e --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GradidoTransfer.php @@ -0,0 +1,109 @@ +proto.gradido.GradidoTransfer + */ +class GradidoTransfer extends \Google\Protobuf\Internal\Message +{ + protected $data; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\LocalTransfer $local + * @type \Proto\Gradido\CrossGroupTransfer $inbound + * @type \Proto\Gradido\CrossGroupTransfer $outbound + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoTransfer::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field .proto.gradido.LocalTransfer local = 1; + * @return \Proto\Gradido\LocalTransfer + */ + public function getLocal() + { + return $this->readOneof(1); + } + + /** + * Generated from protobuf field .proto.gradido.LocalTransfer local = 1; + * @param \Proto\Gradido\LocalTransfer $var + * @return $this + */ + public function setLocal($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\LocalTransfer::class); + $this->writeOneof(1, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.CrossGroupTransfer inbound = 2; + * @return \Proto\Gradido\CrossGroupTransfer + */ + public function getInbound() + { + return $this->readOneof(2); + } + + /** + * Generated from protobuf field .proto.gradido.CrossGroupTransfer inbound = 2; + * @param \Proto\Gradido\CrossGroupTransfer $var + * @return $this + */ + public function setInbound($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\CrossGroupTransfer::class); + $this->writeOneof(2, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.CrossGroupTransfer outbound = 3; + * @return \Proto\Gradido\CrossGroupTransfer + */ + public function getOutbound() + { + return $this->readOneof(3); + } + + /** + * Generated from protobuf field .proto.gradido.CrossGroupTransfer outbound = 3; + * @param \Proto\Gradido\CrossGroupTransfer $var + * @return $this + */ + public function setOutbound($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\CrossGroupTransfer::class); + $this->writeOneof(3, $var); + + return $this; + } + + /** + * @return string + */ + public function getData() + { + return $this->whichOneof("data"); + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php new file mode 100644 index 000000000..22e86d3e1 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate.php @@ -0,0 +1,92 @@ +proto.gradido.GroupFriendsUpdate + */ +class GroupFriendsUpdate extends \Google\Protobuf\Internal\Message +{ + /** + * char[16], alias + * + * Generated from protobuf field string group = 1; + */ + private $group = ''; + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate.Action action = 2; + */ + private $action = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $group + * char[16], alias + * @type int $action + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GroupFriendsUpdate::initOnce(); + parent::__construct($data); + } + + /** + * char[16], alias + * + * Generated from protobuf field string group = 1; + * @return string + */ + public function getGroup() + { + return $this->group; + } + + /** + * char[16], alias + * + * Generated from protobuf field string group = 1; + * @param string $var + * @return $this + */ + public function setGroup($var) + { + GPBUtil::checkString($var, True); + $this->group = $var; + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate.Action action = 2; + * @return int + */ + public function getAction() + { + return $this->action; + } + + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate.Action action = 2; + * @param int $var + * @return $this + */ + public function setAction($var) + { + GPBUtil::checkEnum($var, \Proto\Gradido\GroupFriendsUpdate_Action::class); + $this->action = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php new file mode 100644 index 000000000..2a3396c55 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate/Action.php @@ -0,0 +1,51 @@ +proto.gradido.GroupFriendsUpdate.Action + */ +class Action +{ + /** + * Generated from protobuf enum ADD_FRIEND = 0; + */ + const ADD_FRIEND = 0; + /** + * Generated from protobuf enum REMOVE_FRIEND = 1; + */ + const REMOVE_FRIEND = 1; + + private static $valueToName = [ + self::ADD_FRIEND => 'ADD_FRIEND', + self::REMOVE_FRIEND => 'REMOVE_FRIEND', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(Action::class, \Proto\Gradido\GroupFriendsUpdate_Action::class); + diff --git a/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php new file mode 100644 index 000000000..24f8cef70 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GroupFriendsUpdate_Action.php @@ -0,0 +1,16 @@ +proto.gradido.GroupMemberUpdate + */ +class GroupMemberUpdate extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field bytes user_pubkey = 1; + */ + private $user_pubkey = ''; + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2; + */ + private $member_update_type = 0; + /** + * this only makes sense for user move, TODO: probably restructure + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 3; + */ + private $paired_transaction_id = null; + /** + * Generated from protobuf field string target_group = 4; + */ + private $target_group = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $user_pubkey + * @type int $member_update_type + * @type \Proto\Gradido\Timestamp $paired_transaction_id + * this only makes sense for user move, TODO: probably restructure + * @type string $target_group + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GroupMemberUpdate::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field bytes user_pubkey = 1; + * @return string + */ + public function getUserPubkey() + { + return $this->user_pubkey; + } + + /** + * Generated from protobuf field bytes user_pubkey = 1; + * @param string $var + * @return $this + */ + public function setUserPubkey($var) + { + GPBUtil::checkString($var, False); + $this->user_pubkey = $var; + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2; + * @return int + */ + public function getMemberUpdateType() + { + return $this->member_update_type; + } + + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate.MemberUpdateType member_update_type = 2; + * @param int $var + * @return $this + */ + public function setMemberUpdateType($var) + { + GPBUtil::checkEnum($var, \Proto\Gradido\GroupMemberUpdate_MemberUpdateType::class); + $this->member_update_type = $var; + + return $this; + } + + /** + * this only makes sense for user move, TODO: probably restructure + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 3; + * @return \Proto\Gradido\Timestamp + */ + public function getPairedTransactionId() + { + return $this->paired_transaction_id; + } + + /** + * this only makes sense for user move, TODO: probably restructure + * + * Generated from protobuf field .proto.gradido.Timestamp paired_transaction_id = 3; + * @param \Proto\Gradido\Timestamp $var + * @return $this + */ + public function setPairedTransactionId($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\Timestamp::class); + $this->paired_transaction_id = $var; + + return $this; + } + + /** + * Generated from protobuf field string target_group = 4; + * @return string + */ + public function getTargetGroup() + { + return $this->target_group; + } + + /** + * Generated from protobuf field string target_group = 4; + * @param string $var + * @return $this + */ + public function setTargetGroup($var) + { + GPBUtil::checkString($var, True); + $this->target_group = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php b/src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php new file mode 100644 index 000000000..57580cd75 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GroupMemberUpdate/MemberUpdateType.php @@ -0,0 +1,56 @@ +proto.gradido.GroupMemberUpdate.MemberUpdateType + */ +class MemberUpdateType +{ + /** + * Generated from protobuf enum ADD_USER = 0; + */ + const ADD_USER = 0; + /** + * Generated from protobuf enum MOVE_USER_INBOUND = 1; + */ + const MOVE_USER_INBOUND = 1; + /** + * Generated from protobuf enum MOVE_USER_OUTBOUND = 2; + */ + const MOVE_USER_OUTBOUND = 2; + + private static $valueToName = [ + self::ADD_USER => 'ADD_USER', + self::MOVE_USER_INBOUND => 'MOVE_USER_INBOUND', + self::MOVE_USER_OUTBOUND => 'MOVE_USER_OUTBOUND', + ]; + + public static function name($value) + { + if (!isset(self::$valueToName[$value])) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no name defined for value %s', __CLASS__, $value)); + } + return self::$valueToName[$value]; + } + + + public static function value($name) + { + $const = __CLASS__ . '::' . strtoupper($name); + if (!defined($const)) { + throw new UnexpectedValueException(sprintf( + 'Enum %s has no value defined for name %s', __CLASS__, $name)); + } + return constant($const); + } +} + +// Adding a class alias for backwards compatibility with the previous class name. +class_alias(MemberUpdateType::class, \Proto\Gradido\GroupMemberUpdate_MemberUpdateType::class); + diff --git a/src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php b/src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php new file mode 100644 index 000000000..b7080cf75 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/GroupMemberUpdate_MemberUpdateType.php @@ -0,0 +1,16 @@ +proto.gradido.Key + */ +class Key extends \Google\Protobuf\Internal\Message +{ + protected $key; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $ed25519 + * ed25519 signature (libsodium default) + * @type string $ed25519_ref10 + * ed25519 ref10 signature + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * ed25519 signature (libsodium default) + * + * Generated from protobuf field bytes ed25519 = 2; + * @return string + */ + public function getEd25519() + { + return $this->readOneof(2); + } + + /** + * ed25519 signature (libsodium default) + * + * Generated from protobuf field bytes ed25519 = 2; + * @param string $var + * @return $this + */ + public function setEd25519($var) + { + GPBUtil::checkString($var, False); + $this->writeOneof(2, $var); + + return $this; + } + + /** + * ed25519 ref10 signature + * + * Generated from protobuf field bytes ed25519_ref10 = 3; + * @return string + */ + public function getEd25519Ref10() + { + return $this->readOneof(3); + } + + /** + * ed25519 ref10 signature + * + * Generated from protobuf field bytes ed25519_ref10 = 3; + * @param string $var + * @return $this + */ + public function setEd25519Ref10($var) + { + GPBUtil::checkString($var, False); + $this->writeOneof(3, $var); + + return $this; + } + + /** + * @return string + */ + public function getKey() + { + return $this->whichOneof("key"); + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/LocalTransfer.php b/src/Model/Messages/Proto/Gradido/LocalTransfer.php new file mode 100644 index 000000000..58f5e23ae --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/LocalTransfer.php @@ -0,0 +1,85 @@ +proto.gradido.LocalTransfer + */ +class LocalTransfer extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + */ + private $sender = null; + /** + * Generated from protobuf field bytes receiver = 2; + */ + private $receiver = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\TransferAmount $sender + * @type string $receiver + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\GradidoTransfer::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + * @return \Proto\Gradido\TransferAmount + */ + public function getSender() + { + return $this->sender; + } + + /** + * Generated from protobuf field .proto.gradido.TransferAmount sender = 1; + * @param \Proto\Gradido\TransferAmount $var + * @return $this + */ + public function setSender($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\TransferAmount::class); + $this->sender = $var; + + return $this; + } + + /** + * Generated from protobuf field bytes receiver = 2; + * @return string + */ + public function getReceiver() + { + return $this->receiver; + } + + /** + * Generated from protobuf field bytes receiver = 2; + * @param string $var + * @return $this + */ + public function setReceiver($var) + { + GPBUtil::checkString($var, False); + $this->receiver = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/SignatureMap.php b/src/Model/Messages/Proto/Gradido/SignatureMap.php new file mode 100644 index 000000000..0977169d7 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/SignatureMap.php @@ -0,0 +1,65 @@ +proto.gradido.SignatureMap + */ +class SignatureMap extends \Google\Protobuf\Internal\Message +{ + /** + * Each signature pair corresponds to a unique Key required to sign the transaction. + * + * Generated from protobuf field repeated .proto.gradido.SignaturePair sigPair = 1; + */ + private $sigPair; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Proto\Gradido\SignaturePair[]|\Google\Protobuf\Internal\RepeatedField $sigPair + * Each signature pair corresponds to a unique Key required to sign the transaction. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Each signature pair corresponds to a unique Key required to sign the transaction. + * + * Generated from protobuf field repeated .proto.gradido.SignaturePair sigPair = 1; + * @return \Google\Protobuf\Internal\RepeatedField + */ + public function getSigPair() + { + return $this->sigPair; + } + + /** + * Each signature pair corresponds to a unique Key required to sign the transaction. + * + * Generated from protobuf field repeated .proto.gradido.SignaturePair sigPair = 1; + * @param \Proto\Gradido\SignaturePair[]|\Google\Protobuf\Internal\RepeatedField $var + * @return $this + */ + public function setSigPair($var) + { + $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Proto\Gradido\SignaturePair::class); + $this->sigPair = $arr; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/SignaturePair.php b/src/Model/Messages/Proto/Gradido/SignaturePair.php new file mode 100644 index 000000000..2ef0e81c5 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/SignaturePair.php @@ -0,0 +1,123 @@ +proto.gradido.SignaturePair + */ +class SignaturePair extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field bytes pubKey = 1; + */ + private $pubKey = ''; + protected $signature; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $pubKey + * @type string $ed25519 + * ed25519 signature (libsodium default) + * @type string $ed25519_ref10 + * ed25519 ref10 signature + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field bytes pubKey = 1; + * @return string + */ + public function getPubKey() + { + return $this->pubKey; + } + + /** + * Generated from protobuf field bytes pubKey = 1; + * @param string $var + * @return $this + */ + public function setPubKey($var) + { + GPBUtil::checkString($var, False); + $this->pubKey = $var; + + return $this; + } + + /** + * ed25519 signature (libsodium default) + * + * Generated from protobuf field bytes ed25519 = 2; + * @return string + */ + public function getEd25519() + { + return $this->readOneof(2); + } + + /** + * ed25519 signature (libsodium default) + * + * Generated from protobuf field bytes ed25519 = 2; + * @param string $var + * @return $this + */ + public function setEd25519($var) + { + GPBUtil::checkString($var, False); + $this->writeOneof(2, $var); + + return $this; + } + + /** + * ed25519 ref10 signature + * + * Generated from protobuf field bytes ed25519_ref10 = 3; + * @return string + */ + public function getEd25519Ref10() + { + return $this->readOneof(3); + } + + /** + * ed25519 ref10 signature + * + * Generated from protobuf field bytes ed25519_ref10 = 3; + * @param string $var + * @return $this + */ + public function setEd25519Ref10($var) + { + GPBUtil::checkString($var, False); + $this->writeOneof(3, $var); + + return $this; + } + + /** + * @return string + */ + public function getSignature() + { + return $this->whichOneof("signature"); + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/Timestamp.php b/src/Model/Messages/Proto/Gradido/Timestamp.php new file mode 100644 index 000000000..ae3ecea0e --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/Timestamp.php @@ -0,0 +1,101 @@ +proto.gradido.Timestamp + */ +class Timestamp extends \Google\Protobuf\Internal\Message +{ + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + */ + private $seconds = 0; + /** + * Number of nanoseconds since the start of the last second + * + * Generated from protobuf field int32 nanos = 2; + */ + private $nanos = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int|string $seconds + * Number of complete seconds since the start of the epoch + * @type int $nanos + * Number of nanoseconds since the start of the last second + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + * @return int|string + */ + public function getSeconds() + { + return $this->seconds; + } + + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + * @param int|string $var + * @return $this + */ + public function setSeconds($var) + { + GPBUtil::checkInt64($var); + $this->seconds = $var; + + return $this; + } + + /** + * Number of nanoseconds since the start of the last second + * + * Generated from protobuf field int32 nanos = 2; + * @return int + */ + public function getNanos() + { + return $this->nanos; + } + + /** + * Number of nanoseconds since the start of the last second + * + * Generated from protobuf field int32 nanos = 2; + * @param int $var + * @return $this + */ + public function setNanos($var) + { + GPBUtil::checkInt32($var); + $this->nanos = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/TimestampSeconds.php b/src/Model/Messages/Proto/Gradido/TimestampSeconds.php new file mode 100644 index 000000000..d31aa40d2 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/TimestampSeconds.php @@ -0,0 +1,67 @@ +proto.gradido.TimestampSeconds + */ +class TimestampSeconds extends \Google\Protobuf\Internal\Message +{ + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + */ + private $seconds = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int|string $seconds + * Number of complete seconds since the start of the epoch + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + * @return int|string + */ + public function getSeconds() + { + return $this->seconds; + } + + /** + * Number of complete seconds since the start of the epoch + * + * Generated from protobuf field int64 seconds = 1; + * @param int|string $var + * @return $this + */ + public function setSeconds($var) + { + GPBUtil::checkInt64($var); + $this->seconds = $var; + + return $this; + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/TransactionBody.php b/src/Model/Messages/Proto/Gradido/TransactionBody.php new file mode 100644 index 000000000..0484ecc92 --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/TransactionBody.php @@ -0,0 +1,193 @@ +proto.gradido.TransactionBody + */ +class TransactionBody extends \Google\Protobuf\Internal\Message +{ + /** + * max 150 chars + * + * Generated from protobuf field string memo = 1; + */ + private $memo = ''; + /** + * Generated from protobuf field uint64 version_number = 6; + */ + private $version_number = 0; + protected $data; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $memo + * max 150 chars + * @type \Proto\Gradido\GradidoTransfer $transfer + * @type \Proto\Gradido\GradidoCreation $creation + * @type \Proto\Gradido\GroupFriendsUpdate $group_friends_update + * @type \Proto\Gradido\GroupMemberUpdate $group_member_update + * @type int|string $version_number + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\TransactionBody::initOnce(); + parent::__construct($data); + } + + /** + * max 150 chars + * + * Generated from protobuf field string memo = 1; + * @return string + */ + public function getMemo() + { + return $this->memo; + } + + /** + * max 150 chars + * + * Generated from protobuf field string memo = 1; + * @param string $var + * @return $this + */ + public function setMemo($var) + { + GPBUtil::checkString($var, True); + $this->memo = $var; + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GradidoTransfer transfer = 2; + * @return \Proto\Gradido\GradidoTransfer + */ + public function getTransfer() + { + return $this->readOneof(2); + } + + /** + * Generated from protobuf field .proto.gradido.GradidoTransfer transfer = 2; + * @param \Proto\Gradido\GradidoTransfer $var + * @return $this + */ + public function setTransfer($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\GradidoTransfer::class); + $this->writeOneof(2, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GradidoCreation creation = 3; + * @return \Proto\Gradido\GradidoCreation + */ + public function getCreation() + { + return $this->readOneof(3); + } + + /** + * Generated from protobuf field .proto.gradido.GradidoCreation creation = 3; + * @param \Proto\Gradido\GradidoCreation $var + * @return $this + */ + public function setCreation($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\GradidoCreation::class); + $this->writeOneof(3, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate group_friends_update = 4; + * @return \Proto\Gradido\GroupFriendsUpdate + */ + public function getGroupFriendsUpdate() + { + return $this->readOneof(4); + } + + /** + * Generated from protobuf field .proto.gradido.GroupFriendsUpdate group_friends_update = 4; + * @param \Proto\Gradido\GroupFriendsUpdate $var + * @return $this + */ + public function setGroupFriendsUpdate($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\GroupFriendsUpdate::class); + $this->writeOneof(4, $var); + + return $this; + } + + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate group_member_update = 5; + * @return \Proto\Gradido\GroupMemberUpdate + */ + public function getGroupMemberUpdate() + { + return $this->readOneof(5); + } + + /** + * Generated from protobuf field .proto.gradido.GroupMemberUpdate group_member_update = 5; + * @param \Proto\Gradido\GroupMemberUpdate $var + * @return $this + */ + public function setGroupMemberUpdate($var) + { + GPBUtil::checkMessage($var, \Proto\Gradido\GroupMemberUpdate::class); + $this->writeOneof(5, $var); + + return $this; + } + + /** + * Generated from protobuf field uint64 version_number = 6; + * @return int|string + */ + public function getVersionNumber() + { + return $this->version_number; + } + + /** + * Generated from protobuf field uint64 version_number = 6; + * @param int|string $var + * @return $this + */ + public function setVersionNumber($var) + { + GPBUtil::checkUint64($var); + $this->version_number = $var; + + return $this; + } + + /** + * @return string + */ + public function getData() + { + return $this->whichOneof("data"); + } + +} + diff --git a/src/Model/Messages/Proto/Gradido/TransferAmount.php b/src/Model/Messages/Proto/Gradido/TransferAmount.php new file mode 100644 index 000000000..7673582fa --- /dev/null +++ b/src/Model/Messages/Proto/Gradido/TransferAmount.php @@ -0,0 +1,85 @@ +proto.gradido.TransferAmount + */ +class TransferAmount extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field bytes pubkey = 1; + */ + private $pubkey = ''; + /** + * Generated from protobuf field sint64 amount = 2; + */ + private $amount = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $pubkey + * @type int|string $amount + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Gradido\BasicTypes::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field bytes pubkey = 1; + * @return string + */ + public function getPubkey() + { + return $this->pubkey; + } + + /** + * Generated from protobuf field bytes pubkey = 1; + * @param string $var + * @return $this + */ + public function setPubkey($var) + { + GPBUtil::checkString($var, False); + $this->pubkey = $var; + + return $this; + } + + /** + * Generated from protobuf field sint64 amount = 2; + * @return int|string + */ + public function getAmount() + { + return $this->amount; + } + + /** + * Generated from protobuf field sint64 amount = 2; + * @param int|string $var + * @return $this + */ + public function setAmount($var) + { + GPBUtil::checkInt64($var); + $this->amount = $var; + + return $this; + } + +} + From e6fe7556df9e40ea846689ab966c28b39d0b3478 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Wed, 30 Sep 2020 11:08:02 +0000 Subject: [PATCH 066/293] update logo --- .../Component/JsonRequestClientComponent.php | 38 ++++++++++++++++++ webroot/img/logo_schrift_half.png | Bin 29213 -> 0 bytes webroot/img/logo_schrift_half.webp | Bin 12190 -> 0 bytes 3 files changed, 38 insertions(+) delete mode 100644 webroot/img/logo_schrift_half.png delete mode 100644 webroot/img/logo_schrift_half.webp diff --git a/src/Controller/Component/JsonRequestClientComponent.php b/src/Controller/Component/JsonRequestClientComponent.php index 8a071b70b..4132894eb 100644 --- a/src/Controller/Component/JsonRequestClientComponent.php +++ b/src/Controller/Component/JsonRequestClientComponent.php @@ -41,6 +41,11 @@ class JsonRequestClientComponent extends Component } + public function findePublicKeyForEmailHash($emailHash) { + //'ask' = ['account_publickey' => ''] + $results = $this->sendRequestLoginServerNeighbors(json_encode(['ask' => ['account_publickey' => $emailHash]]), 'search'); + } + public function getRunningUserTasks($email) { if($email == "") { @@ -121,6 +126,39 @@ class JsonRequestClientComponent extends Component return ['state' => 'success', 'data' => $json]; } + public function sendRequestLoginServerNeighbors($transactionBody, $url) { + + $http = new Client(); + if(!Configure::check('NeighborLoginServers')) { + return ['state' => 'warning', 'msg' => 'no neighbor server configured']; + } + $nServers = Configure::read('NeighborLoginServers'); + $results = ['errors' => [], 'data' => []]; + foreach($nServers as $nServer) { + $full_url = $nServer['host'] . ':' . $nServer['port'] . '/' . $url; + $response = $http->post($full_url, $transactionBody, ['type' => 'json']); + $responseStatus = $response->getStatusCode(); + if($responseStatus != 200) { + $results['errors'][] = [ + 'state' => 'error', + 'type' => 'request error', + 'msg' => 'server response status code isn\'t 200', + 'details' => $responseStatus, + 'fullUrl' => $full_url + ]; + continue; + } + $json = $response->getJson(); + if($json == null) { + //$responseType = $response->getType(); + $results['errors'][] = ['state' => 'error', 'type' => 'request error', 'msg' => 'server response isn\'t valid json']; + continue; + } + $results['data'][] = $json; + } + return $results; + } + static public function getLoginServerUrl() { $loginServer = Configure::read('LoginServer'); diff --git a/webroot/img/logo_schrift_half.png b/webroot/img/logo_schrift_half.png deleted file mode 100644 index 5dfb1b3ac7d2177302625e3b6e9712a3b822d91f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29213 zcmeFYbzB`?lPZfY0Ub}aMf}8{jA^{=*06>wF1S`G$UwzwI;9=kXa$+?) z0RULno+|3jN(OEqdq+D{3u_aQvxmJ2$i&^k6aa8vsmjoB-Q~a#d##Jqh1>_E1YKsW z3o~||8vxBMp4T@)q>b2itc`bIR7&5H#Tt(F1GJb_L55#=oW`{ky zy5tgeE?xL`@1q|*zLkAjUM!ouk6vHwD!F=jxA;_f-}<=b!ygw-^Rriob}&)os%CK! z8KeFqKZ-7S&2JJHiVJ}++rPGyeHq2#UwA%vb$#53T|DjbWBz#0`XTq+*O)R|kD79R z5kCfMBS>4&@8!y!Mlhz!?l5P`kNAN+?(*q!Mf7)TR_yEj+5Q=S&3v>rf{PF1u~Ebn zuUr;1Eq|(NXY^~x{hha4XXbSuqou*q9`(itCYFdc(lBE2mMuO(HFX*0A)naeSS9(c+G7mK3h>cl|TJxKl5pe&lX_GDq%!G8^okP(htJ+S~Z`@-zBO z)h#qnzvQw%(qrJuN?<|S&8P+i#cC|idwGAsPCsATnh4|+>hWk8R6)JwG|CREk1k0$ zU}`zK-`=V=wa=Xpq=u)x#^zx}-Y8|k1RVqBq`)C@Usz5{<~=ScVH!$XQ+y}sA3_qD`pPIG8Ay70~>OLajq3YxMSzi$cTS@}GPfUntQWz!P(D`XwM zY|0^ffS@J&mU%6m;}}-MEbogbuT@i>`ir&=a0ky*4hOI$Ju01Mb-ol3#de>~^PHj> zj_$(AfQ@lr>w2fJD*IuHBD0kFTZxhmzYKb%Fga@vgvq4F=scWHldkrW$`A)EQK2>O z!8BS$LR*@R0?>7In0JAxjJ|wMiNGj+(RpVXeNWMPe7~0|!JD`5+=e`O+9p9WhIP|g zMP~HY)R5Qvhb(P?qx$+DY{jE^#9EuSZqbE!b<@!hGPM~7>EN0;nOrl@cy;pJakSOl zH^z^WLA85Is?xd#?Jml#Rt-p0CqjZQ>vGpIIn+M(Uz8d@QAdVAv$coO>FnRO4L!kD zf2*n0qSxELu*up$#Ch}O|F^U1o_{NZJC6u06OF12x_Fvpuz=SL@K zk#iOsVawxFbJJ|~z%s@7*+KBrwGVxl-pGN7K+4JJ6yNi_WoPxCQ_gj3_w(B0RGVJv z+<7jUJ?#hiC})iEZg^+vc}}?p4#VYV$ohN=5cZ2uxpHPdS*BUB%BS42Su6cUGJtHR zCb43Q&srwz3Ba0c)v6i_rC-Wrj-+$JJ~{zz!(vqR2Moh17^=oF5qY|Hvp}zbCXg;? z6229NvN-IFPRX zuRBuK^&wo66-=fXzG@%h0l5Z^W~qn8s5p_g-BYy;MO^a9##2g+onKg?l3{O`p!+_2 zPA|(6h>dNYnE1%jEJ+-{@mrPfET z)OS|xigxiMwh9tP=;p&IRCBV2TS0j(VD9}(Z=3TgiP&7p1w@4KL?I*{mK&%ccq0u( zcZF$Oa&78UUplU)>pH_aK@2 zIH)bJK$f6PZFW+o)gmuE?Zx0(rrCNhlK~D|u~I?Du-r;UOGa_hF=;gy)HI$_=zzc zxK!Q@wjoqqH$^kpQhj#`1Ux$neRO!}`RGG*z3PXZ@OMNi4rK&@2qb%t`>X+D>vIvQ za|PUiVA;zf_fNHyfYxkpsEnYg(V)8ZZ$mT^<+V0E=QNz9l-*klDll`E9(WOld%<*3 zCE5OL42gG36fwG@T?O{hXEn*oj!&*MyH=pB>;ph?7>SVEr}7Lf34mu}$(SHH2onZQ zf)@h|ezs3xoIl~Sg+!M{feJY(gt#CGZ0*7m$_tR$}$V8 zQA)nTPk$yj!n_;Cjz>mlf}m}(@B45Ynh$iQPz3Ue%p-l;$vPw-hMPgqpZ<vO^Qg$^Mh52 z$iKX7z)c2W@#hVX^qrdw2I}irdKUN}VWv0-@SpuQ3Jl?3!eO1L3zuQwXP+sv$DLS{|(g==2oa!>rtw`UM~Q-CHXYP_ncO0E7n1 z*=4+g%*pMGc`^^3D>YOAR3aB~K|99Q%?A_0xYImH6&+Smq=?#fa|I;Wa6(*+R1u@! z_()$;NTOMFG`@qIPskh{FI7L&*+hdf$zKT8|2)g-`1#xS4;sfzeQ5L~7sD^XhJ zXdn_N9u4pw*eV+`K*Xy%gTkAXW1uwAU0SRaS<6jhO$Fbt(&TE+X;Ss*E%95U~vRBFju_)Pid0I2XJ3~k~; z4tJCky9QF-#9Le%>yMxYZuZ3X_cMVgJiQNjVGb_A@qpPEZ%8gQOl2-$Iz|UPo(fb` z=0_62)MG@(0hFzs(IHtP66_*(c;uSWx)9v?QbaZ8CTv~lThJO#w!hxMfmjUVgF|&8 z+sEYh65YjtjfJ>;D*(sA{pyqeO1P^1bzECwLPf;?_D=fkn z4<2#$ULX%4yS5OV_(as%Xc-2}++O%^#2>Iw#57%hmJPBrkdOY_^u5J-7FPQqejJ#x zS?&d`{o~2{)KM_qJ}*xz)4#hH(9?$`1X;Aj(hQ~<>co`1A%h^KwbTm)j03V&9kDlecipR)_LYk^&=N;t@2;uwYm+>Xx z7)16|2~CQ=SEgf#m$jem9O_DZLP>H1R#)IyX@(mS(?%_3{zy)O|2eo~c$-KPq@-7- z#4f`YbPngQiF8+iVcddkNF{b4a zmcx<@him)0nC!dn^eFMX0`+bQW01`J>Ea2;P9&)!IB=Vy43R64PAu=$!7iJCmQ09q zZDX@B@oA_%(~$5ZI101wtpD0QJVX?r%siLVg-w$A)4bVE5zHYn?s>d1_W zWpJv*bkg+x5`>HR@WodI$p)c;037sl_`txhv4BaQZXhCjIPATXrMi%QnB4itFRcKa z!fGsh@#1nNjWD`GSCtcln9rC9=*$DKGBn7k)^r!J=yq@zXh#NY)E=AoK_p}y^5@}%f?=-68(D0q`m9n3sU z4m|krdsFpB&B zz>cao0WT>Ay?isvtO4n*M~Do8wM3ZZhHSe{K$BWLTscQu{?Hc?X?zIhzz2_(vco#^ zYCYW}B7BnJQD8E}X0SNbK->3=%zZ-Q${rk2ZS9Md`tGPIxXXYHvl=Q(HT)jojFDAT zH*}d5WLN(-#9CjA_zsRNsE6INlx_c{UZ5~6%22de!MiPs+OY3bUn7h5-hsH$T7T_*+0i@0vmoV?_Ft0y|vAAvWRx(*eS_=rl<8Q8DkflvK!v zp!VaIM2!*Ju?Z&!YD#3EQ6N8G8g?-ReY{;(OLx*y8a^9u{reZC5qPX3uGllBu!PXI!YJ&0>N7@g7R7aL}CH_70t(|9uIa;zuB_v3XX2o z22)-+h>F&D%I8T$O>UBiT#z~^YQ10r(*gD;4j57x5~Kp`5{4ex3Sh-5mB6peHZ0pr z%eR?szDmNHs0%D_^z~dB3K+*L^HneBstjXUJ5S30?hhq`vK~llWcCj(Swq>&0A`?h^J0 zAe{sq_cgF-tKl*PF_Qs>+jnarWa7-I*oZeIsUnnRwi}lXouF4)sG-)iXp=Dm_}L-6 z_U+k^a4w93$GI@yC=ikCM-wq~9=SX*O_{O!fi&0vry_>6iQb}F zV+M3M^X^C|i8c@no*%|U0CjW~wKSf>A_C(LptcZhqug&~#M=4e9?|O+r@Mjm;0-o5 z=maQdh=}jXo}hrpvJui_vR#YA?OORTjn>cd$}jM(AxwFEct1xym3V-vNS>pPETodn z_|J2fWW}*!ma(U!J^I$5$7QOsDAO7de>47>Q5NbPSh)5fh-bz3{m=&?-OlD8yMZon z03?yJ;G$@i7OaB#KBE?eSdvuh`EG5dGAJiZ$S47JMCbE4BJ)%{^krv$211+Y(95rr zDC(l$i08QtiNLhs;5;&siByqs`n)l_WUNV4kDk`h>Gcb!*LdY{aKLKhF5Etg*B2bgHDl`~Ya~eF3AmU_wq58b{lbFm!#ErF$ zJxO8X7q_TA5LvNeI@1ZlPqHhgy>V17E;DDnOWTxqQ~HOIjx23xy9F2MP>?&B+S53$ z5(awk1S;}_*3}%p_pfgt<|D`xZAA`5c7-vt#blw6TFjgje1Evu^c$YdT&Yb5ORjDQ z7Bz?WB;B~d3`azz$xJCv7Yg>^tpqRSNoDsjjmN+e^NI>nuK ztngl_q&kf5D(9Oyxg|62MbEy$(PwF*w1R^=oL}-mfnXI@Q`*y_3ElV5A3}8JP`yK5 z(8Rs*S7U8Ym69B8u>hyBOOEYiY)CiaArFSg~f8#DZJeR z1`8=cJdUWruAj-+WX?@!OUF$h9ahppY_YhPS=fYzfJ%w5<$aOLO{Fl6+pRYOa1FzI zj!%QCUDaKn$M z`bOKj6Yg3$K70|MDx6{2IUF%OCBf^?ZI(dQ;lCCVb21Aw_h`q<-S=@l&N+h-&7e!6 zuDB|m`5*|adeQXP_ut&CWP&miA$@tbWt(Kyo)dWgwhC(cpDuq|*gG5jS^nggX2$Sm zLSDH>%#DLCzvKS4&@<8VnyU@Fg$mz)c97kK-9jiw#ha@9J05=yGi+O^7yYoch<0A* z;7)miPplDCe^{Yn@EugP?K;T2KL8l zr|S6bXge-VvBHpN=1}8=4=CY|>5PwtO7qDQDXK(YJ#(jGPike&TV^+&kLcksn18^p zo+A>5{3uBVgU)hXnumzQtjVqzo#EUI=+Oc-?B6Y{4;?|p6<4R&`3H%DGz(5$V%_dt?(fdiUHt@` zfR4R1$)e5x0Gg`B+XA?{tPGEloehJ5v7Mm_gS(CW8#Mp`K0$YT10yRFXON+ZnT0Js z*?D^x8OXwzpG=KimPyuL)WqCE($mpI*;7u%$kWP*+n7vH0Flp~=MBKd#MuDkZewlh z#N*CS_7^VC+wq@fMl#S}BFmJMn*R`HwHIW20KSHMrLkqZbl{+Miv(OHwk(t4_jvgcY0eV@;?y& zzyO;#89Bc3*}~2i^asE-+d z{#T%Qz;;G1e^8{r{A7O|;4!u{vM}cP>(JEDnBB;blZBqs)X0dQjpgmgfXS4Vp4r%d zo0W}~g@u)w>u*p}woc9lwnip@px(e4EZ%So*-bc@*$oWonK=zv>Dib#P3XBeSlQ{h zOpFXz47k~uxQvbd1|jcg@kVU}>%V*T2g>*j>dia{vjMXKJ-Y$B2|b&M5hp#j@f+9J zIgQ@@G2k#^;$-;?>Q7*KgcYRt$ygYe{=G%P+Q8Y=&e7&AUo32m?cALHy-UTy#zfiK z;7{0?**Q75Sh+Zv*tog4*;zRMUFegEqthF2|DZB6z5V{xV{F7D{)TDr#vcnC12Ypw zdt0-=I^MkI5p^^%aJF+)v9q)0C;Q_S=#T1O*#P4EC(n6g?2HWlD|3VRVbau0Iw32s}H?%Y{a{jMz{xji!At}9; zDJN$~52^pdMg4DbeE%S(y2HBRxF_ zlc6yaGdG7RH~asF?qp}`>}KF-B5d}SMsN4|Es6fR&mfwA@{IOBdgEqp@`prkVD!vy z)r(1mnVE-;orj5y>>qa<#K-ujH2&Mw^8G0uva&pXj|bnM;=&{Khj7X+_V(5mCXW9x zPXET6{};Kx>Hm|X|0ngoi~U1e)Xv`HEnCf<<=t%mOY{GU;6D&#ER0NSo$UTA*Z(f^ zkFfl01bOrMA8l_V)7wDD_^*-fpDg*4NdFhNf3olYqJ=l;|1t94itqn~>wm)a--^J0 zOZb1-^*`bIZ$;q0CHz0^`u{Cli2weqY-0O1?{j;55^jgja({b@hBf>s0S3JO`N{kC zCGo8V!Cq41?cFm5@;^I-d$FMFTO*val&l!s4l))ZJ+!sntqA}C0!V>{Ro*@-{pR7U zJ>)|DyIu8G_xw;CDw-J7B1J)&P(U%3K=&iTdikq~Sx0|LwtIriHdp$tI|jAG6=kCF z)?!fhWf&A0{yZyh1Qd0L=nvyw4@;%fl%SSZ%xY6^UNAZ(qZPx zL|}@$(#c&25dC9b)$L(z%QJN9)tdQtVsGs3`nmAWCe~-s`a@cwElF8Hi;C!kUfxBZO#oNFf)Mh@ zYm0m|JM0h-N4>W5cR%HydnXKAIQRHnhNONx&&HB<7#4oJPDGnk?vwu-%k%gi|8(@+ zzEueacWB_!&y&K6_}5P@UpQI{HNO(y-KG-&r9v6@PiY&7Y=%6x2QZltwQ2g36TYP+ zC0kIV?dI1HZuv?RLc9=+EdEEmkO;+_!#$coHoUHRGl#;%1idE%dr*}Co7#t~ zv3x6TAYVUuRCPms8eP8NPx2LX&^}{NB-ydKkW)~Wi@Exs_IyFhcv^0zE1aH&eKw&Z zTN5ykv{305`C1$N!(5xpq%B_KRD|j%uFUfyx~=6JcL;4lfh>bmy>F~xclH}}1|hCS z7kS3dPO|;&y6Ony!EykiJ##hACyRGDGUHK>!RB?s>NFMwh@xH=@ad-JC@`?~ro|K@)Gee%T1N;t zhH7pLpOIXcNs3s*Vv^TWb5U{$h;QX9>2iUde&h5VOnrpwts$y~k^T0+w;A+^1o>d^ ze>=(Z)_nO<>~;pU^BDR;2A6sZ4B7wI`?0H?fP#Z?YhakAm&rLNNxvzspa(z%@UMrY zE2WR?nM{8V5RycTA~8Tl0_dBfW;c#w1AyZ)EAMgQle7^;5hN98suDU;2ndvz+hlS7pW-~!1WdmjO@7jnC-HVT*Rn^o{K4h_%)O;P>ekxN()}P++0T0 zvT?_y>K#W$9^uytF1=qTdk>pc`TOn^Tgh-u)m9z$d_pCxl#Vkrg$o0OX3atoWXFUA z=I&#-ZjW#8YBIG*!wOZ2TBe>FlloC(kDZPdwdojGSOlk2q9ZIu>d64=VbCGy-&VKa zVc7sJR5H*={+bYR4-K5wFE&o@U-1An+UP#0Eq%3bAFDryd4>Qttgv|gnlv7mM?UrA(J zC6%KVhUwmpjU5Tj)s^HkFB6A4_vA(}pf4gXgajMl7TOcBe;=h9jIb2|>iNElOH2n{ zczX{}{IFCP2-Bx18Hk4rTkj7eEQx4+m{Y?(-kkEOTutTVu^Dks+N^OUZV*_BHJu|m zpu+4p()QpPW%XQ`>TnMhwCmuF{lS`BGNU$|Hv9?L#XXAK{ILBipSh)wX1jZo&xwAH zeI;I`5#w&b3gV$NP;{&%9AFB71_liWWc%yG0ikv`(|Uj)0G;+2AXEHMlC6+Lo0Xxd z;2oa*cTY-gAjHa*L*d?QxvHhlK=QHOr<11o1*W3Lpc`*!4(LRGCxQia2CUD1sVIaT zBcvV!FmkFNB`we<#f4(x%=_cZj2X^u-pYzMxQ~lM&TK>#KU-a@Qi19;oY0-pa2cr# z*aj3)=dyut)MtZ&iTD)kSVCFwpxTg6#_Eh0n7%~|v*lqQqfZpH3{k1&XD3WS3dRap z0AiRQZt5$15kwJr-l1Z$Yu^1xE#l4$g9`cm1fu9l(Fz)bAvu_E-RDC-Wch&Y_psz< z7;W+XoOxg~9TVx-_vqIYE9srt$+77jv>Y>yRk4W{t`{*_4@kvdUkJ6a1s03s5tMR* z{Ee{5Nt2kjprZHBcl)8+%0$D zG23iGP;PYkJQyL!J}#(*7S!yn8x=JNA3fOHOGX53SO?u;0z~L$etd*2@jmczHr?K( zSq%KXN67e8{Bmae%jGkD^VnhG8X{*WC_dQg zV3PFm0HJWc2M40sgY9AMMLuPLCMG95$*O{r<#@~i6cpPO5y*A$En6aALdc!tC}aI8 zG++cpSb&_ph&*`7Bkw$=7tqRW2XDbfsjqY!>Kl z!W`TOMsZTUjz45SJiclj_~makJf6`MR9d3Q0zgcb?_Ef)I6>Un3M5{#tSq523V z3LI4j##vdqbyD?JiY31^7+=O+>BeSOl4yy9nSqW61lRQm5S0?nH7hF(U5$R87c}}_ zp(fg=e5+FWq9pi0Au&~=OXJmI*xA=w{m4f!|KvpgNNQ6W9tYMvI@8TTo9K1B2muI_ zg;s1B4}!0};pfoA?D2;#M2C&bu@0Wrix~QK-mbKDX=G%yeR&{n%yJa{T-F(%r-I@v zyJ+=!K%{7;v;+?J(bkf!d}cYsBgU-=Bf|LWI!$V4m+xBJSLWZDD#HEf0C9nx}8@doY1T8!TT^f6(3s5@G!1AJf+v_-c zzb?7K?2ew96w#Iq58;5}FyM7B;CJR{(CaHT*=y?5YuLmlMFEfuv6hUM-*KUb2QGk0 zQ3So5Gx*m}#NxBsQf#BKosN@PlJAC>BHWVMNtL;mfNkv3X7;FlUl9n(ESI zkcW6NnnP|cY?5m)<9Db_b`~P#sd$y(8p>Cb$L@StkyTY8o23{NK1^U=j`on3h7hD$ zuS3ey1`ERrLl$-WOBT)YC5uV!Opb7-K%P83ay_Ovc>rue@I#izyvk8d)Fb zI!9LPY+GJS_68!k?0?Y^xCBL?aOQnT2J=_;)de+0F?}ypttef93Lfm`^2csCczC5H z9uZLXE!Pi9r>rFMipPYM{0OJaT1BwQ-NDBG%FV;;M5|kPFCcj7Xp0{>mCaijJ${hD zsGh|hX3_OxeeK78wK4pADh2A>`a@TW_L)fQtX1ZhmhR3R{H?VUO+Pmrv+A6cdbD=& z>fl5Q5u?oy5Iz2wsNgN5lSfQ9C;eXI_mS$hL3DIe?PU)vvfmLcVH5>HnU`^rSRW~8 zrp3)egASNKM95HCByYEEOENFaJWMN9{_Y>Y*=~p06Id)g)-gDACFWuCNkP)M&9Eo4)s z;OQ{CJV;iQ8i;)$m-fIn*wki!6(ws_*M^ST0wQ(FN5Qrk*k+dl_+y)G?5f#Ss%L9m z*Jla5x~8s`v75hiOS=g_)R?`P^?syYg)z}He+it5R+s;o=_Pv&ojq}}YJt3c)P;WV z{qrKvYrS|&PqTK&o>)M`7ibNOY$L1eWIEYy&xhs(7h|N`y)ye*thghssrFcoRWK<5 zXZ*Siv*4wXvC$%acr=2uVpIg4J|PnjppuBJKVIkFWc$&rj3)a2jHrz>Ez2i#pTJL7 zgKncl|M?j%rjJ|S-5t6$M-JM6I1Vxy)ZhCXF|rsjYF;5Sk5BPT+9hjvudP#sdF&}H zl!k8N+bM_bPq#%I0xS)351pw-?dtPD)*lYnHqD#fr8DY2>o6Hv8Me#9iQA2IJlu6n?gUM4Iw@jP`<+>A@D{~Svwl^%=kTG0q;7YS7+|}3%(oi zdSzD+1ecSUrSlmfLl)H@2oK?iho^Zzcrewyy1Q!uyYTW}yFQPPY1Pm6=89l&wg1#& zfAMSuuKI$fr>YVX1Xt;_hQIKsBz!_lGz4$x-e!8|WX|Piyr+7W=2y{0 z_rUQ2O)Of$yfb-si05iE6+saA2g-=D%y>B`WrEJ>FM7G)T#&^JB&6QiyGa>Um7@bS z@Gnk-d3>kkvx0I2>l>L{1i}^akuA3K=+IszWfqN|YC? z7f_y~V8HDH8X@!2GZAs@iQqQ-5MV;xZ+{=UjHZ47^nS9CVBbqbqh4v8MZf;{|}WT86@&bX3caob4X%#t3=$)v*NM-kcj&xxpsn z)QJT54*l*$l*{3>IKGvp-S*fZUi4KucJP)NW&;3sP&` ztP}q|}G#{=-gp;qeySa|eHw3%08kC*~%P5z=c& znXAVWcXH+v40e?-VZG+4aNuY4`2;sl(euD#?cWGfIbmfZ+Gn30|IvdgW$^PM7|y@U z9p>_DSoq~9qiI4y>|ZZ+C9^F0HUu~)5WLVw-b_z+3H9Ydk74=WvBF`NOt+lj%^-Tp z@tJjN>MrrGz7@(o*y}Gs;M$sxx+!w~!cCdL&FQ+J0w8X2AzFC>c%dseAvqog59G}% z(U8*$nVQg;$nAL$_YVo}3l7x%g7stimPpiDXQRGP`aKW2u6QPIdc4`{r!NLroDAs%`G3so&ff=hX^D?Df{Q)xk9ZZN|O`kXcu$Q?n z1ez<9+Ju#@LUNF+pKPY+{Us0I+%3-Kp)`7vFEXzaR7(eza8u=m@fTwR7DplXbqIJa z$+;ll;IfdgJ$2ScU3a~yr$B7?mk%Q1cbr=}_~3e(cQDHo!Jj)FTHK@sMuvSc?Cnds zXa%DJxuCYT?UY_vjE&Joh6ONef}FTE6uFQP;YRP3H>B%|TNwd#u3233s(xC~|HbVYT_vY`o1siL^(r?xBXGN~|LI zS$CxXr%*%qUSkU7wumO2Acy{-_--!_LX-(qwfIO>?Q-{1H3WmpaRQvI#g2qi8y6?1 z_>Ql7DS=_1`V6^ZB-y!q(ZcAFJf3N}WE}>6@|X(d98W(G6?zGhT_^TaV5kxb!aRF0 z&uuf{iJ z#)Wbz`_e_b39}Ae?(X`DtO3W0o>kgu&Ccv~ebhxu^;9{brZjC=$k3V5lQlw+=j5*@ zO1(ONBZwvVN>wXqv>N6xUbsdvWJx$0SR$xN_6@sR_vK7&zXtq69H~OXl^#}{HUlN$ zMv>bLG2w;0S@aBE4-Boa{nku1;4wj%5?&Kd$9`odsX)*(dPV!*r|e7^=Dx4~2B9Jp zIB3wun{|mVyHN6-LJ^r^1r#vI8vbz6F*L)VP#-eKn<^=R)u8386sc zNhrH$#f*|FwOVOcMXro`Fe~gXRB^G`Fqp5dz8SZ0u4c2O$W&Pq^?Ls5bDK(sh*Xdy z7*YxF-cd7tTFv*v7t9KrNo!JoWSM^2W|{eNjTjd$Ar`e<7MtM9R&LQin}awuFX9Iz z+1;gMrfKVZS$HGJZgjHUfM@_M%ul*)-K_Ft%3qg!Q4FFABzx~kyZFML(GSngd>eO6 z2WMw78YM{}{hfJaqs4>lx}NXM8#QGGZ>B{ZopoFfzcuT2rk8f)YcqT{E{7l;?J3-N z{Vbuk>}R+g^zK)!?>T*QN{-jvG6?50GrEDPZ;Iww6qeMkW9!^^kw9Q5X^~Rg3x+sH zcSMtoMt8`4pbO&UT{l@wveHq5)%#v1Fda@1GpsbNx|i)H?L4w1o}9CPG%OYbM+ed* zP3_On9g6bkQ4dwBczP>qCjo|}^?nAum@n@%}zfAzcru9A7Q$8oL zp%N(`mTkw9?9sXG`p7*i5L}6x^Q<@x(o5V2pkQ+!)hZdVp|LTzNU2Qzjr`rTc6Vb& z67SM2r*iR`9;MXD^M8VtOuEgAWXuwR=PhsfP6R{DavtTaZ6bd-DHA6JvtW!uVvI=(Z&N!?kpkg}5NdU?lvN zpbg>7*k#OTvVUeT^RTgL5M{DUl*n@>9{MY%NJ6ZvXy+?gx~AE;6N0tAAUd{!eLTF*@mKCwAs$*s~tXtB+->OF$BaSn~ZzRx1 z-jrhdh>~T!P_KKSZwf68D8s5`){lfTz+b3}2wj1a!HH1@QR_!(u=}sCufO|t-ud(b z#k!+&?zy2ufBW_=#Bt;~{_Q)sUtu|rX(7_&xH2KL z;DnvuH``T(Bw;LY*u7^O1d)6WOlRih{9ya-_S5U05990I*;+g27bV)x+msWkMmg_+ zw)fL~h6o(AT#L(Kd^<<3RIu8;EI_(~R1M*v4-;L8#vE9wy2%r)hk4$7xkQeZisNEq zh9=I*iu(npGnMeT!|mAkWoH%-L%J8EF{zi0nU5k3t6Nr5qhcPkL@MF{HlaA2D0xjQ z_pD>7wxL>=aEzlpR2Ob!FvwEnXqYf=$;M5vCWVG&&Etm7@^`{n(PUyp=EZY`U+%GT z`ao~(yFYwz4F+Sy4vpaTwY&Zt{q#P0>TQ=7e7>23QdU-`C=OOaoaB~i;vrt)OlGbJ zia4uVU7prY^;+B~e*E|`_xSw$_5SJp{B?9l(DzAC;A*&UE?F7|K2QyvlL7&SSVZdG zu9AK>q|6C{;3xmj94B6t_Q&gK%F|0}IBbfDgK6_x-*tbgQ*C`n%css3|8{x*Q`<`Z2|_7ST4E7yGHRa;p>2OhSLj$dhqTGO0jiju6O z0u~6audhWAAa;nza$=dB)wN4!FNT31kMu<#q%KXZU^M*U`<)4Hkotfk@ak3$H;0Ol z(7|!F3*G8Lo{gpl`=$nvvP#8#9M82)s%hdCm;TS6d>^T#v~l5TAtorknAi`Y$&oo( zAWNkfrvpe0qC`E)?ribpOU5M&1ZI8kA6ZYSqfukhdk?%BspW{cJ+uzF&XV9hPE;dz z2P`$730h31jP&?(r^`+5c}l$C9aa0eyWV$>=7n#Eo-n4?H%i#>SZ%2l0&^~)n}gIV zLKj!KEOCjlposLdf((#;BGYNQl{XXwY%0HoPx+DwNgw%M;`%u}xph6Q38tr|xi>ea zL@{6ZyjxpayA{b-X#IUP#>~Sry0Fq}*{FH=wk0U-r=+G1tbg-DhZY8levvNzs;!|h zGBG~>+f&c)6)xiNPQ1_ogb{I(4oh9!|5nINSTtaf)Ds21y>qfbmHAz+HI<}P5z5KQ zDe?ULysET0hg_pk9q&IZG*n?+8GVQp|%sR9w{pvHBx z_HA--a=}-_PkqIQHpv}4Va2u7lvM(RBqt{?b}rxXBdkgfPpL>ojIQ3;&oVizg@Fo& zR6O}E2=Ky5G#}eZA<-nn5CV~1B}sJNkQV#1gZf5HJ%U${PF`PoXfZ<3_MI`S8cFv? zWk5H1pkE|fDbr1;6R67dNGC0Pkf!wX$$x}tPEN0d+ zEB2JaVUQ#y==LvBU7MM}FLt)W|I{6%vJ$fyXP|Wc@U@Y@wpO;y0y}{vw~3N|xaZx| z($K;?F8j@%ouOE?rh?S9uO?&2{=9!GA?|tC>kBn3EbM8CY$ovYfb%!q<{9(vR%`_C zaXxQ#2S9CSSXD1`xi}s_hlp%ZOBc@y)v03*7&>S*Rh+E<{NdK&=jdqYZDKNDQ8hC^ zKOh4C_C$`3ZeU`P4$wDu_m6fB2WKcKo@_>y_ErowEG$t`QzHOMN=nSl&BK34FHABg zSrQmr3lKz%q+2*nZuj>iLv**rlL|OoL35kQebx_zAcaX%nHD!u`7hape;dow>lu3khE<7o@SXdzo0|GN%v>3!ycZb%8n^Kk~$HrNJ2*k>A(O;UALkeg2SY4>ndf4m{t@s|>m?DX2 z&{I2pQ4ntm7sH>m+c;Bx(P6q6)ddaiwK-_(ecb5QkC`OHHW*oZU5e@|5X z?QTVN`TaU+TC(_Bu=P^DfhEYm0J;D7>8hP;Q9^8XF~Hdpr)dFSzG#*_O^nTnUtVMlRWzFyIjpa zX0cL4b?4(TgH@FbRbtkJY3h)C3}HUS-RZJK*G;RQ6kDLQwW}+nrk1mtn^CFX($62w zHCNqGXu)qeIlej$@dI{t{g5NdQlj&Bc=fE80JAosa7SDuZa@$h#q89_Ac zb{$@*#G@h|&X``;Ne&aTC}5Lg)rv4v$#PzbiS_EC0}!VoonKQE>*e_fX{23$W+i*Q z3&ri8v&iTF_6_)`&K%uFtHtW^)!%#*vQw}sHrD_4EDnT5DLy(WjKS;6^UcGQpFmwp3!c_EqoIQZx{r?!9ud** zTDu$WTUec+>Y;^eBO!xoTqq7tppo#MxCxNPS6i6p(aC^s!>BlEXtU>cg||y zLc@H;brRE<_;r5&`rW`UK)+TjnfCj1W)o`BjxM#4w2Gw^6oVaO*h#=L;5|-1b*bWz zu{~qkU)@Qd#lc(DfhD%>!hs!~79|=Shz;%08&=Pbs8dgdc95ZSU9l@MhbBc07@M9H z(n6x|Ny)%{@Q49olJK$dKHg?5d~Fmq+8K=IjUnQ`axg;X;pIh-9rE)tFxZM692~sS zG?_TKX5-=-*5tgkJz1z)ebLcUj3MGPOif8KV`xA9x*xRO`CUNSrah>2YRpxygMw%1zn1NsKfqV@C@~8n32*ov@NT4Y4z4O!%$FdB^seo?x5r`h_4U20 z-Nc>L?(m$>%iM6SA2x1p3k?esynEv=Dv^NqsU~fmPpg8^H(g<}cyKA9t1ZLp^ZHBY zrOOEiU*khUG$Ra8Wn(rjy0BHWHp9@{ydl`Mvx_-*N{}Q1OhXV|Z9JP^HOPG;fhD2? zh2Sr#Kh?>9b)EYB>2lEqk0s?&H?zI@E4uU-UW*^aTD0jhyCTG^8M0;!9xo3E z8`~c1G1A2%PEJnKn&ilR7n?mn8&Xt>%AD)&J9CU(zps$S9tN0gs}3HWH55{;YpevT#r&yqwjh_F-s=M_Pxq}5+@uc_DxXQ~Dk|bzb=9?jtK&G=*49oE3D0thNz;H4?*35Ba(jDQA16C2^M31m$>Cw) z8Sd`+a(8#6Vt@Z?d9N6f{UP=4+t+icDp|Ws^RIHb zzF!M8V)BT8)C~U`eF_mVc&LX%?MSFr`4Im$Qv71OVGeeiF;{LCS&N3{@E(pUb zA&5wcNH+*bcXuwmBHbn3C5<#lcbBxZbV)ael&~O3xO7X$cfS1%ynDUp%*^xLGv|=> z#EfMaX|Rbp8`%6EeAJue`PBbmy4eOMErwiX-;-V?TFhc zJH(14(G_dU&Zd2WPf z9C#{O-cYZ0-#Gbucgm`&JA-svz}t7{*Ty^43Ux`6RB}{fjTa4cJ*g&U%dH?&iz3R$jXmKgI?{QBD&wPB~Wm9t}3rX~V1HbRpaoPNh6c-m)&e+&koiz2y zBDU`u@_^Y;>^(W|pC-6N`)1t``K?W>KKZ#H1sNIHmOSmLDhaRMuYl{Vv?;%xw?+>^ zSbc(|W((B@k(JfI-OrL#g^7%s9q#4wKK{*^7%){QGSeI(D#pi)MB%HU)A&_y5iRI_ zzMV$ycRrmX0nVz&v>CK}C{qY|?8lNgcGMX%;OF`s_n@6wiCR)$6kz*Voz2e9rc&Ik zp|yf9I8t6-K1qqLNrsJERiB1nyXP_bU(_xy_oj~4ojiJM4%ab=Z_8USfpQ%;Xj=E$ z^Ke7r*xyOY`#a-Px3HRM<9fc&NclrCLi*Wm=7hk~<){gNl6jn; z{2NN@I#yiM9)gmwG^({%C=<2}W6FWYR~Ejiq%*R|2H2TyDkh?{TrTO0;D zbRv33%h>Ta`l$*T^%6OnA9k~>9u+NmU4m=6Ek#(AraZMtcrye-Se};aaM|$IAmNdJ zX9@KTi9pbd;w3;Ml=`J+xo^=(Lg+=s%G zwSRv1g=5E68+AW;bsDlsQ{(P#ZwJD5$0Tqtp^PBel%&AKQpUD&e>Z$kz5i8bhB-tV zAr4#H97z%ep`u@)mY?O|yf(TO0)aS`#9{0mZaUu^7?3f8ErPtu` z-ET6K{G0Sy5l1Z>SPK<&)L9dpxPOAs$bZ>Z$xtU8%gV_;Hfb>V0h7H&23b##-<(2{ z!+xgt9!nD^dP>|2wG8FkaR-hXQe#*c50(lSDPgL?StRd#FGs!x3aitPiEyN{?@miZ zl+4zFEYzdH8hBRZeNT#X%$_wqF{Y}*roxmn+tK=Z$S!D}&F`IEKjFb{@p-4I+P!Qj z$25KkReoLbWR9nRJ{$SllTS}SAV~_+UR|6^g(;P;TK`;K?XGTb7t$=(h*zSw1tC~6 z!BkcCp(->D@F8H$7evp-xmqn!$d1oLfP2NHP4~;=D1=v!H*b zXLPszIxR9&L0X89dtQ?16Xn1l;XZij03D)sx%8y_F5Jv*OIiQev`y(S>Q zhnRC_9KFECejL~8zL|4jO*2DeZvC5_RB_;w`D!irLsjJ8Y*!2kpFe%t*nz0`xs@Hz zBf%8Dj}y&zixhWvos#58clUw1A=Eh8jmBu&8=05)eNrN2PmCF05wd0y%!dc<=40~+ zmE3ecRsVw8R*lM@OS){X33LX+@sjIo2vtvSk2RVMMl3o^-im}8K4)-Yu^+Ir_-%}y zX8S1W%w5Z|NLEd8N{J2KZK4^b4o0zMlybnoaKZ=wZZw;^DVb-F~RMy}z%&($SRQY0*vuSwG=Vh8bIu z6B0TZJ)EY+eg6EJbY8a^@%gopFGq7rOS(1V{WsS`TuAl6m!7kZ_hrAPr=5u#ot2G)-jXgaQ<5N?4 z?L7R%GK66a_!#oVu%Vwj=h%?tWy1!^0;isf?WSoV1aC}C%*U!St)2b-jyLE?4lfPL zHKK}>d(7|K}!Rdfoo_Y-D2o`q?%ywhtg(#RwvPkBvtRZTQZm zXsw(Tv-y?(^w0o1eA%#uYbL@YgO(sVCfvlU8)yB365RffM*d6S)JLyd;Fp*jzD~&T z7*2@F2Lq%*3~?ws{x?){+%JOdl`DJR6gmN0gHtcME$-uF!!{oMuTGWoBHi3`Lnu)D zkhLWeu|4o!*h~Bj_IO&rGl5nl_>?)nD)^j{kXY%#-x10hE7lmEL^pU7#H^>4&}ehe z7J9uE!4udJ*oZWVLAYV8Cuk6OZsW8X`je?M%8>6OAO(Mbe_t}1x)AR4sQ$G(XlxmV__)2dw_(Q{ zy|}pen-bl)Y5<_l-G+vSEpyIij9a@tIm+tu1a1iMNlQx`n$izfqL*^?+tcF$(G8!C zjS})a)bCQGK%+NR4d@1l&vx%%%9Gd4=`dG1d=Kosm(tRc0{Z^fTcO}7H(@VG zz(#e=O16=Ma|t;tm6-zEX#tAo;kn@~y{UlzU5hp#;2(3tDbdeeOs?~CTsuImk%tfK$oCXcZ@3;m`kSr`)+b{rLu^|Y2}+2Tcqp6)1|%?Bdc0lgIz8nG}D~pYa_iuc)Zu?#>Pe(3AZBcl;oT zJ^D@S;>gsY1?}xwp*WS$j0sDV&k~|}rGWn}0Dfee3^No;6H2;q zSjcN@Z%-K8TJ8x((<&I%wb1D-9u*iLAOG?FJ4BIDD@NP)1tT3W9NDfp2e|_v56;@~ z)X!Is+VYWs(hDtym0EklU4dyG+U0_S8%D==6&TG}934!-?Ia!^slc)%j?fx0py}Du z#tyyyE&W#KkvKxAv~lq2iocO269=j5sJVzjL-e4%DwzDoq z78xL{*~P^XTRs0?cKv_e2MaY5w@cSC^TZQ|W0s=%A!rD0`Qe$Ue*iAc^0L~p3=R!h z16sJ8TAqxAy9IAuot?#>m&HYpe&zrMdv^DVfA8vQNQ~U)?qp~N$fpn9&K{F^V4GtinMtjBm49S&R8A1?zMbiNjV>oGQtTlOlYfyO@3Y<0c)4B4LAjB@WLY8^U&WJmv`iCe!2QJfVW zQka;bD9~devns_!cahRE8ZfdK7T;rQC%+!%-|e+EbzR^NY%~M4fBnEQ;8yEh`D{4Q zyc3g?zt8L9{Ps7{ut-}J(Stk|q}s*mVCCYBq2`<;(jm}dBm^n=!6)Cl{BCvKv(d3g z`F|LdYiNw2Sl9|#W!v7HQwEJp+O{Ed>DpGn$8p(In$X*D<>4nGq-alNk@wLn( z+~g?)Bd+rL&YN7;7&0O;DysIsC5Yqmm#Q_-ZK&`Wue!Q31DaC0tI|`Tp(@$@ParMl zKNV>J`;!0rekh8x#-+KiaSB3Ne$Bny^b#PqH{DgqH&RtRA}9SX4Z%e!B|v1UG2oX0 zrVo!OEGi0yvwPcjn+fLp{a;)-+1Y(nAg%)kEGQxUA>k3P-GQE_3>-tL)B5_gWACq? zgZECtktik^H%UV%CBszkG;x!~au^Nn>uj*a!%ho!WSFShTg9rjS@-+1Y10t3kjD>nh%SQ zM;Zxfy5Lqw!pr=Dl{3!$>`Ml3Jm*1thFqTz?@?Gz<0_> zq9=}g2^ffa6#y)-C($1#?bh8;8_93CqAPp52M1L#($tUI4EWnJoGn<$m`$}Oqq!n< zmD)>Fgu#7eVE(8EsD8c>$%3fB6iNAK@TM_|ae=5%q!TY;%8+>FEZ%8f(E#|>)s;Jx zadvJl(tSk_OVGE~W#55claJK)#kWsN617X5^=0^^)M|-zPVWx~Rh3jjBML+iInVF@ zjW!yHA;$c6K6!?5FS&LEB&iytXKH%Pi^HDGN+oa;){{S#yrcXq?t+x$EbjTEu^RV9 z1V^65^~X;}TpsJoe2I0xSnBOYP@~)Jjz%BWs^4HhDp1ljD2-q7h!Y9mE(f7v$w(RN z(lAsZ7x}A|1Y5lh9`xgnr2$em6<%x7SDl%e`I;+3$qUR>Y#jgTi$k1Uzp%Hrp8_1f zpEGNs1ARF4j;D9!8EsW;)G?2g-$XKwY$MkTKApB<5lR%eECi}+67qo zIr}RuzLJfTmP9Di3^#>gtIJkw-5J6!I5=1x-t^eo+KIzhaxn&wYH}`M2&3zB1Dtc{B4!QFeD__=5+2G&*?Q`_+5HwOxmRns{gbdN3d)czq&40C2uzY_0 zEk8M-%{Yf!`6ZMQ&py_MgwFvJ8ynkEkrq!ZJu|bgt-7eH>fk^s{I}ncXU$QlWSJ3p;V57*Qp*q4xJpi_5YR{9+K)GhAvw#oj80X61Gzq8`wETWE+hrH$` zI*JS~F~+jGzeWDYjJ&W$xCVyO6Pszx<;jHH1EFt$n}T^6I)BCyM;TcS3&KCezjVcJx60Ng_P6%$(6Do#jQ~Xzo85& zZ?Oiuby5zVdinU=UXl$hI`7VwzXvC@?7Y2if+i;?bHIK@6Cs~kwBm+J7Q~x>rplUF z2TS_@A9wWf@{;1r_*x^&v0{vlg2a>}j~lbYKoCWf9DlSOc5)yoS_ACsGA9pDV}_0S z|5*E*$APX8DONB}p&fj%zaK@w=fcj6n|MW3P;iM~OsuB;ZI@n}UoEzrRfd{x@lX&l z+UAPq>b(;sPK#&?)IKvk{g?nFRLs%Jss(WmEDaoS_TsBfgDgt0M6bZm-CYL=OHMEq z;+;6Mc@r5KSv$7;=GA)rR`L%*YnUXI9jd^ZNAZ>*3Y(bNN1D-^o&b*m4vg_?)Z}DB zXlUrd{8ycK=%JFM8z=Z=Lj}gwNR4 zZ}uFSvnbww4&jzn8jX-e`m=OC9Lcr2^qypRF`;4Y6&=G2DY}IeKIv5JJLG2X-Cb|t z=xfhue80=89apwSUb)vIPvT$|vKcbfk{NirWk^&|b;h+XKjkMU=Lr3eGF!Fx=?&H< zTQju%=(E`1scNY2SyDVv0}JclhizK0K^1xwNd*ZdgK)S_^EIDqE9)ZjJ;m5GT>jFg zDl^Nr#jUY|A%4ZyzyJw!;{Qr$#*hMKN*dWW>h%8irql4K4>6VJLN%-ifjnpb|6YJq zQ=L>TsE+5|l`})J=on$&<|gf5;4j6WH`8ZlX7+AwZo<5EjEttVs&rGxNJyU3<2_qP zdUN=Q9o|Pv9{2L{gCx2eO?crM{R_0x9xL2W;U;gDIoHuP+|`cn>0i>yF!gu6HuN%S zDlPqRJHfYl*ZZe0Tx+pu0yr*Wi0>f#XyeKFI41KLkagLvr2I}0hiE`SRR%Yl2MEnx z)rP{L4!=_NwvV8;a2eFD6sJrMHN?bl91q}XQ5NwlvXct{r70J{cQAW}Q|Eg|UcpoY`259ezIBXv{bLwq* zzjhLQ2veoe8V(||%s5bY{>a3#8B9|*t%tCI!IKj&ixVZ&yIf3I>BP&P1Tsl7q_3}C zPkpsx7k5XGmSV&R_Qw7Ctni4YlaQYS z;%G3jXQ-aklP$HB=s%~v8d!J7`TfnPCTjN}(|2~v+4=bjeb&qQ-MLD~Xld%^5?Hy| zusJ71UPcCopQsUKf;^7rsm8n9WWef*Y@P zQ%`3^-d(JQcS1DynIQ`btQ~`!}fSFgAyRyyox1LhGM5k(7j!d6IsMjlE zKrk)i&FL+go0>!mlb2SPmTpiX@KzU_nVoMLBj#!b?QNK3@TTW1EG&zlVI(FZA`%lP z_Hboi46}}mr1lzEFiKvOA;rVQ(|5AkcR|#fa|+C@tlURhao_AX@!y3`Pfu?JiRZHt zM5|v~u3O@iSQpmSsVgfh(*e0iuUV!056Vn%yMc^`#jU6=(OLWnhqR=c1~0PAj`iTG zgGcP<{s11}z8OQ~X_>TmfaPfujS3&%I<2)Q889v2jAHN%VnZvvF`NBs9d<2EuGIC3;MQWJu1oQw65G!#w%*1%0-F)~>oTzS zCL_6jL4H!oo34IQ6aPwj za%E*J3ZFtb+}iukiR{y$rrPd1(eD&o3POjPiEg1o72A=ebqoTtV@!q z(35O5`=w!lB#GcWUX!@i%+cE<6y}GbOF0P!5r(<`1oh6?|LSs zo0>I-EH}5eIoiw@t3bUq035BM31#F_*0a<}t!K7fawZ)}fuIKALDg|O0&ec{P(|h! z;C%5T<`0&8F?x=|&g=c7m%n{LHn?KK%q^_m^Kf*m;Z#2BeEypCuCSqj>pfG71CHc4 z#0eu*QZQ>GQL>JKPMoPH)09$-Hu?LHnEmi?*0Uf9CP8v{cXyX21dQhY-%blg0V{lB zVvguk!Vna*aRzhH#)ZcfW+Wo3Sz04<&kA47mjnyVm0C)It_(JR722Ll#lgGrvJ zN(Vdn8JFw7JEt0O^A0Us1 z#lj-O!X33ArpR^Py+a-d@?w^V_|&#-Dkt&qkg~Gm%69+xYxf3y`CP+ros^Gf>Uu-K zpSr5HFyk0mUqdGt$D1lAA|7b|7i7jUc^q~8Fj}>c-hx1L6ii}D0TecIt}*}QwLn?! z^tLBiufKC+$Q?&p>Cc54U?y@(GPHc!a{4@_gumOXjL@t$cs%%9vgF6oqfua?q($-3 zjLha^C$U{#zi$<41SB6*7@UjHlD=4;o#dWS%=Z~`wqi!D25IPq%v#96$?HuBW>HbYee>}JmEzkRAFlGNaGbayDK`TIaL|8U1au1| zM${NWpcv1TXV4)jDy138iQ8=|qf&pwOP?mU4U@QaN(+-?^Ls{!t)(4a4Qx0M64Jn+ zL>Qr86o06c&X}8+^fc0%r_{YFv98dkFG_|Av?!)xtc(aRH}f7tN0sFS%Eo+iebXhN1?ZcMa4f%=4~1My^X17BEXChg2wLB}*IN zA0$MD%V(?@Z4t{<@NQN9=!jr`{q^t}-L-fy%%H6iUn?7@SFN5ZLsbiPLbN25X6SzU z5Oszek!PfZvk=d$lX`+|1!Lr{V73l*5~PyB$;ru~nC&wl_A1;rkYGfmLus~ydyJg; zTpsBOUhEk?3SxvJJw-!vK3sqz4oLN}#)G5-Q;Xc2(SpUBVTFV;>!+_&X#w?7 zIL+{XFJRewuZn>nx~x{UHsH}8WIbg6n%5y}N-8RA2hFPzjzqvog#bhYm8jO8KW)QFO^47!8koS0Zj z4SOA8)j_*f-M``b3f&?pY}fm=FDFYsd7|o_{|XIxoKa8qtlyCWvPJVE8x7hhmog~1ez8E0y|{pj2cbk$er1O7Q{t$%?U zPHKpc(DClZZZH?5e0q)pW&Lwj_|tzkS^dBO diff --git a/webroot/img/logo_schrift_half.webp b/webroot/img/logo_schrift_half.webp deleted file mode 100644 index fa7d49642b12e5f2cab00716bccd2e6b7dfa2486..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12190 zcmbW7WmFu`7p4bycXziixVsE4!5xAH3lJcZX5jJ;#!iRRK^U{dBu{=cMM~eqhp%~0q7<_{S@A}N{NWD-XOsh@dI^`Fj<+){Q;c25(-)! zuv?1L$CD}ov6HFM!?1~o_iXn~UeD0BMp~&zUxnglR)!3dByEsC1i@1dh6D*BvSIt* zoL#l7Cs`nKs9B=X#i#rsAJ~j}2R}%cwl!t}K01v!E`hw{94$Dw%f1R?q>U`EB0Pn= z*`Vj(jlmO}P=P7y<-{&j3rE6L+-i63XkjcqJxlnWhB;U%+1{orOic_pM(<*(EGA}| znlsT&o<;Ry8}eo5A|CIjm>PxD)Iy3r4y2}G#Hf$}LwWBf)nl%vy;}Cde-R6R+9)F+MZ-bS_?YD@M0Fq({DdLL#lKbm4C5>*DDg;p!3WW5nbUK1$|%1<4ni zZHk(sc1pecLFj~>6jPoD?fk~r6h1l3{&RG$QrijaPvxQd@Vwj_v-ktGJq_C)nE~b| z6T0Bn{cE$U#G(nI!N{d4JvKYbr^$)UObSxg#4Tf^U7&=WeQWN54_Hgvakbc9dUi3@ zez@#q$>TD8Twib;fX6iNqPeEMMlB`%n0YO~BCtO17%;@T#HN(eew?N6CQ~fP7d*)KYIo-n9-i>A64Wa7r>>x*%z0|?QIx;t-bGSS(e>$IBG%GYUUlGS!Ex*% zbZ@9G_j|!3S=P*Z!@#rU(F2Hmms!f`7Y&$$!}~rBVNTp7M|bgsACa$X+NI0^7gwxa z6sI7^?=rs-5do1fL6-26+^{*sFw|d>0W7irK=1*N?Itj3G1-h83NawcQuK}pRN=N( zqVaGV2@*wB!0HJ^8wbx-N(~)7Wan~xLkSz)s;bF^Xs2csyV|=IDCJSVN;GO2TPXs- z8x9pFO|;D;a#!8ck_^%VCC8zz%Itdsfudl2j<~p_OSn5|5ySoFbp!g5I%6Qlnvt9{ z^b!($81Swm*od*GgkL1*&zya{LS0^|#sKeA(51sv+Gxl*=K@%PgIMr#yzyC1#R#6* z|MwD!qMio?*YhD1y?MF5#Li+?JPq|~el&&w8A;8Jm$JP)zS$aj9ZTVKH@-o`)B#h3 z3)92gO^vqTr=MN=d+av9I&EHTNflehW}|~EFbl?ibz$VLfKXu$Io-=nBcTkKpMVj@ z9s__AHml>;OpB8Y-Tu(g)l!cnB>~y(Zz$G`@P8h)YTu6`W)VTIKghst5PzJW=k686 z+v;0~G$`nJd!y5o!T!dFRY^jw!iAw345a#gPe3CR+sUuAB7|p5u59AMZv!x1na{ds z#4h-pJZ8e1+%?Me6*mYV-nQ+%@dFf;4(kx5>4bT)ionJ~HHQR5U9Gl5K4fO3`BzeIrB4wcy9EZ-zP0UC`-Md_0gA1cgu~V3X3vR}Pep4l&POktTO~& z0|-CkE2ob=TT$bp{mI z1JIE_?KrH$x`X*HeOWdMN_9OqD` zSPYGjp^arTh`*%^{fNfuRq2`VR+1zm_l1Yhml;Lf3jX4mr6Kd_tW!w67$(`g*@u0c zo)oiD+#IAWKqm!2}sRtX=|w| zbZY$iC&n4#^K-UHz z#U`E!BYMumYrKE-YL{Xr6f(_`Qj~XW|D$*fH7O64d?C;PjpRSTci+~*HwnL41rXxaL=F*Qu=9U@cvL3Em^YANm#{604gD6>4o7W_b^=NQmaN`fu z`|!J<846HE#8y9TzFgw(NtkdzU>{oM8q%;aSk1qw@ikK6IWOldj+#Pgnxr#QpTy$l z$HnhIP4yGlgK>h&WD!$)A8~;+nx^_BJQ*f~cBv!-01F0Jmk_T9(?PA&Z{#eisD=Hq zs7EOaPG6kie}l)fZ~AruxOV4OzoT-f^5UprDKh0s;|+Gj!MGbT^U0#@94VKzS8^vF zss{7cBvk5J51LIQfKeo?I@W&@2_Dph5pQgCn{mk^a-!oa5%$Wt3_P5ovECG~(8+Jc z6$0oCkjYF`tgW>;p_Hc?Wb!ro6QLS=r;M2C`fB?8DP#I~ADf8;qHFlam>#kR9TAi1 zwHqnx29=CK6|WQbsHXCN&@XT|VJUP`a@_nLcvPCUCZ$OY8uv8O&knFQe;b&CbbW>L z-F}qyt>bkJHJU^c*!9RRQiypEVYU3~>GJ*b@p^?mtuB-)OY&*V-88jwfE@uI%$C)k z^K{m|&!^c4-L$8W<4V+=t=h?o;x0-MX-jJqtSMLD69sR_M&MTEd-eoSKKo`6WvOga zZo`z3yAcUYX17%2B3Vc|?-aWxtWFLO^jE&th$Q!ajmdDqgpSe|p}*pBLThV@trWvq zM%bIrCu5S*EOs}h{i$4nA0O`vcBS_EoEAY}OVBy0=sqocYafuQa^}fL3=^@QNS`(x zx3b&ukz=K*rhGsCeBMx9RYIVUXxEold%aZie2?XW!RuEWaL`P{?3(TZnz%eHtZYal zA)euAJEV+(A-Gono)4!!-p{o;o{|&Dn_#fU1IRa~0sNw|D2j(19h=n1J|HS2YFnG2 zk&%yEw8f+3L65#;XN<2WiJ3~$z6FKk4`aj~l0$RAI4Y0Gn}X)@`gKMTV{74S7k|FP zw2wVOXd(5!&?DkA+_K#5->=EABVld#TPqfed21DV3NGq~SdCdof%Jgi`K|5b_ss&|Gj5h6$f8&($kEbJyhKEwk-fAiEz-nk~#ZShPH;-f?jLX_2QJe~5Mgo4hgQeF;76m5a- zW1^|D&mP|Ul9LQtnsBfmwRgxV6Q@VZ)o7bGXyWdvRsC{VKXsI8qnF77)`VI&f3?^r zdm$pDhO=8y?$gIR>TB>gFWd0ycP-myk4LCzSrZHsvy#folSGx{!X(T85{e{*Ltn$j z1-$JIsPnJ@fGP<c3ZqrRh zuS~mC512F1q`(c|pnwEu!b|L_-ZRS)++)hE*$kEk)gkmOu-7;BCH5Ww34FyXhnrw~ zfZn($tuI1DvX{7)xPk+B1DD$mZP5c&Uj#15p4B(UPut4^zx!p}s}Gs2o_}Evyp?)s zNEmOWN`$OGhaTTQnxO^Y1fm@wJYro#uLEd&-QBa#vO>fw{FYzl@6?x}R{;^(!#-HI zdav1yNLMcV?R$Yd5LC$HM)z&|)%wxj4e<_WB2*qK1VMXlfM8u_D^X2AhoK~oUr(d1 zB`(Zv+Pk1Bk4O;ZS2hUJy~MRdjf6lz2h_bSLE?k5m3!c_{i{7HyM+3_O>C=luX6RK za<&ArR0Q*1y~y0S_z~_36yN5e7CxO*`^$bgnga*&ParvSHB@D{S2`ZRUQ(fj_$^tG z+Pise^AqAFXi5T088v07AZBWcAh+BLm7o)5*5WW8dnFO#E%Qc7q1#?cC6Z-a00%!h z(GSbe8CjYniHrzDqFpkHWQ3+#q+*pD zJkZVG#JV?&Dni^G)Rfv`BrEsfwp)IXV21U-rd=0H4ilGC%2>pUeePcKU?E|pBw)h& z<*B$yaj1J(L)WB1-+XLXi#iIKMv8HZms`yd$lv+q!45lUFTEKyjaWqa`5dhF7puH* z$-kZV&g5t)-UC@w@6?$0(~yk1QLR`jcDp{OU_ZCjsWD+rR?*R1&4OXYU)xTVzD1# z)Vtgy3Q0Ip`0dmXoA0FS^r|vk#6L{pZDbG$06_e9o-rNlf zvts@si&Q$*w!RyIBWL&LnBS4)xar4DySRor7EK8r+}D0}E?e{3u4^T*b9im#7ReF> zEnsId!~3XU4T&3pUU*??rIzHPmJ`3Z95zNJy?aI`v8Du`j%qTUpawOx3r2}#re2!% z#ReRl-8l;#A%AYg>j3aQT^Iy~J5YV4H6*%m1w=d;r+ff9J-$Gez3Zlvi+m2YU_{i| zeeT1uMUpUA%%_Teu-L9l@S{unPZKrSNyz3XYnW>5zl` z(*EKp4%a`(!#T>Ryz=kD7V-D*kyR~@m;8C%udbecm0-0(6ZCq6rB0O1oj{KSfmV-o zUpgbo#bEz=+=>BkR38_4Y)^~@h#wwo%mKzVf66RYq_K(5)p zF*5!(V$(2U#&oHGUqdnlBVpcj-N84WICoP1U+)jh50<^obm_HW+6ijpCtza?Oo1obG90JXxFVWGB7ooGLOvgQ z`iwkSM*)cfNY;jfZja~iK-ZPsh!yRv)WlJyS1Y{i!RFP%1GAzpj~nrn!xS?ODogzy zrl*WG%_~)>Z7!^yuEdO-oJi!WBx3woeOd!%(hb%JPX~fQBHf+srnTA2ds$Z#6?}sm zozjl<59H2g8`Vy~Wp;NrUlO%->s=;J`6*;^hs4*yGEW{db^z;;SV7*k3smbP@TgFH z#+aOuAChpGO!Mk|H7(-J{O(_fW!^J`gyqaEieiI1yj&kU<)y$3xglY?=MsliS8ejt(~2vK#pJ?tvzvRvtqS&2HHp z<9?4`zpF)V6oeoVbr`E^ygx*(f8n^XTr>(1Tlc%5aS_Dg(>4?rEEISFDV;%IJDYpd zZg-2g{!p>_xq$QK-doVXX)OBH{n>1EYcVC>DmAzoAsQZLo%X?ry|gGZ_2YDj<6zis zsPuF~f}=#^I8nsxb=pO_JTBbiBr{(1{2QeQGq48c;86?YFbg>rlEL z<^idt;8g@*n-LB{k68!fazAhhE@TdClBqL+Q}qub|KP_A-Wnu(3~k!5p0sdvup+H^ zD=JglHJUSt`xjcbz|uy^0)Rta`I6dz3E4K%v2}-@7b5UjX8!d znGaH(AqYSzIr2bjm znY$`FCws`^JY+IrGUH+K^15c|)creRmt7zQvMGMDvzhOZA;f7l88579j(R2#tLzZI zeT!ORSlD672Du(cEcVoRvvJFZ!G<0+BB=HJoyA=MhQM~er>XR|m=z}P7Fj0U9?8Oq zkX+VlCh3t@Dlj~C$?Tm#(pD~o{JS*%#)DT|Pt8w8KlSdYH5KCM6K80QWAo}&QX;)! zCVq$&dvli1^b1;17FHMz)yxS+_vYnQ7xY&zl+y1af>a)GS4!@Z`eY1`GhA>}SP8l7 zMl`7Yuzi^9{`}xJ;YW zsp}I!Q(gAu<7n9z`93^~0>2u!7oq(!q+P-EujWt7{$V1ya24>T~zmtMr4Y|872`Ya# z%I_zEK>=6H5UE_<5a=Y%O4=sI6gdUq?L)}G@9Y%|<{PUaD%4#Uam352@xCd9tL(CI zJF;K3e)bi9X2ytLfnNO=38DM0P{QZM2!AIT<23D|zO!6eC#erThf(ime{{mFm(C1-ai7}-mQpMXYzb2KJI=vQW@A`?)bst5){2xWf$ z;)3huuc;4q-2Hk_FqEb!fQwu<_K2cT!i3_15u+m^WM#NG&8i@*TB<84XXHH2*ZtRb z{h}{ev;e#qtk}oct)xAjNpF*OpW+Vt;7vE~VJsD6FFd8XhY~=gPC-`Dw${6|I&1f- zWeR8q(uQX@Zds*fL5KWy#uKD_pPs3+AP&@!crGZ`gm$qQb^lsoms73J)izWCKY5&d z%oR81v8+-+8IW|?H5%~U30jxFa5?YyA)3?CIMR95Ysj`NAr^i`R!je!PK?vs~8kEgNLzUw&Z_8U)`lh8@5&MY}k_zqw}M98=mZ|?K4 zi%53YWBvw?_Y*m+2tnXEUg{3aHuN2PkM0)6t3%TaqMVOQV5L~7CpmQ;+TF58DcOi# z3@xRMLCNN)>k-)J9y2B5>_~JIT^?@BxuGHaj?~!_``c0AF@nU1=Y~I)(%Ua*K0X(1 zaQ4x^Q`Ozw85}O;Kk)~jhez77_u`fR&I;Q7tA~UKLB)^Qd>x5ZbAs(c(@*+tubOll zUxgU>>4Gm8ct&b`a4UpS%uUAxGE@tmDvka|H5=G37(TV(^zB4N)cu1CwHPXKuP9!7bF3g}#K3z3-Lgz%Q(Gm3obg2r6s>FuFtwIeGVcxj7&47e6yyTl0L zvN@~wGH0_z@HNQZC>&Y8R`2^lK42n1$KrOwczsRxu#c2lA@YT1SwnXYDDKC%*L*IL zpKVzwvvRWW_T>%$kkbdrci{m5AP_46`RyL%?E@Y>0On1tygAH&^xF;|01E>LfO{)_ z-kcN$;a_cn-Za^N^!GQ-{MP25SlBn`hJgiOyp?fp4t&%2Z)Mh-+kg9a{+c&E@#e_? zI@sUB{)zl=sQ^;dpaybszk561;@@!#33GD`1No`B-wE>y3G)fQ^#Pmn?@SGEfpGuP zAKr5OV{a_~8T&tJ|H~o#R`XvD{(qwWGhW2E=ZOECCisv3hZhF+-@S;wwTJzW{)+on z@n-)XJ9GiM0l-$02g$#6^bf|{1-cB70U#qHA|WCmBOxK7pdh27<71$sp`nxD;$h)a zkWx`nkdl*A({nOW)3Vc%lQRpju)pKx<>jSf5)u;xigNPs0{=+@gMxyBj)qQ*fk6zU zA*TWUKO3|IfP)MWhIxaf1;FCKz~R6^djM2#<3xb@m;D>%A5b`W1Vkic6jZdg24L)e zW(p1#9u5Hk9{#P?|E(SXkAr|q!!3n~r)hyi>xvHyj{l8JCtcl1pf!0x&tvHpf`Up& zL`*`;z{teR!ph6XFCZu+EF&u?ub>E0(tfX_tEX>ZX!XI`#@5dMqx)wMPp>cDKA~Y> z!@qrxh)hWQnUtK8nwI`2H!r`Su&B7CrnU}T-_Y39+|}LF+t)uZI5agqGdnlGu(-6j zwY{^uw|{VWba{1sb9;CH@c8r(*FT*9wSSZSA6z(ZT(I!)aPUa~aKXTO{R55zk3hqX zh%2RuWZ{ZO3k*iamyZ8k-HAfSqjf=G={AWWKmu?ECJwtQGowY0>(fymLISfjCNC@xbZ$A9bW_g=pyM8$*MES30U7kc zbAS1NX&0g<&X#MR&a3rjYLyl0>JY|20g5eXQNC6#IPb&ucQk{?Oog{VSRhrYuJ7Sfi@ex5x^2n7yc1vF~JCVt*;8 znTFi?v1yPJY}Bjg-np?q<2MINeve&vamo$@0Uw#$PlhE4^<6k5ErX|@cp_i zwtF$za~^+A8M*&~TBp7lh4i(ioO1i5Kbb0cpggkY!iV*Xhyv?xuO$UKnAbgx{#(ZS z53dMp`Dj!Iroj*~MF2j*F+^o1k2%4!`BZ z_hYo18A9q;H3%Odi_$FZPG88gUJ1d6 zWo<~@qcK6Yruk&+BAT&sTl2=}ir`kJ-^a}?-!vY@-Dj(Vu!vtuv+HKoK)(Qh1@)`) zmXuXob1Uk3SvuCNt89+)>-*$z+!Q9I8r1D0k#*gN~%IT(Y; zxMr3zkbPN^QC&1yw_n0b6q0nFt>|A(f7v7H*(pAAYd%Cw9y-;E*uM=PIe-F|NM%-p z{}L*HV9oQ#^e$$6&EdqBgC~`iz8v`dcWTGGcm*Bn=kxVVg_3qp^L313K0@sg6o8wq zJMF&GUdJA@z9_dsWj7{T`Of+FaIP!?Kz~DU6`QivCLb8HXZPC=-WGT*7wrakU^oTxKz;>NUm$i_E7|4(AHII&l@7Y5TF$HQ-2S&# zWvfcNbpNMOcr8=OgzxAj2Fd`>SMQ2c{;gjP^o#VY$zp)P0tHdG1e_WL@TUN-ha{|U zQGBG(6l~W3=z49EJM|@K}9KY&ty(IBNKtUqn{# zSQuFW}A4#?vBdo(^6Zj7X+_1LIXucFIa=sXqsx5^To9l>;9g9J%#d4~O-ZMwc+M zf$dCNX{fuHB&68#6B1*qZ!Z-k#|z(<(J9Fd$kss*WskiBaf3?TCwzG8F1Pq0c4~AJ z46bdAq5sTklB7uTcqO#|44%~-lxi%k(L9MCCC>|U++NBnsjokE9x+LYUzpA8p3xIW z&G-3Cq) zj9CnLX{2(GSSplFm7ICjjBS5rZ`Mr1owbHp_&*>ZD%~-K1_P2#8|{WxBtV{cc4O){!8KfLA2|fgi}F-{ zalSTan?9*1uZvPH2&ObAb4#Xv2k)NQG{y|aq&mZwiM}G`QoOokr0~rn0-~jl?wXbN z{yzP5E!Xj$=u+&)jzFiPU`1oUi1IcOK1IMW+{PWf=H>M0;qaxgWQsn1{iHdf10>;1 z`AKq|S_83dP@q0enKNtHIey0*xZkeDrqE@$TamIQMx~WT%I51Z2DCv7Upa_TasJ z9EgJ9q?(p|tcmUIu;-|QO25*xu}wnJG-`oGd|c_9%2mm!l(>iYNej3rCWgrUBj0@@ z3}~FtYvPz%AX2Xf_c%j3OmIK)&OviqudnB1%uqM@V2iK^gj^q> z98Xo+Kef7jMBKGfmU9 zn$-@ysinc$4~~gb@+VuqDL>lK?s-#&=Imaeyrp8hCnr@nlhF8~B*}di*L<>`!7bad zw7x}dBajtK#p~sGB>>^$Q&#b2n;ah~%bw#*x-5ab7M5r9i&u07ufIYs(bR({M!Hh> z09sHP&j87jUiAx3y1gh~XipT)%6p0)_voifWBnJ~nS*CjJq}MfdC{?co{D9VsI@XK z;Ob>;`RD!3p}~^xQM$KA3|Swhrv%-_R(aVJ)_2m^s`!_$O-|L$A_^0qD+&jrsE(!~ zj|9WIehJY@XH&lS;zl^)hBbv^j*x2xzCq&Tgh_lTpvq^Oi_bG_^^cJpYmc+8RcNfj zapdB=UMN8HEgJtOgcj3M{dq@EK-8klsxqM6J8YJ9mOv@K#mMBBd@*BTaT3;Up2H;m zFI}%Yo%v^~OdpnTb||3qEk-Mk8*c;z1^7i$yuY;rYoW=Jk;^9)j8Y6D?Z<~t6ff8o zR~lZ()mS1wt7xw4{8>f6Al?%xQ#uCRWu5E8_44H$~{s(e4)K96y(P~*`QDF`NUU9CPq%P@$^Hx2;>{fWvFr%6tLO5qU%7n(lc2ng{U9b{ld04d$Cu~ z;mp+7&;s^EDBwa_=x`tP&yBt<0HJI3O%9R@zoSX|iLLOP;EXcaAN~MVF6${%!XhItAaav0;!+M+<}Zk3Bh2;C^fjjGx~=}5|a!0<>7l#K1+s6 zxiH**rbLb|*%h2_Y-EVXUG1TdUj(jLOewnzPAF~&UrAAdU-H6=Rf6jQl9;gGQuYF=z$>hy#07~&SH7@Xx~=_K_D36Ysl-8(embOI zUgR1`eba_3Ee30`??Ub(Utg!L*v~$NgfeKnyyS`oxij z>2g{(?q)#(H8CIpz)#)g>T%4nA$&2+8sxzwbTjTV5wZXU*sb=ZFrN8lC}`-or_kl} z`bWKn=2AU|Ed*`=1HTG$;DJKq5;%ZELioD|91}P z0e@#s)z+SfBDc;ut?_c0w-_bA+;xol7rPfMnAU)2lj=@#0mHb}aF_VX1@_nd* zit*93txD2A%oXrqE)BV!aM|y19wmCw(Ne@N)?<9nPhLfg?MS<8fLLJW_tcy6Yk={O mw^%0_#DOEU|5@4D@|gUDnkB Date: Mon, 26 Oct 2020 15:01:20 +0000 Subject: [PATCH 067/293] add new logo for desktop --- src/Template/Layout/frontend.ctp | 4 ++-- webroot/img/gradido_logo_web.png | Bin 0 -> 22236 bytes webroot/img/gradido_logo_web.webp | Bin 0 -> 13480 bytes 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 webroot/img/gradido_logo_web.png create mode 100644 webroot/img/gradido_logo_web.webp diff --git a/src/Template/Layout/frontend.ctp b/src/Template/Layout/frontend.ctp index 425073374..cb01fea30 100644 --- a/src/Template/Layout/frontend.ctp +++ b/src/Template/Layout/frontend.ctp @@ -55,8 +55,8 @@ $GLOBALS["self"] = $this; (0f8(p_dFWm9?bV#AG$wy2I)P-xGdw=_tcHq8d6$o zhTQjFu;EK$OK8Cktm0J%X&Xzhs=s^8GzUj89Eeiz&eHdWD+YGiFLy=zhF`H7zkij6 z2SO2bze~3ALu`A3pvl7G1c~B$Ssfuko26)D^xPgC;oNSy*gxmp z9wo?SKz3!cpI$=ua$Y32jqoCEc{~}1v@uS4AZvc`W(k_Oo)9lIU2YJu7lqG86^x2h zxugk*K9eF>YNF%`xg^}XD?s;VAo;Z^Q<)j|BTcqL)+heS`!Uw?Tj=jp%}XvivC5f! zuek+rvbE8D8!qJzcW&e+vY(4jBK>kYNiMCF{%v<%{ghwh;qpR%xN*mg&{t_b);Xp- z`h;KCy!5yRZr^yj5``;CFxPKX9vVymo2a~s)U7PS|*7N+&9N*Xbt*Q@W%O_j(iN;pyw=P``g?-YY z)$${Gw|JA-4*GJihB0>7L#WR*6Kax)V2_vGd^^BFz@B!o1JSxP#zU3I_3B=hf?2^* zjKf+FqOT|Re6C~)S>?mqc598~PUE9X5Oce8W%R9@y;m1d8{eLI^*6BR#LDKsIx0Vi zO^e_4Hhsp2d;>8Fd_y;UDv#`nUv*t~-m)ngm{B;C@}U{!2^?Opi>PA^+puQaZ#`GZ zKS;#)Nd0hkL35L7MxLnUO?{7hqP_8@SKI>SkuZ0|^l zmfUU|dGh9lxq0S-zh%)*RGhVzcX($Xu1#u-en3sQbCA4hkZQq~ImcZeb(M;Gwp>PR zLULbru^?3l`7;qF7fIcQXvR$?!Qz!d$5@Zv7XqaTPj&0i266IQ9>KX`-+;ZgpS3x|&rzg}Y(Nw~ZOX_Zoa>uKrP= z)u99}@IedWpiih?9KIGusGNDnkx;w6rntek_qBcmEPW!!vm(B)Qe1U9O!CT5NaJU_ z9ic{E0&anRSxbIZ8HUnZQ8ZiT(9f76^|%4;(P}_FjLk+O->0jkg+E)I5+l7?(6UlC zJdvNzg@v@-y?LJ2RrC#HuVJ~eu7UvD`+9KW`K}D#h+W~_0KXb{^UfCzjwYHLXQ-K3 zWy5=4D0TOVX}%JI;0DNO^M69z#hk7gS#l2>*lSttKuKKUN? ztmkG)o9NI~oMtpIsPVBZReEeUiL5ZDz9EbEVcV+&5v6P?=`6NJRKs+^Sm(3bt0iwD z^YK}ku1Gu+K|H&jjAsJ%WPVR*DzC_laWQtd&k>r71jdtZyjJc^d5xsMXaxOyp_XHj z(m-RMiQ#KmpdQjWH;scwdiky0S^8~DU!rmkOW0S#S-%78?5;=hKKw z^i1s;c!_MyhdR|hG<-2(8qo^va*2F>ZQMpHghcHIr+$!5eBCqH{si%;uis5~1#!ig zf{l*v8jXaV?XskXFRj&{+_@N{j-`YaRX?tM)0y;?{!`T86}jC!8g&`SXC8At zex6$Hl0^L~gy~$HFBw>KJin~PdG?w0Mb@nXgMkng`UPcvIDdLpnCO=2JJq{O>iB_? zun@29D#@9rvx+&aym;93Z*N+Xg2E`7D=v^5nWT8vM`I;PkJzoNtj>KV$fi~?l`^Xd zxmqT6-*@YY?Zd!2d`FgjHSZ*8!aViPaWO-QU6naOysgJlnLV*PpC6n`VucId%tGKI z&beqsUmjm=dnq0?w&assO;A7iF#qwPZ>8l}bw#jy&9}E#`JY^V(9AUAJ45~Oa#>~pfc}9qr6C%jX%E~8kP7o#{CML$gD#vJb+J4aGFa*k&s3oNd&n<3lB?vK+LUF)kbIVdi{*3 zt=DyuQ}hgsOw2rIdHK%qiy_1%B&DR4RaDh3sB2s_G%_|ZH8ZzB*`e(n9G#rKeSH1= z0|J9?+zgM1jEas)xph1BPTJk{jNH8ZhXsX2#U<4>k8A7d8ycIQw|8`Qb@%l44GoWs zz8M>T`)+3T!0)`3>1$a8ZM}aPjf+@QIFb;o$lo z1EB`35EfWtc9D#hfXQU?CzOQ{ z1nT7P-7i=YpnvC;%;0~j1a2M$n4nxl`?D+C5ItDn{$1ki^p#!1cfya|Bse86sbHSV zQ*3!~8Ij?3=g5Zhni#x|S9+grIJp~@!(RtmC@{Z^1^9cOj09`NC{0-2SYa34qqZhr zEwU<-&AB`7Hmu+C8ArQ;ouV@S*B%;y~UC0t;jvuC}0ctHpoe zD{^6%*kG&39BMCyH(VB-=fVPSowH}f%fA& z?U)(6-6uykD6v2&3Jc6SVuA2mvuoeUZbzM10D5xs6~%OVU5?0k|xI-9s_E+>Qq za@w)L6d2y!jCsDi_eMt!J7J?(;1?CIu>dJ==hQbw%>GvnEI?!RkoKx`_RFJn>6X9h zkpImtaKqTbIGm{U_+MwYr}$ z0c$0x+<=Xao5PI_5{Y(}@RGd#QrxohxHWvNUQPv0P-&m*$~1}9 z@9d2YO|tH-{=j{@=ehfIxkUs<(XjPRMEpqZmPom#5H!z z9RUkypJV&!5hqdH7`}?(o>P3e*ZytW7QUXnF#|63m>CwhWtuQn6- zCErRCZod$wpirseXwKQ;+>|XL*YOXbZ`Z9O$S@!rWee!n+6$~`iof(m2=iR^YLWFB zzoI+qr*(kdQ|E7eD|=fj5dDJCvrnVzf^!OzJ=O6|azo0de)Od7i_=)ZGbr0|*MxGr z|F&I(6A4kZiI;X73%9;#eWrcI3yF7kPKR!)aG$|ct8)|x$i15pDo+WB9-oAZ7Ui|d0pM2}iJbp>$l8>>U=&@K%^qaWjDP>n2dp{@5L-!wi&>8Hs09pEL^!^sOD z>?P9fZmC5~^=%>>9w+U^q&&jdO5vNP8~7JZyk1okzdkP}BzCA{&a5kV(QK|-y->c~ zAcR9-rWqnK(HsLDI@e4rxoU{lUy;c7zAmqCRM1d&Cdw^a{zHcLR8G-O5ZCf0*xRMy zZg1a`&~0%7NY&m%ws!YCN4fq8B2j!*2el9L<1w~8@4aSx<<_mZj5A@pu`iO`iN58( z3&OS5u){*lnm7!T6mJfblzghCMtDa(g925}MXk#m(;WOqH@1o%+;pocwWS`tckjI{!9`*{+&BP6NQ9f~=Hi|g!?&^^O*fA7Y*993Ww3O}{UZat1l9dS z7K$4~%_FQuyhBZ}!AZyIZs9-?$K04jNu?OR9PlvybNhAaKGv?<5XgUQ2Qz;~6&5&K z(af-+_d2oy2Mdr8K5PZgW-;cQs79gWhgVGzQC}Z#%hlGF2AEnlyb&&lX?rInbjHW+ zMUSAmtn+z!l9j3f^KUzNhx1r~`D@9{a^rc`!H&sTKE%lx>UW;0lFROgOZ2&aW|nvqne$hLn-~XO5+j(UnAsfPxtOj^%Q{F3ORG zD+kMr2OJgomV_D0=YbbT2mw-4f1(|ceX|{#z|82!9`?e5IWj2{Ch{|j=eEG05m(gL z5{+|&Kj@lA zhz^cOIcP6fEQn=c7RoRO#y-eJW7B4vi2*^oJR!^TU%W<44Y9zfh0d05gtv~4z+$0O z|1Y$uZdLKYqc4&=7BS118LQp;qiaK$sd2DcD3Sk_l#SP&$9S^V(v5({L*s_WAx=J6 zkAM(1j4*$puQF%%9ZgF)3lxJNFYno@?|2$m0CQaCfc4d12DTCMsfVrq15fo=oiPIY z*XD~V3XkXpV=;^5yoZNisT7m<7jk^$$aDwig}$}!fj~Ar7I?+1yT1=sHFOvLN}oW- zyOZ0Ly=y851uG@7?451-BmTs{kSN1Fn+YPQs;~TdMX)6nP;io8TLt6I@hi#RRk+#G zKwNoC|q7U?rmobR}~4)roAye#wt79Pme4&N-49Mvum3nHi0zf}4B z-<`z&Fh_}fYX<%cOGym?GV%eQNR$iOhtn4A;N&g~S$om~;dHW-g_t6=VcMR`Xh$dY zATP9Gkd6^5$OR>32a%WKlnIayaPxFS`ye?3++5wgr2}LkNIMT(v^3a19u|ghp0N11 z$U=@yDSLRKIl*iz1cRyuIQhXLpbjrPduam|wI3QlN*3biPM!J%-eW8Z%R<>sla{kx>Qx6lbhA(V%k zZ~)R%SVRaW?B@16x3`a~-ye4VmfPDX&=W0efcEzA^+KUl{m||{+&_(Zy83$m*_N+2 z`grKXS64fGVbIMJi$D2~FCl*CKMt6Klbh!W_c7;BE<4okJf6N@t|#+$C}FfK+6^@B z4Qdqmo!8UR!^gwh(Zln1kzYXkKK+Xups~Ma{~4iUPrxurt9YP%k8NtG{M;&b9w;X} z>EG2#i=f3sq{PKhP`E8z5-KGsW)GDF|AB|1By5ogl$aFan})l$57HflKGp{6 z7jgnM!4dXilD76JsHm+d3Mz({vV|gH5=f}1m?%;b1(!feib(#H*Y$D&cRSMc&t4tt zu>zIJgrT5PD0>*x4s8oZ!eB^o2`Ny|ar~tf^)zH5a3R&h8 za6ySvLseP)IIvJq_X&P!WiK?+2dx4&&>(ny1%*jL;gUuoqS9jG(g-mD7+e|#Vgdv5 z8>@$xk%xz?Eadl#uixgh!Gmsx^g;fuB1vfk;?IgePo3-o{}U^i7Ji&qX)O;F^7vH$ z=B(Y1grS6V5C*%#|IGE*8AC@8fA{|&{gdaXtfH5XzlWELu9vQ@GaBXd57Ph2^;6ye z%%$EwUV$3_DP{PA2@P{o!^pzhyS0~Ps)FO>U9fv~}f;w3}JIIe=r@uK0 z|FbRpn_6!Vdmn$K7h2H)Je{%-#p5*2srNG%aKc4|;GBHgNR*TNadtTO)2zQE`gptk z}3FYbFI{m{QVk8(u1JD|a@4VZ;~bLa2ih=_?uiX$aOplAsZ1QfibL_m@D zNGYhOJqm6oZfhrwK!BOye;>}D_VE8E9287kR8$0kfJ#Xs#i3#%A}FY>Ey5NmE-GOQ zvlkN+u@wVP^xwj{04Dj9t7lHWA1US^7DN4J{dWAF zk=8g)GKRjMo~}-4uRk{7iR|Ap{4scPLOuRj=#Tjm8D$U8KrsC}`sn(*|GlYy;W&}g zazdfqz5m|MpXP**k^ZSF0I{45fu+WA_xH+0j`P3Iedq!|Bb+ZBk Date: Thu, 29 Oct 2020 11:34:15 +0000 Subject: [PATCH 068/293] update transfer with new protocoL --- .../TransactionSendCoinsController.php | 175 +++++++----------- src/Form/TransferForm.php | 17 +- src/Template/TransactionSendCoins/create.ctp | 1 + 3 files changed, 81 insertions(+), 112 deletions(-) diff --git a/src/Controller/TransactionSendCoinsController.php b/src/Controller/TransactionSendCoinsController.php index c5a738736..90c6dc670 100644 --- a/src/Controller/TransactionSendCoinsController.php +++ b/src/Controller/TransactionSendCoinsController.php @@ -146,10 +146,17 @@ class TransactionSendCoinsController extends AppController } $user = $session->read('StateUser'); } + + $known_groups = $this->JsonRequestClient->sendRequest(json_encode([ + 'ask' => ['groups'] + ]), '/networkInfos'); + $transferForm = new TransferForm(); $this->set('transferForm', $transferForm); $this->set('timeUsed', microtime(true) - $startTime); + $this->set('groups', $known_groups['data']['data']['groups']); + $this->set('user', $user); if ($this->request->is('post')) { //$this->Flash->error(__('Wird zurzeit noch entwickelt!')); @@ -159,134 +166,88 @@ class TransactionSendCoinsController extends AppController if(isset($requestData['add'])) {$mode = 'add'; } if($transferForm->validate($requestData)) { - $receiverPubKeyHex = ''; - $senderPubKeyHex = $user['public_hex']; $amountCent = $this->GradidoNumber->parseInputNumberToCentNumber($requestData['amount']); if(!isset($user['balance']) || $amountCent > $user['balance']) { $this->Flash->error(__('Du hast nicht genug Geld!')); return; } - + $receiverEmail = $requestData['email']; if($receiverEmail === $user['email']) { $this->Flash->error(__('Du kannst dir leider nicht selbst Geld schicken!')); return; } - $receiverPubkeyHex =''; $requestAnswear = $this->JsonRequestClient->sendRequest(json_encode([ 'session_id' => $session->read('session_id'), - 'email' => $receiverEmail, - 'ask' => ['user.pubkeyhex', 'user.disabled'] - ]), '/getUserInfos'); + 'transaction_type' => 'transfer', + 'memo' => $requestData['memo'], + 'amount' => $amountCent, + 'target_group' => $known_groups['data']['data']['groups'][$requestData['group']], + 'target_email' => $receiverEmail + ]), '/createTransaction'); + if('success' == $requestAnswear['state'] && 'success' == $requestAnswear['data']['state']) { - // will be allways 64 byte long, even if it is empty - $receiverPubKeyHex = $requestAnswear['data']['userData']['pubkeyhex']; - } else { - $this->addAdminError('TransactionSendCoins', 'create', $requestAnswear, $user['id']); - $this->Flash->error(__('Der Empfänger wurde nicht auf dem Login-Server gefunden, hat er sein Konto schon angelegt?')); - $this->set('timeUsed', microtime(true) - $startTime); - return; - } - if(isset($requestAnswear['data']['userData']['disabled']) && $requestAnswear['data']['userData']['disabled']) { - $this->Flash->error(__('Der Empfänger ist deaktiviert, daher können ihm zurzeit keine Gradidos gesendet werden.')); - $this->set('timeUsed', microtime(true) - $startTime); - return; - } - - - if(0 == ord($receiverPubKeyHex)) { - $stateUserTable = TableRegistry::getTableLocator()->get('StateUsers'); - $receiverUser = $stateUserTable - ->find('all') - ->select(['public_key']) - ->contain(false) - ->where(['email' => $receiverEmail]); - - - if(!$receiverUser) { - $this->Flash->error(__('Diese E-Mail ist mir nicht bekannt, hat dein Empfänger denn schon ein Gradido-Konto?')); - $this->set('timeUsed', microtime(true) - $startTime); - return; - } - - if(isset($receiverUser->public_key)) { - $receiverPubKeyHex = bin2hex(stream_get_contents($receiverUser->public_key)); + $pendingTransactionCount = $session->read('Transactions.pending'); + if($pendingTransactionCount == null) { + $pendingTransactionCount = 1; } else { - $this->Flash->error(__('Das Konto mit der E-Mail: ' . $receiverEmail . ' wurde noch nicht aktiviert und kann noch keine GDD empfangen!')); + $pendingTransactionCount++; + } + $session->write('Transactions.pending', $pendingTransactionCount); + //echo "pending: " . $pendingTransactionCount; + if($mode === 'next') { + return $this->redirect($this->loginServerUrl . 'account/checkTransactions', 303); + } else { + $this->Flash->success(__('Transaction submitted for review.')); + } + } else { + + /* + * if request contain unknown parameter format, shouldn't happen't at all + * {"state": "error", "msg": "parameter format unknown"} + * if json parsing failed + * {"state": "error", "msg": "json exception", "details":"exception text"} + * if session_id is zero or not set + * {"state": "error", "msg": "session_id invalid"} + * if session id wasn't found on login server, if server was restartet or user logged out (also per timeout, default: 15 minutes) + * {"state": "error", "msg": "session not found"} + * if session hasn't active user, shouldn't happen't at all, login-server should be checked if happen + * {"state": "code error", "msg":"user is zero"} + * if transaction type not known + * {"state": "error", "msg":"transaction_type unknown"} + * if receiver wasn't known to Login-Server + * {"state": "not found", "msg":"receiver not found"} + * if receiver account disabled, and therefor cannto receive any coins + * {"state": "disabled", "msg":"receiver is disabled"} + * if transaction was okay and will be further proccessed + * {"state":"success"} + */ + $answear_data = $requestAnswear['data']; + if($answear_data['state'] === 'error') { + if($answear_data['msg'] === 'session_id invalid' || $answear_data['msg'] === 'session not found') { + $this->Flash->error(__('Fehler mit der Session, bitte logge dich erneut ein!')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } + } else if($answear_data['state'] === 'not found' && $answear_data['msg'] === 'receiver not found') { + $this->Flash->error(__('Der Empfänger wurde nicht auf dem Login-Server gefunden, hat er sein Konto schon angelegt?')); $this->set('timeUsed', microtime(true) - $startTime); return; - } + } else if($answear_data['state'] === 'disabled') { + $this->Flash->error(__('Der Empfänger ist deaktiviert, daher können ihm zurzeit keine Gradidos gesendet werden.')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } else { + $this->Flash->error(__('Unbehandelter Fehler: ') . json_encode($answear_data)); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } } - //var_dump($sessionStateUser); - - $builderResult = TransactionTransfer::build( - $amountCent, - $requestData['memo'], - $receiverPubKeyHex, - $senderPubKeyHex - ); - if($builderResult['state'] === 'success') { - - $http = new Client(); - try { - $loginServer = Configure::read('LoginServer'); - $url = $loginServer['host'] . ':' . $loginServer['port']; - $session_id = $session->read('session_id'); - /* - * - * $response = $http->post( - * 'http://example.com/tasks', - * json_encode($data), - * ['type' => 'json'] - * ); - */ - $response = $http->post($url . '/checkTransaction', json_encode([ - 'session_id' => $session_id, - 'transaction_base64' => base64_encode($builderResult['transactionBody']->serializeToString()), - 'balance' => $user['balance'] - ]), ['type' => 'json']); - $json = $response->getJson(); - if($json['state'] != 'success') { - if($json['msg'] == 'session not found') { - $session->destroy(); - return $this->redirect($this->loginServerUrl . 'account', 303); - //$this->Flash->error(__('session not found, please login again')); - } else { - $this->Flash->error(__('login server return error: ' . json_encode($json))); - } - } else { - $pendingTransactionCount = $session->read('Transactions.pending'); - if($pendingTransactionCount == null) { - $pendingTransactionCount = 1; - } else { - $pendingTransactionCount++; - } - $session->write('Transactions.pending', $pendingTransactionCount); - //echo "pending: " . $pendingTransactionCount; - if($mode === 'next') { - return $this->redirect($this->loginServerUrl . 'account/checkTransactions', 303); - } else { - $this->Flash->success(__('Transaction submitted for review.')); - } - } - - } catch(\Exception $e) { - $msg = $e->getMessage(); - $this->Flash->error(__('error http request: ') . $msg); - } - - } else { - $this->Flash->error(__('No Valid Receiver Public given: ' . $receiverPubKeyHex)); - } - -// */ - } else { - $this->Flash->error(__('Something was invalid, please try again!')); } } - + $this->set('timeUsed', microtime(true) - $startTime); } diff --git a/src/Form/TransferForm.php b/src/Form/TransferForm.php index 5572ddaf9..cb135ab9e 100644 --- a/src/Form/TransferForm.php +++ b/src/Form/TransferForm.php @@ -1,5 +1,5 @@ -addField('email', ['type' => 'string']) + ->addField('group', ['type' => 'string']) ->addField('amount', ['type' => 'decimal', 'precision' => 2]) ->addField('memo', ['type' =>'text', 'default' => '', 'rows' => 3, 'maxlength' => 150]); } function validationDefault(Validator $validator) { - $validator->setProvider('custom', 'App\Model\Validation\TransactionValidation'); + $validator->setProvider('custom', 'App\Model\Validation\TransactionValidation'); /* $validator->add('receiver_pubkey_hex', 'length', [ 'rule' => ['length', 64], @@ -34,6 +35,12 @@ class TransferForm extends Form 'rule' => 'email', 'message' => __('A valid email address is required') ]) + ->add('group', 'custom', [ + 'rule' => 'alphaNumeric', + 'provider' => 'custom', + //'message' => __('Only Alpha Numeric Character allowed') + 'message' => __('No HTML Tags like > or < please.') + ]) ->add('memo', 'length', [ 'rule' => ['maxLength', 150], 'message' => __('The memo should contain max 150 character') @@ -54,7 +61,7 @@ class TransferForm extends Form ->allowEmptyString('receiver_pubkey_hex', null, 'create')*/ ->add('amount', 'custom', [ 'rule' => 'amount', - 'provider' => 'custom', + 'provider' => 'custom', 'message' => __('Please give a valid positive number with maximal 2 decimal places') ]); return $validator; @@ -72,4 +79,4 @@ class TransferForm extends Form // Send an email. return true; } -} +} \ No newline at end of file diff --git a/src/Template/TransactionSendCoins/create.ctp b/src/Template/TransactionSendCoins/create.ctp index 9b578d0c9..91e7678e0 100644 --- a/src/Template/TransactionSendCoins/create.ctp +++ b/src/Template/TransactionSendCoins/create.ctp @@ -17,6 +17,7 @@ $this->loadHelper('Form', [
Form->create($transferForm) ?> Form->control('email', ['label' => __('Empfänger'), 'placeholder' => 'E-Mail']) ?> + Form->control('group', ['label' => __('Community Alias'), 'options' => $groups, 'default' => $user['group_alias']]) ?> Form->control('memo', ['label' => __('Verwendungszweck'), 'rows' => 3]) ?> Form->control('amount', ['label' => __('Betrag in GDD')]) ?> Form->button(__('Transaktion abschließen'), ['name' => 'next', 'class' => 'form-button']) ?> From 23492e97bb7f21a186959f2f72bae308093c8dbb Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Mon, 2 Nov 2020 15:51:37 +0000 Subject: [PATCH 069/293] update pending tasks, creation and transfer --- .../insert/insert_transaction_types.sql | 10 +- .../gradido_community/transaction_types.sql | 2 +- src/Controller/AppController.php | 11 +- .../JsonRequestHandlerController.php | 37 ++++- .../TransactionCreationsController.php | 154 +++++++++++------- .../TransactionSendCoinsController.php | 5 + src/Template/Element/navi_notify.ctp | 21 ++- 7 files changed, 160 insertions(+), 80 deletions(-) diff --git a/skeema/gradido_community/insert/insert_transaction_types.sql b/skeema/gradido_community/insert/insert_transaction_types.sql index 9dbf5b93f..7cc2ebfdd 100644 --- a/skeema/gradido_community/insert/insert_transaction_types.sql +++ b/skeema/gradido_community/insert/insert_transaction_types.sql @@ -1,5 +1,9 @@ - INSERT INTO `transaction_types` (`id`, `name`, `text`) VALUES -(1, 'creation', 'Aktives oder Bedingungsloses Grundeinkommen.'), -(2, 'transfer', 'Einfache Überweisung'); +(1, 'group create', 'create a new group, trigger creation of new hedera topic and new blockchain on node server'), +(2, 'group add member', 'add user to a group or move if he was already in a group'), +(3, 'creation', 'create new gradidos for member and also for group (in development)'), +(4, 'transfer', 'send gradidos from one member to another, also cross group transfer'), +(5, 'hedera topic create', 'create new topic on hedera'), +(6, 'hedera topic send message', 'send consensus message over hedera topic'), +(7, 'hedera account create', 'create new account on hedera for holding some founds with unencrypted keys'); diff --git a/skeema/gradido_community/transaction_types.sql b/skeema/gradido_community/transaction_types.sql index 87492e1fe..a3e6779d9 100644 --- a/skeema/gradido_community/transaction_types.sql +++ b/skeema/gradido_community/transaction_types.sql @@ -1,6 +1,6 @@ CREATE TABLE `transaction_types` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `name` varchar(24) COLLATE utf8mb4_unicode_ci NOT NULL, + `name` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL, `text` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/src/Controller/AppController.php b/src/Controller/AppController.php index 87ec7afb3..258ee565d 100644 --- a/src/Controller/AppController.php +++ b/src/Controller/AppController.php @@ -129,6 +129,7 @@ class AppController extends Controller if ($this->Auth->user('id')) { $GLOBALS['ServerUser'] = $this->Auth->user(); } + // login server url $loginServer = Configure::read('LoginServer'); if ($loginServer && isset($loginServer['url'])) { @@ -159,12 +160,14 @@ class AppController extends Controller $userStored = $session->read('StateUser'); $transactionPendings = $session->read('Transaction.pending'); - $transactionExecutings = $session->read('Transaction.executing'); + $transactionExecutings = $session->read('Transaction.executing'); + $transaction_can_signed = $session->read('Transaction.can_signed'); if ($session->read('session_id') != $session_id || ( $userStored && (!isset($userStored['id']) || !$userStored['email_checked'])) || intval($transactionPendings) > 0 || - intval($transactionExecutings) > 0) { + intval($transactionExecutings) > 0 || + intval($transaction_can_signed > 0)) { $http = new Client(); try { @@ -188,9 +191,11 @@ class AppController extends Controller //var_dump($json); $transactionPendings = $json['Transaction.pending']; $transactionExecuting = $json['Transaction.executing']; + $transaction_can_signed = $json['Transaction.can_signed']; //echo "read transaction pending: $transactionPendings
"; $session->write('Transaction.pending', $transactionPendings); $session->write('Transaction.executing', $transactionExecuting); + $session->write('Transaction.can_signed', $transaction_can_signed); $session->write('session_id', $session_id); $stateUserTable = TableRegistry::getTableLocator()->get('StateUsers'); @@ -204,7 +209,7 @@ class AppController extends Controller $stateUser = $stateUserQuery->first(); if ($stateUser->first_name != $json['user']['first_name'] || $stateUser->last_name != $json['user']['last_name'] || - $stateUser->disabled != intval($json['user']['disabled']) || + $stateUser->disabled != $json['user']['disabled'] || //$stateUser->username != $json['user']['username'] || // -> throws error $stateUser->email != $json['user']['email'] diff --git a/src/Controller/JsonRequestHandlerController.php b/src/Controller/JsonRequestHandlerController.php index 76bff2324..a0a0748c5 100644 --- a/src/Controller/JsonRequestHandlerController.php +++ b/src/Controller/JsonRequestHandlerController.php @@ -58,7 +58,7 @@ class JsonRequestHandlerController extends AppController { case 'checkUser': return $this->checkUser($jsonData->email, $jsonData->last_name); case 'getUsers' : return $this->getUsers($jsonData->page, $jsonData->limit); case 'getUserBalance': return $this->getUserBalance($jsonData->email, $jsonData->last_name); - case 'errorInTransaction': return $this->errorInTransaction($jsonData->created, $jsonData->transactionGenericHash, $jsonData->error, $jsonData->errorMessage); + case 'errorInTransaction': return $this->errorInTransaction($jsonData); } return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for post', 'details' => $method]); } @@ -71,16 +71,45 @@ class JsonRequestHandlerController extends AppController { //! using sodium_crypto_generichash to calculate // hash also in base64 format //! \param $error short error name in user language - //! \param $errorDetails more detailed error message in user language - private function errorInTransaction($transactionCreated, $transactionBodyBase64GenericHash, $error, $errorDetails) { + //! \param $errorDetails more detailed error message in user language + private function errorInTransaction($jsonData) { /* * payload.set("created", created); * payload.set("id", task_model->getID()); + * payload.set("type", task_model->getTaskTypeString()); * payload.set("public_key", user_model->getPublicKeyHex()); * payload.set("error", error); * payload.set("errorMessage", errorDetails); */ - + $stateErrorTable = TableRegistry::getTableLocator()->get('StateErrors'); + $stateUsersTable = TableRegistry::getTableLocator()->get('StateUsers'); + $transactionTypesTable = TableRegistry::getTableLocator()->get('TransactionTypes'); + $stateError = $stateErrorTable->newEntity(); + // + $pubkey = hex2bin($jsonData->public_key); + $user_query = $stateUsersTable->find('all')->select(['id'])->where(['public_key' => $pubkey]); + if($user_query->count() != 1) { + return $this->returnJson(['state' => 'error', 'msg' => 'user not found', 'details' => 'user pubkey hex:' . $jsonData->public_key]); + } + $stateError->state_user_id = $user_query->first()->id; + //$stateError->transaction_type_id + // TODO: + // - show state errors in navi_notify.ctp + $transaction_type_query = $transactionTypesTable->find('all')->select(['id'])->where(['name' => $jsonData->type]); + if($transaction_type_query->count() != 1) { + return $this->returnJson(['state' => 'error', 'msg' => 'transaction type not found', 'details' => 'transaction type name: ' . $jsonData->type]); + } + $stateError->transaction_type_id = $transaction_type_query->first()->id; + $stateError->created = $jsonData->created; + $stateError->message_json = json_encode(['task_id' => $jsonData->id, 'error' => $jsonData->error, 'errorMessage' => $jsonData->errorMessage]); + if(!$stateErrorTable->save($stateError)) { + $this->returnJsonSaveError($stateError, [ + 'state' => 'error', + 'msg' => 'error saving state_error in db', + 'details' => json_encode($stateError->getErrors()) + ]); + } + return $this->returnJson(['state' => 'success']); } private function putTransaction($transactionBase64) { diff --git a/src/Controller/TransactionCreationsController.php b/src/Controller/TransactionCreationsController.php index 5e29a7997..5acfce2d7 100644 --- a/src/Controller/TransactionCreationsController.php +++ b/src/Controller/TransactionCreationsController.php @@ -335,6 +335,7 @@ class TransactionCreationsController extends AppController if (isset($requestData['add'])) { $mode = 'add'; } + //echo "mode: $mode
"; $memo = $requestData['memo']; $amountCent = $this->GradidoNumber->parseInputNumberToCentNumber($requestData['amount']); //$targetDate = $requestData['target_date']; @@ -342,17 +343,20 @@ class TransactionCreationsController extends AppController $this->Flash->error(__('No user selected')); } else { $users = $requestData['user']; + $pendingTransactionCount = $session->read('Transactions.pending'); + if ($pendingTransactionCount == null) { + $pendingTransactionCount = 0; + } if (isset($requestData['user_pending'])) { $pendings = $requestData['user_pending']; } else { $pendings = []; } - $receiverUsers = $stateUserTable - ->find('all') - ->where(['id IN' => array_keys($users)]) - ->select(['public_key', 'email', 'id']) - ->contain(false); - $transactions = []; + $receiverUsers = $stateUserTable->find('all') + ->where(['id IN' => array_keys($users)]) + ->select(['public_key', 'email', 'id']) + ->contain(false); + foreach ($receiverUsers as $receiverUser) { $localAmountCent = $amountCent; //$localTargetDate = $targetDate; @@ -369,25 +373,87 @@ class TransactionCreationsController extends AppController $pendings[$id] = $localAmountCent; } $pubKeyHex = bin2hex(stream_get_contents($receiverUser->public_key)); - $identHash = TransactionCreation::DRMakeStringHash($receiverUser->email); + $localTargetDateFrozen = FrozenDate::now(); $localTargetDateFrozen = $localTargetDateFrozen - ->year($localTargetDate['year']) - ->month($localTargetDate['month']) - ->day($localTargetDate['day']); - //echo "input: "; var_dump($localTargetDate);echo "
"; - //echo "output: "; var_dump($localTargetDateFrozen); - //die('a'); - $builderResult = TransactionCreation::build( - $localAmountCent, - $memo, - $pubKeyHex, - $identHash, - $localTargetDateFrozen - ); - if ($builderResult['state'] == 'success') { - array_push($transactions, base64_encode($builderResult['transactionBody']->serializeToString())); + ->year($localTargetDate['year']) + ->month($localTargetDate['month']) + ->day($localTargetDate['day']); + + $requestAnswear = $this->JsonRequestClient->sendRequest(json_encode([ + 'session_id' => $session->read('session_id'), + 'transaction_type' => 'creation', + 'memo' => $memo, + 'amount' => $localAmountCent, + 'target_pubkey' => $pubKeyHex, + 'target_date' => $localTargetDateFrozen + ]), '/createTransaction'); + + if('success' != $requestAnswear['state']) { + $this->addAdminError('TransactionCreations', 'createMulti', $requestAnswear, $user['id']); + if ($requestResult['type'] == 'request error') { + $this->Flash->error(__('Error by requesting LoginServer, please try again')); + } else { + $this->Flash->error(__('Error, please wait for the admin to fix it')); + } } + if('success' == $requestAnswear['state'] && 'success' == $requestAnswear['data']['state']) { + $pendingTransactionCount++; + //echo "pending transaction count: $pendingTransactionCount
"; + } else { + /* + * if request contain unknown parameter format, shouldn't happen't at all + * {"state": "error", "msg": "parameter format unknown"} + * if json parsing failed + * {"state": "error", "msg": "json exception", "details":"exception text"} + * if session_id is zero or not set + * {"state": "error", "msg": "session_id invalid"} + * if session id wasn't found on login server, if server was restartet or user logged out (also per timeout, default: 15 minutes) + * {"state": "error", "msg": "session not found"} + * if session hasn't active user, shouldn't happen't at all, login-server should be checked if happen + * {"state": "code error", "msg":"user is zero"} + * if transaction type not known + * {"state": "error", "msg":"transaction_type unknown"} + * if receiver wasn't known to Login-Server + * {"state": "not found", "msg":"receiver not found"} + * if receiver account disabled, and therefor cannto receive any coins + * {"state": "disabled", "msg":"receiver is disabled"} + * if amount is invalid in creation + * {"state": "invalid parameter", "msg":"invalid amount", "details":"GDD amount in GDD cent ]0,10000000]"} + * if transaction was okay and will be further proccessed + * {"state":"success"} + */ + $answear_data = $requestAnswear['data']; + if($answear_data['state'] === 'error') { + if($answear_data['msg'] === 'session_id invalid' || $answear_data['msg'] === 'session not found') { + $this->Flash->error(__('Fehler mit der Session, bitte logge dich erneut ein!')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } + if($answear_data['msg'] === 'user not in group') { + $this->Flash->error(__('Fehler, Benutzer gehört zu einer anderen Gruppe!')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } + } else if($answear_data['state'] === 'not found' && $answear_data['msg'] === 'receiver not found') { + $this->Flash->error(__('Der Empfänger wurde nicht auf dem Login-Server gefunden, hat er sein Konto schon angelegt?')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } else if($answear_data['state'] === 'disabled') { + $this->Flash->error(__('Der Empfänger ist deaktiviert, daher können ihm zurzeit keine Gradidos gesendet werden.')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } else if($answear_data['msg'] === 'invalid amount') { + $this->Flash->error(__('Der Betrag ist ungültig, er muss größer als 0 und <= 1000 sein.')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } else { + $this->Flash->error(__('Unbehandelter Fehler: ') . json_encode($answear_data)); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } + } + } /*echo "pendings: "; var_dump($pendings); @@ -399,49 +465,17 @@ class TransactionCreationsController extends AppController } } $this->set('possibleReceivers', $possibleReceivers); - $creationTransactionCount = count($transactions); - if ($creationTransactionCount > 0) { + if ($pendingTransactionCount > 0) { $user_balance = 0; if (isset($user['balance'])) { $user_balance = $user['balance']; } - // $session_id, $base64Message, $user_balance = 0 - $requestResult = $this->JsonRequestClient->sendTransaction( - $session->read('session_id'), - $transactions, - $user_balance - ); - if ($requestResult['state'] != 'success') { - $this->addAdminError('TransactionCreations', 'createMulti', $requestResult, $user['id']); - if ($requestResult['type'] == 'request error') { - $this->Flash->error(__('Error by requesting LoginServer, please try again')); - } else { - $this->Flash->error(__('Error, please wait for the admin to fix it')); - } + $session->write('Transactions.pending', $pendingTransactionCount); + + if ($mode === 'next') { + return $this->redirect($this->loginServerUrl . 'account/checkTransactions', 303); } else { - $json = $requestResult['data']; - if ($json['state'] != 'success') { - if ($json['msg'] == 'session not found') { - $session->destroy(); - return $this->redirect($this->loginServerUrl . 'account', 303); - } else { - $this->addAdminError('TransactionCreations', 'createMulti', $json, $user['id']); - $this->Flash->error(__('Login Server Error, please wait for the admin to fix it')); - } - } else { - $pendingTransactionCount = $session->read('Transactions.pending'); - if ($pendingTransactionCount == null) { - $pendingTransactionCount = $creationTransactionCount; - } else { - $pendingTransactionCount += $creationTransactionCount; - } - $session->write('Transactions.pending', $pendingTransactionCount); - if ($mode === 'next') { - return $this->redirect($this->loginServerUrl . 'account/checkTransactions', 303); - } else { - $this->Flash->success(__('Transaction submitted for review.')); - } - } + $this->Flash->success(__('Transaction submitted for review.')); } } } diff --git a/src/Controller/TransactionSendCoinsController.php b/src/Controller/TransactionSendCoinsController.php index 90c6dc670..39d1eea1b 100644 --- a/src/Controller/TransactionSendCoinsController.php +++ b/src/Controller/TransactionSendCoinsController.php @@ -230,6 +230,11 @@ class TransactionSendCoinsController extends AppController $this->set('timeUsed', microtime(true) - $startTime); return; } + if($answear_data['msg'] === 'user not in group') { + $this->Flash->error(__('Empfänger befindet sich nicht in Zielgruppe!')); + $this->set('timeUsed', microtime(true) - $startTime); + return; + } } else if($answear_data['state'] === 'not found' && $answear_data['msg'] === 'receiver not found') { $this->Flash->error(__('Der Empfänger wurde nicht auf dem Login-Server gefunden, hat er sein Konto schon angelegt?')); $this->set('timeUsed', microtime(true) - $startTime); diff --git a/src/Template/Element/navi_notify.ctp b/src/Template/Element/navi_notify.ctp index 35687687d..61e6cdd5b 100644 --- a/src/Template/Element/navi_notify.ctp +++ b/src/Template/Element/navi_notify.ctp @@ -11,6 +11,7 @@ use Cake\Routing\Router; $session = $this->getRequest()->getSession(); $errorCount = intval($session->read('StateUser.errorCount')); $transactionPendings = $session->read('Transactions.pending'); +$transactionPendings += $session->read('Transaction.can_signed'); /* class NavHeaderEntry @@ -23,19 +24,21 @@ class NavHeaderEntry } */ ?> + 0) : ?> + Html->link( + 'announcement' + . 'ss', + ['controller' => 'StateErrors', 'action' => 'ShowForUser'], + ['class' => 'nav-link', 'escape' => false, 'title' => "$errorCount " . __('Fehler')]) ?> + 0) : ?> -
" href="account/checkTransactions"> - verified_user + " href="account/checkTransactions"> + verified_user - + () + - 0) : ?> - Html->link( - 'announcement', - ['controller' => 'StateErrors', 'action' => 'ShowForUser'], - ['class' => 'notify-link', 'escape' => false, 'title' => "$errorCount " . __('Fehler')]) ?> - From 01f0bd5323a3131790cbab2211ff7b68b4b621f2 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Thu, 5 Nov 2020 16:06:39 +0000 Subject: [PATCH 070/293] add login server manage links to dashboard --- .../JsonRequestHandlerController.php | 25 +++++++---- src/Template/Dashboard/index.ctp | 42 +++++++++++-------- 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/Controller/JsonRequestHandlerController.php b/src/Controller/JsonRequestHandlerController.php index a0a0748c5..84a9c4b92 100644 --- a/src/Controller/JsonRequestHandlerController.php +++ b/src/Controller/JsonRequestHandlerController.php @@ -59,12 +59,27 @@ class JsonRequestHandlerController extends AppController { case 'getUsers' : return $this->getUsers($jsonData->page, $jsonData->limit); case 'getUserBalance': return $this->getUserBalance($jsonData->email, $jsonData->last_name); case 'errorInTransaction': return $this->errorInTransaction($jsonData); + case 'updateReadNode': return $this->updateReadNode(); } return $this->returnJson(['state' => 'error', 'msg' => 'unknown method for post', 'details' => $method]); } return $this->returnJson(['state' => 'error', 'msg' => 'no post or get']); } - + + // Called from login server like a cron job every 10 minutes or after sending transaction to hedera + private function updateReadNode() + { + return $this->returnJson(['state' => 'success']); + } + + /* + * payload.set("created", created); + * payload.set("id", task_model->getID()); + * payload.set("type", task_model->getTaskTypeString()); + * payload.set("public_key", user_model->getPublicKeyHex()); + * payload.set("error", error); + * payload.set("errorMessage", errorDetails); + */ //! \param $transactionCreated creation of transaction in timestamp in seconds //! -1 if transaction couldn't decode //! \param $transactionBodyBase64Sha256 generic hash from transaction body serialized and converted to base64 @@ -73,14 +88,6 @@ class JsonRequestHandlerController extends AppController { //! \param $error short error name in user language //! \param $errorDetails more detailed error message in user language private function errorInTransaction($jsonData) { - /* - * payload.set("created", created); - * payload.set("id", task_model->getID()); - * payload.set("type", task_model->getTaskTypeString()); - * payload.set("public_key", user_model->getPublicKeyHex()); - * payload.set("error", error); - * payload.set("errorMessage", errorDetails); - */ $stateErrorTable = TableRegistry::getTableLocator()->get('StateErrors'); $stateUsersTable = TableRegistry::getTableLocator()->get('StateUsers'); $transactionTypesTable = TableRegistry::getTableLocator()->get('TransactionTypes'); diff --git a/src/Template/Dashboard/index.ctp b/src/Template/Dashboard/index.ctp index 095234222..fdfe5b072 100644 --- a/src/Template/Dashboard/index.ctp +++ b/src/Template/Dashboard/index.ctp @@ -53,9 +53,8 @@ $this->assign(
redeem - Html->link( - __('schöpfen'), + __('viele schöpfen'), ['controller' => 'TransactionCreations', 'action' => 'createMulti'], ['class' => 'action-button-link'] );?> @@ -63,7 +62,7 @@ $this->assign(
-

Statistik

+ Statistik
cached @@ -112,24 +111,33 @@ $this->assign(
-

Roles ...

+

Login Server ...

- roles - Html->link( - __('View'), - ['controller' => 'Roles', 'action' => 'index'], - ['class' => 'info-item-link'] - ); ?> + groups + + +
- assign_roles - Html->link( - __('Assign Roles'), - ['controller' => 'StateUserRoles', 'action' => 'search'], - ['class' => 'info-item-link'] - ); ?> + servers + + + +
+
+ topics + + + +
+
+
+
+ hedera_accounts + + +
-
From bd6640388d623baa1d1d57e1b9867e5331b83119 Mon Sep 17 00:00:00 2001 From: Dario Rekowski on RockPI Date: Fri, 6 Nov 2020 14:10:38 +0000 Subject: [PATCH 071/293] finish parsing transactions from gradido node --- skeema/gradido_community/address_types.sql | 7 + .../insert/address_types.sql | 2 + .../insert/insert_transaction_types.sql | 15 +- .../state_group_addresses.sql | 3 +- .../transaction_group_addaddress.sql | 1 + .../transaction_send_coins.sql | 5 +- src/Controller/AddressTypesController.php | 5 +- .../JsonRpcRequestClientComponent.php | 13 +- src/Controller/ErrorController.php | 2 +- .../JsonRequestHandlerController.php | 41 ++ src/Controller/StateBalancesController.php | 8 +- src/Model/Entity/AddressType.php | 4 +- .../Entity/TransactionGroupAddaddres.php | 1 + src/Model/Table/AddressTypesTable.php | 11 +- src/Model/Transactions/Record.php | 471 ++++++++++++++++++ src/Template/AddressTypes/add.ctp | 4 +- src/Template/AddressTypes/edit.ctp | 4 +- src/Template/AddressTypes/index.ctp | 8 +- src/Template/AddressTypes/view.ctp | 10 +- src/Template/StateBalances/overview.ctp | 4 +- tests/Fixture/AddressTypesFixture.php | 12 +- 21 files changed, 586 insertions(+), 45 deletions(-) create mode 100644 skeema/gradido_community/address_types.sql create mode 100644 skeema/gradido_community/insert/address_types.sql create mode 100644 src/Model/Transactions/Record.php diff --git a/skeema/gradido_community/address_types.sql b/skeema/gradido_community/address_types.sql new file mode 100644 index 000000000..cb5b1b943 --- /dev/null +++ b/skeema/gradido_community/address_types.sql @@ -0,0 +1,7 @@ +CREATE TABLE `address_types` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL, + `text` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + diff --git a/skeema/gradido_community/insert/address_types.sql b/skeema/gradido_community/insert/address_types.sql new file mode 100644 index 000000000..2a6dc00a5 --- /dev/null +++ b/skeema/gradido_community/insert/address_types.sql @@ -0,0 +1,2 @@ +INSERT INTO `address_types` (`id`, `name`, `text`) VALUES +(1, 'user main', 'user main address'); diff --git a/skeema/gradido_community/insert/insert_transaction_types.sql b/skeema/gradido_community/insert/insert_transaction_types.sql index 7cc2ebfdd..02ef8374a 100644 --- a/skeema/gradido_community/insert/insert_transaction_types.sql +++ b/skeema/gradido_community/insert/insert_transaction_types.sql @@ -1,9 +1,10 @@ INSERT INTO `transaction_types` (`id`, `name`, `text`) VALUES -(1, 'group create', 'create a new group, trigger creation of new hedera topic and new blockchain on node server'), -(2, 'group add member', 'add user to a group or move if he was already in a group'), -(3, 'creation', 'create new gradidos for member and also for group (in development)'), -(4, 'transfer', 'send gradidos from one member to another, also cross group transfer'), -(5, 'hedera topic create', 'create new topic on hedera'), -(6, 'hedera topic send message', 'send consensus message over hedera topic'), -(7, 'hedera account create', 'create new account on hedera for holding some founds with unencrypted keys'); +(1, 'creation', 'create new gradidos for member and also for group (in development)'), +(2, 'transfer', 'send gradidos from one member to another, also cross group transfer'), +(3, 'group create', 'create a new group, trigger creation of new hedera topic and new blockchain on node server'), +(4, 'group add member', 'add user to a group or move if he was already in a group'), +(5, 'group remove member', 'remove user from group, maybe he was moved elsewhere'), +(6, 'hedera topic create', 'create new topic on hedera'), +(7, 'hedera topic send message', 'send consensus message over hedera topic'), +(8, 'hedera account create', 'create new account on hedera for holding some founds with unencrypted keys'); diff --git a/skeema/gradido_community/state_group_addresses.sql b/skeema/gradido_community/state_group_addresses.sql index 1d256f3e0..698a79b98 100644 --- a/skeema/gradido_community/state_group_addresses.sql +++ b/skeema/gradido_community/state_group_addresses.sql @@ -3,5 +3,6 @@ CREATE TABLE `state_group_addresses` ( `group_id` int(10) unsigned NOT NULL, `public_key` binary(32) NOT NULL, `address_type_id` int(10) unsigned NOT NULL, - PRIMARY KEY (`id`) + PRIMARY KEY (`id`), + UNIQUE(`public_key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/skeema/gradido_community/transaction_group_addaddress.sql b/skeema/gradido_community/transaction_group_addaddress.sql index dceac273c..b9ca95651 100644 --- a/skeema/gradido_community/transaction_group_addaddress.sql +++ b/skeema/gradido_community/transaction_group_addaddress.sql @@ -2,6 +2,7 @@ CREATE TABLE `transaction_group_addaddress` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `transaction_id` int(10) unsigned NOT NULL, `address_type_id` int(10) unsigned NOT NULL, + `remove_from_group` BOOLEAN DEFAULT FALSE, `public_key` binary(32) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/skeema/gradido_community/transaction_send_coins.sql b/skeema/gradido_community/transaction_send_coins.sql index f57a2175e..49423fdbc 100644 --- a/skeema/gradido_community/transaction_send_coins.sql +++ b/skeema/gradido_community/transaction_send_coins.sql @@ -1,9 +1,10 @@ CREATE TABLE `transaction_send_coins` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `transaction_id` int(10) unsigned NOT NULL, - `state_user_id` int(10) unsigned NOT NULL, + `sender_public_key` binary(32) NOT NULL, + `state_user_id` int(10) unsigned DEFAULT 0, `receiver_public_key` binary(32) NOT NULL, - `receiver_user_id` int(10) unsigned NOT NULL, + `receiver_user_id` int(10) unsigned DEFAULT 0, `amount` bigint(20) NOT NULL, `sender_final_balance` bigint(20) NOT NULL, PRIMARY KEY (`id`) diff --git a/src/Controller/AddressTypesController.php b/src/Controller/AddressTypesController.php index 348a8e9e6..9b13a7720 100644 --- a/src/Controller/AddressTypesController.php +++ b/src/Controller/AddressTypesController.php @@ -2,7 +2,6 @@ namespace App\Controller; use App\Controller\AppController; -use Cake\I18n\Number; /** * AddressTypes Controller @@ -35,7 +34,7 @@ class AddressTypesController extends AppController public function view($id = null) { $addressType = $this->AddressTypes->get($id, [ - 'contain' => ['StateGroupAddresses', 'TransactionGroupAddaddress'] + 'contain' => ['StateGroupAddresses', 'TransactionGroupAddaddress'], ]); $this->set('addressType', $addressType); @@ -71,7 +70,7 @@ class AddressTypesController extends AppController public function edit($id = null) { $addressType = $this->AddressTypes->get($id, [ - 'contain' => [] + 'contain' => [], ]); if ($this->request->is(['patch', 'post', 'put'])) { $addressType = $this->AddressTypes->patchEntity($addressType, $this->request->getData()); diff --git a/src/Controller/Component/JsonRpcRequestClientComponent.php b/src/Controller/Component/JsonRpcRequestClientComponent.php index d5ca72808..980a64e8d 100644 --- a/src/Controller/Component/JsonRpcRequestClientComponent.php +++ b/src/Controller/Component/JsonRpcRequestClientComponent.php @@ -41,7 +41,11 @@ class JsonRpcRequestClientComponent extends Component public function sendRequest($message) { $http = new Client(); - $response = $http->post($this->getGradidoNodeUrl(), $message, ['type' => 'json']); + try { + $response = $http->post($this->pickGradidoNodeUrl(), $message, ['type' => 'json']); + } catch(Exception $e) { + return ['state' => 'error', 'type' => 'http exception', 'details' => $e->getMessage()]; + } $responseStatus = $response->getStatusCode(); if($responseStatus != 200) { return ['state' => 'error', 'type' => 'request error', 'msg' => 'server response status code isn\'t 200', 'details' => $responseStatus]; @@ -59,10 +63,11 @@ class JsonRpcRequestClientComponent extends Component //return ['state' => 'success', 'data' => $json]; } - static public function getGradidoNodeUrl() + static public function pickGradidoNodeUrl() { - $gradidoNode = Configure::read('GradidoNode'); - return $gradidoNode['host'] . ':' . $gradidoNode['port']; + $gradidoNodes = Configure::read('GradidoNode'); + $i = rand(0, count($gradidoNodes)-1); + return $gradidoNodes[$i]['host'] . ':' . $gradidoNodes[$i]['port']; } diff --git a/src/Controller/ErrorController.php b/src/Controller/ErrorController.php index 43bd2fb52..c5421a24d 100644 --- a/src/Controller/ErrorController.php +++ b/src/Controller/ErrorController.php @@ -54,7 +54,7 @@ class ErrorController extends AppController public function beforeRender(Event $event) { parent::beforeRender($event); - + $this->RequestHandler->renderAs($this, 'json'); $this->viewBuilder()->setTemplatePath('Error'); } diff --git a/src/Controller/JsonRequestHandlerController.php b/src/Controller/JsonRequestHandlerController.php index 84a9c4b92..928559d7b 100644 --- a/src/Controller/JsonRequestHandlerController.php +++ b/src/Controller/JsonRequestHandlerController.php @@ -10,6 +10,7 @@ use Cake\Core\Configure; use Model\Transactions\TransactionTransfer; use Model\Transactions\Transaction; +use Model\Transactions\Record; /*! * @author: Dario Rekowski# * @@ -24,6 +25,7 @@ class JsonRequestHandlerController extends AppController { { parent::initialize(); $this->loadComponent('JsonRequestClient'); + $this->loadComponent('JsonRpcRequestClient'); //$this->Auth->allow(['add', 'edit']); $this->Auth->allow('index'); } @@ -69,6 +71,45 @@ class JsonRequestHandlerController extends AppController { // Called from login server like a cron job every 10 minutes or after sending transaction to hedera private function updateReadNode() { + $this->autoRender = false; + $response = $this->response->withType('application/json'); + + $transactionsTable = TableRegistry::getTableLocator()->get('Transactions'); + $last_transaction = $transactionsTable->find('all')->order(['id' => 'DESC'])->first(); + $group_alias = Configure::read('GroupAlias'); + $result = $this->JsonRpcRequestClient->request('getTransactions', ['groupAlias' => $group_alias, 'lastKnownSequenceNumber' => $last_transaction->id]); + if(isset($result['state']) && $result['state'] == 'error') { + return $this->returnJson(['state' => 'error', 'msg' => 'jsonrpc error', 'details' => $result]); + } + $part_count = -1; + $temp_record = new Record; + $errors = []; + foreach($result as $_record) { + $parse_result = $temp_record->parseRecord($_record); + if($parse_result == true) { + $sequenceNumber = $temp_record->getSequenceNumber(); + if($part_count == -1) { + $part_count = $temp_record->getPartCount(); + } + $part_count--; + + if($part_count == 0) { + $finalize_result = $temp_record->finalize(); + if($finalize_result != true) { + $errors[] = ['msg' => 'error in finalize', 'record' => $_record, 'details' => $finalize_result, 'sequenceNumber' => $sequenceNumber]; + } + $temp_record = new Record; + $part_count = -1; + } + } else { + $temp_record = new Record; + $part_count = -1; + $errors[] = ['msg' => 'error in parse record', 'record' => $_record, 'details' => $parse_result]; + } + } + if(count($errors)) { + return $this->returnJson(['state' => 'error', 'msg' => 'error in parsing records', 'details' => $errors]); + } return $this->returnJson(['state' => 'success']); } diff --git a/src/Controller/StateBalancesController.php b/src/Controller/StateBalancesController.php index bddf35125..2436d83d3 100644 --- a/src/Controller/StateBalancesController.php +++ b/src/Controller/StateBalancesController.php @@ -170,17 +170,22 @@ class StateBalancesController extends AppController foreach ($transferTransactions as $sendCoins) { $type = ''; $otherUser = null; + $other_user_public = ''; if ($sendCoins->state_user_id == $user['id']) { $type = 'send'; if(isset($involvedUserIndices[$sendCoins->receiver_user_id])) { $otherUser = $involvedUserIndices[$sendCoins->receiver_user_id]; } + $other_user_public = bin2hex(stream_get_contents($sendCoins->receiver_public_key)); } else if ($sendCoins->receiver_user_id == $user['id']) { $type = 'receive'; if(isset($involvedUserIndices[$sendCoins->state_user_id])) { $otherUser = $involvedUserIndices[$sendCoins->state_user_id]; } + if($sendCoins->sender_public_key) { + $other_user_public = bin2hex(stream_get_contents($sendCoins->sender_public_key)); + } } if(null == $otherUser) { $otherUser = $this->StateBalances->StateUsers->newEntity(); @@ -192,7 +197,8 @@ class StateBalancesController extends AppController 'transaction_id' => $sendCoins->transaction_id, 'date' => $sendCoins->transaction->received, 'balance' => $sendCoins->amount, - 'memo' => $sendCoins->transaction->memo + 'memo' => $sendCoins->transaction->memo, + 'pubkey' => $other_user_public ]); } uasort($transactions, array($this, 'sortTransactions')); diff --git a/src/Model/Entity/AddressType.php b/src/Model/Entity/AddressType.php index 08dbba281..87d64d61a 100644 --- a/src/Model/Entity/AddressType.php +++ b/src/Model/Entity/AddressType.php @@ -8,7 +8,7 @@ use Cake\ORM\Entity; * * @property int $id * @property string $name - * @property string|null $text + * @property string $text * * @property \App\Model\Entity\StateGroupAddress[] $state_group_addresses * @property \App\Model\Entity\TransactionGroupAddaddres[] $transaction_group_addaddress @@ -28,6 +28,6 @@ class AddressType extends Entity 'name' => true, 'text' => true, 'state_group_addresses' => true, - 'transaction_group_addaddress' => true + 'transaction_group_addaddress' => true, ]; } diff --git a/src/Model/Entity/TransactionGroupAddaddres.php b/src/Model/Entity/TransactionGroupAddaddres.php index 3cb73b9ee..0559a6302 100644 --- a/src/Model/Entity/TransactionGroupAddaddres.php +++ b/src/Model/Entity/TransactionGroupAddaddres.php @@ -28,6 +28,7 @@ class TransactionGroupAddaddres extends Entity protected $_accessible = [ 'transaction_id' => true, 'address_type_id' => true, + 'remove_from_group' => true, 'public_key' => true, 'transaction' => true, 'address_type' => true diff --git a/src/Model/Table/AddressTypesTable.php b/src/Model/Table/AddressTypesTable.php index ea0c86d6e..ba94c99c7 100644 --- a/src/Model/Table/AddressTypesTable.php +++ b/src/Model/Table/AddressTypesTable.php @@ -38,10 +38,10 @@ class AddressTypesTable extends Table $this->setPrimaryKey('id'); $this->hasMany('StateGroupAddresses', [ - 'foreignKey' => 'address_type_id' + 'foreignKey' => 'address_type_id', ]); $this->hasMany('TransactionGroupAddaddress', [ - 'foreignKey' => 'address_type_id' + 'foreignKey' => 'address_type_id', ]); } @@ -54,19 +54,20 @@ class AddressTypesTable extends Table public function validationDefault(Validator $validator) { $validator - ->integer('id') + ->nonNegativeInteger('id') ->allowEmptyString('id', null, 'create'); $validator ->scalar('name') - ->maxLength('name', 25) + ->maxLength('name', 45) ->requirePresence('name', 'create') ->notEmptyString('name'); $validator ->scalar('text') ->maxLength('text', 255) - ->allowEmptyString('text'); + ->requirePresence('text', 'create') + ->notEmptyString('text'); return $validator; } diff --git a/src/Model/Transactions/Record.php b/src/Model/Transactions/Record.php new file mode 100644 index 000000000..da52db8ac --- /dev/null +++ b/src/Model/Transactions/Record.php @@ -0,0 +1,471 @@ +signature = $signature; + $this->publicKey = $pubkey; + } + + public function finalize($transactionId) + { + $signaturesTable = TableRegistry::getTableLocator()->get('TransactionSignatures'); + $entity = $signaturesTable->newEntity(); + $entity->transaction_id = $transactionId; + if(count($this->signature) != 128) { + return ['state' => 'error', 'msg' => 'invalid signature size', 'details' => count($this->signature)]; + } + if(count($this->publicKey) != 64) { + return ['state' => 'error', 'msg' => 'invalid pubkey size', 'details' => count($this->publicKey)]; + } + if(!preg_match('/^[0-9a-fA-F]*$/', $this->signature)) { + return ['state' => 'error', 'msg' => 'signature isn\'t in hex format']; + } + if(!preg_match('/^[0-9a-fA-F]*$/', $this->publicKey)) { + return ['state' => 'error', 'msg' => 'publicKey isn\'t in hex format']; + } + $entity->signature = hex2bin($this->signature); + $entity->pubkey = hex2bin($this->publicKey); + + if(!$signaturesTable->save($entity)) { + return ['state' => 'error', 'msg' => 'error saving signature', 'details' => $entity->getErrors()]; + } + return true; + } +} + + +class ManageNodeGroupAdd +{ + /* + "add_user": { + "user\": " << user << ", + }, + OR + + "move_user_inbound|move_user_outbound": { + "user": " << user << ", + "other_group": " << other_group << ", + "paired_transaction_id": { + "seconds": << ts.seconds <<, + "nanos": << ts.nanos + } + }, + + */ + + private $user_pubkey; + private $other_group = ''; + private $remove_from_group = false; + + public function __construct($data) + { + $this->user_pubkey = $data['user']; + if(isset($data['other_group'])) { + $this->other_group = $data['other_group']; + } + } + + public function finalize($transactionId, $received) + { + $transactionGroupAddadressTable = TableRegistry::getTableLocator()->get('TransactionGroupAddaddress'); + $stateGroupAddresses = TableRegistry::getTableLocator()->get('StateGroupAddresses'); + $transactionGroupEntity = $transactionGroupAddadressTable->newEntity(); + $transactionGroupEntity->transaction_id = $transactionId; + if(count($this->user_pubkey) != 64) { + return ['state' => 'error', 'msg' => 'invalid size user pubkey', 'details' => count($this->user_pubkey)]; + } + if(!preg_match('/^[0-9a-fA-F]*$/', $this->user_pubkey)) { + return ['state' => 'error', 'msg' => 'user_pubkey isn\'t in hex format']; + } + + $transactionGroupEntity->public_key = hex2bin($this->user_pubkey); + $transactionGroupEntity->remove_from_group = $this->remove_from_group; + if(!$transactionGroupAddadressTable->save($transactionGroupEntity)) { + return ['state' => 'error', 'msg' => 'error saving TransactionGroupAddaddress Entity', 'details' => $transactionGroupEntity->getErrors()]; + } + $userPubkeyBin = hex2bin($this->user_pubkey); + if($this->remove_from_group) { + $stateGroup_query = $stateGroupAddresses->find('all')->where(['public_key' => hex2bin($this->user_pubkey)]); + if(!$stateGroup_query->isEmpty()) { + $stateGroupAddresses->delete($stateGroup_query->first()); + } + } else { + $stateGroupAddressesEntity = $stateGroupAddresses->newEntity(); + $stateGroupAddressesEntity->group_id = 1; + $stateGroupAddressesEntity->public_key = $userPubkeyBin; + $stateGroupAddressesEntity->address_type_id = 1; + if(!$stateGroupAddresses->save($stateGroupAddressesEntity)) { + return ['state' => 'error', 'msg' => 'error saving state group addresses entity', 'details' => $stateGroupAddressesEntity->getErrors()]; + } + } + + return true; + } + + public function setRemoveFromGroup($removeFromGroup) { + $this->remove_from_group = $removeFromGroup; + } +} + +class GradidoModifieUserBalance +{ + + public function getUserId($userPublicKey) + { + $stateUsersTable = TableRegistry::getTableLocator()->get('StateUsers'); + $stateUser = $stateUsersTable->find('all')->where(['public_key' => hex2bin($userPublicKey)]); + if($stateUser->isEmpty()) { + return ['state' => 'error', 'msg' => 'couldn\'t find user via public key']; + } + return $stateUser->first()->id; + } + + public function updateBalance($newBalance, $recordDate, $userId) + { + $stateBalancesTable = TableRegistry::getTableLocator()->get('StateBalances'); + $stateBalanceQuery = $stateBalancesTable->find('all')->where(['state_user_id' => $userId]); + $entity = null; + + if(!$stateBalanceQuery->isEmpty()) { + $entity = $stateBalanceQuery->first(); + if($entity->record_date != NULL && $entity->record_date > $recordDate) { + return false; + } + } else { + $entity = $stateBalancesTable->newEntity(); + $entity->state_user_id = $userId; + } + $entity->record_date = $recordDate; + $entity->amount = $newBalance; + if(!$stateBalancesTable->save($entity)) { + return ['state' => 'error', 'msg' => 'error saving state balance', 'details' => $entity->getErrors()]; + } + return true; + } +} + +class GradidoCreation extends GradidoModifieUserBalance +{ + /* + * "gradido_creation": { + "user": " << user << ", + "new_balance": << v.new_balance << , + "prev_transfer_rec_num": << v.prev_transfer_rec_num <<, + "amount": << v.amount << + } + */ + private $userPubkey; + private $amount; + private $targetDate; // seems currently not in node server implementet, use hedera date until it is implemented + private $new_balance; + + public function __construct($data) + { + $this->userPubkey = $data['user']; + $this->amount = $data['amount']; + $this->new_balance = $data['new_balance']; + //$this->targetDate = $received; + } + + public function finalize($transactionId, $received) + { + // TODO: don't use, after node server transmit correct date + $this->targetDate = $received; + + $transactionCreationTable = TableRegistry::getTableLocator()->get('TransactionCreations'); + + + $state_user_id = $this->getUserId($this->userPubkey); + if(!is_int($state_user_id)) { + return $state_user_id; + } + + $entity = $transactionCreationTable->newEntity(); + $entity->transaction_id = $transactionId; + $entity->amount = $this->amount; + $entity->target_date = $this->targetDate; + $entity->state_user_id = $state_user_id; + + if(!$transactionCreationTable->save($entity)) { + return ['state' => 'error', 'msg' => 'error saving create transaction', 'details' => $entity->getErrors()]; + } + + $balance_result = $this->updateBalance($this->new_balance, $received, $state_user_id); + if(is_array($balance_result)) { + return $balance_result; + } + + return true; + } + +} + +class GradidoTransfer extends GradidoModifieUserBalance +{ + /* + "local_transfer|inbound_transfer|outbound_transfer": { + "sender": { + "user": " << sender << ", + "new_balance": << tt.sender.new_balance << , + "prev_transfer_rec_num": << tt.sender.prev_transfer_rec_num << + }, + "receiver": { + "user": " << receiver << ", + "new_balance": << tt.receiver.new_balance << , + "prev_transfer_rec_num": << tt.receiver.prev_transfer_rec_num << + }, + "amount": << tt.amount << + }, + * */ + private $amount; + private $sender_new_balance; + private $sender_pubkey; + + private $receiver_pubkey; + private $receiver_new_balance; + + public function __construct($data) + { + $this->amount = $data['amount']; + + $sender = $data['sender']; + $this->sender_pubkey = $sender['user']; + $this->sender_new_balance = $sender['new_balance']; + + $receiver = $data['receiver']; + $this->receiver_pubkey = $receiver['user']; + $this->receiver_new_balance = $receiver['new_balance']; + + } + + public function finalize($transactionId, $received) + { + $transactionTransferTable = TableRegistry::getTableLocator()->get('TransactionSendCoins'); + if(count($this->sender_pubkey) != 64) { + return ['state' => 'error', 'msg' => 'invalid size sender pubkey', 'details' => count($this->user_pubkey)]; + } + if(!preg_match('/^[0-9a-fA-F]*$/', $this->sender_pubkey)) { + return ['state' => 'error', 'msg' => 'sender_pubkey isn\'t in hex format']; + } + if(count($this->receiver_pubkey) != 64) { + return ['state' => 'error', 'msg' => 'invalid size receiver pubkey', 'details' => count($this->user_pubkey)]; + } + if(!preg_match('/^[0-9a-fA-F]*$/', $this->receiver_pubkey)) { + return ['state' => 'error', 'msg' => 'receiver_pubkey isn\'t in hex format']; + } + + $sender_id = $this->getUserId($this->sender_pubkey); + $receiver_id = $this->getUserId($this->receiver_pubkey); + if(is_array($sender_id) && is_array($receiver_id)) { + return ['state' => 'error', 'msg' => 'neither sender or receiver known']; + } + $transferEntity = $transactionTransferTable->newEntity(); + $transferEntity->transaction_id = $transactionId; + $transferEntity->sender_public_key = hex2bin($this->sender_pubkey); + $transferEntity->receiver_public_key = hex2bin($this->receiver_pubkey); + $transferEntity->amount = $this->amount; + $transferEntity->sender_final_balance = $this->sender_new_balance; + + if(is_int($sender_id) && $sender_id > 0) { + $transferEntity->state_user_id = $sender_id; + $balance_result = $this->updateBalance($this->sender_new_balance, $received, $sender_id); + if(is_array($balance_result)) { + return $balance_result; + } + } + if(is_int($receiver_id) && $receiver_id > 0) { + $transferEntity->receiver_user_id = $receiver_id; + $balance_result = $this->updateBalance($this->receiver_new_balance, $received, $receiver_id); + if(is_array($balance_result)) { + return $balance_result; + } + } + + if(!$transactionTransferTable->save($transferEntity)) { + return ['state' => 'error', 'msg' => 'error saving transaction send coins entity', 'details' => $transferEntity->getErrors()]; + } + + return true; + } +} + + + + +class Record +{ + private $sequenceNumber = 0; + private $transactionType = ''; + private $memo = ''; + private $signatures = []; + private $received; + private $transactionObj = null; + private $result; + private $partCount = 0; + + public function __construct() + { + + } + + + public function parseRecord($json) { + switch($json['record_type']) { + case 'GRADIDO_TRANSACTION': + return $this->parseTransaction($json['transaction']); + case 'MEMO': + $this->memo = $json['memo']; + return true; + case 'SIGNATURES': + return $this->parseSignatures($json['signature']); + case 'STRUCTURALLY_BAD_MESSAGE': + case 'RAW_MESSAGE': + case 'BLANK': + return false; + } + } + + /*! + * \brief save data parts in db + */ + public function finalize() + { + $transactionTypesTable = TableRegistry::getTableLocator()->get('TransactionTypes'); + $transactionsTable = TableRegistry::getTableLocator()->get('Transactions'); + + $transactionTypeName = $this->nodeTransactionTypeToDBTransactionType($this->transactionType); + $transactionTypeResults = $transactionTypesTable->find('all')->where(['name' => $transactionTypeName]); + if($transactionTypeResults->isEmpty()) { + return [ + 'state' => 'error', 'msg' => 'transaction type not found', + 'details' => ['nodeType' => $this->transactionType, 'dbType' => $transactionTypeName] + ]; + } + if(!$this->transactionObj) { + return ['state' => 'error', 'msg' => 'transaction obj is null']; + } + if($this->sequenceNumber <= 0) { + return ['state' => 'error', 'msg' => 'sequence number invalid', 'details' => $this->sequenceNumber]; + } + $transactionExistResult = $transactionsTable->find('all')->where(['id' => $this->sequenceNumber]); + if(!$transactionExistResult->isEmpty()) { + return ['state' => 'warning', 'msg' => 'transaction already exist in db', 'details' => $this->sequenceNumber]; + } + $newTransaction = $transactionsTable->newEntity(); + $newTransaction->id = $this->sequenceNumber; + $newTransaction->transaction_type_id = $transactionTypeResults->first()->id; + $newTransaction->memo = $this->memo; + $newTransaction->received = $this->received; + + if(!$transactionsTable->save($newTransaction)) { + return ['state' => 'error', 'msg' => 'error saving transaction', 'details' => $newTransaction->getErrors()]; + } + foreach($this->signatures as $sign) { + $sign_result = $sign->finalize($this->sequenceNumber); + iF($sign_result != true) { + return ['state' => 'error', 'msg', 'error finalizing signature', 'details' => $sign_result]; + } + } + $transaction_obj_result = $this->transactionObj->finalize($newTransaction->id, $this->received); + if($transaction_obj_result != true) { + return ['state' => 'error', 'msg' => 'error finalizing transaction object', 'details' => $transaction_obj_result]; + } + return true; + + } + + private function nodeTransactionTypeToDBTransactionType($nodeTransactionType) + { + switch($nodeTransactionType) { + case 'GRADIDO_CREATION': + return 'creation'; + + case 'MOVE_USER_INBOUND': + case 'ADD_USER': + return 'group add member'; + + case 'MOVE_USER_OUTBOUND': + return 'group remove member'; + + case 'LOCAL_TRANSFER': + case 'INBOUND_TRANSFER': + case 'OUTBOUND_TRANSFER': + return 'transfer'; + } + return 'unknown'; + } + + private function parseSignatures($signaturesArray) + { + foreach($signaturesArray as $sign) { + $this->signatures[] = new Signature($sign['signature'], $sign['pubkey']); + } + return true; + } + + private function parseTransaction($data) + { + $this->transactionType = $data['transaction_type']; + $sign = $data['signature']; + $this->signatures[] = new Signature($sign['signature'], $sign['pubkey']); + + $hedera = $data['hedera_transaction']; + $this->sequenceNumber = $hedera['sequenceNumber']; + $this->received = Time::createFromTimestamp($hedera['consensusTimestamp']['seconds']); + + $field_index = ''; + $class_name = ''; + + $removeFromGroup = false; + switch($this->transactionType) + { + case 'GRADIDO_CREATION': $field_index = 'gradido_creation'; $class_name = 'GradidoCreation'; break; + case 'ADD_USER': $field_index = 'add_user'; $class_name = 'ManageNodeGroupAdd'; break; + case 'MOVE_USER_INBOUND': $field_index = 'move_user_inbound'; $class_name = 'ManageNodeGroupAdd'; break; + case 'MOVE_USER_OUTBOUND': $field_index = 'move_user_outbound'; $class_name = 'ManageNodeGroupAdd'; $removeFromGroup = true; break; + case 'LOCAL_TRANSFER': $field_index = 'local_transfer'; $class_name = 'GradidoTransfer'; break; + case 'INBOUND_TRANSFER': $field_index = 'inbound_transfer'; $class_name = 'GradidoTransfer'; break; + case 'OUTBOUND_TRANSFER': $field_index = 'outbound_transfer'; $class_name = 'GradidoTransfer'; break; + } + if($class_name == '' || $field_index == '') { + return ['state' => 'error', 'msg' => 'node transaction type unknown', 'details' => $this->transactionType]; + } + $this->transactionObj = new $class_name($data[$field_index]); + if($class_name == 'ManageNodeGroupAdd') { + $this->transactionObj->setRemoveFromGroup($removeFromGroup); + } + + $this->result = $data['result']; + $this->partCount = intval($data['parts']); + $this->memo = $data['memo']; + return true; + } + + public function getSequenceNumber() { + return $this->sequenceNumber; + } + public function getPartCount() { + return $this->partCount; + } + +} \ No newline at end of file diff --git a/src/Template/AddressTypes/add.ctp b/src/Template/AddressTypes/add.ctp index 7422b666a..f62c5115e 100644 --- a/src/Template/AddressTypes/add.ctp +++ b/src/Template/AddressTypes/add.ctp @@ -4,8 +4,8 @@ * @var \App\Model\Entity\AddressType $addressType */ ?> -