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 f844a6aa1..93bf1eb6a 100644 --- a/src/cpp/SingletonManager/ConnectionManager.cpp +++ b/src/cpp/SingletonManager/ConnectionManager.cpp @@ -73,6 +73,7 @@ Poco::Data::Session ConnectionManager::getConnection(ConnectionType type) throw Poco::NotFoundException("Connection Type unknown", std::to_string(type)); } auto session = mSessionPools.getPool(mSessionPoolNames[type]).get(); + //return mSessionPoolNames[type]; /*if (!session.isConnected()) { @@ -85,6 +86,7 @@ Poco::Data::Session ConnectionManager::getConnection(ConnectionType type) sendErrorsAsEmail(); return mSessionPools.getPool(mSessionPoolNames[type]).get(); } + }*/ //std::string dateTimeString = Poco::DateTimeFormatter::format(Poco::DateTime(), "%d.%m.%y %H:%M:%S"); //printf("[getConnection] %s impl: %p\n", dateTimeString.data(), session.impl()); diff --git a/src/cpp/SingletonManager/SessionManager.cpp b/src/cpp/SingletonManager/SessionManager.cpp index d7286f1fd..1f7e87303 100644 --- a/src/cpp/SingletonManager/SessionManager.cpp +++ b/src/cpp/SingletonManager/SessionManager.cpp @@ -50,6 +50,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 e3202d536..e1469d539 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 5dfb709fb..7bb7301f6 100644 --- a/src/cpp/model/table/ModelBase.cpp +++ b/src/cpp/model/table/ModelBase.cpp @@ -48,17 +48,22 @@ namespace model { 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