From 3820fb947f9002e3c979d38f23ba499537e9b737 Mon Sep 17 00:00:00 2001 From: Dario Date: Thu, 16 Jul 2020 13:19:59 +0200 Subject: [PATCH] !db Update!, add disabled field for user for disabling accounts, check field by login and don't login if user account is disabled --- skeema/gradido_login/users.sql | 1 + src/cpp/HTTPInterface/LoginPage.cpp | 43 +++++++++++++-------- src/cpp/SingletonManager/SessionManager.cpp | 3 +- src/cpp/model/Session.cpp | 4 ++ src/cpp/model/User.h | 3 +- src/cpp/model/table/User.cpp | 23 +++++++---- src/cpp/model/table/User.h | 7 +++- src/cpsp/login.cpsp | 11 ++++++ 8 files changed, 67 insertions(+), 28 deletions(-) diff --git a/skeema/gradido_login/users.sql b/skeema/gradido_login/users.sql index 19c9c76f4..e010af2ad 100644 --- a/skeema/gradido_login/users.sql +++ b/skeema/gradido_login/users.sql @@ -10,6 +10,7 @@ CREATE TABLE `users` ( `email_checked` tinyint(1) NOT NULL DEFAULT 0, `passphrase_shown` tinyint(1) NOT NULL DEFAULT 0, `language` varchar(4) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT 'de', + `disabled` BOOLEAN NULL DEFAULT FALSE, PRIMARY KEY (`id`), UNIQUE KEY `email` (`email`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/src/cpp/HTTPInterface/LoginPage.cpp b/src/cpp/HTTPInterface/LoginPage.cpp index 4e42aaf5c..2da987edf 100644 --- a/src/cpp/HTTPInterface/LoginPage.cpp +++ b/src/cpp/HTTPInterface/LoginPage.cpp @@ -102,6 +102,9 @@ void LoginPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net:: if(userState >= USER_LOADED_FROM_DB && !user->getModel()->getPublicKey()) { if(mSession->generateKeys(true, true)) { userState = USER_COMPLETE; + if(user->getModel()->isDisabled()) { + userState = USER_DISABLED; + } } } else { //printf("pubkey exist: %p\n",user->getModel()->getPublicKey()); @@ -124,6 +127,14 @@ void LoginPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net:: case USER_KEYS_DONT_MATCH: addError(new Error(langCatalog->gettext("User"), langCatalog->gettext("Error in saved data, the server admin will look at it."))); break; + case USER_DISABLED: + addError(new Error(langCatalog->gettext("User"), langCatalog->gettext("Benutzer ist deaktiviert, kein Login möglich!"))); + if(mSession) { + getErrors(mSession); + sm->releaseSession(mSession); + } + sm->deleteLoginCookies(request, response); + break; case USER_NO_PRIVATE_KEY: case USER_COMPLETE: case USER_EMAIL_NOT_ACTIVATED: @@ -232,20 +243,20 @@ void LoginPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net:: responseStream << "
\n"; responseStream << "
\n"; responseStream << " \n"; responseStream << "\t\t\t\n"; responseStream << "\t\t\t\t\n"; responseStream << "\t\t\t\t \n"; responseStream << "\t\t\t\t\"logo\"\n"; responseStream << "\t\t\t\n"; @@ -257,14 +268,14 @@ void LoginPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net:: responseStream << "
\n"; responseStream << "\t\t\t
\n"; responseStream << "\t\t\t\t"; -#line 175 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp" +#line 186 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp" responseStream << ( getErrorsHtml() ); responseStream << "\t \n"; responseStream << "\t\t\t
\n"; responseStream << "
\n"; responseStream << " \n"; responseStream << "\t\t\t \n"; responseStream << "\t\t\t "; @@ -304,51 +315,51 @@ void LoginPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net:: // end include flags.cpsp responseStream << "\n"; responseStream << "\t\t\t
\n"; responseStream << "
\n"; responseStream << "
\n"; responseStream << "
\n"; responseStream << " gettext("E-Mail") ); responseStream << "\" value=\""; -#line 185 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp" +#line 196 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp" responseStream << ( presetEmail ); responseStream << "\"/>\n"; responseStream << "
\n"; responseStream << "
\n"; responseStream << " gettext("Password") ); responseStream << "\" />\n"; responseStream << "
\n"; responseStream << " \n"; responseStream << "
\n"; responseStream << "\t\t\t\t\t\n"; diff --git a/src/cpp/SingletonManager/SessionManager.cpp b/src/cpp/SingletonManager/SessionManager.cpp index 46b25e8b2..39c795fd5 100644 --- a/src/cpp/SingletonManager/SessionManager.cpp +++ b/src/cpp/SingletonManager/SessionManager.cpp @@ -372,7 +372,8 @@ Session* SessionManager::findByUserId(int userId) //mWorkingMutex.lock(); for (auto it = mRequestSessionMap.begin(); it != mRequestSessionMap.end(); it++) { auto user = it->second->getNewUser(); - assert(user && user->getModel() && user->getModel()->getID()); + if(!user) continue; + assert(user->getModel() && user->getModel()->getID()); if (userId == user->getModel()->getID()) { return it->second; } diff --git a/src/cpp/model/Session.cpp b/src/cpp/model/Session.cpp index f50bd6172..463241fcd 100644 --- a/src/cpp/model/Session.cpp +++ b/src/cpp/model/Session.cpp @@ -755,6 +755,10 @@ UserStates Session::loadUser(const std::string& email, const std::string& passwo mSessionUser = new User(mNewUser); //mSessionUser = new User(email.data()); } + auto user_model = mNewUser->getModel(); + if (user_model && user_model->isDisabled()) { + return USER_DISABLED; + } if (mSessionUser->getUserState() >= USER_LOADED_FROM_DB) { int loginResult = mNewUser->login(password); diff --git a/src/cpp/model/User.h b/src/cpp/model/User.h index 94bbe0678..c041cea7d 100644 --- a/src/cpp/model/User.h +++ b/src/cpp/model/User.h @@ -36,7 +36,8 @@ enum UserStates USER_NO_KEYS, USER_NO_PRIVATE_KEY, USER_KEYS_DONT_MATCH, - USER_COMPLETE + USER_COMPLETE, + USER_DISABLED }; enum UserFields diff --git a/src/cpp/model/table/User.cpp b/src/cpp/model/table/User.cpp index 3349eb1d9..806338856 100644 --- a/src/cpp/model/table/User.cpp +++ b/src/cpp/model/table/User.cpp @@ -13,18 +13,20 @@ namespace model { namespace table { User::User() - : mPasswordHashed(0), mEmailChecked(false), mLanguageKey("de"), mRole(ROLE_NOT_LOADED) + : mPasswordHashed(0), mEmailChecked(false), mLanguageKey("de"), mDisabled(false), mRole(ROLE_NOT_LOADED) { } User::User(const std::string& email, const std::string& first_name, const std::string& last_name, Poco::UInt64 passwordHashed/* = 0*/, std::string languageKey/* = "de"*/) - : 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), mDisabled(false), mRole(ROLE_NOT_LOADED) { } //id, first_name, last_name, email, pubkey, created, 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>()), mCreated(tuple.get<5>()), mEmailChecked(tuple.get<6>()), + : ModelBase(tuple.get<0>()), + mFirstName(tuple.get<1>()), mLastName(tuple.get<2>()), mEmail(tuple.get<3>()), + mPublicKey(tuple.get<4>()), mCreated(tuple.get<5>()), mEmailChecked(tuple.get<6>()), mDisabled(tuple.get<7>()), mPasswordHashed(0), mLanguageKey("de"), mRole(ROLE_NOT_LOADED) { @@ -80,11 +82,13 @@ namespace model { _fieldName = getTableName() + std::string(".id"); } Poco::Data::Statement select(session); - select << "SELECT " << getTableName() << ".id, email, first_name, last_name, password, pubkey, privkey, created, email_checked, language, user_roles.role_id " + select << "SELECT " << getTableName() << ".id, email, first_name, last_name, password, pubkey, privkey, created, email_checked, language, disabled, user_roles.role_id " << " FROM " << getTableName() << " LEFT JOIN user_roles ON " << getTableName() << ".id = user_roles.user_id " - << " WHERE " << _fieldName << " = ?" - ,into(mID), into(mEmail), into(mFirstName), into(mLastName), into(mPasswordHashed), into(mPublicKey), into(mPrivateKey), into(mCreated), into(mEmailChecked), into(mLanguageKey), into(mRole); + << " WHERE " << _fieldName << " = ?" , + into(mID), into(mEmail), into(mFirstName), into(mLastName), into(mPasswordHashed), + into(mPublicKey), into(mPrivateKey), into(mCreated), into(mEmailChecked), + into(mLanguageKey), into(mDisabled), into(mRole); return select; @@ -94,7 +98,7 @@ namespace model { { Poco::Data::Statement select(session); // typedef Poco::Tuple, int> UserTuple; - select << "SELECT id, first_name, last_name, email, pubkey, created, email_checked FROM " << getTableName() + select << "SELECT id, first_name, last_name, email, pubkey, created, email_checked, disabled FROM " << getTableName() << " where " << fieldName << " LIKE ?"; @@ -110,7 +114,7 @@ namespace model { } // typedef Poco::Tuple, int> UserTuple; - select << "SELECT id, first_name, last_name, email, pubkey, created, email_checked FROM " << getTableName() + select << "SELECT id, first_name, last_name, email, pubkey, created, email_checked, disabled FROM " << getTableName() << " where " << fieldNames[0] << " LIKE ?"; if (conditionType == MYSQL_CONDITION_AND) { for (int i = 1; i < fieldNames.size(); i++) { @@ -259,6 +263,7 @@ namespace model { ss << "created: " << Poco::DateTimeFormatter::format(mCreated, "%f.%m.%Y %H:%M:%S") << std::endl; ss << "email checked: " << mEmailChecked << std::endl; ss << "language key: " << mLanguageKey << std::endl; + ss << "disabled: " << mDisabled << std::endl; mm->releaseMemory(pubkeyHex); mm->releaseMemory(privkeyHex); @@ -285,6 +290,7 @@ namespace model { ss << "email checked: " << mEmailChecked << "
"; ss << "language key: " << mLanguageKey << "
"; ss << "role: " << UserRoles::typeToString(getRole()) << "
"; + ss << "disabled: " << mDisabled << "
"; mm->releaseMemory(pubkeyHex); @@ -322,6 +328,7 @@ namespace model { userObj.set("created", createTimeStamp.raw() / createTimeStamp.resolution()); userObj.set("email_checked", mEmailChecked); userObj.set("ident_hash", DRMakeStringHash(mEmail.data(), mEmail.size())); + userObj.set("disabled", mDisabled); try { userObj.set("role", UserRoles::typeToString(getRole())); } diff --git a/src/cpp/model/table/User.h b/src/cpp/model/table/User.h index 9fc48051c..7f097308c 100644 --- a/src/cpp/model/table/User.h +++ b/src/cpp/model/table/User.h @@ -27,7 +27,7 @@ namespace model { USER_FIELDS_LANGUAGE }; - typedef Poco::Tuple, Poco::DateTime, int> UserTuple; + typedef Poco::Tuple, Poco::DateTime, int, int> UserTuple; class User : public ModelBase { @@ -62,6 +62,7 @@ namespace model { inline const std::vector& getPrivateKeyEncrypted() const { return mPrivateKey.value().content(); } inline bool isEmailChecked() const { return mEmailChecked; } inline const std::string& getLanguageKey() const { return mLanguageKey; } + inline bool isDisabled() const { return mDisabled; } // default setter unlocked inline void setEmail(const std::string& email) { mEmail = email; } @@ -99,7 +100,9 @@ namespace model { bool mEmailChecked; std::string mLanguageKey; - + //! if account should delete but cannot because public keys for transaction needed, until gradido node is running + //! if set to true, prevent login + bool mDisabled; // from neighbor tables Poco::Nullable mRole; diff --git a/src/cpsp/login.cpsp b/src/cpsp/login.cpsp index a63792968..273501653 100644 --- a/src/cpsp/login.cpsp +++ b/src/cpsp/login.cpsp @@ -81,6 +81,9 @@ if(userState >= USER_LOADED_FROM_DB && !user->getModel()->getPublicKey()) { if(mSession->generateKeys(true, true)) { userState = USER_COMPLETE; + if(user->getModel()->isDisabled()) { + userState = USER_DISABLED; + } } } else { //printf("pubkey exist: %p\n",user->getModel()->getPublicKey()); @@ -103,6 +106,14 @@ case USER_KEYS_DONT_MATCH: addError(new Error(langCatalog->gettext("User"), langCatalog->gettext("Error in saved data, the server admin will look at it."))); break; + case USER_DISABLED: + addError(new Error(langCatalog->gettext("User"), langCatalog->gettext("Benutzer ist deaktiviert, kein Login möglich!"))); + if(mSession) { + getErrors(mSession); + sm->releaseSession(mSession); + } + sm->deleteLoginCookies(request, response); + break; case USER_NO_PRIVATE_KEY: case USER_COMPLETE: case USER_EMAIL_NOT_ACTIVATED: