diff --git a/login_server/src/cpp/JSONInterface/JsonGetUsers.cpp b/login_server/src/cpp/JSONInterface/JsonGetUsers.cpp index dc6c1faac..77f5e0a24 100644 --- a/login_server/src/cpp/JSONInterface/JsonGetUsers.cpp +++ b/login_server/src/cpp/JSONInterface/JsonGetUsers.cpp @@ -12,7 +12,8 @@ Poco::JSON::Object* JsonGetUsers::handle(Poco::Dynamic::Var params) int session_id = 0; std::string searchString; - + std::string accountState = ""; + static std::string emptySearchString = "... empty ..."; // if is json object if (params.type() == typeid(Poco::JSON::Object::Ptr)) { Poco::JSON::Object::Ptr paramJsonObject = params.extract(); @@ -23,6 +24,9 @@ Poco::JSON::Object* JsonGetUsers::handle(Poco::Dynamic::Var params) /// Throws InvalidAccessException if Var is empty. try { paramJsonObject->get("search").convert(searchString); + if (paramJsonObject->has("account_state")) { + paramJsonObject->get("account_state").convert(accountState); + } paramJsonObject->get("session_id").convert(session_id); } catch (Poco::Exception& ex) { @@ -67,17 +71,20 @@ Poco::JSON::Object* JsonGetUsers::handle(Poco::Dynamic::Var params) } auto user = session->getNewUser(); + if (searchString == emptySearchString) { + searchString = ""; + } if (user.isNull()) { return customStateError("not found", "Session didn't contain user"); } - else if (searchString == "") { - return customStateError("not found", "Search string is empty"); + else if (searchString == "" && (accountState == "" || accountState == "all")) { + return customStateError("not found", "Search string is empty and account_state is all or empty"); } else if (user->getModel()->getRole() != model::table::ROLE_ADMIN) { return customStateError("wrong role", "User hasn't correct role"); } - auto results = controller::User::search(searchString); + auto results = controller::User::search(searchString, accountState); if (!results.size()) { return stateSuccess(); } diff --git a/login_server/src/cpp/controller/User.cpp b/login_server/src/cpp/controller/User.cpp index 7aedbb701..e71d4b70a 100644 --- a/login_server/src/cpp/controller/User.cpp +++ b/login_server/src/cpp/controller/User.cpp @@ -46,24 +46,49 @@ namespace controller { return Poco::AutoPtr(user); } - std::vector User::search(const std::string& searchString) + std::vector User::search(const std::string& searchString, const std::string& accountState /* = "all" */) { auto sm = SessionManager::getInstance(); + auto cm = ConnectionManager::getInstance(); auto db = new model::table::User(); + static const char* functionName = "User::search"; std::string globalSearch = "%" + searchString + "%"; std::vector resultFromDB; - // check if search string is email - /*if (sm->isValid(searchString, VALIDATE_EMAIL)) { - resultFromDB = db->loadFromDB ("email", globalSearch); + if (accountState == "email not activated") { + + std::vector fieldNames = { "first_name", "last_name", "email", "email_checked" }; + auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + std::vector results; + + using namespace Poco::Data::Keywords; + Poco::Data::Statement select(session); + // typedef Poco::Tuple, int> UserTuple; + select << "SELECT id, first_name, last_name, email, pubkey, created, email_checked, disabled FROM " << db->getTableName(); + select << " where email_checked = 0 "; + select, into(resultFromDB); + if (searchString != "") { + select << "AND (first_name LIKE ? OR last_name LIKE ? OR email LIKE ?)"; + select, useRef(globalSearch), useRef(globalSearch), useRef(globalSearch); + } + try { + select.execute(); + } + catch (Poco::Exception& ex) { + ErrorList errors; + errors.addError(new ParamError(functionName, "mysql error ", ex.displayText())); + errors.addError(new ParamError(functionName, "search string", searchString)); + errors.addError(new ParamError(functionName, "account state", accountState)); + errors.sendErrorsAsEmail(); + } } - else {*/ + else { std::vector fieldNames = { "first_name", "last_name", "email" }; std::vector fieldValues = { globalSearch, globalSearch, globalSearch }; resultFromDB = db->loadFromDB(fieldNames, fieldValues, model::table::MYSQL_CONDITION_OR); - //} + } db->release(); db = nullptr; diff --git a/login_server/src/cpp/controller/User.h b/login_server/src/cpp/controller/User.h index 33daa9eda..f6b124cd5 100644 --- a/login_server/src/cpp/controller/User.h +++ b/login_server/src/cpp/controller/User.h @@ -28,7 +28,7 @@ namespace controller { static Poco::AutoPtr create(); static Poco::AutoPtr create(const std::string& email, const std::string& first_name, const std::string& last_name, Poco::UInt64 passwordHashed = 0, std::string languageKey = "de"); - static std::vector search(const std::string& searchString); + static std::vector search(const std::string& searchString, const std::string& accountState = "all"); //! \brief go through whole db and search users with email_checked = false and schedule resend 7 days after email_opt_in created date //! diff --git a/login_server/src/cpp/model/table/ModelBase.h b/login_server/src/cpp/model/table/ModelBase.h index 3d3bc3ab8..13bcc467c 100644 --- a/login_server/src/cpp/model/table/ModelBase.h +++ b/login_server/src/cpp/model/table/ModelBase.h @@ -40,10 +40,19 @@ namespace model { size_t loadFromDB(const std::string& fieldName, const T& fieldValue); template bool isExistInDB(const std::string& fieldName, const T& fieldValue); + template std::vector loadFromDB(const std::string& fieldName, const WhereFieldType& fieldValue, int expectedResults = 0); + template size_t loadFromDB(const std::vector& fieldNames, const T1& field1Value, const T2& field2Value, MysqlConditionType conditionType = MYSQL_CONDITION_AND); + + template + std::vector loadMultipleFromDB( + const std::vector& fieldNames, + const T1& field1Value, const T2& field2Value, const T3& field3Value, const T4& field4Value, + MysqlConditionType conditionType = MYSQL_CONDITION_AND); + template std::vector loadFromDB(const std::vector& fieldNames, const std::vector& fieldValues, MysqlConditionType conditionType = MYSQL_CONDITION_AND, int expectedResults = 0); bool insertIntoDB(bool loadId); @@ -211,6 +220,43 @@ namespace model { return resultCount; } + template + std::vector ModelBase::loadMultipleFromDB( + const std::vector& fieldNames, + const T1& field1Value, const T2& field2Value, const T3& field3Value, const T4& field4Value, + MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/) + { + auto cm = ConnectionManager::getInstance(); + std::vector results; + if (fieldNames.size() != 4) { + addError(new Error(getTableName(), "error in loadFromDB with 4 different field values, fieldNames count isn't 4")); + return results; + } + Poco::ScopedLock _lock(mWorkMutex); + + auto session = cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER); + Poco::Data::Statement select = _loadMultipleFromDB(session, fieldNames, conditionType); + select, Poco::Data::Keywords::into(results), + Poco::Data::Keywords::useRef(field1Value), Poco::Data::Keywords::useRef(field2Value), + Poco::Data::Keywords::useRef(field3Value), Poco::Data::Keywords::useRef(field4Value); + + size_t resultCount = 0; + try { + resultCount = select.execute(); + } + catch (Poco::Exception& ex) { + lock(); + addError(new ParamError(getTableName(), "mysql error by selecting with 4 different field types", ex.displayText())); + int count = 0; + for (auto it = fieldNames.begin(); it != fieldNames.end(); it++) { + addError(new ParamError(getTableName(), "field name for select: ", *it)); + } + + //addError(new ParamError(getTableName(), "field name for select: ", fieldName.data())); + unlock(); + } + return resultCount; + } template size_t ModelBase::updateIntoDB(const std::string& fieldName, const T& fieldValue)