diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7edd92df4..097ea9df6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -268,7 +268,7 @@ jobs: report_name: Coverage Backend Login type: lcov result_path: ./coverage/coverage.info - min_coverage: 13 + min_coverage: 25 token: ${{ github.token }} ############################################################################## @@ -341,7 +341,7 @@ jobs: report_name: Coverage Backend Community type: phpunit result_path: ./coverage/coverage.info - min_coverage: 10 + min_coverage: 14 token: ${{ github.token }} #test: diff --git a/community_server/src/Controller/AppController.php b/community_server/src/Controller/AppController.php index eb11299ce..2c6344511 100644 --- a/community_server/src/Controller/AppController.php +++ b/community_server/src/Controller/AppController.php @@ -289,7 +289,7 @@ class AppController extends Controller } } else { if(!$redirect) { - return ['state' => 'not found', 'msg' => 'invalid session']; + return ['state' => 'not found', 'msg' => 'invalid session', 'details' => $json]; } if ($json['state'] === 'not found') { $this->Flash->error(__('invalid session')); diff --git a/community_server/src/Model/Table/TransactionsTable.php b/community_server/src/Model/Table/TransactionsTable.php index 7e59c2d88..03e0e08ad 100644 --- a/community_server/src/Model/Table/TransactionsTable.php +++ b/community_server/src/Model/Table/TransactionsTable.php @@ -184,7 +184,7 @@ class TransactionsTable extends Table $calculated_decay = $stateBalancesTable->calculateDecay($prev->balance, $prev->balance_date, $current->balance_date, true); $balance = floatval($prev->balance - $calculated_decay['balance']); - if($balance) + if($balance > 100) { $final_transactions[] = [ 'type' => 'decay', diff --git a/community_server/tests/TestCase/Controller/AppRequestControllerTest.php b/community_server/tests/TestCase/Controller/AppRequestControllerTest.php index 118f25a32..bff10d997 100644 --- a/community_server/tests/TestCase/Controller/AppRequestControllerTest.php +++ b/community_server/tests/TestCase/Controller/AppRequestControllerTest.php @@ -109,9 +109,11 @@ class AppRequestControllerTest extends TestCase 'public_hex' => '8190bda585ee5f1d9fbf7d06e81e69ec18e13376104cff54b7457eb7d3ef710d' ] ]); - + $this->getAndParse('/api/get-balance/' . 1211, - ['state' => 'not found', 'msg' => 'invalid session'] + ['state' => 'not found', 'msg' => 'invalid session', + 'details' => ['msg' => 'session not found', 'state' => 'not found'] + ] ); } @@ -128,7 +130,9 @@ class AppRequestControllerTest extends TestCase ]); $this->getAndParse('/api/get-balance/' , - ['state' => 'not found', 'msg' => 'invalid session'] + ['state' => 'not found', 'msg' => 'invalid session', + 'details' => ['msg' => 'session not found', 'state' => 'not found'] + ] ); } diff --git a/login_server/src/cpp/JSONInterface/JsonGetLogin.cpp b/login_server/src/cpp/JSONInterface/JsonGetLogin.cpp index 92ef5e887..76f4e6524 100644 --- a/login_server/src/cpp/JSONInterface/JsonGetLogin.cpp +++ b/login_server/src/cpp/JSONInterface/JsonGetLogin.cpp @@ -10,8 +10,6 @@ Poco::JSON::Object* JsonGetLogin::handle(Poco::Dynamic::Var params) { - - int session_id = 0; auto sm = SessionManager::getInstance(); auto pt = PendingTasksManager::getInstance(); auto observer = SingletonTaskObserver::getInstance(); @@ -58,4 +56,4 @@ Poco::JSON::Object* JsonGetLogin::handle(Poco::Dynamic::Var params) //printf("[JsonGetLogin] %s\n", user_string.data()); return result; -} \ No newline at end of file +} diff --git a/login_server/src/cpp/JSONInterface/JsonRequestHandlerFactory.cpp b/login_server/src/cpp/JSONInterface/JsonRequestHandlerFactory.cpp index 19772f3e1..b50fc7957 100644 --- a/login_server/src/cpp/JSONInterface/JsonRequestHandlerFactory.cpp +++ b/login_server/src/cpp/JSONInterface/JsonRequestHandlerFactory.cpp @@ -65,7 +65,7 @@ Poco::Net::HTTPRequestHandler* JsonRequestHandlerFactory::createRequestHandler(c auto sm = SessionManager::getInstance(); Session* s = nullptr; - if (!session_id) { + if (session_id) { s = sm->getSession(session_id); } diff --git a/login_server/src/cpp/SingletonManager/PendingTasksManager.cpp b/login_server/src/cpp/SingletonManager/PendingTasksManager.cpp index c5200b766..065520b0a 100644 --- a/login_server/src/cpp/SingletonManager/PendingTasksManager.cpp +++ b/login_server/src/cpp/SingletonManager/PendingTasksManager.cpp @@ -42,6 +42,7 @@ int PendingTasksManager::addTask(Poco::AutoPtr task) if (task.isNull() || !task->getModel()) { return -1; } + auto model = task->getModel(); Poco::ScopedLock _lock(mWorkMutex); auto pending_task_list = getTaskListForUser(model->getUserId()); @@ -235,30 +236,3 @@ Poco::AutoPtr PendingTasksManager::getPendingTask(int p return nullptr; } - -void PendingTasksManager::reportErrorToCommunityServer(Poco::AutoPtr task, std::string error, std::string errorDetails) -{ - // TODO: choose user specific server - JsonRequest phpServerRequest(ServerConfig::g_php_serverHost, ServerConfig::g_phpServerPort); - //Poco::Net::NameValueCollection payload; - Poco::JSON::Object payload; - - auto task_model = task->getModel(); - auto user_model = task->getUser()->getModel(); - - payload.set("created", task_model->getCreated()); - 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); - - auto ret = phpServerRequest.request("errorInTransaction", payload); - if (ret == JSON_REQUEST_RETURN_ERROR) - { - auto em = ErrorManager::getInstance(); - em->addError(new Error("PendingTasksManager::reportErrorToCommunityServer", "php server error")); - em->getErrors(&phpServerRequest); - em->sendErrorsAsEmail(); - } -} diff --git a/login_server/src/cpp/SingletonManager/PendingTasksManager.h b/login_server/src/cpp/SingletonManager/PendingTasksManager.h index 8444f32ea..2ee96266a 100644 --- a/login_server/src/cpp/SingletonManager/PendingTasksManager.h +++ b/login_server/src/cpp/SingletonManager/PendingTasksManager.h @@ -50,7 +50,6 @@ public: std::vector> getTransactionsUserMustSign(Poco::AutoPtr user); std::vector> getTransactionSomeoneMustSign(Poco::AutoPtr user); - void reportErrorToCommunityServer(Poco::AutoPtr task, std::string error, std::string errorDetails); protected: PendingTasksManager(); diff --git a/login_server/src/cpp/SingletonManager/SessionManager.cpp b/login_server/src/cpp/SingletonManager/SessionManager.cpp index a26ecb0ab..114cff0c9 100644 --- a/login_server/src/cpp/SingletonManager/SessionManager.cpp +++ b/login_server/src/cpp/SingletonManager/SessionManager.cpp @@ -57,17 +57,17 @@ bool SessionManager::init() //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].*"); + case VALIDATE_HAS_UPPERCASE_LETTER: + mValidations[i] = new Poco::RegularExpression(".*[A-Z].*"); ServerConfig::g_ServerKeySeed->put(i, DRRandom::r64()); break; case VALIDATE_HAS_LOWERCASE_LETTER: mValidations[i] = new Poco::RegularExpression(".*[a-z].*"); break; default: printf("[SessionManager::%s] unknown validation type\n", __FUNCTION__); } } - - mInitalized = true; + + mInitalized = true; mWorkingMutex.unlock(); return true; } @@ -98,7 +98,7 @@ void SessionManager::deinitalize() } printf("[SessionManager::deinitalize] count of dead locked sessions: %d\n", mDeadLockedSessionCount); - + mInitalized = false; mWorkingMutex.unlock(); } @@ -142,7 +142,7 @@ Session* SessionManager::getNewSession(int* handle) // first check if we have any timeouted session to directly reuse it checkTimeoutSession(); - // lock + // lock try { //Poco::Mutex::ScopedLock _lock(mWorkingMutex, 500); mWorkingMutex.tryLock(500); @@ -156,8 +156,8 @@ Session* SessionManager::getNewSession(int* handle) //UniLib::controller::TaskPtr checkSessionTimeout(new CheckSessionTimeouted); //checkSessionTimeout->scheduleTask(checkSessionTimeout); - // check if we have an existing session ready to use - while (mEmptyRequestStack.size() > 0) { + // check if we have an existing session ready to use + while (mEmptyRequestStack.size() > 0) { int local_handle = mEmptyRequestStack.top(); mEmptyRequestStack.pop(); auto resultIt = mRequestSessionMap.find(local_handle); @@ -186,10 +186,10 @@ Session* SessionManager::getNewSession(int* handle) mRequestSessionMap.erase(local_handle); } - + } } - + // else create new RequestSession Object // calculate random handle // check if already exist, if get new @@ -211,7 +211,7 @@ Session* SessionManager::getNewSession(int* handle) //printf("[SessionManager::getNewSession] handle: %ld, sum: %u\n", newHandle, mRequestSessionMap.size()); mWorkingMutex.unlock(); return requestSession; - + //return nullptr; } @@ -231,7 +231,7 @@ bool SessionManager::releaseSession(int requestHandleSession) return false; } //mWorkingMutex.lock(); - + auto it = mRequestSessionMap.find(requestHandleSession); if (it == mRequestSessionMap.end()) { //printf("[SessionManager::releaseRequestSession] requestSession with handle: %d not found\n", requestHandleSession); @@ -242,16 +242,15 @@ bool SessionManager::releaseSession(int requestHandleSession) // delete session, not reuse as workaround for server freeze bug - mRequestSessionMap.erase(requestHandleSession); + /*mRequestSessionMap.erase(requestHandleSession); delete session; mWorkingMutex.unlock(); return true; - +*/ // check if dead locked - if (session->tryLock()) { - session->unlock(); + if (!session->isDeadLocked()) { session->reset(); session->setActive(false); } @@ -264,9 +263,9 @@ bool SessionManager::releaseSession(int requestHandleSession) mWorkingMutex.unlock(); return true; } - + // change request handle we don't want session hijacking - + // hardcoded disabled session max if (mEmptyRequestStack.size() > 100) { mRequestSessionMap.erase(requestHandleSession); @@ -285,11 +284,11 @@ bool SessionManager::releaseSession(int requestHandleSession) mWorkingMutex.unlock(); return true; } - + session->setHandle(newHandle); mRequestSessionMap.insert(std::pair(newHandle, session)); mEmptyRequestStack.push(newHandle); - + mWorkingMutex.unlock(); return true; } @@ -354,13 +353,11 @@ Session* SessionManager::getSession(int handle) } if (0 == handle) return nullptr; Session* result = nullptr; - try { - //Poco::Mutex::ScopedLock _lock(mWorkingMutex, 500); - mWorkingMutex.tryLock(500); - } - catch (Poco::TimeoutException &ex) { - printf("[SessionManager::getSession] exception timout mutex: %s\n", ex.displayText().data()); - return result; + + + if(!mWorkingMutex.tryLock(500)) { + printf("[SessionManager::getSession] exception timout mutex: \n"); + return result; } //mWorkingMutex.lock(); auto it = mRequestSessionMap.find(handle); @@ -376,14 +373,12 @@ Session* SessionManager::getSession(int handle) return nullptr; } if (0 == iResult) { - //printf("[SessionManager::getSession] session isn't active\n"); mWorkingMutex.unlock(); return nullptr; } //result->setActive(true); result->updateTimeout(); } - //printf("[SessionManager::getSession] handle: %ld\n", handle); mWorkingMutex.unlock(); return result; } @@ -418,8 +413,8 @@ Session* SessionManager::findByUserId(int userId) } //mWorkingMutex.lock(); for (auto it = mRequestSessionMap.begin(); it != mRequestSessionMap.end(); it++) { - while (it->second->isDeadLocked()) - { + while (it->second->isDeadLocked()) + { it = mRequestSessionMap.erase(it); mDeadLockedSessionCount++; auto em = ErrorManager::getInstance(); @@ -484,7 +479,7 @@ std::vector SessionManager::findAllByUserId(int userId) Session* SessionManager::findByEmail(const std::string& email) { assert(email.size() > 0); - + try { //Poco::Mutex::ScopedLock _lock(mWorkingMutex, 500); mWorkingMutex.tryLock(500); @@ -605,23 +600,23 @@ bool SessionManager::checkPwdValidation(const std::string& pwd, NotificationList if (!isValid(pwd, VALIDATE_PASSWORD)) { errorReciver->addError(new Error( - lang->gettext("Password"), + lang->gettext("Password"), lang->gettext("Please enter a valid password with at least 8 characters, upper and lower case letters, at least one number and one special character (@$!%*?&+-_)!"))); // @$!%*?&+- if (pwd.size() < 8) { errorReciver->addError(new Error( - lang->gettext("Password"), + lang->gettext("Password"), lang->gettext("Your password is to short!"))); } else if (!isValid(pwd, VALIDATE_HAS_LOWERCASE_LETTER)) { errorReciver->addError(new Error( - lang->gettext("Password"), + lang->gettext("Password"), lang->gettext("Your password does not contain lowercase letters!"))); } else if (!isValid(pwd, VALIDATE_HAS_UPPERCASE_LETTER)) { errorReciver->addError(new Error( - lang->gettext("Password"), + lang->gettext("Password"), lang->gettext("Your password does not contain any capital letters!"))); } else if (!isValid(pwd, VALIDATE_HAS_NUMBER)) { diff --git a/login_server/src/cpp/lib/MultithreadContainer.h b/login_server/src/cpp/lib/MultithreadContainer.h index dafc4f9ad..2596fb2fd 100644 --- a/login_server/src/cpp/lib/MultithreadContainer.h +++ b/login_server/src/cpp/lib/MultithreadContainer.h @@ -21,7 +21,7 @@ ***************************************************************************/ /*! - + \brief Container Wrapper class for mutex protected container changed to poco mutex for gradido login server default mutex from poco is recursive so it is some heavy thing @@ -47,7 +47,7 @@ namespace UniLib { // \return false if mutex was locked from another thread bool tryLock(); - inline void unlock() { mLastSucceededLock = ""; mWorkMutex.unlock(); } + inline void unlock() { mWorkMutex.unlock(); mLastSucceededLock = ""; } inline const std::string& getLastSucceededLock() { return mLastSucceededLock; } protected: @@ -58,4 +58,4 @@ namespace UniLib { } } -#endif //__DR_UNIVERSUM_LIB_LIB_MULTITHREAD_CONTAINER_H__ \ No newline at end of file +#endif //__DR_UNIVERSUM_LIB_LIB_MULTITHREAD_CONTAINER_H__ diff --git a/login_server/src/cpp/model/Session.cpp b/login_server/src/cpp/model/Session.cpp index 767f1acb3..42b7202fd 100644 --- a/login_server/src/cpp/model/Session.cpp +++ b/login_server/src/cpp/model/Session.cpp @@ -84,29 +84,30 @@ void Session::reset() int Session::isActive() { int ret = 0; - try { - mWorkMutex.tryLock(100); - } - catch (Poco::TimeoutException &ex) { - return -1; - } + + if(!mWorkMutex.tryLock(100)) { + return -1; + } + ret = (int)mActive; - unlock(); + + try { + unlock(); + } catch(Poco::SystemException& ex) { + addError(new ParamError("Session::isActive", "exception unlocking mutex", ex.what())); + return -1; + } return ret; } bool Session::isDeadLocked() { - try { - mWorkMutex.tryLock(200); - unlock(); - return false; - } - catch (Poco::Exception& ex) { - - } - return true; + if(!mWorkMutex.tryLock(200)) { + return true; + }; + unlock(); + return false; } bool Session::setActive(bool active) @@ -922,12 +923,11 @@ bool Session::useOrGeneratePassphrase(const std::string& passphase) bool Session::lastTransactionTheSame(Poco::AutoPtr newTransaction) { assert(!newTransaction.isNull()); - lock(); + Poco::ScopedLock _lock(mWorkMutex); if (mLastTransaction.isNull()) { return false; } bool result = mLastTransaction->isTheSameTransaction(newTransaction); - unlock(); return result; } diff --git a/login_server/src/cpp/model/gradido/Transaction.cpp b/login_server/src/cpp/model/gradido/Transaction.cpp index 404d4f747..e3c4ada0f 100644 --- a/login_server/src/cpp/model/gradido/Transaction.cpp +++ b/login_server/src/cpp/model/gradido/Transaction.cpp @@ -358,6 +358,9 @@ namespace model { } //UniLib::controller::TaskPtr transaction_send_task(new SendTransactionTask(Poco::AutoPtr(this, true))); //transaction_send_task->scheduleTask(transaction_send_task); + auto pt = PendingTasksManager::getInstance(); + + pt->removeTask(Poco::AutoPtr(this, true)); return 1 == runSendTransaction(); //return true; } @@ -507,9 +510,6 @@ namespace model { addError(new ParamError(function_name, "unknown error", TransactionValidationToString(result))); //sendErrorsAsEmail(); } - - auto pt = PendingTasksManager::getInstance(); - pt->reportErrorToCommunityServer(Poco::AutoPtr(this, true), error_name, error_description); addError(new ParamError(function_name, error_name, error_description)); } return -1; @@ -563,13 +563,13 @@ namespace model { auto result = json_request.request("putTransaction", param); json_request.getWarnings(&json_request); - if (JSON_REQUEST_RETURN_OK == result) - { + if (JSON_REQUEST_RETURN_OK == result) + { if (!json_request.errorCount()) { finishSuccess(); } else { - getErrors(&json_request); + getErrors(&json_request); return -1; } return 1; diff --git a/login_server/src/cpp/model/table/ModelBase.cpp b/login_server/src/cpp/model/table/ModelBase.cpp index 8ddab7ade..737db3f98 100644 --- a/login_server/src/cpp/model/table/ModelBase.cpp +++ b/login_server/src/cpp/model/table/ModelBase.cpp @@ -56,9 +56,9 @@ namespace model { try { auto res = select.execute(); if (1 == res) { return true; } - + } - catch (Poco::Exception& ex) { + catch (Poco::Exception& ex) { addError(new ParamError(getTableName(), "mysql error by select id", ex.displayText().data())); addError(new ParamError(getTableName(), "data set: ", toString().data())); } @@ -126,20 +126,22 @@ namespace model { { Poco::ScopedLock _lock(mWorkMutex); mReferenceCount++; - //printf("[ModelBase::duplicate] new value: %d\n", mReferenceCount); } void ModelBase::release() { - Poco::ScopedLock _lock(mWorkMutex); + if(mReferenceCount <= 0) { + throw Poco::Exception("ModelBase already released", getTableName()); + } + + Poco::ScopedLock _lock(mWorkMutex); + mReferenceCount--; - //printf("[ModelBase::release] new value: %d\n", mReferenceCount); + if (0 == mReferenceCount) { - delete this; return; } - } Poco::Data::Statement ModelBase::_loadFromDB(Poco::Data::Session session, const std::vector& fieldNames, MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/) @@ -180,7 +182,7 @@ namespace model { Poco::Mutex& timeMutex = ServerConfig::g_TimeMutex; int year, month, day, hour, minute, second; - // ex: 2009-10-29 + // ex: 2009-10-29 if (sscanf(decodedDateString.data(), "%d-%d-%dT%d:%dZ", &year, &month, &day, &hour, &minute) != EOF) { time_t rawTime; time(&rawTime); diff --git a/login_server/src/cpp/model/table/PendingTask.cpp b/login_server/src/cpp/model/table/PendingTask.cpp index 3b1856aa1..541e9c262 100644 --- a/login_server/src/cpp/model/table/PendingTask.cpp +++ b/login_server/src/cpp/model/table/PendingTask.cpp @@ -70,7 +70,11 @@ namespace model { SHARED_LOCK; temp = mResultJsonString; + if(!mResultJsonString.size()) { + return new Poco::JSON::Object; + } } + Poco::JSON::Parser parser; Poco::Dynamic::Var result; try