diff --git a/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp b/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp index ddc240e91..350146926 100644 --- a/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp +++ b/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp @@ -14,6 +14,7 @@ #include "ElopageWebhook.h" #include "UpdateUserPasswordPage.h" #include "Error500Page.h" +#include "CheckTransactionPage.h" #include "../SingletonManager/SessionManager.h" @@ -113,7 +114,10 @@ Poco::Net::HTTPRequestHandler* PageRequestHandlerFactory::createRequestHandler(c //else if (uri == "/saveKeys") { return new SaveKeysPage(s); } - if (s && !s->getUser().isNull()) { + if (url_first_part == "/checkTransactions") { + return new CheckTransactionPage(s); + } + if (s && !user.isNull() && user->hasCryptoKey()) { //printf("[PageRequestHandlerFactory] go to dashboard page with user\n"); return new DashboardPage(s); } diff --git a/src/cpp/JSONInterface/JsonRequestHandlerFactory.cpp b/src/cpp/JSONInterface/JsonRequestHandlerFactory.cpp index 31bb61775..b428176e9 100644 --- a/src/cpp/JSONInterface/JsonRequestHandlerFactory.cpp +++ b/src/cpp/JSONInterface/JsonRequestHandlerFactory.cpp @@ -6,6 +6,7 @@ #include "JsonGetLogin.h" #include "JsonUnknown.h" +#include "JsonTransaction.h" JsonRequestHandlerFactory::JsonRequestHandlerFactory() : mRemoveGETParameters("^/([a-zA-Z0-9_-]*)") @@ -21,6 +22,9 @@ Poco::Net::HTTPRequestHandler* JsonRequestHandlerFactory::createRequestHandler(c if (url_first_part == "/login") { return new JsonGetLogin; } + else if (url_first_part == "/checkTransaction") { + return new JsonTransaction; + } return new JsonUnknown; } diff --git a/src/cpp/JSONInterface/JsonTransaction.cpp b/src/cpp/JSONInterface/JsonTransaction.cpp new file mode 100644 index 000000000..4b2099981 --- /dev/null +++ b/src/cpp/JSONInterface/JsonTransaction.cpp @@ -0,0 +1,50 @@ +#include "JsonTransaction.h" +#include "Poco/URI.h" + +#include "../SingletonManager/SessionManager.h" + +Poco::JSON::Object* JsonTransaction::handle(Poco::Dynamic::Var params) +{ + Poco::JSON::Object* result = new Poco::JSON::Object; + int session_id = 0; + + if (params.isVector()) { + const Poco::URI::QueryParameters queryParams = params.extract(); + auto transactionIT = queryParams.begin(); + for (auto it = queryParams.begin(); it != queryParams.end(); it++) { + if (it->first == "session_id") { + session_id = stoi(it->second); + //break; + } + else if (it->first == "transaction_base64") { + transactionIT = it; + } + } + if (session_id) { + auto sm = SessionManager::getInstance(); + auto session = sm->getSession(session_id); + if (!session) { + result->set("state", "error"); + result->set("msg", "session not found"); + return result; + } + if (!session->startProcessingTransaction(transactionIT->second)) { + result->set("state", "error"); + result->set("msg", "already enlisted"); + return result; + } + result->set("state", "success"); + return result; + } + else { + result->set("state", "error"); + result->set("msg", "session id not set"); + return result; + } + } + + result->set("state", "error"); + result->set("msg", "format not implemented"); + + return result; +} \ No newline at end of file diff --git a/src/cpp/JSONInterface/JsonTransaction.h b/src/cpp/JSONInterface/JsonTransaction.h new file mode 100644 index 000000000..7a93cbbca --- /dev/null +++ b/src/cpp/JSONInterface/JsonTransaction.h @@ -0,0 +1,16 @@ +#ifndef __JSON_INTERFACE_JSON_TRANSACTION_ +#define __JSON_INTERFACE_JSON_TRANSACTION_ + +#include "JsonRequestHandler.h" + +class JsonTransaction : public JsonRequestHandler +{ +public: + Poco::JSON::Object* handle(Poco::Dynamic::Var params); + +protected: + + +}; + +#endif // __JSON_INTERFACE_JSON_TRANSACTION_ \ No newline at end of file diff --git a/src/cpp/model/Session.cpp b/src/cpp/model/Session.cpp index 0e77d4924..60253f5ac 100644 --- a/src/cpp/model/Session.cpp +++ b/src/cpp/model/Session.cpp @@ -79,7 +79,7 @@ int WritePassphraseIntoDB::run() // -------------------------------------------------------------------------------------------------------------- Session::Session(int handle) - : mHandleId(handle), mSessionUser(nullptr), mEmailVerificationCode(0), mState(SESSION_STATE_EMPTY), mActive(false), mProcessingTransaction(nullptr) + : mHandleId(handle), mSessionUser(nullptr), mEmailVerificationCode(0), mState(SESSION_STATE_EMPTY), mActive(false) { } @@ -98,7 +98,6 @@ void Session::reset() lock(); mSessionUser = nullptr; - mProcessingTransaction = nullptr; // watch out //updateTimeout(); @@ -279,7 +278,7 @@ bool Session::updateEmailVerification(Poco::UInt64 emailVerificationCode) return false; } -bool Session::startProcessingTransaction(std::string proto_message_base64) +bool Session::startProcessingTransaction(const std::string& proto_message_base64) { lock(); HASH hs = ProcessingTransaction::calculateHash(proto_message_base64); @@ -294,7 +293,7 @@ bool Session::startProcessingTransaction(std::string proto_message_base64) return false; } } - UniLib::controller::TaskPtr processorTask(new ProcessingTransaction(proto_message_base64)); + Poco::AutoPtr processorTask(new ProcessingTransaction(proto_message_base64)); processorTask->scheduleTask(processorTask); mProcessingTransactions.push_back(processorTask); unlock(); @@ -302,14 +301,31 @@ bool Session::startProcessingTransaction(std::string proto_message_base64) } -Poco::AutoPtr Session::getNextReadyTransaction() +Poco::AutoPtr Session::getNextReadyTransaction(size_t* working/* = nullptr*/) { lock(); + if (working) { + *working = 0; + } + Poco::AutoPtr ret; for (auto it = mProcessingTransactions.begin(); it != mProcessingTransactions.end(); it++) { - if ((*it)->isTaskFinished()) { - + if (working && !(*it)->isTaskFinished()) { + *working++; + } + if (ret.isNull() && (*it)->isTaskFinished()) { + if (!working) { + unlock(); + return *it; + } + // no early exit + else { + ret = *it; + } + } } + unlock(); + return nullptr; } bool Session::isPwdValid(const std::string& pwd) @@ -324,13 +340,21 @@ UserStates Session::loadUser(const std::string& email, const std::string& passwo { //Profiler usedTime; lock(); - if (mSessionUser) mSessionUser = nullptr; - mSessionUser = new User(email.data()); + if (mSessionUser && mSessionUser->getEmail() != email) { + mSessionUser = nullptr; + } + if (!mSessionUser) { + // load user for email only once from db + mSessionUser = new User(email.data()); + } if (mSessionUser->getUserState() >= USER_LOADED_FROM_DB) { if (!mSessionUser->validatePwd(password, this)) { return USER_PASSWORD_INCORRECT; } } + else { + User::fakeCreateCryptoKey(); + } /*if (!mSessionUser->validatePwd(password, this)) { addError(new Error("Login", "E-Mail oder Passwort nicht korrekt, bitte versuche es erneut!")); diff --git a/src/cpp/model/Session.h b/src/cpp/model/Session.h index 274201399..49420f89d 100644 --- a/src/cpp/model/Session.h +++ b/src/cpp/model/Session.h @@ -65,7 +65,7 @@ public: bool updateEmailVerification(Poco::UInt64 emailVerificationCode); - bool startProcessingTransaction(std::string proto_message_base64); + Poco::Net::HTTPCookie getLoginCookie(); @@ -98,7 +98,11 @@ public: inline Poco::DateTime getLastActivity() { return mLastActivity; } - Poco::AutoPtr getNextReadyTransaction(); + //! \return true if succeed + bool startProcessingTransaction(const std::string& proto_message_base64); + //! \param working if set will filled with transaction running + Poco::AutoPtr getNextReadyTransaction(size_t* working = nullptr); + inline size_t getProcessingTransactionCount() { lock(); auto ret = mProcessingTransactions.size(); unlock(); return ret; } protected: void updateTimeout(); @@ -123,7 +127,6 @@ private: bool mActive; std::list> mProcessingTransactions; - std::list> }; diff --git a/src/cpp/model/TransactionCreation.cpp b/src/cpp/model/TransactionCreation.cpp index 73f46303d..ba4363595 100644 --- a/src/cpp/model/TransactionCreation.cpp +++ b/src/cpp/model/TransactionCreation.cpp @@ -32,7 +32,7 @@ int TransactionCreation::prepare() mReceiverUser = new User(receiverPublic.data()); getErrors(mReceiverUser); if (mReceiverUser->getUserState() == USER_EMPTY) { - sodium_bin2hex(mReceiverPublicHex, 64, (const unsigned char*)receiverPublic.data(), receiverPublic.size()); + sodium_bin2hex(mReceiverPublicHex, 65, (const unsigned char*)receiverPublic.data(), receiverPublic.size()); delete mReceiverUser; mReceiverUser = nullptr; } diff --git a/src/cpp/model/User.cpp b/src/cpp/model/User.cpp index 532961375..2acb5c03e 100644 --- a/src/cpp/model/User.cpp +++ b/src/cpp/model/User.cpp @@ -553,12 +553,12 @@ bool User::deleteFromDB() void User::duplicate() { - mWorkingMutex.lock(); + mReferenceMutex.lock(); mReferenceCount++; #ifdef DEBUG_USER_DELETE_ENV printf("[User::duplicate] new value: %d\n", mReferenceCount); #endif - mWorkingMutex.unlock(); + mReferenceMutex.unlock(); } void User::release() @@ -566,17 +566,17 @@ void User::release() if (!mCreateCryptoKeyTask.isNull() && mCreateCryptoKeyTask->isTaskFinished()) { mCreateCryptoKeyTask = nullptr; } - mWorkingMutex.lock(); + mReferenceMutex.lock(); mReferenceCount--; #ifdef DEBUG_USER_DELETE_ENV printf("[User::release] new value: %d, this: %d\n", mReferenceCount, this); #endif if (0 == mReferenceCount) { - mWorkingMutex.unlock(); + mReferenceMutex.unlock(); delete this; return; } - mWorkingMutex.unlock(); + mReferenceMutex.unlock(); } @@ -624,6 +624,11 @@ ObfusArray* User::createCryptoKey(const std::string& password) return cryptoKey; } +void User::fakeCreateCryptoKey() +{ + Poco::Thread::sleep(820); +} + bool User::generateKeys(bool savePrivkey, const std::string& passphrase, Session* session) { Profiler timeUsed; diff --git a/src/cpp/model/User.h b/src/cpp/model/User.h index 13be5d3f4..07663468b 100644 --- a/src/cpp/model/User.h +++ b/src/cpp/model/User.h @@ -94,13 +94,16 @@ public: // 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; ObfusArray* createCryptoKey(const std::string& password); inline void setCryptoKey(ObfusArray* cryptoKey) { lock(); mCryptoKey = cryptoKey; unlock(); } - void detectState(); + //void detectState(); Poco::Data::Statement insertIntoDB(Poco::Data::Session session); bool updateIntoDB(UserFields fieldType); @@ -135,6 +138,7 @@ private: ObfusArray* mCryptoKey; Poco::Mutex mWorkingMutex; + Poco::Mutex mReferenceMutex; // for poco auto ptr int mReferenceCount; diff --git a/src/cpp/tasks/ProcessingTransaction.cpp b/src/cpp/tasks/ProcessingTransaction.cpp index ed911be0d..6debc796b 100644 --- a/src/cpp/tasks/ProcessingTransaction.cpp +++ b/src/cpp/tasks/ProcessingTransaction.cpp @@ -4,7 +4,7 @@ #include "../model/TransactionCreation.h" #include "../model/TransactionTransfer.h" -ProcessingTransaction::ProcessingTransaction(std::string proto_message_base64) +ProcessingTransaction::ProcessingTransaction(const std::string& proto_message_base64) : mType(TRANSACTION_NONE), mProtoMessageBase64(proto_message_base64), mTransactionSpecific(nullptr) { mHashMutex.lock(); @@ -23,14 +23,13 @@ ProcessingTransaction::~ProcessingTransaction() } -HASH ProcessingTransaction::calculateHash(std::string proto_message_base64) +HASH ProcessingTransaction::calculateHash(const std::string& proto_message_base64) { return DRMakeStringHash(proto_message_base64.data(), proto_message_base64.size()); } int ProcessingTransaction::run() { - lock(); //mTransactionBody.ParseFromString(); unsigned char* binBuffer = (unsigned char*)malloc(mProtoMessageBase64.size()); diff --git a/src/cpp/tasks/ProcessingTransaction.h b/src/cpp/tasks/ProcessingTransaction.h index 0b56909b6..8ad24803a 100644 --- a/src/cpp/tasks/ProcessingTransaction.h +++ b/src/cpp/tasks/ProcessingTransaction.h @@ -4,6 +4,7 @@ #include "CPUTask.h" #include "../model/ErrorList.h" +#include "../Crypto/DRHash.h" #include "../model/TransactionBase.h" #include "../proto/gradido/TransactionBody.pb.h" @@ -27,7 +28,7 @@ class TransactionTransfer; class ProcessingTransaction : public UniLib::controller::CPUTask, public ErrorList { public: - ProcessingTransaction(std::string proto_message_base64); + ProcessingTransaction(const std::string& proto_message_base64); virtual ~ProcessingTransaction(); int run(); @@ -44,7 +45,7 @@ public: TransactionCreation* getCreationTransaction(); TransactionTransfer* getTransferTransaction(); - static HASH calculateHash(std::string proto_message_base64); + static HASH calculateHash(const std::string& proto_message_base64); inline HASH getHash() { mHashMutex.lock(); HASH hs = mHash; mHashMutex.unlock(); return hs; } protected: diff --git a/src/cpp/tasks/Task.cpp b/src/cpp/tasks/Task.cpp index 7c95c220c..ce9080e66 100644 --- a/src/cpp/tasks/Task.cpp +++ b/src/cpp/tasks/Task.cpp @@ -59,23 +59,23 @@ namespace UniLib { void Task::duplicate() { - lock(); + mReferenceMutex.lock(); mReferenceCount++; //printf("[Task::duplicate] new value: %d\n", mReferenceCount); - unlock(); + mReferenceMutex.unlock(); } void Task::release() { - lock(); + mReferenceMutex.lock(); mReferenceCount--; //printf("[Task::release] new value: %d\n", mReferenceCount); if (0 == mReferenceCount) { - unlock(); + mReferenceMutex.unlock(); delete this; return; } - unlock(); + mReferenceMutex.unlock(); } diff --git a/src/cpp/tasks/Task.h b/src/cpp/tasks/Task.h index b52417c89..d47becdb3 100644 --- a/src/cpp/tasks/Task.h +++ b/src/cpp/tasks/Task.h @@ -119,6 +119,7 @@ namespace UniLib { TaskPtr* mParentTaskPtrArray; size_t mParentTaskPtrArraySize; Poco::Mutex mWorkingMutex; + Poco::Mutex mReferenceMutex; bool mDeleted; bool mFinished; // for poco auto ptr diff --git a/src/cpsp/checkTransaction.cpsp b/src/cpsp/checkTransaction.cpsp index 6a21b6e76..9c682e2b3 100644 --- a/src/cpsp/checkTransaction.cpsp +++ b/src/cpsp/checkTransaction.cpsp @@ -6,8 +6,28 @@ <%@ page compressed="true" %> <%! #include "../SingletonManager/SessionManager.h" + +enum PageState { + PAGE_TRANSACTION_CREATION, + PAGE_TRANSACTION_TRANSFER, + PAGE_NO_TRANSACTIONS +}; + %> <%% + PageState state = PAGE_NO_TRANSACTIONS; + size_t notReadyTransactions = 0; + size_t sumTransactions = mSession->getProcessingTransactionCount(); + auto processingTransaction = mSession->getNextReadyTransaction(¬ReadyTransactions); + if(!processingTransaction.isNull()) { + auto transactionType = processingTransaction->getType(); + switch(transactionType) { + case TRANSACTION_CREATION: state = PAGE_TRANSACTION_CREATION; break; + case TRANSACTION_TRANSFER: state = PAGE_TRANSACTION_TRANSFER; break; + } + } + + %> @@ -39,7 +59,20 @@ label:not(.grd_radio_label) {

Eine Transaktion prüfen

<%= getErrorsHtml() %> + <% if(sumTransactions - notReadyTransactions != 1) { %> +
<%= sumTransactions - notReadyTransactions %> von <%= sumTransactions %> Transaktionen sind bereit zum prüfen
+ <% } %> + <% if(state == PAGE_NO_TRANSACTIONS) { %> +
+ <% if(sumTransactions == 0) { %> +
Es gibt zurzeit keine Transaktionen zum überprüfen
+ <% } else { %> +
Transaktion(en) werden noch vorbereitet, bitte lade die Seite in wenigen Augenblicken erneut.
+ <% } %> +
+ <% } else if(state == PAGE_TRANSACTION_CREATION) { %> + <% } %>
<%= mTimeProfiler.string() %>