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 {
result->set("state", "not found");
result->set("msg", "Session not found");
result->set("msg", "session not found");
return result;
}

View File

@ -1,16 +1,39 @@
#include "JsonGetUsers.h"
#include "Poco/URI.h"
#include "Poco/JSON/Array.h"
#include "../SingletonManager/SessionManager.h"
#include "../model/table/User.h"
#include "../controller/User.h"
Poco::JSON::Object* JsonGetUsers::handle(Poco::Dynamic::Var params)
{
int session_id = 0;
std::string searchString;
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"];
searchString = params["search"].toString();
//std::string miau = params["miau"];
}
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++) {
if (it->first == "session_id") {
session_id = stoi(it->second);
break;
}
else if (it->first == "search") {
searchString = it->second;
}
}
//auto var = params[0];
@ -56,26 +81,42 @@ Poco::JSON::Object* JsonGetUsers::handle(Poco::Dynamic::Var params)
auto session = sm->getSession(session_id);
//Session* session = nullptr;
if (session) {
auto user = session->getUser();
if (!user) {
auto user = session->getNewUser();
if (user.isNull()) {
result->set("state", "not found");
result->set("msg", "Session didn't contain user");
return result;
}
result->set("state", "success");
result->set("clientIP", session->getClientIp().toString());
Poco::JSON::Object usersObj;
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;
else if (searchString == "") {
result->set("state", "not found");
result->set("msg", "search string is empty");
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 {
result->set("state", "not found");
result->set("msg", "Session not found");
return result;
result->set("msg", "session not found");
}
}

View File

@ -1,5 +1,5 @@
#ifndef __JSON_INTERFACE_JSON_GET_LOGIN_
#define __JSON_INTERFACE_JSON_GET_LOGIN_
#ifndef __JSON_INTERFACE_JSON_GET_USERS_
#define __JSON_INTERFACE_JSON_GET_USERS_
#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 "JsonTransaction.h"
#include "JsonGetRunningUserTasks.h"
#include "JsonGetUsers.h"
JsonRequestHandlerFactory::JsonRequestHandlerFactory()
: mRemoveGETParameters("^/([a-zA-Z0-9_-]*)")
@ -29,6 +30,9 @@ Poco::Net::HTTPRequestHandler* JsonRequestHandlerFactory::createRequestHandler(c
else if (url_first_part == "/getRunningUserTasks") {
return new JsonGetRunningUserTasks;
}
else if (url_first_part == "/getUsers") {
return new JsonGetUsers;
}
return new JsonUnknown;
}

View File

@ -2,6 +2,8 @@
#include "sodium.h"
#include "../SingletonManager/SessionManager.h"
namespace controller {
User::User(model::table::User* dbModel)
{
@ -27,6 +29,36 @@ namespace controller {
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)
{
@ -41,8 +73,6 @@ namespace controller {
}
auto mm = MemoryManager::getInstance();
auto pubkeyHex = mm->getFreeMemory(65);
memset(*pubkeyHex, 0, 65);
lock("User::getJson");
Poco::JSON::Object userObj;
@ -50,21 +80,31 @@ namespace controller {
auto pubkey = getModel()->getPublicKey();
if (pubkey) {
auto pubkeyHex = mm->getFreeMemory(65);
memset(*pubkeyHex, 0, 65);
sodium_bin2hex(*pubkeyHex, 65, pubkey, 32);
mPublicHex = (char*)*pubkeyHex;
mm->releaseMemory(pubkeyHex);
unlock();
return mPublicHex;
}
mPublicHex = (char*)*pubkeyHex;
else {
unlock();
return "";
}
unlock();
mm->releaseMemory(pubkeyHex);
return mPublicHex;
return "<error>";
}
Poco::JSON::Object User::getJson()
{
auto json = getModel()->getJson();
json.set("public_hex", getPublicHex());
auto pubkey = getPublicHex();
if (pubkey != "") {
json.set("public_hex", pubkey);
}
return json;
}

View File

@ -24,7 +24,7 @@ namespace controller {
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 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(int user_id) { return getModel()->loadFromDB("id", user_id); }

View File

@ -420,10 +420,25 @@ User::User(Poco::AutoPtr<controller::User> ctrl_user)
mLanguage = LanguageManager::languageFromString(model->getLanguageKey());
mLanguageCatalog = LanguageManager::getInstance()->getFreeCatalog(mLanguage);
mState = USER_LOADED_FROM_DB;
if (!mEmailChecked) { mState = USER_EMAIL_NOT_ACTIVATED; }
else if (!mPrivateKey) { mState = USER_NO_PRIVATE_KEY; }
else { mState = USER_COMPLETE; }
/*
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;
if (!mEmailChecked) { mState = USER_EMAIL_NOT_ACTIVATED; }
else if (!mPublicKey) { mState = USER_NO_KEYS; }
else if (!mPrivateKey) { mState = USER_NO_PRIVATE_KEY; }
else { mState = USER_COMPLETE; }
}
}

View File

@ -136,6 +136,13 @@ namespace model {
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)
{
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);
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);
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 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::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::vector<std::string> fieldNames, MysqlConditionType conditionType = MYSQL_CONDITION_AND);
virtual Poco::Data::Statement _insertIntoDB(Poco::Data::Session session) = 0;
int mID;
@ -92,7 +95,7 @@ namespace model {
{
//printf("ModelBase::loadFromDB multi\n");
std::vector<Tuple> results;
return results;
//return results;
if (expectedResults > 0) {
results.reserve(expectedResults);
}
@ -113,6 +116,42 @@ namespace model {
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>
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)
{
}
//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()
@ -82,6 +89,45 @@ namespace model {
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 select(session);

View File

@ -4,6 +4,7 @@
#include "ModelBase.h"
#include "../../SingletonManager/MemoryManager.h"
#include "Poco/Tuple.h"
//#include "Poco/Nullable.h"
//#include "Poco/Data/LOB.h"
@ -24,12 +25,13 @@ namespace model {
USER_FIELDS_LANGUAGE
};
typedef Poco::Tuple<int, std::string, std::string, std::string, Poco::Nullable<Poco::Data::BLOB>, int> UserTuple;
class User : public ModelBase
{
public:
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();
@ -67,6 +69,8 @@ namespace model {
Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName);
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
Poco::Data::Statement _insertIntoDB(Poco::Data::Session session);