mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
refactor gradido transaction handling
This commit is contained in:
parent
c8b9e3b0f5
commit
5e524d7ac6
@ -8,6 +8,7 @@
|
||||
#include "SingletonManager/ConnectionManager.h"
|
||||
#include "SingletonManager/SessionManager.h"
|
||||
#include "SingletonManager/EmailManager.h"
|
||||
#include "SingletonManager/PendingTasksManager.h"
|
||||
|
||||
#include "controller/User.h"
|
||||
|
||||
@ -252,6 +253,9 @@ int Gradido_LoginServer::main(const std::vector<std::string>& args)
|
||||
// start the json server
|
||||
json_srv.start();
|
||||
|
||||
// load pending tasks not finished in last session
|
||||
PendingTasksManager::getInstance()->load();
|
||||
|
||||
printf("[Gradido_LoginServer::main] started in %s\n", usedTime.string().data());
|
||||
// wait for CTRL-C or kill
|
||||
waitForTerminationRequest();
|
||||
|
||||
@ -52,6 +52,14 @@ int MemoryBin::convertFromHex(const std::string& hex)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool MemoryBin::isSame(const MemoryBin* b) const
|
||||
{
|
||||
if (b->size() != size()) {
|
||||
return false;
|
||||
}
|
||||
return 0 == memcmp(data(), b->data(), size());
|
||||
}
|
||||
|
||||
|
||||
// *************************************************************
|
||||
|
||||
|
||||
@ -50,6 +50,8 @@ public:
|
||||
//! -2 if hex is invalid
|
||||
int convertFromHex(const std::string& hex);
|
||||
|
||||
bool isSame(const MemoryBin* b) const;
|
||||
|
||||
protected:
|
||||
MemoryBin(Poco::UInt32 size);
|
||||
~MemoryBin();
|
||||
|
||||
67
src/cpp/SingletonManager/PendingTasksManager.cpp
Normal file
67
src/cpp/SingletonManager/PendingTasksManager.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
#include "PendingTasksManager.h"
|
||||
|
||||
PendingTasksManager::PendingTasksManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
PendingTasksManager::~PendingTasksManager()
|
||||
{
|
||||
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);
|
||||
for (auto it = mPendingTasks.begin(); it != mPendingTasks.end(); it++) {
|
||||
delete it->second;
|
||||
}
|
||||
mPendingTasks.clear();
|
||||
}
|
||||
|
||||
PendingTasksManager* PendingTasksManager::getInstance()
|
||||
{
|
||||
static PendingTasksManager theOne;
|
||||
return &theOne;
|
||||
}
|
||||
|
||||
int PendingTasksManager::load()
|
||||
{
|
||||
auto pending_tasks = controller::PendingTask::loadAll();
|
||||
for (auto it = pending_tasks.begin(); it != pending_tasks.end(); it++) {
|
||||
addTask(*it);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PendingTasksManager::addTask(Poco::AutoPtr<controller::PendingTask> task)
|
||||
{
|
||||
if (task.isNull() || !task->getModel()) {
|
||||
return -1;
|
||||
}
|
||||
auto model = task->getModel();
|
||||
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);
|
||||
auto pending_task_list = getTaskListForUser(model->getUserId());
|
||||
pending_task_list->push_back(task);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
PendingTasksManager::PendingTaskList* PendingTasksManager::getTaskListForUser(int userId)
|
||||
{
|
||||
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);
|
||||
auto it = mPendingTasks.find(userId);
|
||||
if (it == mPendingTasks.end()) {
|
||||
auto pending_list = new PendingTaskList;
|
||||
mPendingTasks.insert(std::pair<int, PendingTaskList*>(userId, pending_list));
|
||||
return pending_list;
|
||||
}
|
||||
else {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
}
|
||||
const PendingTasksManager::PendingTaskList* PendingTasksManager::getTaskListForUser(int userId) const
|
||||
{
|
||||
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);
|
||||
auto it = mPendingTasks.find(userId);
|
||||
if (it != mPendingTasks.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
50
src/cpp/SingletonManager/PendingTasksManager.h
Normal file
50
src/cpp/SingletonManager/PendingTasksManager.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*!
|
||||
*
|
||||
* \author: einhornimmond
|
||||
*
|
||||
* \date: 13.10.20
|
||||
*
|
||||
* \brief: manage tasks which need to wait on extern work
|
||||
|
||||
* like hedera tasks waiting on hedera network processing transactions
|
||||
* like gradido transactions which are signed from additional people like ManageGroup Tasks
|
||||
*/
|
||||
|
||||
#ifndef GRADIDO_LOGIN_SERVER_SINGLETON_MANAGER_PENDING_TASKS_MANAGER
|
||||
#define GRADIDO_LOGIN_SERVER_SINGLETON_MANAGER_PENDING_TASKS_MANAGER
|
||||
|
||||
#include "../controller/PendingTask.h"
|
||||
|
||||
class PendingTasksManager: public UniLib::lib::MultithreadContainer
|
||||
{
|
||||
public:
|
||||
typedef std::list<Poco::AutoPtr<controller::PendingTask>> PendingTaskList;
|
||||
|
||||
~PendingTasksManager();
|
||||
|
||||
static PendingTasksManager* getInstance();
|
||||
|
||||
//! \brief load pending tasks from db at server start
|
||||
int load();
|
||||
|
||||
//! \return -1 task is zero
|
||||
//! \return 0 if added
|
||||
int addTask(Poco::AutoPtr<controller::PendingTask> task);
|
||||
|
||||
//! by calling this, important is to call lock to prevent vanishing the list while working with it,
|
||||
//! and unlock afterwards
|
||||
//! \return list or nullptr if no list for user exist
|
||||
const PendingTaskList* getTaskListForUser(int userId) const;
|
||||
|
||||
protected:
|
||||
PendingTasksManager();
|
||||
|
||||
|
||||
std::map<int, PendingTaskList*> mPendingTasks;
|
||||
//! \return list for user, creating new list and map entry if not exist
|
||||
PendingTaskList* getTaskListForUser(int userId);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //GRADIDO_LOGIN_SERVER_SINGLETON_MANAGER_PENDING_TASKS_MANAGER
|
||||
@ -1,5 +1,8 @@
|
||||
#include "PendingTask.h"
|
||||
|
||||
#include "../tasks/GradidoGroupAddMemberTask.h"
|
||||
|
||||
|
||||
namespace controller {
|
||||
|
||||
PendingTask::PendingTask(model::table::PendingTask* dbModel)
|
||||
@ -15,7 +18,7 @@ namespace controller {
|
||||
Poco::AutoPtr<PendingTask> 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);
|
||||
auto pending_task = loadCorrectDerivedClass(db);
|
||||
return Poco::AutoPtr<PendingTask>(pending_task);
|
||||
}
|
||||
|
||||
@ -26,11 +29,41 @@ namespace controller {
|
||||
std::vector<Poco::AutoPtr<PendingTask>> 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)));
|
||||
resultVector.push_back(loadCorrectDerivedClass(new model::table::PendingTask(*it)));
|
||||
}
|
||||
return resultVector;
|
||||
|
||||
|
||||
}
|
||||
|
||||
std::vector<Poco::AutoPtr<PendingTask>> PendingTask::loadAll()
|
||||
{
|
||||
auto db = new model::table::PendingTask();
|
||||
std::vector<model::table::PendingTaskTuple> task_list;
|
||||
// throw an unresolved external symbol error
|
||||
task_list = db->loadAllFromDB<model::table::PendingTaskTuple>();
|
||||
|
||||
|
||||
//*/ //work around end
|
||||
std::vector<Poco::AutoPtr<PendingTask>> resultVector;
|
||||
|
||||
resultVector.reserve(task_list.size());
|
||||
for (auto it = task_list.begin(); it != task_list.end(); it++) {
|
||||
auto group_ptr = loadCorrectDerivedClass(new model::table::PendingTask(*it));
|
||||
resultVector.push_back(group_ptr);
|
||||
}
|
||||
return resultVector;
|
||||
}
|
||||
|
||||
Poco::AutoPtr<PendingTask> PendingTask::loadCorrectDerivedClass(model::table::PendingTask* dbModel)
|
||||
{
|
||||
if (!dbModel) return nullptr;
|
||||
auto type = dbModel->getTaskType();
|
||||
switch (type) {
|
||||
case model::table::TASK_TYPE_GROUP_ADD_MEMBER: return new GradidoGroupAddMemberTask(dbModel);
|
||||
default: return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
@ -21,13 +21,20 @@ namespace controller {
|
||||
static Poco::AutoPtr<PendingTask> create(int userId, std::string serializedProtoRequest, model::table::TaskType type);
|
||||
|
||||
static std::vector<Poco::AutoPtr<PendingTask>> load(int userId);
|
||||
static std::vector<Poco::AutoPtr<PendingTask>> loadAll();
|
||||
|
||||
inline bool deleteFromDB() { return mDBModel->deleteFromDB(); }
|
||||
|
||||
inline Poco::AutoPtr<model::table::PendingTask> getModel() { return _getModel<model::table::PendingTask>(); }
|
||||
|
||||
virtual bool isTimeoutTask() = 0;
|
||||
virtual Poco::DateTime getNextRunTime() { return Poco::DateTime(); };
|
||||
//! \return 1 run finished, more runs needed
|
||||
//! \return 0 run finished, no more runs needed
|
||||
//! \return -1 error, more runs needed
|
||||
//! \return -2 critical error, abort, remove
|
||||
virtual int run() { return false; };
|
||||
|
||||
protected:
|
||||
static Poco::AutoPtr<PendingTask> loadCorrectDerivedClass(model::table::PendingTask* dbModel);
|
||||
PendingTask(model::table::PendingTask* dbModel);
|
||||
|
||||
|
||||
|
||||
@ -277,6 +277,13 @@ namespace DataTypeConverter
|
||||
return microseconds;
|
||||
}
|
||||
|
||||
Poco::Timestamp convertFromProtoTimestampSeconds(const proto::gradido::TimestampSeconds& timestampSeconds)
|
||||
{
|
||||
google::protobuf::int64 microseconds = timestampSeconds.seconds() * (google::protobuf::int64)10e5;
|
||||
|
||||
return microseconds;
|
||||
}
|
||||
|
||||
Poco::Timespan convertFromProtoDuration(const proto::Duration& duration)
|
||||
{
|
||||
return Poco::Timespan(duration.seconds(), 0);
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
|
||||
#include "../proto/hedera/Timestamp.pb.h"
|
||||
#include "../proto/hedera/Duration.pb.h"
|
||||
#include "../proto/gradido/BasicTypes.pb.h"
|
||||
|
||||
#include "sodium.h"
|
||||
|
||||
@ -50,6 +51,7 @@ namespace DataTypeConverter {
|
||||
std::string convertTimespanToLocalizedString(Poco::Timespan duration, LanguageCatalog* lang);
|
||||
|
||||
Poco::Timestamp convertFromProtoTimestamp(const proto::Timestamp& timestamp);
|
||||
Poco::Timestamp convertFromProtoTimestampSeconds(const proto::gradido::TimestampSeconds& timestampSeconds);
|
||||
Poco::Timespan convertFromProtoDuration(const proto::Duration& duration);
|
||||
};
|
||||
|
||||
|
||||
@ -18,15 +18,59 @@ namespace model {
|
||||
|
||||
int GroupMemberUpdate::prepare()
|
||||
{
|
||||
const static char functionName[] = { "GroupMemberUpdate::prepare" };
|
||||
auto target_group = mProtoMemberUpdate.target_group();
|
||||
auto sm = SessionManager::getInstance();
|
||||
auto mm = MemoryManager::getInstance();
|
||||
|
||||
if (mProtoMemberUpdate.user_pubkey().size() != KeyPairEd25519::getPublicKeySize()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto pubkey_copy = mm->getFreeMemory(KeyPairEd25519::getPublicKeySize());
|
||||
memcpy(*pubkey_copy, mProtoMemberUpdate.user_pubkey().data(), KeyPairEd25519::getPublicKeySize());
|
||||
mRequiredSignPublicKeys.push_back(pubkey_copy);
|
||||
|
||||
if (sm->isValid(target_group, VALIDATE_GROUP_ALIAS)) {
|
||||
auto groups = controller::Group::load(mProtoMemberUpdate.target_group());
|
||||
if (groups.size() > 0 && !groups[0].isNull() && groups[0]->getModel()) {
|
||||
auto user_db = controller::User::create();
|
||||
auto count = user_db->getModel()->countColumns("group_id", groups[0]->getModel()->getID());
|
||||
if (!count)
|
||||
{
|
||||
// no current user in group, at least login server known, so we need only one signature for transaction
|
||||
// TODO: maybe check with node server, but maybe it isn't necessary
|
||||
mMinSignatureCount = 1;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// at least one more user is in group
|
||||
// now we need the voting system to decide how many and which signatures are needed
|
||||
|
||||
// for current version we need only one another
|
||||
mMinSignatureCount = 2;
|
||||
}
|
||||
}
|
||||
/*if (groups.size() != 1) {
|
||||
addError(new ParamError(functionName, "target group not known or not unambiguous: ", target_group));
|
||||
return TRANSACTION_VALID_INVALID_GROUP_ALIAS;
|
||||
}*/
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TransactionValidation GroupMemberUpdate::validate()
|
||||
{
|
||||
const static char functionName[] = { "GroupMemberUpdate::validate" };
|
||||
if (mProtoMemberUpdate.user_pubkey().size() != KeyPairEd25519::getPublicKeySize()) {
|
||||
addError(new Error(functionName, "pubkey not set or wrong size"));
|
||||
return -1;
|
||||
return TRANSCATION_VALID_INVALID_PUBKEY;
|
||||
}
|
||||
|
||||
if (mProtoMemberUpdate.member_update_type() != proto::gradido::GroupMemberUpdate::ADD_USER) {
|
||||
addError(new Error(functionName, "user move not implemented yet!"));
|
||||
return 1;
|
||||
return TRANSACTION_VALID_CODE_ERROR;
|
||||
}
|
||||
auto target_group = mProtoMemberUpdate.target_group();
|
||||
auto sm = SessionManager::getInstance();
|
||||
@ -34,15 +78,21 @@ namespace model {
|
||||
auto groups = controller::Group::load(mProtoMemberUpdate.target_group());
|
||||
if (groups.size() != 1) {
|
||||
addError(new ParamError(functionName, "target group not known or not unambiguous: ", target_group));
|
||||
return -2;
|
||||
return TRANSACTION_VALID_INVALID_GROUP_ALIAS;
|
||||
}
|
||||
}
|
||||
else {
|
||||
addError(new Error(functionName, "target group isn't valid group alias string "));
|
||||
return -3;
|
||||
return TRANSACTION_VALID_INVALID_GROUP_ALIAS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return TRANSACTION_VALID_OK;
|
||||
}
|
||||
/*
|
||||
GroupMemberUpdate::GroupMemberUpdate(const std::string& memo, Poco::AutoPtr<controller::User> user, Poco::AutoPtr<controller::Group> group)
|
||||
{
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,7 @@
|
||||
#include "TransactionBase.h"
|
||||
#include "../../proto/gradido/GroupMemberUpdate.pb.h"
|
||||
|
||||
|
||||
namespace model {
|
||||
namespace gradido {
|
||||
class GroupMemberUpdate : public TransactionBase
|
||||
@ -12,6 +13,7 @@ namespace model {
|
||||
GroupMemberUpdate(const std::string& memo, const proto::gradido::GroupMemberUpdate &protoGroupMemberUpdate);
|
||||
~GroupMemberUpdate();
|
||||
int prepare();
|
||||
TransactionValidation validate();
|
||||
|
||||
protected:
|
||||
const proto::gradido::GroupMemberUpdate& mProtoMemberUpdate;
|
||||
|
||||
123
src/cpp/model/gradido/Transaction.cpp
Normal file
123
src/cpp/model/gradido/Transaction.cpp
Normal file
@ -0,0 +1,123 @@
|
||||
#include "Transaction.h"
|
||||
#include "../../SingletonManager/ErrorManager.h"
|
||||
|
||||
namespace model {
|
||||
namespace gradido {
|
||||
Transaction::Transaction(Poco::AutoPtr<TransactionBody> body)
|
||||
: mTransactionBody(body), mBodyBytesHash(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Transaction::~Transaction()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Transaction::addSign(Poco::AutoPtr<controller::User> user)
|
||||
{
|
||||
static const char function_name[] = "Transaction::addSign";
|
||||
|
||||
if (user.isNull() || !user->getModel())
|
||||
{
|
||||
addError(new Error(function_name, "error user is invalid"));
|
||||
return false;
|
||||
}
|
||||
std::string bodyBytes;
|
||||
try {
|
||||
bodyBytes = mTransactionBody->getBodyBytes();
|
||||
}
|
||||
catch (Poco::Exception& ex) {
|
||||
addError(new Error(function_name, "error getting body bytes"));
|
||||
return false;
|
||||
}
|
||||
auto hash = DRMakeStringHash(bodyBytes.data(), bodyBytes.size());
|
||||
|
||||
|
||||
auto sigMap = mProtoTransaction.mutable_sig_map();
|
||||
if (sigMap->sigpair_size() > 0 && mBodyBytesHash && mBodyBytesHash != hash)
|
||||
{
|
||||
addError(new Error(function_name, "body bytes hash has changed and signature(s) exist already!"));
|
||||
return false;
|
||||
}
|
||||
mBodyBytesHash = hash;
|
||||
|
||||
auto pubkeyBin = user->getModel()->getPublicKey();
|
||||
|
||||
// check if pubkey already exist
|
||||
for (auto it = sigMap->sigpair().begin(); it != sigMap->sigpair().end(); it++)
|
||||
{
|
||||
if (it->pubkey().size() != KeyPairEd25519::getPublicKeySize()) {
|
||||
addError(new Error(function_name, "error signature pubkey hasn't expected size!"));
|
||||
return false;
|
||||
}
|
||||
if (0 == memcmp(pubkeyBin, it->pubkey().data(), KeyPairEd25519::getPublicKeySize())) {
|
||||
addError(new ParamError(function_name, "error, pubkey has signed already from user: ", user->getModel()->getEmail()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
auto mm = MemoryManager::getInstance();
|
||||
auto gradido_key_pair = user->getGradidoKeyPair();
|
||||
KeyPairEd25519* recovered_gradido_key_pair = nullptr;
|
||||
|
||||
if (!gradido_key_pair || !gradido_key_pair->hasPrivateKey())
|
||||
{
|
||||
if (!user->tryLoadPassphraseUserBackup(&recovered_gradido_key_pair))
|
||||
{
|
||||
if (user->setGradidoKeyPair(recovered_gradido_key_pair))
|
||||
{
|
||||
user->getModel()->updatePrivkey();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
addError(new Error(function_name, "user cannot decrypt private key"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MemoryBin* sign = nullptr;
|
||||
if (gradido_key_pair)
|
||||
{
|
||||
sign = gradido_key_pair->sign(bodyBytes);
|
||||
}
|
||||
else if (recovered_gradido_key_pair)
|
||||
{
|
||||
sign = recovered_gradido_key_pair->sign(bodyBytes);
|
||||
}
|
||||
if (!sign)
|
||||
{
|
||||
ErrorManager::getInstance()->sendErrorsAsEmail();
|
||||
addError(new Error(function_name, "error by calculate signature"));
|
||||
mm->releaseMemory(sign);
|
||||
return false;
|
||||
}
|
||||
auto sigPair = sigMap->add_sigpair();
|
||||
auto pubkeyBytes = sigPair->mutable_pubkey();
|
||||
*pubkeyBytes = std::string((const char*)pubkeyBin, crypto_sign_PUBLICKEYBYTES);
|
||||
|
||||
auto sigBytes = sigPair->mutable_ed25519();
|
||||
*sigBytes = std::string((char*)*sign, sign->size());
|
||||
mm->releaseMemory(sign);
|
||||
|
||||
return true;
|
||||
}
|
||||
TransactionValidation Transaction::validate()
|
||||
{
|
||||
auto sig_map = mProtoTransaction.sig_map();
|
||||
auto transaction_base = mTransactionBody->getTransactionBase();
|
||||
auto result = transaction_base->checkRequiredSignatures(&sig_map);
|
||||
|
||||
if (result == TRANSACTION_VALID_OK)
|
||||
{
|
||||
return transaction_base->validate();
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
37
src/cpp/model/gradido/Transaction.h
Normal file
37
src/cpp/model/gradido/Transaction.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef GRADIDO_LOGIN_SERVER_MODEL_GRADIDO_TRANSACTION_H
|
||||
#define GRADIDO_LOGIN_SERVER_MODEL_GRADIDO_TRANSACTION_H
|
||||
|
||||
/*
|
||||
* @author: Dario Rekowski
|
||||
*
|
||||
* @date: 12.10.2020
|
||||
*
|
||||
* @brief: mainly for signing gradido transaction
|
||||
*/
|
||||
|
||||
#include "../../proto/gradido/GradidoTransaction.pb.h"
|
||||
#include "TransactionBody.h"
|
||||
#include "../../controller/User.h"
|
||||
|
||||
|
||||
namespace model {
|
||||
namespace gradido {
|
||||
class Transaction : public NotificationList
|
||||
{
|
||||
public:
|
||||
Transaction(Poco::AutoPtr<TransactionBody> body);
|
||||
~Transaction();
|
||||
|
||||
bool addSign(Poco::AutoPtr<controller::User> user);
|
||||
TransactionValidation validate();
|
||||
|
||||
|
||||
protected:
|
||||
Poco::AutoPtr<TransactionBody> mTransactionBody;
|
||||
proto::gradido::GradidoTransaction mProtoTransaction;
|
||||
HASH mBodyBytesHash;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif //GRADIDO_LOGIN_SERVER_MODEL_GRADIDO_TRANSACTION_H
|
||||
@ -1,15 +1,32 @@
|
||||
#include "TransactionBase.h"
|
||||
#include "../../Crypto/KeyPairEd25519.h"
|
||||
#include <iomanip>
|
||||
|
||||
namespace model {
|
||||
namespace gradido {
|
||||
|
||||
TransactionBase::TransactionBase(const std::string& memo)
|
||||
: mMemo(memo)
|
||||
: mMemo(memo), mMinSignatureCount(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TransactionBase::~TransactionBase()
|
||||
{
|
||||
auto mm = MemoryManager::getInstance();
|
||||
for (auto it = mRequiredSignPublicKeys.begin(); it != mRequiredSignPublicKeys.end(); it++)
|
||||
{
|
||||
mm->releaseMemory(*it);
|
||||
}
|
||||
mRequiredSignPublicKeys.clear();
|
||||
for (auto it = mForbiddenSignPublicKeys.begin(); it != mForbiddenSignPublicKeys.end(); it++)
|
||||
{
|
||||
mm->releaseMemory(*it);
|
||||
}
|
||||
mForbiddenSignPublicKeys.clear();
|
||||
}
|
||||
|
||||
|
||||
std::string TransactionBase::amountToString(google::protobuf::int64 amount)
|
||||
{
|
||||
std::stringstream ss;
|
||||
@ -25,6 +42,77 @@ namespace model {
|
||||
return amountString;
|
||||
//return ss.str();
|
||||
}
|
||||
|
||||
TransactionValidation TransactionBase::checkRequiredSignatures(const proto::gradido::SignatureMap* sig_map)
|
||||
{
|
||||
if (!mMinSignatureCount) {
|
||||
addError(new Error("TransactionBase::checkRequiredSignatures", "mMinSignatureCount is zero"));
|
||||
return TRANSACTION_VALID_CODE_ERROR;
|
||||
}
|
||||
// not enough
|
||||
if (mMinSignatureCount > sig_map->sigpair_size()) {
|
||||
return TRANSACTION_VALID_MISSING_SIGN;
|
||||
}
|
||||
// enough
|
||||
if (!mRequiredSignPublicKeys.size() && !mForbiddenSignPublicKeys.size()) {
|
||||
return TRANSACTION_VALID_OK;
|
||||
}
|
||||
// check if specific signatures can be found
|
||||
static const char function_name[] = "TransactionBase::checkRequiredSignatures";
|
||||
// prepare
|
||||
std::vector<MemoryBin*> required_keys = mRequiredSignPublicKeys;
|
||||
|
||||
bool forbidden_key_found = false;
|
||||
for (auto it = sig_map->sigpair().begin(); it != sig_map->sigpair().end(); it++)
|
||||
{
|
||||
auto pubkey_size = it->pubkey().size();
|
||||
if (pubkey_size != KeyPairEd25519::getPublicKeySize())
|
||||
{
|
||||
addError(new ParamError(function_name, "signature pubkey size is not as expected: ", pubkey_size));
|
||||
return TRANSACTION_VALID_CODE_ERROR;
|
||||
}
|
||||
// check for forbidden key
|
||||
if (!forbidden_key_found && mForbiddenSignPublicKeys.size())
|
||||
{
|
||||
for (auto it2 = mForbiddenSignPublicKeys.begin(); it2 != mForbiddenSignPublicKeys.end(); it2++) {
|
||||
if ((*it2)->size() != KeyPairEd25519::getPublicKeySize())
|
||||
{
|
||||
addError(new ParamError(function_name, "forbidden sign public key size is not as expected: ", (*it2)->size()));
|
||||
return TRANSACTION_VALID_CODE_ERROR;
|
||||
}
|
||||
if (0 == memcmp((*it2)->data(), it->pubkey().data(), pubkey_size))
|
||||
{
|
||||
forbidden_key_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (forbidden_key_found) break;
|
||||
|
||||
// compare with required keys
|
||||
for (auto it3 = required_keys.begin(); it3 != required_keys.end(); it3++)
|
||||
{
|
||||
if ((*it3)->size() != KeyPairEd25519::getPublicKeySize())
|
||||
{
|
||||
addError(new ParamError(function_name, "required sign public key size is not as expected: ", (*it3)->size()));
|
||||
return TRANSACTION_VALID_CODE_ERROR;
|
||||
}
|
||||
if (0 == memcmp((*it3)->data(), it->pubkey().data(), pubkey_size))
|
||||
{
|
||||
it3 = required_keys.erase(it3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (forbidden_key_found) return TRANSACTION_VALID_FORBIDDEN_SIGN;
|
||||
if (!required_keys.size()) return TRANSACTION_VALID_OK;
|
||||
|
||||
// TODO: check that given pubkeys are registered for same group
|
||||
|
||||
return TRANSACTION_VALID_MISSING_SIGN;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -17,18 +17,40 @@
|
||||
|
||||
namespace model {
|
||||
namespace gradido {
|
||||
|
||||
enum TransactionValidation {
|
||||
TRANSACTION_VALID_OK,
|
||||
TRANSACTION_VALID_MISSING_SIGN,
|
||||
TRANSACTION_VALID_FORBIDDEN_SIGN,
|
||||
TRANSACTION_VALID_MISSING_PARAM,
|
||||
TRANSACTION_VALID_CODE_ERROR,
|
||||
TRANSACTION_VALID_INVALID_TARGET_DATE,
|
||||
TRANSACTION_VALID_CREATION_OUT_OF_BORDER,
|
||||
TRANSACTION_VALID_INVALID_AMOUNT,
|
||||
TRANSCATION_VALID_INVALID_PUBKEY,
|
||||
TRANSACTION_VALID_INVALID_GROUP_ALIAS
|
||||
};
|
||||
|
||||
class TransactionBase : public NotificationList, public UniLib::lib::MultithreadContainer
|
||||
{
|
||||
public:
|
||||
TransactionBase(const std::string& memo);
|
||||
virtual ~TransactionBase();
|
||||
//! \return 0 if ok, < 0 if error, > 0 if not implemented
|
||||
virtual int prepare() = 0;
|
||||
virtual TransactionValidation validate() = 0;
|
||||
|
||||
static std::string amountToString(google::protobuf::int64 amount);
|
||||
inline const std::string& getMemo() const { return mMemo; }
|
||||
|
||||
//! \return true if all required signatures are found in signature pairs
|
||||
TransactionValidation checkRequiredSignatures(const proto::gradido::SignatureMap* sig_map);
|
||||
|
||||
protected:
|
||||
std::string mMemo;
|
||||
Poco::UInt32 mMinSignatureCount;
|
||||
std::vector<MemoryBin*> mRequiredSignPublicKeys;
|
||||
std::vector<MemoryBin*> mForbiddenSignPublicKeys;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,6 +91,8 @@ namespace model {
|
||||
return "<uninitalized>";
|
||||
}
|
||||
|
||||
|
||||
|
||||
TransactionCreation* TransactionBody::getCreationTransaction()
|
||||
{
|
||||
return dynamic_cast<TransactionCreation*>(mTransactionSpecific);
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
#define GRADIDO_LOGIN_SERVER_MODEL_GRADIDO_TRANSACTION_BASE_H
|
||||
|
||||
#include "../../controller/User.h"
|
||||
#include "../../controller/Group.h"
|
||||
#include "GroupMemberUpdate.h"
|
||||
#include "TransactionCreation.h"
|
||||
#include "TransactionTransfer.h"
|
||||
@ -20,6 +21,7 @@ namespace model {
|
||||
TRANSACTION_GROUP_MEMBER_UPDATE
|
||||
};
|
||||
|
||||
|
||||
|
||||
class TransactionBody : public Poco::RefCountedObject, UniLib::lib::MultithreadContainer
|
||||
{
|
||||
|
||||
@ -26,8 +26,8 @@ namespace model {
|
||||
auto receiver_amount = mProtoCreation.receiver();
|
||||
|
||||
auto receiverPublic = receiver_amount.pubkey();
|
||||
if (receiverPublic.size() != 32) {
|
||||
addError(new Error(functionName, "receiver public invalid (size not 32)"));
|
||||
if (receiverPublic.size() != KeyPairEd25519::getPublicKeySize()) {
|
||||
addError(new ParamError(functionName, "receiver public invalid: ", receiverPublic.size()));
|
||||
return -2;
|
||||
}
|
||||
mReceiverUser = controller::User::create();
|
||||
@ -49,7 +49,11 @@ namespace model {
|
||||
}*/
|
||||
}
|
||||
//
|
||||
|
||||
mMinSignatureCount = 1;
|
||||
auto mm = MemoryManager::getInstance();
|
||||
auto pubkey_copy = mm->getFreeMemory(KeyPairEd25519::getPublicKeySize());
|
||||
memcpy(*pubkey_copy, receiverPublic.data(), KeyPairEd25519::getPublicKeySize());
|
||||
mForbiddenSignPublicKeys.push_back(pubkey_copy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -62,6 +66,56 @@ namespace model {
|
||||
return Poco::DateTimeFormatter::format(pocoStamp, "%d. %b %y");
|
||||
}
|
||||
|
||||
TransactionValidation TransactionCreation::validate()
|
||||
{
|
||||
static const char function_name[] = "TransactionCreation::validate";
|
||||
auto target_date = Poco::DateTime(DataTypeConverter::convertFromProtoTimestampSeconds(mProtoCreation.target_date()));
|
||||
auto now = Poco::DateTime();
|
||||
if (target_date.year() == now.year())
|
||||
{
|
||||
if (target_date.month() + 3 < now.month()) {
|
||||
addError(new Error(function_name, "year is the same, target date month is more than 3 month in past"));
|
||||
return TRANSACTION_VALID_INVALID_TARGET_DATE;
|
||||
}
|
||||
if (target_date.month() > now.month()) {
|
||||
addError(new Error(function_name, "year is the same, target date month is in future"));
|
||||
return TRANSACTION_VALID_INVALID_TARGET_DATE;
|
||||
}
|
||||
}
|
||||
else if(target_date.year() > now.year())
|
||||
{
|
||||
addError(new Error(function_name, "target date year is in future"));
|
||||
return TRANSACTION_VALID_INVALID_TARGET_DATE;
|
||||
}
|
||||
else if(target_date.year() +1 < now.year())
|
||||
{
|
||||
addError(new Error(function_name, "target date year is in past"));
|
||||
return TRANSACTION_VALID_INVALID_TARGET_DATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// target_date.year +1 == now.year
|
||||
if (target_date.month() + 3 < now.month() + 12) {
|
||||
addError(new Error(function_name, "target date is more than 3 month in past"));
|
||||
return TRANSACTION_VALID_INVALID_TARGET_DATE;
|
||||
}
|
||||
}
|
||||
if (mProtoCreation.receiver().amount() > 1000 * 10000) {
|
||||
addError(new Error(function_name, "creation amount to high, max 1000 per month"));
|
||||
return TRANSACTION_VALID_CREATION_OUT_OF_BORDER;
|
||||
}
|
||||
|
||||
if (mProtoCreation.receiver().pubkey().size() != KeyPairEd25519::getPublicKeySize()) {
|
||||
addError(new Error(function_name, "receiver pubkey has invalid size"));
|
||||
return TRANSCATION_VALID_INVALID_PUBKEY;
|
||||
}
|
||||
|
||||
// TODO: check creation amount from last 3 month from node server
|
||||
|
||||
|
||||
return TRANSACTION_VALID_OK;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -25,6 +25,9 @@ namespace model {
|
||||
~TransactionCreation();
|
||||
|
||||
int prepare();
|
||||
//! TODO: check created sum in the last 3 month if 1.000 per month isn't exceed
|
||||
//! maybe ask node server and hope the answer came fast
|
||||
TransactionValidation validate();
|
||||
|
||||
inline Poco::AutoPtr<controller::User> getUser() { return mReceiverUser; }
|
||||
inline google::protobuf::int64 getAmount() { return mProtoCreation.receiver().amount(); }
|
||||
|
||||
@ -97,7 +97,14 @@ namespace model {
|
||||
else {
|
||||
mKontoTable.push_back(KontoTableEntry(sender_user->getModel(), amount, true));
|
||||
}
|
||||
mMinSignatureCount = 1;
|
||||
auto mm = MemoryManager::getInstance();
|
||||
auto pubkey_copy = mm->getFreeMemory(KeyPairEd25519::getPublicKeySize());
|
||||
memcpy(*pubkey_copy, sender_pubkey.data(), KeyPairEd25519::getPublicKeySize());
|
||||
mRequiredSignPublicKeys.push_back(pubkey_copy);
|
||||
}
|
||||
|
||||
|
||||
// TODO: add version for group transfer
|
||||
|
||||
|
||||
@ -118,6 +125,34 @@ namespace model {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TransactionValidation TransactionTransfer::validate()
|
||||
{
|
||||
static const char function_name[] = "TransactionTransfer::validate";
|
||||
if (!mProtoTransfer.has_local()) {
|
||||
addError(new Error(function_name, "only local currently implemented"));
|
||||
return TRANSACTION_VALID_CODE_ERROR;
|
||||
}
|
||||
auto amount = mProtoTransfer.local().sender().amount();
|
||||
if (0 == amount) {
|
||||
addError(new Error(function_name, "amount is empty"));
|
||||
return TRANSACTION_VALID_INVALID_AMOUNT;
|
||||
}
|
||||
else if (amount < 0) {
|
||||
addError(new Error(function_name, "negative amount"));
|
||||
return TRANSACTION_VALID_INVALID_AMOUNT;
|
||||
}
|
||||
if (mProtoTransfer.local().receiver().size() != KeyPairEd25519::getPublicKeySize()) {
|
||||
addError(new Error(function_name, "invalid size of receiver pubkey"));
|
||||
return TRANSCATION_VALID_INVALID_PUBKEY;
|
||||
}
|
||||
if (mProtoTransfer.local().sender().pubkey().size() != KeyPairEd25519::getPublicKeySize()) {
|
||||
addError(new Error(function_name, "invalid size of sender pubkey"));
|
||||
return TRANSCATION_VALID_INVALID_PUBKEY;
|
||||
}
|
||||
return TRANSACTION_VALID_OK;
|
||||
|
||||
}
|
||||
|
||||
const std::string& TransactionTransfer::getKontoNameCell(int index)
|
||||
{
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@ namespace model {
|
||||
~TransactionTransfer();
|
||||
|
||||
int prepare();
|
||||
TransactionValidation validate();
|
||||
|
||||
inline size_t getKontoTableSize() { lock(); size_t s = mKontoTable.size(); unlock(); return s; }
|
||||
const std::string& getKontoNameCell(int index);
|
||||
|
||||
@ -42,7 +42,6 @@ namespace model {
|
||||
std::string mUrl;
|
||||
std::string mDescription;
|
||||
|
||||
mutable std::shared_mutex mSharedMutex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -16,6 +16,9 @@
|
||||
#include <shared_mutex>
|
||||
//using namespace Poco::Data::Keywords;
|
||||
|
||||
#define SHARED_LOCK std::shared_lock<std::shared_mutex> _lock(mSharedMutex)
|
||||
#define UNIQUE_LOCK std::unique_lock<std::shared_mutex> _lock(mSharedMutex)
|
||||
|
||||
namespace model {
|
||||
namespace table {
|
||||
|
||||
@ -42,6 +45,9 @@ namespace model {
|
||||
size_t updateIntoDB(std::string fieldNames[3], const T1& fieldValue1, const T2& fieldValue2, const T3& fieldValue3);
|
||||
template<class T>
|
||||
size_t loadFromDB(const std::string& fieldName, const T& fieldValue);
|
||||
//! \brief count columes for "SELECT count(id) from <tableName> where <fieldName> = <fieldValue> group by id";
|
||||
template<class T>
|
||||
size_t countColumns(const std::string& fieldName, const T& fieldValue);
|
||||
template<class T>
|
||||
bool isExistInDB(const std::string& fieldName, const T& fieldValue);
|
||||
bool isExistInDB();
|
||||
@ -79,7 +85,9 @@ namespace model {
|
||||
int mID;
|
||||
|
||||
// for poco auto ptr
|
||||
int mReferenceCount;
|
||||
int mReferenceCount;
|
||||
|
||||
mutable std::shared_mutex mSharedMutex;
|
||||
|
||||
};
|
||||
|
||||
@ -103,6 +111,31 @@ namespace model {
|
||||
return resultCount;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
size_t ModelBase::countColumns(const std::string& fieldName, const T& fieldValue)
|
||||
{
|
||||
auto cm = ConnectionManager::getInstance();
|
||||
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);
|
||||
auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
|
||||
Poco::Data::Statement select(session);
|
||||
size_t count = 0;
|
||||
select
|
||||
<< "SELECT count(id) from " << getTableName()
|
||||
<< " where " << fieldName << " LIKE ? group by id"
|
||||
,Poco::Data::Keywords::into(count)
|
||||
,Poco::Data::Keywords::useRef(fieldValue);
|
||||
|
||||
size_t resultCount = 0;
|
||||
try {
|
||||
resultCount = select.execute();
|
||||
}
|
||||
catch (Poco::Exception& ex) {
|
||||
addError(new ParamError(getTableName(), "mysql error by selecting", ex.displayText().data()));
|
||||
addError(new ParamError(getTableName(), "field name for select: ", fieldName.data()));
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool ModelBase::isExistInDB(const std::string& fieldName, const T& fieldValue)
|
||||
{
|
||||
|
||||
@ -36,7 +36,7 @@ namespace model {
|
||||
|
||||
static const char* nodeServerTypeToString(NodeServerType type);
|
||||
|
||||
inline void setLastLiveSign(Poco::DateTime lastLiveSign) { std::unique_lock<std::shared_mutex> _lock(mSharedMutex); mLastLiveSign = lastLiveSign; }
|
||||
inline void setLastLiveSign(Poco::DateTime lastLiveSign) { UNIQUE_LOCK; mLastLiveSign = lastLiveSign; }
|
||||
|
||||
inline std::string getUrl() const { return mUrl; }
|
||||
inline int getPort() const { return mPort; }
|
||||
@ -46,7 +46,7 @@ namespace model {
|
||||
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<std::shared_mutex> _lock(mSharedMutex); return mLastLiveSign; }
|
||||
inline Poco::DateTime getLastLiveSign() const { SHARED_LOCK; return mLastLiveSign; }
|
||||
|
||||
protected:
|
||||
Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName);
|
||||
@ -60,8 +60,6 @@ namespace model {
|
||||
int mServerType;
|
||||
int mNodeHederaId;
|
||||
Poco::DateTime mLastLiveSign;
|
||||
|
||||
mutable std::shared_mutex mSharedMutex;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -66,6 +66,16 @@ namespace model
|
||||
return select;
|
||||
}
|
||||
|
||||
Poco::Data::Statement PendingTask::_loadAllFromDB(Poco::Data::Session session)
|
||||
{
|
||||
Poco::Data::Statement select(session);
|
||||
|
||||
select << "SELECT id, user_id, request, created, finished, result_json, task_type_id FROM " << getTableName();
|
||||
|
||||
return select;
|
||||
}
|
||||
|
||||
|
||||
Poco::Data::Statement PendingTask::_loadIdFromDB(Poco::Data::Session session)
|
||||
{
|
||||
Poco::Data::Statement select(session);
|
||||
|
||||
@ -4,8 +4,6 @@
|
||||
#include "ModelBase.h"
|
||||
#include "Poco/Types.h"
|
||||
|
||||
#include <shared_mutex>
|
||||
|
||||
namespace model {
|
||||
namespace table {
|
||||
|
||||
@ -20,12 +18,13 @@ namespace model {
|
||||
TASK_TYPE_HEDERA_ACCOUNT_CREATE = 25,
|
||||
|
||||
};
|
||||
|
||||
|
||||
typedef Poco::Tuple<int, int, Poco::Data::BLOB, Poco::DateTime, Poco::DateTime, std::string, int> PendingTaskTuple;
|
||||
|
||||
class PendingTask : public ModelBase
|
||||
{
|
||||
public:
|
||||
|
||||
PendingTask();
|
||||
PendingTask(int userId, std::string serializedProtoRequest, TaskType type);
|
||||
PendingTask(const PendingTaskTuple& tuple);
|
||||
@ -36,10 +35,13 @@ namespace model {
|
||||
const char* getTableName() const { return "pending_tasks"; }
|
||||
std::string toString();
|
||||
|
||||
inline int getUserId() const { SHARED_LOCK; return mUserId; }
|
||||
TaskType getTaskType() const { SHARED_LOCK; return (TaskType)mTaskTypeId; }
|
||||
|
||||
static const char* typeToString(TaskType type);
|
||||
protected:
|
||||
Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName);
|
||||
Poco::Data::Statement _loadAllFromDB(Poco::Data::Session session);
|
||||
Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session);
|
||||
Poco::Data::Statement _insertIntoDB(Poco::Data::Session session);
|
||||
|
||||
@ -50,8 +52,6 @@ namespace model {
|
||||
std::string mResultJsonString;
|
||||
int mTaskTypeId;
|
||||
|
||||
std::shared_mutex mSharedMutex;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
//#include "Poco/Nullable.h"
|
||||
//#include "Poco/Data/LOB.h"
|
||||
|
||||
#include <shared_mutex>
|
||||
|
||||
#include "UserRole.h"
|
||||
|
||||
@ -34,8 +33,6 @@ namespace model {
|
||||
class User : public ModelBase
|
||||
{
|
||||
public:
|
||||
#define SHARED_LOCK std::shared_lock<std::shared_mutex> _lock(mSharedMutex)
|
||||
#define UNIQUE_LOCK std::unique_lock<std::shared_mutex> _lock(mSharedMutex)
|
||||
User();
|
||||
User(UserTuple tuple);
|
||||
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");
|
||||
@ -123,7 +120,7 @@ namespace model {
|
||||
// from neighbor tables
|
||||
Poco::Nullable<int> mRole;
|
||||
|
||||
mutable std::shared_mutex mSharedMutex;
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
27
src/cpp/tasks/GradidoGroupAddMemberTask.cpp
Normal file
27
src/cpp/tasks/GradidoGroupAddMemberTask.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "GradidoGroupAddMemberTask.h"
|
||||
#include "../model/gradido/GroupMemberUpdate.h"
|
||||
|
||||
GradidoGroupAddMemberTask::GradidoGroupAddMemberTask(model::table::PendingTask* dbModel, Poco::AutoPtr<model::gradido::TransactionBody> transactionBody)
|
||||
: GradidoTask(dbModel, transactionBody)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
Poco::AutoPtr<controller::PendingTask> GradidoGroupAddMemberTask::create(Poco::AutoPtr<controller::User> user, Poco::AutoPtr<controller::Group> group, const std::string& memo)
|
||||
{
|
||||
if (user.isNull() || !user->getModel() || group.isNull() || !group->getModel()) {
|
||||
return nullptr;
|
||||
}
|
||||
static const char* function_name = "GradidoGroupAddMemberTask::create";
|
||||
auto group_model = group->getModel();
|
||||
auto transaction = model::gradido::TransactionBody::create(memo, user, proto::gradido::GroupMemberUpdate_MemberUpdateType_ADD_USER, group_model->getAlias());
|
||||
auto user_model = user->getModel();
|
||||
auto dbModel = new model::table::PendingTask(user_model->getID(), transaction->getBodyBytes(), model::table::TASK_TYPE_GROUP_ADD_MEMBER);
|
||||
if (!dbModel->insertIntoDB(true)) {
|
||||
dbModel->addError(new Error(function_name, "error inserting pending task into db, abort"));
|
||||
dbModel->sendErrorsAsEmail();
|
||||
return nullptr;
|
||||
}
|
||||
return new GradidoGroupAddMemberTask(dbModel, transaction);
|
||||
}
|
||||
19
src/cpp/tasks/GradidoGroupAddMemberTask.h
Normal file
19
src/cpp/tasks/GradidoGroupAddMemberTask.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef GRADIDO_LOGIN_SERVER_TASKS_GRADIDO_GROUP_ADD_MEMBER_TASK_H
|
||||
#define GRADIDO_LOGIN_SERVER_TASKS_GRADIDO_GROUP_ADD_MEMBER_TASK_H
|
||||
|
||||
#include "GradidoTask.h"
|
||||
#include "../controller/User.h"
|
||||
#include "../controller/Group.h"
|
||||
|
||||
class GradidoGroupAddMemberTask : public GradidoTask
|
||||
{
|
||||
public:
|
||||
GradidoGroupAddMemberTask(model::table::PendingTask* dbModel, Poco::AutoPtr<model::gradido::TransactionBody> transactionBody);
|
||||
|
||||
static Poco::AutoPtr<controller::PendingTask> create(Poco::AutoPtr<controller::User> user, Poco::AutoPtr<controller::Group> group, const std::string& memo);
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
#endif //GRADIDO_LOGIN_SERVER_TASKS_GRADIDO_GROUP_ADD_MEMBER_TASK_H
|
||||
@ -0,0 +1,7 @@
|
||||
#include "GradidoTask.h"
|
||||
|
||||
GradidoTask::GradidoTask(model::table::PendingTask* dbModel, Poco::AutoPtr<model::gradido::TransactionBody> transactionBody)
|
||||
: controller::PendingTask(dbModel), mGradidoTransactionBody(transactionBody)
|
||||
{
|
||||
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
#ifndef GRADIDO_LOGIN_SERVER_TASKS_GRADIDO_TASK
|
||||
#define GRADIDO_LOGIN_SERVER_TASKS_GRADIDO_TASK
|
||||
|
||||
#include "../controller/PendingTask.h"
|
||||
#include "../model/gradido/TransactionBody.h"
|
||||
|
||||
class GradidoTask : public controller::PendingTask, public NotificationList
|
||||
{
|
||||
public:
|
||||
GradidoTask(model::table::PendingTask* dbModel, Poco::AutoPtr<model::gradido::TransactionBody> transactionBody);
|
||||
bool isTimeoutTask() { return false; }
|
||||
|
||||
protected:
|
||||
|
||||
Poco::AutoPtr<model::gradido::TransactionBody> mGradidoTransactionBody;
|
||||
};
|
||||
|
||||
#endif //GRADIDO_LOGIN_SERVER_TASKS_GRADIDO_TASK
|
||||
12
src/cpp/tasks/PendingTask.h
Normal file
12
src/cpp/tasks/PendingTask.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef GRADIDO_LOGIN_SERVER_TASKS_PENDING_TASK
|
||||
#define GRADIDO_LOGIN_SERVER_TASKS_PENDING_TASK
|
||||
|
||||
/*
|
||||
* @author: Dario Rekowski
|
||||
*
|
||||
* @date: 13.10.2020
|
||||
*
|
||||
* @brief:
|
||||
*/
|
||||
|
||||
#endif //GRADIDO_LOGIN_SERVER_TASKS_PENDING_TASK
|
||||
@ -24,6 +24,15 @@ ProcessingTransaction::ProcessingTransaction(const std::string& proto_message_ba
|
||||
}
|
||||
}
|
||||
|
||||
ProcessingTransaction::ProcessingTransaction(Poco::AutoPtr<model::gradido::TransactionBody> transactionBody, DHASH userEmailHash, Languages lang, Poco::DateTime transactionCreated/* = Poco::DateTime()*/)
|
||||
: mTransactionBody(transactionBody), mUserEmailHash(userEmailHash),
|
||||
mLang(lang), mTransactionCreated(transactionCreated)
|
||||
{
|
||||
auto observer = SingletonTaskObserver::getInstance();
|
||||
if (userEmailHash != 0) {
|
||||
observer->addTask(userEmailHash, TASK_OBSERVER_PREPARE_TRANSACTION);
|
||||
}
|
||||
}
|
||||
ProcessingTransaction::~ProcessingTransaction()
|
||||
{
|
||||
lock();
|
||||
@ -75,22 +84,23 @@ int ProcessingTransaction::run()
|
||||
{
|
||||
lock();
|
||||
|
||||
|
||||
auto mm = MemoryManager::getInstance();
|
||||
auto protoMessageBin = DataTypeConverter::base64ToBin(mProtoMessageBase64);
|
||||
|
||||
auto langM = LanguageManager::getInstance();
|
||||
auto catalog = langM->getFreeCatalog(mLang);
|
||||
|
||||
if (!protoMessageBin)
|
||||
{
|
||||
addError(new Error("ProcessingTransaction", "error decoding base64"));
|
||||
reportErrorToCommunityServer(catalog->gettext("decoding error"), catalog->gettext("Error decoding base64 string"), "-1");
|
||||
unlock();
|
||||
return -1;
|
||||
if (mProtoMessageBase64 != "") {
|
||||
auto protoMessageBin = DataTypeConverter::base64ToBin(mProtoMessageBase64);
|
||||
|
||||
if (!protoMessageBin)
|
||||
{
|
||||
addError(new Error("ProcessingTransaction", "error decoding base64"));
|
||||
reportErrorToCommunityServer(catalog->gettext("decoding error"), catalog->gettext("Error decoding base64 string"), "-1");
|
||||
unlock();
|
||||
return -1;
|
||||
}
|
||||
mTransactionBody = model::gradido::TransactionBody::create(protoMessageBin);
|
||||
mm->releaseMemory(protoMessageBin);
|
||||
}
|
||||
mTransactionBody = model::gradido::TransactionBody::create(protoMessageBin);
|
||||
mm->releaseMemory(protoMessageBin);
|
||||
if (mTransactionBody.isNull()) {
|
||||
addError(new Error("ProcessingTransaction", "error creating Transaction from binary Message"));
|
||||
reportErrorToCommunityServer(catalog->gettext("decoding error"), catalog->gettext("Error by parsing to protobuf message"), "-1");
|
||||
|
||||
@ -33,6 +33,7 @@ class ProcessingTransaction : public UniLib::controller::CPUTask, public Notific
|
||||
public:
|
||||
//! \param lang for error messages in user language
|
||||
ProcessingTransaction(const std::string& proto_message_base64, DHASH userEmailHash, Languages lang, Poco::DateTime transactionCreated = Poco::DateTime());
|
||||
ProcessingTransaction(Poco::AutoPtr<model::gradido::TransactionBody> transactionBody, DHASH userEmailHash, Languages lang, Poco::DateTime transactionCreated = Poco::DateTime());
|
||||
//ProcessingTransaction(const model::gradido::TransactionBody)
|
||||
virtual ~ProcessingTransaction();
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user