From f414ca8ddb42bd227e84e046a266f5051c162ba4 Mon Sep 17 00:00:00 2001 From: Dario Date: Mon, 15 Jun 2020 17:37:02 +0200 Subject: [PATCH] add function to search for verification emails to resend at startup and by register direct --- src/cpp/Gradido_LoginServer.cpp | 5 ++- src/cpp/ServerConfig.cpp | 1 + src/cpp/ServerConfig.h | 2 ++ src/cpp/controller/User.cpp | 57 +++++++++++++++++++++++++++++++++ src/cpp/controller/User.h | 9 ++++++ src/cpp/model/Session.cpp | 4 +++ 6 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/cpp/Gradido_LoginServer.cpp b/src/cpp/Gradido_LoginServer.cpp index ed85f935b..399aa6f3e 100644 --- a/src/cpp/Gradido_LoginServer.cpp +++ b/src/cpp/Gradido_LoginServer.cpp @@ -9,6 +9,8 @@ #include "SingletonManager/SessionManager.h" #include "SingletonManager/EmailManager.h" +#include "controller/User.h" + #include "Poco/Util/HelpFormatter.h" #include "Poco/Net/ServerSocket.h" #include "Poco/Net/HTTPServer.h" @@ -192,7 +194,8 @@ int Gradido_LoginServer::main(const std::vector& args) return Application::EXIT_CONFIG; } - + // schedule email verification resend + controller::User::checkIfVerificationEmailsShouldBeResend(ServerConfig::g_CronJobsTimer); // HTTP Interface Server // set-up a server socket diff --git a/src/cpp/ServerConfig.cpp b/src/cpp/ServerConfig.cpp index 4382ce528..1f7295e87 100644 --- a/src/cpp/ServerConfig.cpp +++ b/src/cpp/ServerConfig.cpp @@ -40,6 +40,7 @@ namespace ServerConfig { UniLib::controller::CPUSheduler* g_CPUScheduler = nullptr; UniLib::controller::CPUSheduler* g_CryptoCPUScheduler = nullptr; Context::Ptr g_SSL_CLient_Context = nullptr; + Poco::Util::Timer g_CronJobsTimer; EmailAccount g_EmailAccount; int g_SessionTimeout = SESSION_TIMEOUT_DEFAULT; std::string g_serverPath; diff --git a/src/cpp/ServerConfig.h b/src/cpp/ServerConfig.h index 02d01ad34..ac218aa1f 100644 --- a/src/cpp/ServerConfig.h +++ b/src/cpp/ServerConfig.h @@ -6,6 +6,7 @@ #include "Poco/Util/LayeredConfiguration.h" #include "Poco/Net/Context.h" #include "Poco/Types.h" +#include "Poco/Util/Timer.h" #include "tasks/CPUSheduler.h" @@ -48,6 +49,7 @@ namespace ServerConfig { extern UniLib::controller::CPUSheduler* g_CPUScheduler; extern UniLib::controller::CPUSheduler* g_CryptoCPUScheduler; extern Poco::Net::Context::Ptr g_SSL_CLient_Context; + extern Poco::Util::Timer g_CronJobsTimer; extern EmailAccount g_EmailAccount; extern int g_SessionTimeout; extern std::string g_serverPath; diff --git a/src/cpp/controller/User.cpp b/src/cpp/controller/User.cpp index 78a6ed6c3..a9d89f9ca 100644 --- a/src/cpp/controller/User.cpp +++ b/src/cpp/controller/User.cpp @@ -3,8 +3,15 @@ #include "sodium.h" #include "../SingletonManager/SessionManager.h" +#include "../SingletonManager/ErrorManager.h" + #include "../lib/DataTypeConverter.h" +#include "../tasks/VerificationEmailResendTask.h" + +#include "../ServerConfig.h" + +#include "Poco/Timestamp.h" namespace controller { User::User(model::table::User* dbModel) @@ -224,4 +231,54 @@ namespace controller { return result; } + int User::checkIfVerificationEmailsShouldBeResend(const Poco::Util::Timer& timer) + { + auto cm = ConnectionManager::getInstance(); + auto em = ErrorManager::getInstance(); + static const char* function_name = "User::checkIfVerificationEmailsShouldBeResend"; + + auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + Poco::Data::Statement select(session); + std::vector> results; + select << "select u.id, v.created from users as u " + << "LEFT JOIN email_opt_in as v ON(u.id = v.user_id) " + << "where u.email_checked = 0 " + << "AND v.resend_count <= 1", Poco::Data::Keywords::into(results) + ; + + try { + auto now = Poco::DateTime(); + select.execute(); + int count_scheduled_at_once = 0; + int count_scheduled = 0; + + for (auto it = results.begin(); it != results.end(); it++) { + auto user_id = it->get<0>(); + auto created = it->get<1>(); + + auto age = now - created; + // older than 7 days, schedule at once + if (age.days() > 7) { + UniLib::controller::TaskPtr verificationResendTask(new VerificationEmailResendTask(user_id)); + verificationResendTask->scheduleTask(verificationResendTask); + count_scheduled_at_once++; + } + // younger than 7 days, schedule for created + 7 days + else { + auto runDateTime = created + Poco::Timespan(7, 0, 0, 0, 0); + ServerConfig::g_CronJobsTimer.schedule(new VerificationEmailResendTimerTask(user_id), Poco::Timestamp(runDateTime.microsecond())); + count_scheduled++; + } + } + if(count_scheduled_at_once) printf("scheduled %d verification email resend at once\n", count_scheduled_at_once); + if(count_scheduled) printf("scheduled %d verification email resend in the next 7 days\n", count_scheduled); + } + catch (Poco::Exception& ex) { + em->addError(new ParamError(function_name, "mysql error by select", ex.displayText().data())); + em->sendErrorsAsEmail(); + return -1; + } + return 0; + } + } \ No newline at end of file diff --git a/src/cpp/controller/User.h b/src/cpp/controller/User.h index 01d24c3ff..f9f98cac3 100644 --- a/src/cpp/controller/User.h +++ b/src/cpp/controller/User.h @@ -29,7 +29,16 @@ namespace controller { static std::vector search(const std::string& searchString); + //! \brief go through whole db and search users with email_checked = false and schedule resend 7 days after email_opt_in created date + //! + //! Should be only called by server start, later it aren't necessary, because register function schedule resend tasks by himself. + //! By users which has registered long time ago and haven't activated there account and haven't get a second email send verification email with duration at once + // TODO: instead scheduling all, scheduling only for next day and run this function every day (own task for that) + static int checkIfVerificationEmailsShouldBeResend(const Poco::Util::Timer& timer); + inline size_t load(const std::string& email) { return getModel()->loadFromDB("email", email); } + //! \brief try to load user from db via user_id + //! \return count of found rows, should be 1 or 0 inline size_t load(int user_id) { return getModel()->loadFromDB("id", user_id); } int load(const unsigned char* pubkey_array); Poco::JSON::Object getJson(); diff --git a/src/cpp/model/Session.cpp b/src/cpp/model/Session.cpp index a5e0ae7e3..f6f448584 100644 --- a/src/cpp/model/Session.cpp +++ b/src/cpp/model/Session.cpp @@ -16,6 +16,7 @@ #include "../tasks/SendEmailTask.h" #include "../tasks/SigningTransaction.h" #include "../tasks/AuthenticatedEncryptionCreateKeyTask.h" +#include "../tasks/VerificationEmailResendTask.h" #include "../lib/JsonRequest.h" @@ -389,6 +390,9 @@ bool Session::createUserDirect(const std::string& first_name, const std::string& auto email_verification = controller::EmailVerificationCode::create(user_id, model::table::EMAIL_OPT_IN_REGISTER_DIRECT); email_verification->getModel()->insertIntoDB(false); + auto _7days_later = Poco::DateTime() + Poco::Timespan(7, 0, 0, 0, 0); + ServerConfig::g_CronJobsTimer.schedule(new VerificationEmailResendTimerTask(user_id), Poco::Timestamp(_7days_later.microsecond())); + email_manager->addEmail(new model::Email(email_verification, mNewUser, model::EMAIL_USER_VERIFICATION_CODE)); return true;