diff --git a/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp b/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp index 20e47b344..3261e5591 100644 --- a/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp +++ b/src/cpp/HTTPInterface/PageRequestHandlerFactory.cpp @@ -18,6 +18,7 @@ #include "Error500Page.h" #include "CheckTransactionPage.h" #include "ResetPassword.h" +#include "RegisterAdminPage.h" #include "DecodeTransactionPage.h" @@ -131,6 +132,11 @@ Poco::Net::HTTPRequestHandler* PageRequestHandlerFactory::createRequestHandler(c pageRequestHandler->setProfiler(timeUsed); return pageRequestHandler; } + if (url_first_part == "/adminRegister") { + auto pageRequestHandler = new RegisterAdminPage(s); + pageRequestHandler->setProfiler(timeUsed); + return pageRequestHandler; + } if(url_first_part == "/logout") { sm->releaseSession(s); diff --git a/src/cpp/HTTPInterface/RegisterAdminPage.cpp b/src/cpp/HTTPInterface/RegisterAdminPage.cpp new file mode 100644 index 000000000..db101dbc6 --- /dev/null +++ b/src/cpp/HTTPInterface/RegisterAdminPage.cpp @@ -0,0 +1,179 @@ +#include "RegisterAdminPage.h" +#include "Poco/Net/HTTPServerRequest.h" +#include "Poco/Net/HTTPServerResponse.h" +#include "Poco/Net/HTMLForm.h" +#include "Poco/DeflatingStream.h" + + +#line 7 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\registerAdmin.cpsp" + +#include "../SingletonManager/SessionManager.h" +#include "Poco/Net/HTTPCookie.h" +#line 1 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_old.cpsp" + +#include "../ServerConfig.h" + + +RegisterAdminPage::RegisterAdminPage(Session* arg): + SessionHTTPRequestHandler(arg) +{ +} + + +void RegisterAdminPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) +{ + response.setChunkedTransferEncoding(true); + response.setContentType("text/html"); + bool _compressResponse(request.hasToken("Accept-Encoding", "gzip")); + if (_compressResponse) response.set("Content-Encoding", "gzip"); + + Poco::Net::HTMLForm form(request, request.stream()); +#line 11 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\registerAdmin.cpsp" + + const char* pageName = "Admin Registrieren"; + //auto sm = SessionManager::getInstance(); + + bool userReturned = false; + + if(!form.empty()) { + userReturned = mSession->adminCreateUser( + form.get("register-first-name", ""), + form.get("register-last-name", ""), + form.get("register-email", "") + ); + getErrors(mSession); + } + + + std::ostream& _responseStream = response.send(); + Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1); + std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream; + responseStream << "\n"; + // begin include header_old.cpsp + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "Gradido Login Server: "; +#line 9 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_old.cpsp" + responseStream << ( pageName ); + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "\t

Login Server in Entwicklung

\n"; + responseStream << "\t

Alpha "; +#line 53 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header_old.cpsp" + responseStream << ( ServerConfig::g_versionString ); + responseStream << "

\n"; + responseStream << "
\n"; + // end include header_old.cpsp + responseStream << "\n"; + responseStream << "
\n"; + responseStream << "\t

Einen neuen Account anlegen

\n"; + responseStream << "\t"; +#line 30 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\registerAdmin.cpsp" + responseStream << ( getErrorsHtml() ); + responseStream << "\n"; + responseStream << "\t"; +#line 31 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\registerAdmin.cpsp" + if(!form.empty() && userReturned) { responseStream << "\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t\t\tDie Anmeldung wird verarbeitet und es wird dem Benutzer eine Aktivierungs-E-Mail zugeschickt. \n"; + responseStream << "\t\t\t
\n"; + responseStream << "\t\t
\n"; + responseStream << "\t"; +#line 37 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\registerAdmin.cpsp" + } else { responseStream << "\n"; + responseStream << "\t
\n"; + responseStream << "\t\t\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\tAccount anlegen\n"; + responseStream << "\t\t\t

Bitte gebe deine Daten um einen Account anzulegen

\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t\t\n"; + responseStream << "\t\t\t

\n"; + responseStream << "\t\t
\n"; + responseStream << "\t\t\n"; + responseStream << "\t\t\n"; + responseStream << "\t
\n"; + responseStream << "\t"; +#line 59 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\registerAdmin.cpsp" + } responseStream << "\n"; + responseStream << "
\n"; + // begin include footer.cpsp + responseStream << "\t
\n"; + responseStream << "\t\t\t"; +#line 2 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp" + responseStream << ( mTimeProfiler.string() ); + responseStream << "\n"; + responseStream << "\t
\n"; + responseStream << "\n"; + responseStream << ""; + // end include footer.cpsp + responseStream << "\n"; + if (_compressResponse) _gzipStream.close(); +} diff --git a/src/cpp/HTTPInterface/RegisterAdminPage.h b/src/cpp/HTTPInterface/RegisterAdminPage.h new file mode 100644 index 000000000..df43d1216 --- /dev/null +++ b/src/cpp/HTTPInterface/RegisterAdminPage.h @@ -0,0 +1,20 @@ +#ifndef RegisterAdminPage_INCLUDED +#define RegisterAdminPage_INCLUDED + + +#include "Poco/Net/HTTPRequestHandler.h" + + +#include "SessionHTTPRequestHandler.h" + + +class RegisterAdminPage: public SessionHTTPRequestHandler +{ +public: + RegisterAdminPage(Session*); + + void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response); +}; + + +#endif // RegisterAdminPage_INCLUDED diff --git a/src/cpp/JSONInterface/JsonCreateUser.cpp b/src/cpp/JSONInterface/JsonCreateUser.cpp new file mode 100644 index 000000000..034faf4f8 --- /dev/null +++ b/src/cpp/JSONInterface/JsonCreateUser.cpp @@ -0,0 +1,116 @@ +#include "JsonCreateUser.h" +#include "Poco/URI.h" + +#include "../SingletonManager/SessionManager.h" +#include "../SingletonManager/SingletonTaskObserver.h" +#include "../SingletonManager/ErrorManager.h" + +Poco::JSON::Object* JsonCreateUser::handle(Poco::Dynamic::Var params) +{ + + + int session_id = 0; + Poco::JSON::Object* result = new Poco::JSON::Object; + /*result->set("state", "debugging"); + result->set("msg", "deactivate for debugging"); + return result; + */ + + if (params.isStruct()) { + session_id = params["session_id"]; + //std::string miau = params["miau"]; + } + else if (params.isVector()) { + try { + const Poco::URI::QueryParameters queryParams = params.extract(); + for (auto it = queryParams.begin(); it != queryParams.end(); it++) { + if (it->first == "session_id") { + session_id = stoi(it->second); + break; + } + } + //auto var = params[0]; + } + catch (const std::invalid_argument& ia) { + result->set("state", "error"); + result->set("msg", "error parsing query params, invalid argument: "); + result->set("details", ia.what()); + return result; + } + catch (const std::out_of_range& oor) { + result->set("state", "error"); + result->set("msg", "error parsing query params, Out of Range error: "); + result->set("details", oor.what()); + return result; + } + catch (const std::logic_error & ler) { + result->set("state", "error"); + result->set("msg", "error parsing query params, Logical error: "); + result->set("details", ler.what()); + return result; + } + catch (Poco::Exception& ex) { + //printf("[JsonGetLogin::handle] exception: %s\n", ex.displayText().data()); + result->set("state", "error"); + result->set("msg", "error parsing query params, Poco Error"); + result->set("details", ex.displayText()); + return result; + } + } + + if (session_id) { + auto sm = SessionManager::getInstance(); + auto observer = SingletonTaskObserver::getInstance(); + auto session = sm->getSession(session_id); + if (session) { + auto userNew = session->getNewUser(); + auto user = session->getUser(); + if (user.isNull()) { + result->set("state", "not found"); + result->set("msg", "Session didn't contain user"); + return result; + } + auto userModel = userNew->getModel(); + if (userModel.isNull()) { + result->set("state", "not found"); + result->set("msg", "user is empty"); + return result; + }//*/ + result->set("state", "success"); + result->set("clientIP", session->getClientIp().toString()); + try { + result->set("user", userNew->getJson()); + } + catch (Poco::Exception ex) { + auto em = ErrorManager::getInstance(); + em->addError(new ParamError("JsonGetLogin::handle", "poco exception calling userModel->getJson: ", ex.displayText().data())); + em->sendErrorsAsEmail(); + } + catch (...) { + auto em = ErrorManager::getInstance(); + em->addError(new Error("JsonGetLogin::handle", "generic exception calling userModel->getJson: ")); + em->sendErrorsAsEmail(); + } + result->set("Transaction.pending", session->getProcessingTransactionCount()); + auto executing = observer->getTaskCount(userModel->getEmail(), TASK_OBSERVER_SIGN_TRANSACTION); + if (executing < 0) { + executing = 0; + } + result->set("Transaction.executing", executing); + //printf("pending: %d\n", session->getProcessingTransactionCount()); + return result; + } + else { + result->set("state", "not found"); + result->set("msg", "session not found"); + return result; + } + + } + else { + result->set("state", "error"); + result->set("msg", "empty session id"); + } + + return result; +} \ No newline at end of file diff --git a/src/cpp/JSONInterface/JsonCreateUser.h b/src/cpp/JSONInterface/JsonCreateUser.h new file mode 100644 index 000000000..a7123f12a --- /dev/null +++ b/src/cpp/JSONInterface/JsonCreateUser.h @@ -0,0 +1,16 @@ +#ifndef __JSON_INTERFACE_JSON_CREATE_USER_ +#define __JSON_INTERFACE_JSON_CREATE_USER_ + +#include "JsonRequestHandler.h" + +class JsonCreateUser : public JsonRequestHandler +{ +public: + Poco::JSON::Object* handle(Poco::Dynamic::Var params); + +protected: + + +}; + +#endif // __JSON_INTERFACE_JSON_CREATE_USER_ \ No newline at end of file diff --git a/src/cpp/model/Email.cpp b/src/cpp/model/Email.cpp index 6c9f5ceb8..e4996a2e7 100644 --- a/src/cpp/model/Email.cpp +++ b/src/cpp/model/Email.cpp @@ -16,6 +16,17 @@ Mit freundlichen Grüßen\n\ Dario, Gradido Server Admin\n\ "}; +const static char EmailText_adminEmailVerification[] = { u8"\ +Hallo [first_name] [last_name],\n\ +\n\ +Der Admin hat soeben ein Gradido Konto für dich mit dieser E-Mail angelegt.\n\ +Bitte klicke zur Bestätigung 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\ @@ -77,6 +88,8 @@ Gradido Login Server\ Poco::Net::MediaType mt("text", "plain"); mt.setParameter("charset", "utf-8"); + const char* messageTemplate = nullptr; + switch (mType) { case EMAIL_DEFAULT: mailMessage->addRecipient(adminRecipient); @@ -91,6 +104,7 @@ Gradido Login Server\ break; case EMAIL_USER_VERIFICATION_CODE: + case EMAIL_ADMIN_USER_VERIFICATION_CODE: if (userTableModel.isNull() || mUser->getModel()->getEmail() == "") { addError(new Error(functionName, "no receiver email set for user email verification email")); return false; @@ -102,9 +116,14 @@ Gradido Login Server\ mailMessage->addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, mUser->getModel()->getEmail())); mailMessage->setSubject(langCatalog->gettext_str("Gradido: E-Mail Verification")); + messageTemplate = EmailText_emailVerification; + if (mType == EMAIL_ADMIN_USER_VERIFICATION_CODE) { + messageTemplate = EmailText_adminEmailVerification; + } + mailMessage->addContent( new Poco::Net::StringPartSource(replaceUserNamesAndLink( - langCatalog->gettext(EmailText_emailVerification), + langCatalog->gettext(messageTemplate), userTableModel->getFirstName(), userTableModel->getLastName(), mEmailVerificationCode->getLink() diff --git a/src/cpp/model/Email.h b/src/cpp/model/Email.h index 8fe0e85cc..e06c17d52 100644 --- a/src/cpp/model/Email.h +++ b/src/cpp/model/Email.h @@ -27,6 +27,7 @@ namespace model { EMAIL_DEFAULT, EMAIL_ERROR, EMAIL_USER_VERIFICATION_CODE, + EMAIL_ADMIN_USER_VERIFICATION_CODE, EMAIL_USER_RESET_PASSWORD, EMAIL_ADMIN_RESET_PASSWORD_REQUEST_WITHOUT_MEMORIZED_PASSPHRASE }; diff --git a/src/cpp/model/Session.cpp b/src/cpp/model/Session.cpp index dff919135..944b6bb18 100644 --- a/src/cpp/model/Session.cpp +++ b/src/cpp/model/Session.cpp @@ -135,6 +135,58 @@ Poco::AutoPtr Session::getEmailVerificationCo return ret; } +bool Session::adminCreateUser(const std::string& first_name, const std::string& last_name, const std::string& email) +{ + Profiler usedTime; + + if (mNewUser->getModel()->getRole() != model::table::ROLE_ADMIN) { + addError(new Error(gettext("Benutzer"), gettext("Eingeloggter Benutzer ist kein Admin"))); + return false; + } + + auto sm = SessionManager::getInstance(); + if (!sm->isValid(first_name, VALIDATE_NAME)) { + addError(new Error(gettext("Vorname"), gettext("Bitte gebe einen Namen an. Mindestens 3 Zeichen, keines folgender Zeichen <>&;"))); + return false; + } + if (!sm->isValid(last_name, VALIDATE_NAME)) { + addError(new Error(gettext("Nachname"), gettext("Bitte gebe einen Namen an. Mindestens 3 Zeichen, keines folgender Zeichen <>&;"))); + return false; + } + if (!sm->isValid(email, VALIDATE_EMAIL)) { + addError(new Error(gettext("E-Mail"), gettext("Bitte gebe eine gültige E-Mail Adresse an."))); + return false; + } + + + // check if user with that email already exist + if (mNewUser->getModel()->isExistInDB("email", email)) { + addError(new Error(gettext("E-Mail"), gettext("Für diese E-Mail Adresse gibt es bereits einen Account"))); + return false; + } + + auto newUser = controller::User::create(email, first_name, last_name); + updateTimeout(); + + + auto newUserModel = newUser->getModel(); + if (!newUserModel->insertIntoDB(true)) { + addError(new Error(gettext("Benutzer"), gettext("Fehler beim speichern!"))); + return false; + } + + auto emailVerificationCode = controller::EmailVerificationCode::create(newUserModel->getID(), model::table::EMAIL_OPT_IN_REGISTER); + if (!emailVerificationCode->getModel()->insertIntoDB(false)) { + addError(new Error(gettext("Email Verification Code"), gettext("Fehler beim speichern!"))); + return false; + } + + EmailManager::getInstance()->addEmail(new model::Email(emailVerificationCode, newUser, model::EMAIL_ADMIN_USER_VERIFICATION_CODE)); + + + return true; +} + bool Session::createUser(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password) { Profiler usedTime; diff --git a/src/cpp/model/Session.h b/src/cpp/model/Session.h index f1e5ae33a..f53124155 100644 --- a/src/cpp/model/Session.h +++ b/src/cpp/model/Session.h @@ -70,6 +70,10 @@ public: // TODO: automatic redirect after some time, median profiled time for register // TODO: register state: written into db, mails sended, update state only if new state is higher as old state bool createUser(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password); + + // adminRegister without passwort + bool adminCreateUser(const std::string& first_name, const std::string& last_name, const std::string& email); + // TODO: check if email exist and if not, fake waiting on password hashing with profiled times of real password hashing UserStates loadUser(const std::string& email, const std::string& password); bool ifUserExist(const std::string& email); diff --git a/src/cpp/model/table/ElopageBuy.h b/src/cpp/model/table/ElopageBuy.h index ed16c179d..e2b88fb1b 100644 --- a/src/cpp/model/table/ElopageBuy.h +++ b/src/cpp/model/table/ElopageBuy.h @@ -34,7 +34,7 @@ namespace model { ~ElopageBuy(); // generic db operations - const char* getTableName() { return "elopage_buys"; } + const char* getTableName() const { return "elopage_buys"; } std::string toString(); diff --git a/src/cpp/model/table/EmailOptIn.h b/src/cpp/model/table/EmailOptIn.h index aad4fe918..a4027ab3d 100644 --- a/src/cpp/model/table/EmailOptIn.h +++ b/src/cpp/model/table/EmailOptIn.h @@ -28,7 +28,7 @@ namespace model { ~EmailOptIn(); // generic db operations - const char* getTableName() { return "email_opt_in"; } + const char* getTableName() const { return "email_opt_in"; } std::string toString(); inline Poco::UInt64 getCode() const { return mEmailVerificationCode; } diff --git a/src/cpp/model/table/ModelBase.h b/src/cpp/model/table/ModelBase.h index c5123e6cf..e3e03cab6 100644 --- a/src/cpp/model/table/ModelBase.h +++ b/src/cpp/model/table/ModelBase.h @@ -30,13 +30,15 @@ namespace model { ModelBase() : mID(0), mReferenceCount(1) {} virtual ~ModelBase(); - virtual const char* getTableName() = 0; + virtual const char* getTableName() const = 0; virtual std::string toString() = 0; template size_t updateIntoDB(const std::string& fieldName, const T& fieldValue ); template size_t loadFromDB(const std::string& fieldName, const T& fieldValue); + template + bool isExistInDB(const std::string& fieldName, const T& fieldValue) const; template std::vector loadFromDB(const std::string& fieldName, const WhereFieldType& fieldValue, int expectedResults = 0); template @@ -90,6 +92,30 @@ namespace model { return resultCount; } + template + bool ModelBase::isExistInDB(const std::string& fieldName, const T& fieldValue) const + { + auto cm = ConnectionManager::getInstance(); + Poco::Data::Statement select(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER)); + int id; + select << "SELECT " << "id " + << " FROM " << getTableName() + << " WHERE " << fieldName << " = ?" + , into(id), Poco::Data::Keywords::useRef(fieldValue); + try { + if (select.execute() == 1) { + return true; + } + } + catch (Poco::Exception& ex) { + /*lock(); + addError(new ParamError(getTableName(), "mysql error by isExistInDB", ex.displayText().data())); + addError(new ParamError(getTableName(), "field name for select: ", fieldName.data())); + unlock();*/ + } + return false; + } + template std::vector ModelBase::loadFromDB(const std::string& fieldName, const WhereFieldType& fieldValue, int expectedResults) { diff --git a/src/cpp/model/table/User.h b/src/cpp/model/table/User.h index 56bf1cd5a..f5d927de0 100644 --- a/src/cpp/model/table/User.h +++ b/src/cpp/model/table/User.h @@ -38,7 +38,7 @@ namespace model { ~User(); // generic db operations - const char* getTableName() { return "users"; } + const char* getTableName() const { return "users"; } std::string toString(); diff --git a/src/cpp/model/table/UserRoles.h b/src/cpp/model/table/UserRoles.h index f44bf9885..7b3fad790 100644 --- a/src/cpp/model/table/UserRoles.h +++ b/src/cpp/model/table/UserRoles.h @@ -26,7 +26,7 @@ namespace model { ~UserRoles(); // generic db operations - const char* getTableName() { return "user_roles"; } + const char* getTableName() const { return "user_roles"; } std::string toString(); inline int getUserId() const { return mUserId; } diff --git a/src/cpsp/decodeTransaction.cpsp b/src/cpsp/decodeTransaction.cpsp index 79d473f1c..6c6d101d1 100644 --- a/src/cpsp/decodeTransaction.cpsp +++ b/src/cpsp/decodeTransaction.cpsp @@ -77,8 +77,11 @@

pubkey: <%= hex %>

amount: <%= receiver.amount() %>

<% } %> - <% } else if(transactionBody.has_creation()) { %> + <% } else if(transactionBody.has_creation()) { + auto creation = transactionBody.creation(); + %>

Creation

+

pubkey: <%= creation. <% } %> <% } %> diff --git a/src/cpsp/header_old.cpsp b/src/cpsp/header_old.cpsp index 480d535b0..0334bace6 100644 --- a/src/cpsp/header_old.cpsp +++ b/src/cpsp/header_old.cpsp @@ -52,11 +52,3 @@ label:not(.grd_radio_label) {

Login Server in Entwicklung

Alpha <%= ServerConfig::g_versionString %>

- \ No newline at end of file diff --git a/src/cpsp/registerAdmin.cpsp b/src/cpsp/registerAdmin.cpsp new file mode 100644 index 000000000..6f1db5b76 --- /dev/null +++ b/src/cpsp/registerAdmin.cpsp @@ -0,0 +1,61 @@ +<%@ page class="RegisterAdminPage" %> +<%@ page form="true" %> +<%@ page compressed="true" %> +<%@ page baseClass="SessionHTTPRequestHandler" %> +<%@ page ctorArg="Session*" %> +<%@ header include="SessionHTTPRequestHandler.h" %> +<%! +#include "../SingletonManager/SessionManager.h" +#include "Poco/Net/HTTPCookie.h" +%> +<%% + const char* pageName = "Admin Registrieren"; + //auto sm = SessionManager::getInstance(); + + bool userReturned = false; + + if(!form.empty()) { + userReturned = mSession->adminCreateUser( + form.get("register-first-name", ""), + form.get("register-last-name", ""), + form.get("register-email", "") + ); + getErrors(mSession); + } + + +%><%@ include file="header_old.cpsp" %> +
+

Einen neuen Account anlegen

+ <%= getErrorsHtml() %> + <% if(!form.empty() && userReturned) {%> +
+
+ Die Anmeldung wird verarbeitet und es wird dem Benutzer eine Aktivierungs-E-Mail zugeschickt. +
+
+ <% } else { %> +
+ +
+ Account anlegen +

Bitte gebe die Benutzer-Daten ein um einen Account anzulegen

+

+ + "/> +

+

+ + "/> +

+

+ + "/> +

+
+ + +
+ <% } %> +
+<%@ include file="footer.cpsp" %>