!db Update!, add disabled field for user for disabling accounts, check field by login and don't login if user account is disabled

This commit is contained in:
Dario 2020-07-16 13:19:59 +02:00
parent 4e1b74ca9d
commit 3820fb947f
8 changed files with 67 additions and 28 deletions

View File

@ -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;

View File

@ -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 << " <div class=\"row\">\n";
responseStream << " <div class=\"col-12 logo-section\">\n";
responseStream << " <a href=\"";
#line 162 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
#line 173 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "\" class=\"logo\">\n";
responseStream << "\t\t\t<picture>\n";
responseStream << "\t\t\t\t<source srcset=\"";
#line 164 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
#line 175 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "img/logo_schrift.webp\" type=\"image/webp\">\n";
responseStream << "\t\t\t\t<source srcset=\"";
#line 165 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
#line 176 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "img/logo_schrift.png\" type=\"image/png\"> \n";
responseStream << "\t\t\t\t<img src=\"";
#line 166 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
#line 177 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "img/logo_schrift.png\" alt=\"logo\" />\n";
responseStream << "\t\t\t</picture>\n";
@ -257,14 +268,14 @@ void LoginPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::
responseStream << " <div class=\"grid\">\n";
responseStream << "\t\t\t<div class=\"center-ul-container\">\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</div>\n";
responseStream << " <div class=\"grid-body\">\n";
responseStream << " \n";
responseStream << "\t\t\t <!--<input type=\"hidden\" name=\"lang\" value=\"";
#line 179 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
#line 190 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
responseStream << ( LanguageManager::keyForLanguage(lang) );
responseStream << "\">-->\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 <form action=\"";
#line 181 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
#line 192 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
responseStream << ( ServerConfig::g_serverPath );
responseStream << "/\" method=\"POST\">\n";
responseStream << " <div class=\"row display-block\">\n";
responseStream << " <div class=\"col-lg-7 col-md-8 col-sm-9 col-12 mx-auto form-wrapper\">\n";
responseStream << " <div class=\"form-group input-rounded\">\n";
responseStream << " <input type=\"text\" class=\"form-control\" name=\"login-email\" placeholder=\"";
#line 185 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
#line 196 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->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 << " </div>\n";
responseStream << " <div class=\"form-group input-rounded\">\n";
responseStream << " <input type=\"password\" class=\"form-control\" name=\"login-password\" placeholder=\"";
#line 188 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
#line 199 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext("Password") );
responseStream << "\" />\n";
responseStream << " </div>\n";
responseStream << " <button type=\"submit\" name=\"submit\" class=\"btn btn-primary btn-block\">";
#line 190 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
#line 201 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext(" Login ") );
responseStream << "</button>\n";
responseStream << " <div class=\"signup-link\">\n";
responseStream << " <p>";
#line 192 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
#line 203 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext("You haven't any account yet? Please follow the link to create one.") );
responseStream << "</p>\n";
responseStream << " <a href=\"";
#line 193 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
#line 204 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
responseStream << ( ServerConfig::g_serverPath );
responseStream << "/registerDirect\">\n";
responseStream << "\t\t\t\t\t\t";
#line 194 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
#line 205 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext("Create New Account") );
responseStream << "\n";
responseStream << "\t\t\t\t\t </a>\n";
responseStream << " </div>\n";
responseStream << "\t\t\t\t\t<div class=\"reset-pwd-link\">\n";
responseStream << "\t\t\t\t\t\t<a href=\"";
#line 198 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
#line 209 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
responseStream << ( ServerConfig::g_serverPath );
responseStream << "/resetPassword\">";
#line 198 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
#line 209 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\login.cpsp"
responseStream << ( langCatalog->gettext("Passwort vergessen") );
responseStream << "</a>\n";
responseStream << "\t\t\t\t\t</div>\n";

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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<std::string, std::string, std::string, Poco::Nullable<Poco::Data::BLOB>, 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<std::string, std::string, std::string, Poco::Nullable<Poco::Data::BLOB>, 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 << "<br>";
ss << "language key: " << mLanguageKey << "<br>";
ss << "role: " << UserRoles::typeToString(getRole()) << "<br>";
ss << "disabled: " << mDisabled << "<br>";
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()));
}

View File

@ -27,7 +27,7 @@ namespace model {
USER_FIELDS_LANGUAGE
};
typedef Poco::Tuple<int, std::string, std::string, std::string, Poco::Nullable<Poco::Data::BLOB>, Poco::DateTime, int> UserTuple;
typedef Poco::Tuple<int, std::string, std::string, std::string, Poco::Nullable<Poco::Data::BLOB>, Poco::DateTime, int, int> UserTuple;
class User : public ModelBase
{
@ -62,6 +62,7 @@ namespace model {
inline const std::vector<unsigned char>& 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<int> mRole;

View File

@ -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: