adding new email system, work in progress

This commit is contained in:
Dario 2020-01-02 12:47:32 +01:00
parent a8c4acd81d
commit feb3067f3a
24 changed files with 462 additions and 32 deletions

View File

@ -1,3 +1,4 @@
HTTPInterface/LoginPage.cpp HTTPInterface/LoginPage.cpp
HTTPInterface/CheckEmailPage.cpp HTTPInterface/CheckEmailPage.cpp
model/Session.cpp model/Session.cpp
model/Email.cpp

View File

@ -7,7 +7,7 @@
#include "SingletonManager/ConnectionManager.h" #include "SingletonManager/ConnectionManager.h"
#include "SingletonManager/SessionManager.h" #include "SingletonManager/SessionManager.h"
#include "SingletonManager/EmailManager.h"
#include "Poco/Util/HelpFormatter.h" #include "Poco/Util/HelpFormatter.h"
#include "Poco/Net/ServerSocket.h" #include "Poco/Net/ServerSocket.h"
@ -161,6 +161,7 @@ int Gradido_LoginServer::main(const std::vector<std::string>& args)
ServerConfig::g_ServerKeySeed->put(1, i1 | (i2 << 8)); ServerConfig::g_ServerKeySeed->put(1, i1 | (i2 << 8));
ServerConfig::initEMailAccount(config()); ServerConfig::initEMailAccount(config());
EmailManager::getInstance()->init(config());
// start cpu scheduler // start cpu scheduler
uint8_t worker_count = Poco::Environment::processorCount() * 2; uint8_t worker_count = Poco::Environment::processorCount() * 2;

View File

@ -16,7 +16,7 @@ using namespace Poco::Data::Keywords;
#include "../tasks/PrepareEmailTask.h" #include "../tasks/PrepareEmailTask.h"
#include "../tasks/SendEmailTask.h" #include "../tasks/SendEmailTask.h"
#include "../model/EmailVerificationCode.h" #include "../controller/EmailVerificationCode.h"
#include "../model/table/ElopageBuy.h" #include "../model/table/ElopageBuy.h"
@ -301,7 +301,7 @@ int HandleElopageRequestTask::run()
} }
// email verification code // email verification code
auto emailVerification = model::EmailVerificationCode::create(user_id); auto emailVerification = controller::EmailVerificationCode::create(user_id);
//Poco::AutoPtr<model::table::EmailOptIn> emailVerification(new model::table::EmailOptIn(user_id)); //Poco::AutoPtr<model::table::EmailOptIn> emailVerification(new model::table::EmailOptIn(user_id));
// create email verification code // create email verification code

View File

@ -114,7 +114,7 @@ namespace ServerConfig {
g_EmailAccount.url = cfg.getString("email.smtp.url"); g_EmailAccount.url = cfg.getString("email.smtp.url");
g_EmailAccount.port = cfg.getInt("email.smtp.port"); g_EmailAccount.port = cfg.getInt("email.smtp.port");
DISASM_FALSERET; DISASM_FALSERET;
g_ServerKeySeed->put(3, DRRandom::r64()); //g_ServerKeySeed->put(3, DRRandom::r64());
return true; return true;
} }

View File

@ -11,6 +11,7 @@
#include "SingletonManager/LanguageManager.h" #include "SingletonManager/LanguageManager.h"
#define DISABLE_EMAIL #define DISABLE_EMAIL
namespace ServerConfig { namespace ServerConfig {
@ -20,9 +21,10 @@ namespace ServerConfig {
MNEMONIC_BIP0039_SORTED_ORDER, MNEMONIC_BIP0039_SORTED_ORDER,
MNEMONIC_MAX MNEMONIC_MAX
}; };
// depracted, moved to email manager
struct EmailAccount { struct EmailAccount {
std::string sender; std::string sender;
std::string admin_receiver;
std::string username; std::string username;
std::string password; std::string password;
std::string url; std::string url;

View File

@ -0,0 +1,61 @@
#include "EmailManager.h"
#include "../ServerConfig.h"
#include "../Crypto/Obfus_array.h"
#include "../Crypto/DRRandom.h"
EmailManager::EmailManager()
: mInitalized(false), mDisableEmail(false)
{
}
EmailManager::~EmailManager()
{
exit();
}
EmailManager* EmailManager::getInstance()
{
static EmailManager theOne;
return &theOne;
}
bool EmailManager::init(const Poco::Util::LayeredConfiguration& cfg)
{
try {
mDisableEmail = cfg.getBool("email.disable", false);
mEmailAccount.sender = cfg.getString("email.sender");
mEmailAccount.admin_receiver = cfg.getString("email.admin_receiver");
mEmailAccount.username = cfg.getString("email.username");
mEmailAccount.password = cfg.getString("email.password");
mEmailAccount.url = cfg.getString("email.smtp.url");
mEmailAccount.port = cfg.getInt("email.smtp.port");
}
catch (Poco::Exception& ex) {
printf("email account not set in config: %s\n", ex.displayText().data());
return false;
}
mInitalized = true;
DISASM_FALSERET;
ServerConfig::g_ServerKeySeed->put(3, DRRandom::r64());
return true;
}
void EmailManager::exit()
{
model::Email* email = nullptr;
while (mPendingEmails.pop(email)) {
delete email;
}
mInitalized = false;
}
int EmailManager::ThreadFunction()
{
return 0;
}

View File

@ -0,0 +1,59 @@
/*!
*
* \author: einhornimmond
*
* \date: 02.01.19
*
* \brief: manage emails, send all emails with only one connection to mail server, on after on
*/
#ifndef GRADIDO_LOGIN_SERVER_SINGLETON_MANAGER_EMAIL_MANAGER_H
#define GRADIDO_LOGIN_SERVER_SINGLETON_MANAGER_EMAIL_MANAGER_H
#include "Poco/AutoPtr.h"
#include "Poco/Util/LayeredConfiguration.h"
#include "../lib/MultithreadQueue.h"
#include "../tasks/Thread.h"
#include "../model/Email.h"
class EmailManager : public UniLib::lib::Thread
{
public:
~EmailManager();
static EmailManager* getInstance();
bool init(const Poco::Util::LayeredConfiguration& cfg);
inline const std::string& getAdminReceiver() { return mEmailAccount.admin_receiver; }
inline void addEmail(model::Email* email) { mPendingEmails.push(email); }
protected:
EmailManager();
void exit();
int ThreadFunction();
struct EmailAccount {
std::string sender;
std::string admin_receiver;
std::string username;
std::string password;
std::string url;
int port;
};
EmailAccount mEmailAccount;
bool mInitalized;
bool mDisableEmail;
UniLib::lib::MultithreadQueue<model::Email*> mPendingEmails;
};
#endif //GRADIDO_LOGIN_SERVER_SINGLETON_MANAGER_EMAIL_MANAGER_H

View File

@ -64,6 +64,7 @@ protected:
Languages mThisLanguage; Languages mThisLanguage;
}; };
// TODO: max cached catalog count
class LanguageManager : protected UniLib::lib::MultithreadContainer class LanguageManager : protected UniLib::lib::MultithreadContainer
{ {

View File

@ -1,4 +1,5 @@
#include "EmailVerificationCode.h" #include "EmailVerificationCode.h"
#include "../ServerConfig.h"
#include "sodium.h" #include "sodium.h"
@ -43,4 +44,12 @@ namespace controller {
} }
return resultCode; return resultCode;
} }
std::string EmailVerificationCode::getLink()
{
std::string link = ServerConfig::g_serverPath;
link += "/checkEmail/";
link += std::to_string(getModel()->getCode());
return link;
}
} }

View File

@ -15,6 +15,8 @@ namespace controller {
static Poco::AutoPtr<EmailVerificationCode> create(int user_id); static Poco::AutoPtr<EmailVerificationCode> create(int user_id);
inline Poco::AutoPtr<model::table::EmailOptIn> getModel() { return _getModel<model::table::EmailOptIn>(); } inline Poco::AutoPtr<model::table::EmailOptIn> getModel() { return _getModel<model::table::EmailOptIn>(); }
std::string getLink();
protected: protected:
EmailVerificationCode(model::table::EmailOptIn* dbModel); EmailVerificationCode(model::table::EmailOptIn* dbModel);
static Poco::UInt64 createEmailVerificationCode(); static Poco::UInt64 createEmailVerificationCode();

View File

@ -14,11 +14,22 @@ namespace controller {
Poco::AutoPtr<User> User::create() Poco::AutoPtr<User> User::create()
{ {
/*auto code = createEmailVerificationCode(); auto db = new model::table::User();
auto db = new model::table::EmailOptIn(code, user_id); auto user = new User(db);
auto result = new EmailVerificationCode(db); return Poco::AutoPtr<User>(user);
return Poco::AutoPtr<EmailVerificationCode>(result); }
*/
Poco::AutoPtr<User> User::create(const std::string& email, const std::string& first_name, const std::string& last_name, Poco::UInt64 passwordHashed/* = 0*/, std::string languageKey/* = "de"*/)
{
auto db = new model::table::User(email, first_name, last_name, passwordHashed, languageKey);
auto user = new User(db);
return Poco::AutoPtr<User>(user);
}
int User::load(const unsigned char* pubkey_array)
{
Poco::Data::BLOB pubkey(pubkey_array, 32);
return getModel()->loadFromDB("pubkey", pubkey);
} }
} }

View File

@ -13,6 +13,11 @@ namespace controller {
~User(); ~User();
static Poco::AutoPtr<User> create(); static Poco::AutoPtr<User> create();
static Poco::AutoPtr<User> create(const std::string& email, const std::string& first_name, const std::string& last_name, Poco::UInt64 passwordHashed = 0, std::string languageKey = "de");
inline int load(const std::string& email) { return getModel()->loadFromDB("email", email); }
inline int load(int user_id) { return getModel()->loadFromDB("id", user_id); }
int load(const unsigned char* pubkey_array);
inline Poco::AutoPtr<model::table::User> getModel() { return _getModel<model::table::User>(); } inline Poco::AutoPtr<model::table::User> getModel() { return _getModel<model::table::User>(); }

View File

@ -33,6 +33,7 @@
#define _DR_UNIVERSUM_LIB_LIB_MULTITHREAD_QUEUE_H__ #define _DR_UNIVERSUM_LIB_LIB_MULTITHREAD_QUEUE_H__
#include "MultithreadContainer.h" #include "MultithreadContainer.h"
#include <queue>
namespace UniLib { namespace UniLib {
namespace lib { namespace lib {

186
src/cpp/model/Email.cpp Normal file
View File

@ -0,0 +1,186 @@
#include "Email.h"
#include "../SingletonManager/EmailManager.h"
namespace model {
const static char EmailText_emailVerification[] = {u8"\
Hallo [first_name] [last_name],\n\
\n\
Du oder jemand anderes hat sich soeben mit dieser E-Mail Adresse bei Gradido registriert.\n\
Wenn du es warst, klicke bitte auf den Link: [link]\n\
oder kopiere den obigen Link in Dein Browserfenster.\n\
\n\
Mit freundlichen Grüßen\n\
Dario, Gradido Server Admin\n\
"};
const static char EmailText_emailResetPassword[] = { u8"\
Hallo [first_name] [last_name],\n\
\n\
Du oder jemand anderes hat für dieses Konto ein Passwort Reset angefordert.\n\
Wenn du es warst, klicke bitte auf den Link: [link]\n\
oder kopiere den obigen Link in Dein Browserfenster.\n\
\n\
Mit freundlichen Grüßen\n\
Dario, Gradido Server Admin\n\
" };
const static char EmailText_adminEmailResetPassword[] = { u8"\
Der Benutzer mit der Email-Adresse: [email] hat sein Passwort vergessen.\n\
Außerdem hat er auch seine Passphrase vergessen. \n\
Bitte logge dich im Admin-Bereich um das Problem zu lösen.\n\
\n\
LG \n\
Gradido Login Server\
" };
Email::Email(AutoPtr<controller::EmailVerificationCode> emailVerification, AutoPtr<controller::User> user, EmailType type)
: mEmailVerificationCode(emailVerification), mUser(user), mType(type)
{
}
Email::Email(const std::string& errorHtml, EmailType type)
: mErrorHtml(errorHtml), mType(type)
{
}
bool Email::draft(Net::MailMessage* mailMessage, LanguageCatalog* langCatalog)
{
auto em = EmailManager::getInstance();
auto adminRecipient = Net::MailRecipient(Net::MailRecipient::PRIMARY_RECIPIENT, em->getAdminReceiver());
Poco::AutoPtr<model::table::User> userTableModel;
if (!mUser.isNull()) {
userTableModel = mUser->getModel();
}
static const char* functionName = "Email::draft";
std::string content;
switch (mType) {
case EMAIL_DEFAULT:
mailMessage->addRecipient(adminRecipient);
mailMessage->setSubject(langCatalog->gettext_str("Default Email Subject"));
mailMessage->addContent(new Poco::Net::StringPartSource(langCatalog->gettext_str("Empty Email Content")));
return true;
case EMAIL_ERROR:
mailMessage->addRecipient(adminRecipient);
mailMessage->setSubject(langCatalog->gettext_str("Error from Gradido Login Server"));
mailMessage->addContent(new Poco::Net::StringPartSource(mErrorHtml));
return true;
case EMAIL_USER_VERIFICATION_CODE:
if (userTableModel.isNull() || mUser->getModel()->getEmail() == "") {
addError(new Error(functionName, "no receiver email set for user email verification email"));
return false;
}
if (mEmailVerificationCode.isNull()) {
addError(new Error(functionName, "no email verification code set for user email verification email"));
return false;
}
mailMessage->addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, mUser->getModel()->getEmail()));
mailMessage->setSubject(langCatalog->gettext_str("Gradido: E-Mail Verification"));
mailMessage->addContent(
new Poco::Net::StringPartSource(replaceUserNamesAndLink(
langCatalog->gettext(EmailText_emailVerification),
userTableModel->getFirstName(),
userTableModel->getLastName(),
mEmailVerificationCode->getLink()
))
);
return true;
case EMAIL_USER_RESET_PASSWORD:
if (userTableModel.isNull() || mUser->getModel()->getEmail() == "") {
addError(new Error(functionName, "no receiver email set for user reset password email"));
return false;
}
if (mEmailVerificationCode.isNull()) {
addError(new Error(functionName, "no email verification code set for user reset password email"));
return false;
}
mailMessage->addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, mUser->getModel()->getEmail()));
mailMessage->setSubject(langCatalog->gettext_str(u8"Gradido: Passwort zurücksetzen"));
mailMessage->addContent(
new Poco::Net::StringPartSource(replaceUserNamesAndLink(
langCatalog->gettext(EmailText_emailResetPassword),
userTableModel->getFirstName(),
userTableModel->getLastName(),
mEmailVerificationCode->getLink()
))
);
return true;
case EMAIL_ADMIN_RESET_PASSWORD_REQUEST_WITHOUT_MEMORIZED_PASSPHRASE:
if (userTableModel.isNull() || mUser->getModel()->getEmail() == "") {
addError(new Error(functionName, "no user email set for admin reset password email"));
return false;
}
mailMessage->addRecipient(adminRecipient);
mailMessage->setSubject(langCatalog->gettext_str("Reset Password Request without memorized passphrase"));
mailMessage->addContent(
new Poco::Net::StringPartSource(replaceEmail(
EmailText_adminEmailResetPassword,
userTableModel->getEmail()
))
);
return true;
default: return false;
}
return false;
}
std::string Email::replaceUserNamesAndLink(const char* src, const std::string& first_name, const std::string& last_name, const std::string& link)
{
std::string result = src;
int findCursor = 0;
static const char* functionName = "Email::replaceUserNamesAndLink";
int findPos = result.find("[first_name]", findCursor);
if (findPos != result.npos) {
findCursor = findPos + 13;
result.replace(findPos, 12, first_name);
}
else {
addError(new Error(functionName, "no first_name placeholder found"));
}
findPos = result.find("[last_name]", findCursor);
if (findPos != result.npos) {
findCursor = findPos + 12;
result.replace(findPos, 11, last_name);
}
else {
addError(new Error(functionName, "no last_name placeholder found"));
}
findPos = result.find("[link]", findCursor);
if (findPos != result.npos) {
findCursor = findPos + 7;
result.replace(findPos, 6, link);
}
else {
addError(new Error(functionName, "no email placeholder found"));
}
return result;
}
std::string Email::replaceEmail(const char* src, const std::string& email)
{
std::string result = src;
static const char* functionName = "Email::replaceEmail";
int findPos = result.find("[email]");
if (findPos != result.npos) {
result.replace(findPos, 7, email);
}
else {
addError(new Error(functionName, "no email placeholder found"));
}
return result;
}
}

56
src/cpp/model/Email.h Normal file
View File

@ -0,0 +1,56 @@
/*!
*
* \author: einhornimmond
*
* \date: 02.01.20
*
* \brief: store email for
*/
#ifndef GRADIDO_LOGIN_SERVER_MODEL_EMAIL_INCLUDE
#define GRADIDO_LOGIN_SERVER_MODEL_EMAIL_INCLUDE
#include "Poco/Net/MailMessage.h"
#include "../controller/EmailVerificationCode.h"
#include "../controller/User.h"
#include "../SingletonManager/LanguageManager.h"
#include "../lib/ErrorList.h"
namespace model {
using namespace Poco;
enum EmailType
{
EMAIL_DEFAULT,
EMAIL_ERROR,
EMAIL_USER_VERIFICATION_CODE,
EMAIL_USER_RESET_PASSWORD,
EMAIL_ADMIN_RESET_PASSWORD_REQUEST_WITHOUT_MEMORIZED_PASSPHRASE
};
class Email: public ErrorList
{
public:
Email(AutoPtr<controller::EmailVerificationCode> emailVerification, AutoPtr<controller::User> user, EmailType type);
//! \param errors copy errors into own memory
Email(const std::string& errorHtml, EmailType type);
inline EmailType getType() { return mType; }
bool draft(Net::MailMessage* mailMessage, LanguageCatalog* langCatalog);
protected:
std::string replaceUserNamesAndLink(const char* src, const std::string& first_name, const std::string& last_name, const std::string& link);
std::string replaceEmail(const char* src, const std::string& email);
AutoPtr<controller::EmailVerificationCode> mEmailVerificationCode;
AutoPtr<controller::User> mUser;
std::string mErrorHtml;
EmailType mType;
};
}
#endif //GRADIDO_LOGIN_SERVER_MODEL_EMAIL_INCLUDE

View File

@ -84,7 +84,7 @@ int WritePassphraseIntoDB::run()
// -------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------
Session::Session(int handle) Session::Session(int handle)
: mHandleId(handle), mSessionUser(nullptr), mEmailVerificationCode(0), mEmailVerificationCodeObject(nullptr), mState(SESSION_STATE_EMPTY), mActive(false) : mHandleId(handle), mSessionUser(nullptr), mEmailVerificationCode(0), mState(SESSION_STATE_EMPTY), mActive(false)
{ {
} }
@ -106,10 +106,8 @@ void Session::reset()
lock("Session::reset"); lock("Session::reset");
mSessionUser = nullptr; mSessionUser = nullptr;
if (mEmailVerificationCodeObject) { mNewUser = nullptr;
delete mEmailVerificationCodeObject; mEmailVerificationCodeObject = nullptr;
mEmailVerificationCodeObject = nullptr;
}
// watch out // watch out
//updateTimeout(); //updateTimeout();
@ -131,7 +129,7 @@ void Session::updateTimeout()
unlock(); unlock();
} }
controller::EmailVerificationCode* Session::getEmailVerificationCodeObject() Poco::AutoPtr<controller::EmailVerificationCode> Session::getEmailVerificationCodeObject()
{ {
lock("Session::getEmailVerificationCodeObject"); lock("Session::getEmailVerificationCodeObject");
auto ret = mEmailVerificationCodeObject; auto ret = mEmailVerificationCodeObject;
@ -376,7 +374,9 @@ int Session::updateEmailVerification(Poco::UInt64 emailVerificationCode)
bool Session::createNewEmailVerificationCode() bool Session::createNewEmailVerificationCode()
{ {
return false; mEmailVerificationCodeObject = controller::EmailVerificationCode::create(mNewUser->getModel()->getID());
return true;
} }
bool Session::startProcessingTransaction(const std::string& proto_message_base64) bool Session::startProcessingTransaction(const std::string& proto_message_base64)

View File

@ -12,6 +12,7 @@
#include "../lib/ErrorList.h" #include "../lib/ErrorList.h"
#include "User.h" #include "User.h"
#include "../controller/User.h"
#include "../lib/MultithreadContainer.h" #include "../lib/MultithreadContainer.h"
#include "../tasks/ProcessingTransaction.h" #include "../tasks/ProcessingTransaction.h"
@ -57,7 +58,10 @@ public:
~Session(); ~Session();
// get new model objects // get new model objects
controller::EmailVerificationCode* getEmailVerificationCodeObject(); Poco::AutoPtr<controller::EmailVerificationCode> getEmailVerificationCodeObject();
// set new model objects
inline void setUser(Poco::AutoPtr<controller::User> user) { mNewUser = user; }
// ---------------- User functions ---------------------------- // ---------------- User functions ----------------------------
// TODO: automatic redirect after some time, median profiled time for register // TODO: automatic redirect after some time, median profiled time for register
@ -69,6 +73,7 @@ public:
inline void setUser(Poco::AutoPtr<User> user) { mSessionUser = user; } inline void setUser(Poco::AutoPtr<User> user) { mSessionUser = user; }
bool deleteUser(); bool deleteUser();
Poco::AutoPtr<User> getUser() { Poco::AutoPtr<User> getUser() {
@ -144,11 +149,12 @@ protected:
private: private:
int mHandleId; int mHandleId;
Poco::AutoPtr<User> mSessionUser; Poco::AutoPtr<User> mSessionUser;
Poco::AutoPtr<controller::User> mNewUser;
std::string mPassphrase; std::string mPassphrase;
Poco::DateTime mLastActivity; Poco::DateTime mLastActivity;
Poco::Net::IPAddress mClientLoginIP; Poco::Net::IPAddress mClientLoginIP;
Poco::UInt64 mEmailVerificationCode; Poco::UInt64 mEmailVerificationCode;
controller::EmailVerificationCode* mEmailVerificationCodeObject; Poco::AutoPtr<controller::EmailVerificationCode> mEmailVerificationCodeObject;
SessionStates mState; SessionStates mState;

View File

@ -67,7 +67,7 @@ namespace model {
} }
Poco::Data::Statement ElopageBuy::_loadFromDB(Poco::Data::Session session, std::string& fieldName) Poco::Data::Statement ElopageBuy::_loadFromDB(Poco::Data::Session session, const std::string& fieldName)
{ {
// Poco::Data::Statement select(session); // Poco::Data::Statement select(session);

View File

@ -38,7 +38,7 @@ namespace model {
protected: protected:
Poco::Data::Statement _loadFromDB(Poco::Data::Session session, std::string& fieldName); Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName);
Poco::Data::Statement _insertIntoDB(Poco::Data::Session session); Poco::Data::Statement _insertIntoDB(Poco::Data::Session session);
Poco::Int32 mIDs[ELOPAGE_BUY_MAX]; Poco::Int32 mIDs[ELOPAGE_BUY_MAX];

View File

@ -37,7 +37,7 @@ namespace model {
} }
Poco::Data::Statement EmailOptIn::_loadFromDB(Poco::Data::Session session, std::string& fieldName) Poco::Data::Statement EmailOptIn::_loadFromDB(Poco::Data::Session session, const std::string& fieldName)
{ {
Poco::Data::Statement select(session); Poco::Data::Statement select(session);

View File

@ -19,8 +19,9 @@ namespace model {
const char* getTableName() { return "email_opt_in"; } const char* getTableName() { return "email_opt_in"; }
inline Poco::UInt64 getCode() const { return mEmailVerificationCode; } inline Poco::UInt64 getCode() const { return mEmailVerificationCode; }
inline void setCode(Poco::UInt64 code) { mEmailVerificationCode = code; }
protected: protected:
Poco::Data::Statement _loadFromDB(Poco::Data::Session session, std::string& fieldName); Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName);
Poco::Data::Statement _insertIntoDB(Poco::Data::Session session); Poco::Data::Statement _insertIntoDB(Poco::Data::Session session);
// data type must be a multiple of 4 // data type must be a multiple of 4

View File

@ -9,6 +9,8 @@
#include "../../MySQL/MysqlTable.h" #include "../../MySQL/MysqlTable.h"
//using namespace Poco::Data::Keywords;
namespace model { namespace model {
namespace table { namespace table {
@ -21,8 +23,8 @@ namespace model {
virtual const char* getTableName() = 0; virtual const char* getTableName() = 0;
template<class T> size_t updateIntoDB(const std::string& fieldName, T fieldValue ); template<class T> size_t updateIntoDB(const std::string& fieldName, const T& fieldValue );
template<class T> size_t loadFromDB(const std::string& fieldName, T fieldValue); template<class T> size_t loadFromDB(const std::string& fieldName, const T& fieldValue);
bool insertIntoDB(); bool insertIntoDB();
inline void setID(int id) { lock(); mID = id; unlock(); } inline void setID(int id) { lock(); mID = id; unlock(); }
@ -35,7 +37,7 @@ namespace model {
void release(); void release();
protected: protected:
virtual Poco::Data::Statement _loadFromDB(Poco::Data::Session session, std::string& fieldName) = 0; virtual Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName) = 0;
virtual Poco::Data::Statement _insertIntoDB(Poco::Data::Session session) = 0; virtual Poco::Data::Statement _insertIntoDB(Poco::Data::Session session) = 0;
int mID; int mID;
@ -46,11 +48,11 @@ namespace model {
}; };
template<class T> template<class T>
size_t ModelBase::loadFromDB(const std::string& fieldName, T fieldValue) size_t ModelBase::loadFromDB(const std::string& fieldName, const T& fieldValue)
{ {
auto cm = ConnectionManager::getInstance(); auto cm = ConnectionManager::getInstance();
Poco::Data::Statement select = _loadFromDB(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER), fieldName); Poco::Data::Statement select = _loadFromDB(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER), fieldName);
select, use(fieldValue); select, Poco::Data::Keywords::useRef(fieldValue);
size_t resultCount = 0; size_t resultCount = 0;
try { try {
@ -66,7 +68,7 @@ namespace model {
} }
template<class T> template<class T>
size_t ModelBase::updateIntoDB(const std::string& fieldName, T fieldValue) size_t ModelBase::updateIntoDB(const std::string& fieldName, const T& fieldValue)
{ {
auto cm = ConnectionManager::getInstance(); auto cm = ConnectionManager::getInstance();
Poco::Data::Statement update(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER)); Poco::Data::Statement update(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER));
@ -77,7 +79,7 @@ namespace model {
} }
update << "UPDATE " << getTableName() << " SET " << fieldName << " = ? where id = ?", update << "UPDATE " << getTableName() << " SET " << fieldName << " = ? where id = ?",
use(fieldValue), use(mID); Poco::Data::Keywords::useRef(fieldValue), Poco::Data::Keywords::use(mID);
size_t resultCount = 0; size_t resultCount = 0;
try { try {
@ -107,6 +109,32 @@ namespace model {
Poco::AutoPtr<ModelBase> mModel; Poco::AutoPtr<ModelBase> mModel;
}; };
template <class T>
class ModelUpdateTask : public UniLib::controller::CPUTask
{
public:
ModelUpdateTask(Poco::AutoPtr<ModelBase> model, const std::string& fieldName, const T& fieldValue)
: UniLib::controller::CPUTask(ServerConfig::g_CPUScheduler), mModel(model), mFieldName(fieldName), mFieldValue(fieldValue)
{
#ifdef _UNI_LIB_DEBUG
setName(model->getTableName());
#endif
}
int run() {
mModel->updateIntoDB(mFieldName, mFieldValue);
}
const char* getResourceType() const { return "ModelUpdateTask"; };
protected:
Poco::AutoPtr<ModelBase> mModel;
std::string mFieldName;
T mFieldValue;
};
} }
} }

View File

@ -61,7 +61,7 @@ namespace model {
return insert; return insert;
} }
Poco::Data::Statement User::_loadFromDB(Poco::Data::Session session, std::string& fieldName) Poco::Data::Statement User::_loadFromDB(Poco::Data::Session session, const std::string& fieldName)
{ {
Poco::Data::Statement select(session); Poco::Data::Statement select(session);

View File

@ -60,7 +60,7 @@ namespace model {
protected: protected:
Poco::Data::Statement _loadFromDB(Poco::Data::Session session, std::string& fieldName); Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName);
// insert only with email, first_name, last_name, password if exist and language // insert only with email, first_name, last_name, password if exist and language
Poco::Data::Statement _insertIntoDB(Poco::Data::Session session); Poco::Data::Statement _insertIntoDB(Poco::Data::Session session);