work on multiple select for JsonGetUsers, fix bug with user states with empty user

This commit is contained in:
Dario 2020-01-16 13:09:27 +01:00
parent 1c5159930e
commit 094904ab0f
11 changed files with 232 additions and 36 deletions

View File

@ -102,7 +102,7 @@ Poco::JSON::Object* JsonGetLogin::handle(Poco::Dynamic::Var params)
} }
else { else {
result->set("state", "not found"); result->set("state", "not found");
result->set("msg", "Session not found"); result->set("msg", "session not found");
return result; return result;
} }

View File

@ -1,16 +1,39 @@
#include "JsonGetUsers.h" #include "JsonGetUsers.h"
#include "Poco/URI.h" #include "Poco/URI.h"
#include "Poco/JSON/Array.h"
#include "../SingletonManager/SessionManager.h" #include "../SingletonManager/SessionManager.h"
#include "../model/table/User.h" #include "../controller/User.h"
Poco::JSON::Object* JsonGetUsers::handle(Poco::Dynamic::Var params) Poco::JSON::Object* JsonGetUsers::handle(Poco::Dynamic::Var params)
{ {
int session_id = 0; int session_id = 0;
std::string searchString;
Poco::JSON::Object* result = new Poco::JSON::Object; Poco::JSON::Object* result = new Poco::JSON::Object;
if (params.isStruct()) { // if is json object
if (params.type() == typeid(Poco::JSON::Object::Ptr)) {
Poco::JSON::Object::Ptr paramJsonObject = params.extract<Poco::JSON::Object::Ptr>();
/// Throws a RangeException if the value does not fit
/// into the result variable.
/// Throws a NotImplementedException if conversion is
/// not available for the given type.
/// Throws InvalidAccessException if Var is empty.
try {
paramJsonObject->get("search").convert(searchString);
paramJsonObject->get("session_id").convert(session_id);
}
catch (Poco::Exception& ex) {
printf("[JsonGetUsers::handle] try to use params as jsonObject: %s\n", ex.displayText().data());
result->set("state", "error");
result->set("msg", "json exception");
result->set("details", ex.displayText());
return result;
}
}
else if (params.isStruct()) {
session_id = params["session_id"]; session_id = params["session_id"];
searchString = params["search"].toString();
//std::string miau = params["miau"]; //std::string miau = params["miau"];
} }
else if (params.isVector()) { else if (params.isVector()) {
@ -19,7 +42,9 @@ Poco::JSON::Object* JsonGetUsers::handle(Poco::Dynamic::Var params)
for (auto it = queryParams.begin(); it != queryParams.end(); it++) { for (auto it = queryParams.begin(); it != queryParams.end(); it++) {
if (it->first == "session_id") { if (it->first == "session_id") {
session_id = stoi(it->second); session_id = stoi(it->second);
break; }
else if (it->first == "search") {
searchString = it->second;
} }
} }
//auto var = params[0]; //auto var = params[0];
@ -56,26 +81,42 @@ Poco::JSON::Object* JsonGetUsers::handle(Poco::Dynamic::Var params)
auto session = sm->getSession(session_id); auto session = sm->getSession(session_id);
//Session* session = nullptr; //Session* session = nullptr;
if (session) { if (session) {
auto user = session->getUser(); auto user = session->getNewUser();
if (!user) { if (user.isNull()) {
result->set("state", "not found"); result->set("state", "not found");
result->set("msg", "Session didn't contain user"); result->set("msg", "Session didn't contain user");
return result; return result;
} }
result->set("state", "success"); else if (searchString == "") {
result->set("clientIP", session->getClientIp().toString()); result->set("state", "not found");
Poco::JSON::Object usersObj; result->set("msg", "search string is empty");
model::table::User newUser;
//auto newUsers = newUser.loadFromDB("email_checked", 0, 0);
result->set("user", user->getJson());
result->set("Transaction.pending", session->getProcessingTransactionCount());
//printf("pending: %d\n", session->getProcessingTransactionCount());
return result; return result;
} }
else if (user->getModel()->getRole() != model::table::ROLE_ADMIN) {
result->set("state", "wrong role");
result->set("msg", "User hasn't correct role");
return result;
}
auto results = controller::User::search(searchString);
if (results.size() > 0) {
result->set("state", "success");
//Poco::JSON::Object jsonResultObject;
Poco::JSON::Array jsonUsersArray;
for (auto it = results.begin(); it != results.end(); it++) {
jsonUsersArray.add((*it)->getJson());
(*it)->release();
}
results.clear();
result->set("users", jsonUsersArray);
}
}
else { else {
result->set("state", "not found"); result->set("state", "not found");
result->set("msg", "Session not found"); result->set("msg", "session not found");
return result;
} }
} }

View File

@ -1,5 +1,5 @@
#ifndef __JSON_INTERFACE_JSON_GET_LOGIN_ #ifndef __JSON_INTERFACE_JSON_GET_USERS_
#define __JSON_INTERFACE_JSON_GET_LOGIN_ #define __JSON_INTERFACE_JSON_GET_USERS_
#include "JsonRequestHandler.h" #include "JsonRequestHandler.h"
@ -13,4 +13,4 @@ protected:
}; };
#endif // __JSON_INTERFACE_JSON_GET_LOGIN_ #endif // __JSON_INTERFACE_JSON_GET_USERS_

View File

@ -8,6 +8,7 @@
#include "JsonUnknown.h" #include "JsonUnknown.h"
#include "JsonTransaction.h" #include "JsonTransaction.h"
#include "JsonGetRunningUserTasks.h" #include "JsonGetRunningUserTasks.h"
#include "JsonGetUsers.h"
JsonRequestHandlerFactory::JsonRequestHandlerFactory() JsonRequestHandlerFactory::JsonRequestHandlerFactory()
: mRemoveGETParameters("^/([a-zA-Z0-9_-]*)") : mRemoveGETParameters("^/([a-zA-Z0-9_-]*)")
@ -29,6 +30,9 @@ Poco::Net::HTTPRequestHandler* JsonRequestHandlerFactory::createRequestHandler(c
else if (url_first_part == "/getRunningUserTasks") { else if (url_first_part == "/getRunningUserTasks") {
return new JsonGetRunningUserTasks; return new JsonGetRunningUserTasks;
} }
else if (url_first_part == "/getUsers") {
return new JsonGetUsers;
}
return new JsonUnknown; return new JsonUnknown;
} }

View File

@ -2,6 +2,8 @@
#include "sodium.h" #include "sodium.h"
#include "../SingletonManager/SessionManager.h"
namespace controller { namespace controller {
User::User(model::table::User* dbModel) User::User(model::table::User* dbModel)
{ {
@ -27,6 +29,36 @@ namespace controller {
return Poco::AutoPtr<User>(user); return Poco::AutoPtr<User>(user);
} }
std::vector<User*> User::search(const std::string& searchString)
{
auto sm = SessionManager::getInstance();
auto db = new model::table::User();
std::string globalSearch = "%" + searchString + "%";
std::vector<model::table::UserTuple> resultFromDB;
// check if search string is email
if (sm->isValid(searchString, VALIDATE_EMAIL)) {
resultFromDB = db->loadFromDB <std::string, model::table::UserTuple>("email", globalSearch);
}
else {
std::vector<std::string> fieldNames = { "first_name", "last_name" };
std::vector<std::string> fieldValues = { globalSearch, globalSearch };
resultFromDB = db->loadFromDB<std::string, model::table::UserTuple>(fieldNames, fieldValues, model::table::MYSQL_CONDITION_OR);
}
db->release();
db = nullptr;
std::vector<User*> resultVector;
resultVector.reserve(resultFromDB.size());
for (auto it = resultFromDB.begin(); it != resultFromDB.end(); it++) {
resultVector.push_back(new User(new model::table::User(*it)));
}
return resultVector;
}
int User::load(const unsigned char* pubkey_array) int User::load(const unsigned char* pubkey_array)
{ {
@ -41,8 +73,6 @@ namespace controller {
} }
auto mm = MemoryManager::getInstance(); auto mm = MemoryManager::getInstance();
auto pubkeyHex = mm->getFreeMemory(65);
memset(*pubkeyHex, 0, 65);
lock("User::getJson"); lock("User::getJson");
Poco::JSON::Object userObj; Poco::JSON::Object userObj;
@ -50,21 +80,31 @@ namespace controller {
auto pubkey = getModel()->getPublicKey(); auto pubkey = getModel()->getPublicKey();
if (pubkey) { if (pubkey) {
auto pubkeyHex = mm->getFreeMemory(65);
memset(*pubkeyHex, 0, 65);
sodium_bin2hex(*pubkeyHex, 65, pubkey, 32); sodium_bin2hex(*pubkeyHex, 65, pubkey, 32);
}
mPublicHex = (char*)*pubkeyHex; mPublicHex = (char*)*pubkeyHex;
mm->releaseMemory(pubkeyHex);
unlock();
return mPublicHex;
}
else {
unlock();
return "";
}
unlock(); unlock();
return "<error>";
mm->releaseMemory(pubkeyHex);
return mPublicHex;
} }
Poco::JSON::Object User::getJson() Poco::JSON::Object User::getJson()
{ {
auto json = getModel()->getJson(); auto json = getModel()->getJson();
json.set("public_hex", getPublicHex()); auto pubkey = getPublicHex();
if (pubkey != "") {
json.set("public_hex", pubkey);
}
return json; return json;
} }

View File

@ -24,7 +24,7 @@ namespace controller {
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"); 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");
static std::vector<User*> search(const std::string& searchString);
inline size_t load(const std::string& email) { return getModel()->loadFromDB("email", email); } inline size_t load(const std::string& email) { return getModel()->loadFromDB("email", email); }
inline size_t load(int user_id) { return getModel()->loadFromDB("id", user_id); } inline size_t load(int user_id) { return getModel()->loadFromDB("id", user_id); }

View File

@ -420,11 +420,26 @@ User::User(Poco::AutoPtr<controller::User> ctrl_user)
mLanguage = LanguageManager::languageFromString(model->getLanguageKey()); mLanguage = LanguageManager::languageFromString(model->getLanguageKey());
mLanguageCatalog = LanguageManager::getInstance()->getFreeCatalog(mLanguage); mLanguageCatalog = LanguageManager::getInstance()->getFreeCatalog(mLanguage);
/*
USER_EMPTY,
USER_LOADED_FROM_DB,
USER_PASSWORD_INCORRECT,
USER_PASSWORD_ENCRYPTION_IN_PROCESS,
USER_EMAIL_NOT_ACTIVATED,
USER_NO_KEYS,
USER_NO_PRIVATE_KEY,
USER_COMPLETE
*/
if (mEmail != "") {
mState = USER_LOADED_FROM_DB; mState = USER_LOADED_FROM_DB;
if (!mEmailChecked) { mState = USER_EMAIL_NOT_ACTIVATED; } if (!mEmailChecked) { mState = USER_EMAIL_NOT_ACTIVATED; }
else if (!mPublicKey) { mState = USER_NO_KEYS; }
else if (!mPrivateKey) { mState = USER_NO_PRIVATE_KEY; } else if (!mPrivateKey) { mState = USER_NO_PRIVATE_KEY; }
else { mState = USER_COMPLETE; } else { mState = USER_COMPLETE; }
} }
}
User::~User() User::~User()

View File

@ -136,6 +136,13 @@ namespace model {
throw Poco::Exception(message); throw Poco::Exception(message);
} }
Poco::Data::Statement ModelBase::_loadMultipleFromDB(Poco::Data::Session session, const std::vector<std::string> fieldNames, MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/)
{
std::string message = getTableName();
message += "::_loadMultipleFromDB multi not implemented";
throw Poco::Exception(message);
}
Poco::DateTime ModelBase::parseElopageDate(std::string dateString) Poco::DateTime ModelBase::parseElopageDate(std::string dateString)
{ {
std::string decodedDateString = ""; std::string decodedDateString = "";

View File

@ -41,6 +41,8 @@ namespace model {
std::vector<Tuple> loadFromDB(const std::string& fieldName, const WhereFieldType& fieldValue, int expectedResults = 0); std::vector<Tuple> loadFromDB(const std::string& fieldName, const WhereFieldType& fieldValue, int expectedResults = 0);
template<class T1, class T2> template<class T1, class T2>
size_t loadFromDB(const std::vector<std::string>& fieldNames, const T1& field1Value, const T2& field2Value, MysqlConditionType conditionType = MYSQL_CONDITION_AND); size_t loadFromDB(const std::vector<std::string>& fieldNames, const T1& field1Value, const T2& field2Value, MysqlConditionType conditionType = MYSQL_CONDITION_AND);
template<class WhereFieldType, class Tuple>
std::vector<Tuple> loadFromDB(const std::vector<std::string>& fieldNames, const std::vector<WhereFieldType>& fieldValues, MysqlConditionType conditionType = MYSQL_CONDITION_AND, int expectedResults = 0);
bool insertIntoDB(bool loadId); bool insertIntoDB(bool loadId);
bool deleteFromDB(); bool deleteFromDB();
@ -58,6 +60,7 @@ namespace model {
virtual Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName) = 0; virtual Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName) = 0;
virtual Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::vector<std::string>& fieldNames, MysqlConditionType conditionType = MYSQL_CONDITION_AND); virtual Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::vector<std::string>& fieldNames, MysqlConditionType conditionType = MYSQL_CONDITION_AND);
virtual Poco::Data::Statement _loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName); virtual Poco::Data::Statement _loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName);
virtual Poco::Data::Statement _loadMultipleFromDB(Poco::Data::Session session, const std::vector<std::string> fieldNames, MysqlConditionType conditionType = MYSQL_CONDITION_AND);
virtual Poco::Data::Statement _insertIntoDB(Poco::Data::Session session) = 0; virtual Poco::Data::Statement _insertIntoDB(Poco::Data::Session session) = 0;
int mID; int mID;
@ -92,7 +95,7 @@ namespace model {
{ {
//printf("ModelBase::loadFromDB multi\n"); //printf("ModelBase::loadFromDB multi\n");
std::vector<Tuple> results; std::vector<Tuple> results;
return results; //return results;
if (expectedResults > 0) { if (expectedResults > 0) {
results.reserve(expectedResults); results.reserve(expectedResults);
} }
@ -113,6 +116,42 @@ namespace model {
return results; return results;
} }
template<class WhereFieldType, class Tuple>
std::vector<Tuple> ModelBase::loadFromDB(const std::vector<std::string>& fieldNames, const std::vector<WhereFieldType>& fieldValues, MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/, int expectedResults/* = 0*/)
{
std::vector<Tuple> results;
if (fieldNames.size() != fieldValues.size() || fieldNames.size() <= 1) {
lock();
addError(new Error(getTableName(), "fieldNames and fieldValues size don't match or smaller as 1"));
unlock();
return results;
}
if (expectedResults > 0) {
results.reserve(expectedResults);
}
auto cm = ConnectionManager::getInstance();
Poco::Data::Statement select = _loadMultipleFromDB(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER), fieldNames, conditionType);
select, Poco::Data::Keywords::into(results);// Poco::Data::Keywords::useRef(fieldValue);
for (auto it = fieldValues.begin(); it != fieldValues.end(); it++) {
select, Poco::Data::Keywords::useRef(*it);
}
size_t resultCount = 0;
try {
resultCount = select.execute();
}
catch (Poco::Exception& ex) {
lock();
addError(new ParamError(getTableName(), "mysql error by multi selecting", ex.displayText().data()));
for (auto it = fieldNames.begin(); it != fieldNames.end(); it++) {
addError(new ParamError(getTableName(), "field name for select: ", (*it).data()));
}
unlock();
}
return results;
}
template<class T1, class T2> template<class T1, class T2>
size_t ModelBase::loadFromDB(const std::vector<std::string>& fieldNames, const T1& field1Value, const T2& field2Value, MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/) size_t ModelBase::loadFromDB(const std::vector<std::string>& fieldNames, const T1& field1Value, const T2& field2Value, MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/)
{ {

View File

@ -20,6 +20,13 @@ namespace model {
: mEmail(email), mFirstName(first_name), mLastName(last_name), mPasswordHashed(passwordHashed), mEmailChecked(false), mLanguageKey(languageKey), mRole(ROLE_NOT_LOADED) : mEmail(email), mFirstName(first_name), mLastName(last_name), mPasswordHashed(passwordHashed), mEmailChecked(false), mLanguageKey(languageKey), mRole(ROLE_NOT_LOADED)
{ {
}
//id, first_name, last_name, email, pubkey, email_checked
User::User(UserTuple tuple)
: ModelBase(tuple.get<0>()), mFirstName(tuple.get<1>()), mLastName(tuple.get<2>()), mEmail(tuple.get<3>()), mPublicKey(tuple.get<4>()), mEmailChecked(tuple.get<5>()),
mPasswordHashed(0), mLanguageKey("de"), mRole(ROLE_NOT_LOADED)
{
} }
User::~User() User::~User()
@ -82,6 +89,45 @@ namespace model {
return select; return select;
} }
Poco::Data::Statement User::_loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName)
{
Poco::Data::Statement select(session);
// typedef Poco::Tuple<std::string, std::string, std::string, Poco::Nullable<Poco::Data::BLOB>, int> UserTuple;
select << "SELECT id, first_name, last_name, email, pubkey, email_checked FROM " << getTableName()
<< " where " << fieldName << " LIKE ?";
return select;
}
Poco::Data::Statement User::_loadMultipleFromDB(Poco::Data::Session session, const std::vector<std::string> fieldNames, MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/)
{
Poco::Data::Statement select(session);
if (fieldNames.size() <= 1) {
throw Poco::NullValueException("User::_loadMultipleFromDB fieldNames empty or contain only one field");
}
// typedef Poco::Tuple<std::string, std::string, std::string, Poco::Nullable<Poco::Data::BLOB>, int> UserTuple;
select << "SELECT id, first_name, last_name, email, pubkey, email_checked FROM " << getTableName()
<< " where " << fieldNames[0] << " LIKE ?";
if (conditionType == MYSQL_CONDITION_AND) {
for (int i = 1; i < fieldNames.size(); i++) {
select << " AND " << fieldNames[i] << " LIKE ? ";
}
}
else if (conditionType == MYSQL_CONDITION_OR) {
for (int i = 1; i < fieldNames.size(); i++) {
select << " OR " << fieldNames[i] << " LIKE ? ";
}
}
else {
addError(new ParamError("User::_loadMultipleFromDB", "condition type not implemented", conditionType));
}
return select;
}
Poco::Data::Statement User::_loadIdFromDB(Poco::Data::Session session) Poco::Data::Statement User::_loadIdFromDB(Poco::Data::Session session)
{ {
Poco::Data::Statement select(session); Poco::Data::Statement select(session);

View File

@ -4,6 +4,7 @@
#include "ModelBase.h" #include "ModelBase.h"
#include "../../SingletonManager/MemoryManager.h" #include "../../SingletonManager/MemoryManager.h"
#include "Poco/Tuple.h"
//#include "Poco/Nullable.h" //#include "Poco/Nullable.h"
//#include "Poco/Data/LOB.h" //#include "Poco/Data/LOB.h"
@ -24,12 +25,13 @@ namespace model {
USER_FIELDS_LANGUAGE USER_FIELDS_LANGUAGE
}; };
typedef Poco::Tuple<int, std::string, std::string, std::string, Poco::Nullable<Poco::Data::BLOB>, int> UserTuple;
class User : public ModelBase class User : public ModelBase
{ {
public: public:
User(); User();
User(UserTuple tuple);
User(const std::string& email, const std::string& first_name, const std::string& last_name, Poco::UInt64 passwordHashed = 0, std::string languageKey = "de"); User(const std::string& email, const std::string& first_name, const std::string& last_name, Poco::UInt64 passwordHashed = 0, std::string languageKey = "de");
~User(); ~User();
@ -67,6 +69,8 @@ namespace model {
Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName); Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName);
Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session); Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session);
Poco::Data::Statement _loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName);
Poco::Data::Statement _loadMultipleFromDB(Poco::Data::Session session, const std::vector<std::string> fieldNames, MysqlConditionType conditionType = MYSQL_CONDITION_AND);
// 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);