mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
1187 lines
39 KiB
C++
1187 lines
39 KiB
C++
#include "Session.h"
|
||
#include "../lib/Profiler.h"
|
||
#include "../ServerConfig.h"
|
||
|
||
#include "Poco/RegularExpression.h"
|
||
#include "Poco/Net/StringPartSource.h"
|
||
#include "Poco/Net/MediaType.h"
|
||
|
||
#include "../SingletonManager/SessionManager.h"
|
||
#include "../SingletonManager/ConnectionManager.h"
|
||
#include "../SingletonManager/ErrorManager.h"
|
||
#include "../SingletonManager/EmailManager.h"
|
||
#include "../SingletonManager/SingletonTaskObserver.h"
|
||
|
||
#include "../tasks/PrepareEmailTask.h"
|
||
#include "../tasks/SendEmailTask.h"
|
||
#include "../tasks/SigningTransaction.h"
|
||
#include "../tasks/AuthenticatedEncryptionCreateKeyTask.h"
|
||
#include "../tasks/VerificationEmailResendTask.h"
|
||
|
||
#include "../lib/JsonRequest.h"
|
||
|
||
#include "../Crypto/Passphrase.h"
|
||
|
||
|
||
#include "../controller/User.h"
|
||
#include "../controller/UserBackups.h"
|
||
#include "../controller/EmailVerificationCode.h"
|
||
|
||
#include "table/ModelBase.h"
|
||
|
||
|
||
#include "sodium.h"
|
||
|
||
using namespace Poco::Data::Keywords;
|
||
|
||
int WriteEmailVerification::run()
|
||
{
|
||
auto em = ErrorManager::getInstance();
|
||
|
||
mEmailVerificationCode->getModel()->setUserId(mUser->getDBId());
|
||
auto emailVerificationModel = mEmailVerificationCode->getModel();
|
||
emailVerificationModel->setUserId(mUser->getDBId());
|
||
if (!emailVerificationModel->insertIntoDB(true) || emailVerificationModel->errorCount() > 0) {
|
||
emailVerificationModel->sendErrorsAsEmail();
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
// ---------------------------------------------------------------------------------------------------------------
|
||
|
||
int WritePassphraseIntoDB::run()
|
||
{
|
||
Profiler timeUsed;
|
||
|
||
// TODO: encrypt passphrase, need server admin crypto box pubkey
|
||
//int crypto_box_seal(unsigned char *c, const unsigned char *m,
|
||
//unsigned long long mlen, const unsigned char *pk);
|
||
size_t mlen = mPassphrase.size();
|
||
size_t crypto_size = crypto_box_SEALBYTES + mlen;
|
||
|
||
auto em = ErrorManager::getInstance();
|
||
|
||
auto dbSession = ConnectionManager::getInstance()->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
|
||
Poco::Data::Statement insert(dbSession);
|
||
insert << "INSERT INTO user_backups (user_id, passphrase) VALUES(?,?)",
|
||
use(mUserId), use(mPassphrase);
|
||
try {
|
||
if (insert.execute() != 1) {
|
||
em->addError(new ParamError("WritePassphraseIntoDB::run", "inserting passphrase for user failed", std::to_string(mUserId)));
|
||
em->sendErrorsAsEmail();
|
||
}
|
||
}
|
||
catch (Poco::Exception& ex) {
|
||
em->addError(new ParamError("WritePassphraseIntoDB::run", "insert passphrase mysql error", ex.displayText().data()));
|
||
em->sendErrorsAsEmail();
|
||
}
|
||
|
||
//printf("[WritePassphraseIntoDB] timeUsed: %s\n", timeUsed.string().data());
|
||
return 0;
|
||
}
|
||
|
||
|
||
// --------------------------------------------------------------------------------------------------------------
|
||
|
||
Session::Session(int handle)
|
||
: mHandleId(handle), mSessionUser(nullptr), mState(SESSION_STATE_EMPTY), mActive(false)
|
||
{
|
||
|
||
}
|
||
|
||
Session::~Session()
|
||
{
|
||
//printf("[Session::~Session] \n");
|
||
if (tryLock()) {
|
||
unlock();
|
||
reset();
|
||
}
|
||
|
||
|
||
//printf("[Session::~Session] finished \n");
|
||
}
|
||
|
||
|
||
void Session::reset()
|
||
{
|
||
//printf("[Session::reset]\n");
|
||
lock("Session::reset");
|
||
|
||
mSessionUser.assign(nullptr);
|
||
mNewUser.assign(nullptr);
|
||
mEmailVerificationCodeObject.assign(nullptr);
|
||
|
||
// watch out
|
||
//updateTimeout();
|
||
mLastActivity = Poco::DateTime();
|
||
|
||
mState = SESSION_STATE_EMPTY;
|
||
|
||
mPassphrase = "";
|
||
mLastExternReferer = "";
|
||
mClientLoginIP = Poco::Net::IPAddress();
|
||
unlock();
|
||
|
||
// reset transactions
|
||
mCurrentActiveProcessingTransaction = nullptr;
|
||
mProcessingTransactions.clear();
|
||
|
||
//printf("[Session::reset] finished\n");
|
||
}
|
||
|
||
void Session::updateTimeout()
|
||
{
|
||
lock("Session::updateTimeout");
|
||
mLastActivity = Poco::DateTime();
|
||
unlock();
|
||
}
|
||
|
||
Poco::AutoPtr<controller::EmailVerificationCode> Session::getEmailVerificationCodeObject()
|
||
{
|
||
lock("Session::getEmailVerificationCodeObject");
|
||
auto ret = mEmailVerificationCodeObject;
|
||
unlock();
|
||
return ret;
|
||
}
|
||
|
||
bool Session::adminCreateUser(const std::string& first_name, const std::string& last_name, const std::string& email)
|
||
{
|
||
Profiler usedTime;
|
||
|
||
if (mNewUser->getModel()->getRole() != model::table::ROLE_ADMIN) {
|
||
addError(new Error(gettext("Benutzer"), gettext("Eingeloggter Benutzer ist kein Admin")), false);
|
||
return false;
|
||
}
|
||
|
||
auto sm = SessionManager::getInstance();
|
||
if (!sm->isValid(first_name, VALIDATE_NAME)) {
|
||
addError(new Error(gettext("Vorname"), gettext("Bitte gebe einen Namen an. Mindestens 3 Zeichen, keines folgender Zeichen <>&;")), false);
|
||
return false;
|
||
}
|
||
if (!sm->isValid(last_name, VALIDATE_NAME)) {
|
||
addError(new Error(gettext("Nachname"), gettext("Bitte gebe einen Namen an. Mindestens 3 Zeichen, keines folgender Zeichen <>&;")), false);
|
||
return false;
|
||
}
|
||
if (!sm->isValid(email, VALIDATE_EMAIL)) {
|
||
addError(new Error(gettext("E-Mail"), gettext("Bitte gebe eine gültige E-Mail Adresse an.")), false);
|
||
return false;
|
||
}
|
||
|
||
|
||
// check if user with that email already exist
|
||
if (mNewUser->getModel()->isExistInDB("email", email)) {
|
||
addError(new Error(gettext("E-Mail"), gettext("Für diese E-Mail Adresse gibt es bereits einen Account")), false);
|
||
return false;
|
||
}
|
||
|
||
auto newUser = controller::User::create(email, first_name, last_name);
|
||
updateTimeout();
|
||
|
||
|
||
auto newUserModel = newUser->getModel();
|
||
if (!newUserModel->insertIntoDB(true)) {
|
||
addError(new Error(gettext("Benutzer"), gettext("Fehler beim speichern!")));
|
||
return false;
|
||
}
|
||
|
||
auto emailVerificationCode = controller::EmailVerificationCode::create(newUserModel->getID(), model::table::EMAIL_OPT_IN_REGISTER);
|
||
if (!emailVerificationCode->getModel()->insertIntoDB(false)) {
|
||
addError(new Error(gettext("Email Verification Code"), gettext("Fehler beim speichern!")));
|
||
return false;
|
||
}
|
||
|
||
EmailManager::getInstance()->addEmail(new model::Email(emailVerificationCode, newUser, model::EMAIL_ADMIN_USER_VERIFICATION_CODE));
|
||
|
||
|
||
return true;
|
||
}
|
||
|
||
bool Session::createUser(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password)
|
||
{
|
||
Profiler usedTime;
|
||
auto sm = SessionManager::getInstance();
|
||
if (!sm->isValid(first_name, VALIDATE_NAME)) {
|
||
addError(new Error(gettext("Vorname"), gettext("Bitte gebe einen Namen an. Mindestens 3 Zeichen, keines folgender Zeichen <>&;")), false);
|
||
return false;
|
||
}
|
||
if (!sm->isValid(last_name, VALIDATE_NAME)) {
|
||
addError(new Error(gettext("Nachname"), gettext("Bitte gebe einen Namen an. Mindestens 3 Zeichen, keines folgender Zeichen <>&;")), false);
|
||
return false;
|
||
}
|
||
if (!sm->isValid(email, VALIDATE_EMAIL)) {
|
||
addError(new Error(gettext("E-Mail"), gettext("Bitte gebe eine gültige E-Mail Adresse an.")), false);
|
||
return false;
|
||
}
|
||
if (!sm->checkPwdValidation(password, this)) {
|
||
return false;
|
||
}
|
||
/*if (passphrase.size() > 0 && !sm->isValid(passphrase, VALIDATE_PASSPHRASE)) {
|
||
addError(new Error("Merkspruch", "Der Merkspruch ist nicht gültig, er besteht aus 24 Wörtern, mit Komma getrennt."));
|
||
return false;
|
||
}
|
||
if (passphrase.size() == 0) {
|
||
//mPassphrase = User::generateNewPassphrase(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]);
|
||
mPassphrase = User::generateNewPassphrase(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]);
|
||
}
|
||
else {
|
||
//mPassphrase = passphrase;
|
||
}*/
|
||
|
||
// check if user with that email already exist
|
||
|
||
auto dbConnection = ConnectionManager::getInstance()->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
|
||
Poco::Data::Statement select(dbConnection);
|
||
select << "SELECT email from users where email = ?;", useRef(email);
|
||
try {
|
||
if (select.execute() > 0) {
|
||
addError(new Error(gettext("E-Mail"), gettext("Für diese E-Mail Adresse gibt es bereits einen Account")), false);
|
||
return false;
|
||
}
|
||
}
|
||
catch (Poco::Exception& exc) {
|
||
printf("mysql exception: %s\n", exc.displayText().data());
|
||
}
|
||
|
||
mSessionUser = new User(email.data(), first_name.data(), last_name.data());
|
||
mNewUser = controller::User::create(email, first_name, last_name);
|
||
updateTimeout();
|
||
|
||
// Prepare E-Mail
|
||
//UniLib::controller::TaskPtr prepareEmail(new PrepareEmailTask(ServerConfig::g_CPUScheduler));
|
||
//prepareEmail->scheduleTask(prepareEmail);
|
||
|
||
// create user crypto key
|
||
UniLib::controller::TaskPtr cryptoKeyTask(new UserCreateCryptoKey(mSessionUser, mNewUser, password, ServerConfig::g_CryptoCPUScheduler));
|
||
cryptoKeyTask->setFinishCommand(new SessionStateUpdateCommand(SESSION_STATE_CRYPTO_KEY_GENERATED, this));
|
||
cryptoKeyTask->scheduleTask(cryptoKeyTask);
|
||
|
||
// depends on crypto key, write user record into db
|
||
UniLib::controller::TaskPtr writeUserIntoDB(new UserWriteIntoDB(mSessionUser, ServerConfig::g_CPUScheduler, 1));
|
||
writeUserIntoDB->setParentTaskPtrInArray(cryptoKeyTask, 0);
|
||
writeUserIntoDB->setFinishCommand(new SessionStateUpdateCommand(SESSION_STATE_USER_WRITTEN, this));
|
||
writeUserIntoDB->scheduleTask(writeUserIntoDB);
|
||
|
||
|
||
mEmailVerificationCodeObject = controller::EmailVerificationCode::create(model::table::EMAIL_OPT_IN_REGISTER);
|
||
UniLib::controller::TaskPtr writeEmailVerification(new WriteEmailVerification(mSessionUser, mEmailVerificationCodeObject, ServerConfig::g_CPUScheduler, 1));
|
||
|
||
writeEmailVerification->setParentTaskPtrInArray(writeUserIntoDB, 0);
|
||
writeEmailVerification->setFinishCommand(new SessionStateUpdateCommand(SESSION_STATE_EMAIL_VERIFICATION_WRITTEN, this));
|
||
writeEmailVerification->scheduleTask(writeEmailVerification);
|
||
|
||
|
||
/*printf("LastName: %s\n", last_name.data());
|
||
for (int i = 0; i < last_name.size(); i++) {
|
||
char c = last_name.data()[i];
|
||
//printf("%d ", c);
|
||
}
|
||
//printf("\n\n");
|
||
*/
|
||
|
||
// depends on writeUser because need user_id, write email verification into db
|
||
/*auto message = new Poco::Net::MailMessage;
|
||
Poco::Net::MediaType mt("text", "plain");
|
||
mt.setParameter("charset", "utf-8");
|
||
message->setContentType(mt);
|
||
|
||
message->addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, email));
|
||
message->setSubject(gettext("Gradido: E-Mail Verification"));
|
||
std::stringstream ss;
|
||
ss << "Hallo " << first_name << " " << last_name << "," << std::endl << std::endl;
|
||
ss << "Du oder jemand anderes hat sich soeben mit dieser E-Mail Adresse bei Gradido registriert. " << std::endl;
|
||
ss << "Wenn du es warst, klicke bitte auf den Link: " << ServerConfig::g_serverPath << "/checkEmail/" << mEmailVerificationCode << std::endl;
|
||
//ss << "oder kopiere den Code: " << mEmailVerificationCode << " selbst dort hinein." << std::endl;
|
||
ss << "oder kopiere den obigen Link in Dein Browserfenster." << std::endl;
|
||
ss << std::endl;
|
||
ss << "Mit freundlichen " << u8"Gr<47><72>en" << std::endl;
|
||
ss << "Dario, Gradido Server Admin" << std::endl;
|
||
|
||
|
||
message->addContent(new Poco::Net::StringPartSource(ss.str()));
|
||
*/
|
||
//UniLib::controller::TaskPtr sendEmail(new SendEmailTask(message, ServerConfig::g_CPUScheduler, 1));
|
||
//Email(AutoPtr<controller::EmailVerificationCode> emailVerification, AutoPtr<controller::User> user, EmailType type);
|
||
UniLib::controller::TaskPtr sendEmail(new SendEmailTask(new model::Email(mEmailVerificationCodeObject, mNewUser, model::EMAIL_USER_VERIFICATION_CODE), ServerConfig::g_CPUScheduler, 1));
|
||
//sendEmail->setParentTaskPtrInArray(prepareEmail, 0);
|
||
sendEmail->setParentTaskPtrInArray(writeEmailVerification, 0);
|
||
sendEmail->setFinishCommand(new SessionStateUpdateCommand(SESSION_STATE_EMAIL_VERIFICATION_SEND, this));
|
||
sendEmail->scheduleTask(sendEmail);
|
||
|
||
// write user into db
|
||
// generate and write email verification into db
|
||
// send email
|
||
|
||
//printf("[Session::createUser] time: %s\n", usedTime.string().data());
|
||
|
||
return true;
|
||
}
|
||
|
||
bool Session::createUserDirect(const std::string& first_name, const std::string& last_name, const std::string& email, const std::string& password)
|
||
{
|
||
static const char* function_name = "Session::createUserDirect";
|
||
auto sm = SessionManager::getInstance();
|
||
auto em = ErrorManager::getInstance();
|
||
auto email_manager = EmailManager::getInstance();
|
||
|
||
if (!sm->isValid(first_name, VALIDATE_NAME)) {
|
||
addError(new Error(gettext("Vorname"), gettext("Bitte gebe einen Namen an. Mindestens 3 Zeichen, keines folgender Zeichen <>&;")), false);
|
||
return false;
|
||
}
|
||
if (!sm->isValid(last_name, VALIDATE_NAME)) {
|
||
addError(new Error(gettext("Nachname"), gettext("Bitte gebe einen Namen an. Mindestens 3 Zeichen, keines folgender Zeichen <>&;")), false);
|
||
return false;
|
||
}
|
||
if (!sm->isValid(email, VALIDATE_EMAIL)) {
|
||
addError(new Error(gettext("E-Mail"), gettext("Bitte gebe eine gültige E-Mail Adresse an.")), false);
|
||
return false;
|
||
}
|
||
if (!sm->checkPwdValidation(password, this)) {
|
||
return false;
|
||
}
|
||
|
||
// check if email already exist
|
||
auto user = controller::User::create();
|
||
if (user->load(email) >= 1) {
|
||
addError(new Error(gettext("E-Mail"), gettext("Für diese E-Mail Adresse gibt es bereits ein Konto")), false);
|
||
return false;
|
||
}
|
||
|
||
// user
|
||
mNewUser = controller::User::create(email, first_name, last_name);
|
||
auto user_model = mNewUser->getModel();
|
||
user_model->insertIntoDB(true);
|
||
auto user_id = user_model->getID();
|
||
|
||
|
||
// one retry in case of connection error
|
||
if (!user_id) {
|
||
user_model->insertIntoDB(true);
|
||
auto user_id = user_model->getID();
|
||
if (!user_id) {
|
||
em->addError(new ParamError(function_name, "error saving new user in db, after one retry with email", email));
|
||
em->sendErrorsAsEmail();
|
||
addError(new Error(gettext("Server"), gettext("Fehler beim speichen des Kontos bitte versuche es sp<73>ter noch einmal")), false);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
generateKeys(true, true);
|
||
|
||
// calculate encryption key, could need some time, will save encrypted privkey to db
|
||
UniLib::controller::TaskPtr create_authenticated_encrypten_key = new AuthenticatedEncryptionCreateKeyTask(mNewUser, password);
|
||
create_authenticated_encrypten_key->scheduleTask(create_authenticated_encrypten_key);
|
||
|
||
// email verification code
|
||
auto email_verification = controller::EmailVerificationCode::create(user_id, model::table::EMAIL_OPT_IN_REGISTER_DIRECT);
|
||
email_verification->getModel()->insertIntoDB(false);
|
||
|
||
auto _7days_later = Poco::DateTime() + Poco::Timespan(7, 0, 0, 0, 0);
|
||
ServerConfig::g_CronJobsTimer.schedule(new VerificationEmailResendTimerTask(user_id), Poco::Timestamp(_7days_later.microsecond()));
|
||
|
||
email_manager->addEmail(new model::Email(email_verification, mNewUser, model::EMAIL_USER_VERIFICATION_CODE));
|
||
|
||
return true;
|
||
}
|
||
|
||
bool Session::ifUserExist(const std::string& email)
|
||
{
|
||
auto em = ErrorManager::getInstance();
|
||
const char* funcName = "Session::ifUserExist";
|
||
auto dbConnection = ConnectionManager::getInstance()->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
|
||
Poco::Data::Statement select(dbConnection);
|
||
bool emailChecked = false;
|
||
int userId = 0;
|
||
select << "SELECT email_checked, id from users where email = ? and email_checked = 1",
|
||
into(emailChecked), into(userId), useRef(email);
|
||
|
||
try {
|
||
if(select.execute() == 1) return true;
|
||
}
|
||
catch (Poco::Exception& ex) {
|
||
em->addError(new ParamError(funcName, "select user from email verification code mysql error ", ex.displayText().data()));
|
||
em->sendErrorsAsEmail();
|
||
}
|
||
return false;
|
||
}
|
||
|
||
int Session::updateEmailVerification(Poco::UInt64 emailVerificationCode)
|
||
{
|
||
const static char* funcName = "Session::updateEmailVerification";
|
||
|
||
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);
|
||
Profiler usedTime;
|
||
|
||
auto em = ErrorManager::getInstance();
|
||
if (mEmailVerificationCodeObject.isNull()) {
|
||
em->addError(new Error(funcName, "email verification object is zero"));
|
||
em->sendErrorsAsEmail();
|
||
|
||
return -2;
|
||
}
|
||
auto email_verification_code_model = mEmailVerificationCodeObject->getModel();
|
||
if(email_verification_code_model->getCode() == emailVerificationCode) {
|
||
if (mSessionUser && mSessionUser->getDBId() == 0) {
|
||
//addError(new Error("E-Mail Verification", "Benutzer wurde nicht richtig gespeichert, bitte wende dich an den Server-Admin"));
|
||
em->addError(new Error(funcName, "user exist with 0 as id"));
|
||
em->sendErrorsAsEmail();
|
||
|
||
//return false;
|
||
return -2;
|
||
}
|
||
|
||
// load correct user from db
|
||
if (mNewUser.isNull() || mNewUser->getModel()->getID() != email_verification_code_model->getUserId()) {
|
||
mNewUser = controller::User::create();
|
||
if (1 != mNewUser->load(email_verification_code_model->getUserId())) {
|
||
em->addError(new ParamError(funcName, "user load didn't return 1 with user_id ", email_verification_code_model->getUserId()));
|
||
em->sendErrorsAsEmail();
|
||
|
||
return -2;
|
||
}
|
||
}
|
||
|
||
auto user_model = mNewUser->getModel();
|
||
bool first_email_activation = false;
|
||
auto verification_type = email_verification_code_model->getType();
|
||
if (model::table::EMAIL_OPT_IN_REGISTER == verification_type ||
|
||
model::table::EMAIL_OPT_IN_EMPTY == verification_type ||
|
||
model::table::EMAIL_OPT_IN_REGISTER_DIRECT == verification_type) {
|
||
first_email_activation = true;
|
||
}
|
||
if (first_email_activation && user_model->isEmailChecked()) {
|
||
mSessionUser = new User(mNewUser);
|
||
addError(new Error(gettext("E-Mail Verification"), gettext("Du hast dein Konto bereits aktiviert!")), false);
|
||
|
||
return 1;
|
||
}
|
||
if (first_email_activation) {
|
||
user_model->setEmailChecked(true);
|
||
|
||
user_model->updateIntoDB("email_checked", 1);
|
||
if (user_model->errorCount() > 0) {
|
||
user_model->sendErrorsAsEmail();
|
||
}
|
||
|
||
updateState(SESSION_STATE_EMAIL_VERIFICATION_CODE_CHECKED);
|
||
return 0;
|
||
}
|
||
|
||
if (email_verification_code_model->getType() == model::table::EMAIL_OPT_IN_RESET_PASSWORD) {
|
||
|
||
if (mEmailVerificationCodeObject->deleteFromDB()) {
|
||
mEmailVerificationCodeObject.assign(nullptr);
|
||
}
|
||
else {
|
||
em->getErrors(mEmailVerificationCodeObject->getModel());
|
||
em->addError(new Error(funcName, "error deleting email verification code"));
|
||
em->sendErrorsAsEmail();
|
||
return -2;
|
||
}
|
||
updateState(SESSION_STATE_RESET_PASSWORD_REQUEST);
|
||
return 0;
|
||
}
|
||
|
||
em->addError(new Error(funcName, "invalid code path"));
|
||
em->sendErrorsAsEmail();
|
||
|
||
return -2;
|
||
|
||
/*if (updated_rows == 1) {
|
||
Poco::Data::Statement delete_row(dbConnection);
|
||
delete_row << "DELETE FROM email_opt_in where verification_code = ?", use(emailVerificationCode);
|
||
if (delete_row.execute() != 1) {
|
||
em->addError(new Error(funcName, "delete from email_opt_in entry didn't work as expected, please check db"));
|
||
em->sendErrorsAsEmail();
|
||
}
|
||
if (mSessionUser) {
|
||
mSessionUser->setEmailChecked();
|
||
mSessionUser->setLanguage(getLanguage());
|
||
}
|
||
updateState(SESSION_STATE_EMAIL_VERIFICATION_CODE_CHECKED);
|
||
//printf("[%s] time: %s\n", funcName, usedTime.string().data());
|
||
unlock();
|
||
return true;
|
||
}
|
||
else {
|
||
em->addError(new ParamError(funcName, "update user work not like expected, updated row count", updated_rows));
|
||
em->sendErrorsAsEmail();
|
||
}*/
|
||
|
||
|
||
}
|
||
else {
|
||
addError(new Error(gettext("E-Mail Verification"), gettext("Falscher Code für aktiven Login")));
|
||
//printf("[%s] time: %s\n", funcName, usedTime.string().data());
|
||
|
||
return -1;
|
||
}
|
||
//printf("[%s] time: %s\n", funcName, usedTime.string().data());
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
int Session::sendResetPasswordEmail(Poco::AutoPtr<controller::User> user, bool passphraseMemorized)
|
||
{
|
||
mNewUser = user;
|
||
mSessionUser = new User(user);
|
||
auto em = EmailManager::getInstance();
|
||
|
||
// creating email verification code also for user without passphrase
|
||
// first check if already exist
|
||
mEmailVerificationCodeObject = controller::EmailVerificationCode::create(mNewUser->getModel()->getID(), model::table::EMAIL_OPT_IN_RESET_PASSWORD);
|
||
auto foundCount = mEmailVerificationCodeObject->load(user->getModel()->getID(), model::table::EMAIL_OPT_IN_RESET_PASSWORD);
|
||
auto emailVerificationModel = mEmailVerificationCodeObject->getModel();
|
||
|
||
UniLib::controller::TaskPtr insertEmailVerificationCode(
|
||
new model::table::ModelInsertTask(emailVerificationModel, true, true)
|
||
);
|
||
insertEmailVerificationCode->scheduleTask(insertEmailVerificationCode);
|
||
|
||
if (passphraseMemorized) {
|
||
em->addEmail(new model::Email(mEmailVerificationCodeObject, mNewUser, model::EMAIL_USER_RESET_PASSWORD));
|
||
}
|
||
else {
|
||
em->addEmail(new model::Email(user, model::EMAIL_ADMIN_RESET_PASSWORD_REQUEST_WITHOUT_MEMORIZED_PASSPHRASE));
|
||
}
|
||
|
||
if (foundCount) {
|
||
return 1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
int Session::comparePassphraseWithSavedKeys(const std::string& inputPassphrase, Mnemonic* wordSource)
|
||
{
|
||
KeyPair keys;
|
||
static const char* functionName = "Session::comparePassphraseWithSavedKeys";
|
||
if (!wordSource) {
|
||
addError(new Error(functionName, "wordSource is empty"));
|
||
sendErrorsAsEmail();
|
||
return -2;
|
||
}
|
||
if (!keys.generateFromPassphrase(inputPassphrase.data(), wordSource)) {
|
||
addError(new ParamError(functionName, "invalid passphrase", inputPassphrase));
|
||
if (!mNewUser.isNull() && mNewUser->getModel()) {
|
||
addError(new ParamError(functionName, "user email", mNewUser->getModel()->getEmail()));
|
||
}
|
||
sendErrorsAsEmail();
|
||
addError(new Error(gettext("Passphrase"), gettext("Deine Passphrase ist ungütig")), false);
|
||
return 0;
|
||
}
|
||
auto userModel = mNewUser->getModel();
|
||
auto existingPublic = userModel->getPublicKey();
|
||
if (!existingPublic) {
|
||
userModel->loadFromDB("email", userModel->getEmail());
|
||
existingPublic = userModel->getPublicKey();
|
||
if (!existingPublic) {
|
||
addError(new Error(functionName, "cannot load existing public key from db"));
|
||
addError(new ParamError(functionName, "user email", userModel->getEmail()));
|
||
sendErrorsAsEmail();
|
||
addError(new Error(gettext("Passphrase"), gettext("Ein Fehler trat auf, bitte versuche es erneut")), false);
|
||
return -1;
|
||
}
|
||
}
|
||
if (0 == memcmp(userModel->getPublicKey(), keys.getPublicKey(), crypto_sign_PUBLICKEYBYTES)) {
|
||
mPassphrase = inputPassphrase;
|
||
return 1;
|
||
}
|
||
addError(new Error(gettext("Passphrase"), gettext("Das ist nicht die richtige Passphrase.")), false);
|
||
return 0;
|
||
}
|
||
|
||
bool Session::startProcessingTransaction(const std::string& proto_message_base64)
|
||
{
|
||
static const char* funcName = "Session::startProcessingTransaction";
|
||
lock(funcName);
|
||
HASH hs = ProcessingTransaction::calculateHash(proto_message_base64);
|
||
// check if it is already running or waiting
|
||
for (auto it = mProcessingTransactions.begin(); it != mProcessingTransactions.end(); it++) {
|
||
if (it->isNull()) {
|
||
it = mProcessingTransactions.erase(it);
|
||
}
|
||
if (hs == (*it)->getHash()) {
|
||
addError(new Error(funcName, "transaction already in list"));
|
||
unlock();
|
||
return false;
|
||
}
|
||
}
|
||
if (mSessionUser.isNull() || !mSessionUser->getEmail()) {
|
||
addError(new Error(funcName, "user is zero"));
|
||
unlock();
|
||
return false;
|
||
}
|
||
|
||
Poco::AutoPtr<ProcessingTransaction> processorTask(new ProcessingTransaction(proto_message_base64, DRMakeStringHash(mSessionUser->getEmail())));
|
||
processorTask->scheduleTask(processorTask);
|
||
mProcessingTransactions.push_back(processorTask);
|
||
unlock();
|
||
return true;
|
||
|
||
}
|
||
|
||
Poco::AutoPtr<ProcessingTransaction> Session::getNextReadyTransaction(size_t* working/* = nullptr*/)
|
||
{
|
||
lock("Session::getNextReadyTransaction");
|
||
if (working) {
|
||
*working = 0;
|
||
}
|
||
else if (!mCurrentActiveProcessingTransaction.isNull())
|
||
{
|
||
unlock();
|
||
return mCurrentActiveProcessingTransaction;
|
||
}
|
||
for (auto it = mProcessingTransactions.begin(); it != mProcessingTransactions.end(); it++) {
|
||
if (working && !(*it)->isTaskFinished()) {
|
||
(*working)++;
|
||
}
|
||
if (mCurrentActiveProcessingTransaction.isNull() && (*it)->isTaskFinished()) {
|
||
if (!working) {
|
||
mCurrentActiveProcessingTransaction = *it;
|
||
unlock();
|
||
return mCurrentActiveProcessingTransaction;
|
||
}
|
||
// no early exit
|
||
else {
|
||
mCurrentActiveProcessingTransaction = *it;
|
||
}
|
||
|
||
}
|
||
}
|
||
unlock();
|
||
return mCurrentActiveProcessingTransaction;
|
||
}
|
||
|
||
void Session::finalizeTransaction(bool sign, bool reject)
|
||
{
|
||
lock("Session::finalizeTransaction");
|
||
if (mCurrentActiveProcessingTransaction.isNull()) {
|
||
unlock();
|
||
return;
|
||
}
|
||
mProcessingTransactions.remove(mCurrentActiveProcessingTransaction);
|
||
|
||
if (!reject) {
|
||
if (sign) {
|
||
Poco::AutoPtr<SigningTransaction> signingTransaction(new SigningTransaction(mCurrentActiveProcessingTransaction, mNewUser));
|
||
signingTransaction->scheduleTask(signingTransaction);
|
||
}
|
||
}
|
||
mCurrentActiveProcessingTransaction.assign(nullptr);
|
||
unlock();
|
||
}
|
||
|
||
size_t Session::getProcessingTransactionCount()
|
||
{
|
||
size_t count = 0;
|
||
lock("Session::getProcessingTransactionCount");
|
||
|
||
for (auto it = mProcessingTransactions.begin(); it != mProcessingTransactions.end(); it++) {
|
||
|
||
(*it)->lock();
|
||
if ((*it)->errorCount() > 0) {
|
||
(*it)->sendErrorsAsEmail();
|
||
(*it)->unlock();
|
||
it = mProcessingTransactions.erase(it);
|
||
if (it == mProcessingTransactions.end()) break;
|
||
}
|
||
else {
|
||
(*it)->unlock();
|
||
}
|
||
|
||
}
|
||
count = mProcessingTransactions.size();
|
||
unlock();
|
||
return count;
|
||
}
|
||
|
||
bool Session::isPwdValid(const std::string& pwd)
|
||
{
|
||
if (mSessionUser) {
|
||
return mSessionUser->validatePwd(pwd, this);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
UserStates Session::loadUser(const std::string& email, const std::string& password)
|
||
{
|
||
static const char* functionName = "Session::loadUser";
|
||
auto observer = SingletonTaskObserver::getInstance();
|
||
if (email != "") {
|
||
if (observer->getTaskCount(email, TASK_OBSERVER_PASSWORD_CREATION) > 0) {
|
||
return USER_PASSWORD_ENCRYPTION_IN_PROCESS;
|
||
}
|
||
}
|
||
//Profiler usedTime;
|
||
lock(functionName);
|
||
if (mSessionUser && mSessionUser->getEmail() != email) {
|
||
mSessionUser.assign(nullptr);
|
||
mNewUser.assign(nullptr);
|
||
}
|
||
//if (!mSessionUser) {
|
||
if (mNewUser.isNull()) {
|
||
mNewUser = controller::User::create();
|
||
|
||
// load user for email only once from db
|
||
mNewUser->load(email);
|
||
mSessionUser = new User(mNewUser);
|
||
//mSessionUser = new User(email.data());
|
||
}
|
||
if (mSessionUser->getUserState() >= USER_LOADED_FROM_DB) {
|
||
int loginResult = mNewUser->login(password);
|
||
|
||
if (-1 == loginResult) {
|
||
addError(new Error(functionName, "error in user data set, saved pubkey didn't match extracted pubkey from private key"));
|
||
addError(new ParamError(functionName, "user email", mNewUser->getModel()->getEmail()));
|
||
sendErrorsAsEmail();
|
||
//unlock();
|
||
//return USER_KEYS_DONT_MATCH;
|
||
}
|
||
if (0 == loginResult) {
|
||
unlock();
|
||
return USER_PASSWORD_INCORRECT;
|
||
}
|
||
// error decrypting private key
|
||
if (-2 == loginResult) {
|
||
// check if we have access to the passphrase, if so we can reencrypt the private key
|
||
auto user_model = mNewUser->getModel();
|
||
auto user_backups = controller::UserBackups::load(user_model->getID());
|
||
for (auto it = user_backups.begin(); it != user_backups.end(); it++) {
|
||
auto key = std::unique_ptr<KeyPairEd25519>((*it)->createGradidoKeyPair());
|
||
if (key->isTheSame(user_model->getPublicKey()))
|
||
{
|
||
|
||
// set valid key pair
|
||
if (1 == mNewUser->setGradidoKeyPair(key.release())) {
|
||
// save new encrypted private key
|
||
user_model->updatePrivkey();
|
||
}
|
||
else {
|
||
auto em = ErrorManager::getInstance();
|
||
em->addError(new Error(functionName, "error reencrypt private key"));
|
||
em->addError(new ParamError(functionName, "for user with email", user_model->getEmail()));
|
||
em->sendErrorsAsEmail();
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
// can be removed if session user isn't used any more
|
||
if (mNewUser->getModel()->getPasswordHashed() && !mSessionUser->validatePwd(password, this)) {
|
||
unlock();
|
||
return USER_PASSWORD_INCORRECT;
|
||
}
|
||
}
|
||
else {
|
||
User::fakeCreateCryptoKey();
|
||
}
|
||
|
||
/*if (!mSessionUser->validatePwd(password, this)) {
|
||
addError(new Error("Login", "E-Mail oder Passwort nicht korrekt, bitte versuche es erneut!"));
|
||
unlock();
|
||
return false;
|
||
}
|
||
if (!mSessionUser->isEmailChecked()) {
|
||
addError(new Error("Account", "E-Mail Adresse wurde noch nicht bestätigt, hast du schon eine E-Mail erhalten?"));
|
||
unlock();
|
||
return false;
|
||
}*/
|
||
detectSessionState();
|
||
unlock();
|
||
|
||
return mSessionUser->getUserState();
|
||
}
|
||
|
||
bool Session::deleteUser()
|
||
{
|
||
lock("Session::deleteUser");
|
||
bool bResult = false;
|
||
if(mSessionUser) {
|
||
JsonRequest phpServerRequest(ServerConfig::g_php_serverHost, 443);
|
||
Poco::Net::NameValueCollection payload;
|
||
payload.add("user", std::string(mSessionUser->getPublicKeyHex()));
|
||
//auto ret = phpServerRequest.request("userDelete", payload);
|
||
JsonRequestReturn ret = JSON_REQUEST_RETURN_OK;
|
||
if (ret == JSON_REQUEST_RETURN_ERROR) {
|
||
addError(new Error("Session::deleteUser", "php server error"));
|
||
getErrors(&phpServerRequest);
|
||
sendErrorsAsEmail();
|
||
}
|
||
else if (ret == JSON_REQUEST_RETURN_OK) {
|
||
bResult = mSessionUser->deleteFromDB();
|
||
}
|
||
else {
|
||
addError(new Error(gettext("Benutzer"), gettext("Konnte Community Server nicht erreichen. E-Mail an den Admin ist raus.")));
|
||
unlock();
|
||
return false;
|
||
}
|
||
}
|
||
if(!bResult) {
|
||
addError(new Error(gettext("Benutzer"), gettext("Fehler beim Löschen des Accounts. Bitte logge dich erneut ein und versuche es nochmal.")));
|
||
}
|
||
unlock();
|
||
return bResult;
|
||
}
|
||
|
||
void Session::setLanguage(Languages lang)
|
||
{
|
||
//printf("[Session::setLanguage] new language: %d\n", lang);
|
||
lock("Session::setLanguage");
|
||
if (mLanguageCatalog.isNull() || mLanguageCatalog->getLanguage() != lang) {
|
||
auto lm = LanguageManager::getInstance();
|
||
mLanguageCatalog = lm->getFreeCatalog(lang);
|
||
}
|
||
unlock();
|
||
}
|
||
|
||
Languages Session::getLanguage()
|
||
{
|
||
Languages lang = LANG_NULL;
|
||
lock("Session::getLanguage");
|
||
if (!mLanguageCatalog.isNull()) {
|
||
lang = mLanguageCatalog->getLanguage();
|
||
}
|
||
unlock();
|
||
return lang;
|
||
}
|
||
|
||
|
||
/*
|
||
SESSION_STATE_CRYPTO_KEY_GENERATED,
|
||
SESSION_STATE_USER_WRITTEN,
|
||
SESSION_STATE_EMAIL_VERIFICATION_WRITTEN,
|
||
SESSION_STATE_EMAIL_VERIFICATION_SEND,
|
||
SESSION_STATE_EMAIL_VERIFICATION_CODE_CHECKED,
|
||
SESSION_STATE_PASSPHRASE_GENERATED,
|
||
SESSION_STATE_PASSPHRASE_SHOWN,
|
||
SESSION_STATE_PASSPHRASE_WRITTEN,
|
||
SESSION_STATE_KEY_PAIR_GENERATED,
|
||
SESSION_STATE_KEY_PAIR_WRITTEN,
|
||
SESSION_STATE_COUNT
|
||
*/
|
||
void Session::detectSessionState()
|
||
{
|
||
if (!mSessionUser || !mSessionUser->hasCryptoKey()) {
|
||
return;
|
||
}
|
||
UserStates userState = mSessionUser->getUserState();
|
||
|
||
int checkEmail = -1, resetPasswd = -1;
|
||
try {
|
||
auto emailVerificationCodeObjects = controller::EmailVerificationCode::load(mSessionUser->getDBId());
|
||
|
||
for (int i = 0; i < emailVerificationCodeObjects.size(); i++) {
|
||
auto type = emailVerificationCodeObjects[i]->getModel()->getType();
|
||
if (type == model::table::EMAIL_OPT_IN_EMPTY || type == model::table::EMAIL_OPT_IN_REGISTER) {
|
||
checkEmail = i;
|
||
}
|
||
else if (type == model::table::EMAIL_OPT_IN_RESET_PASSWORD) {
|
||
resetPasswd = i;
|
||
}
|
||
}
|
||
|
||
if (resetPasswd != -1) {
|
||
mEmailVerificationCodeObject = emailVerificationCodeObjects[resetPasswd];
|
||
}
|
||
else if (checkEmail != -1) {
|
||
mEmailVerificationCodeObject = emailVerificationCodeObjects[checkEmail];
|
||
}
|
||
|
||
}
|
||
catch (Poco::Exception& ex) {
|
||
printf("[Session::detectSessionState] exception: %s\n", ex.displayText().data());
|
||
//return;
|
||
}
|
||
|
||
if (userState <= USER_EMAIL_NOT_ACTIVATED) {
|
||
|
||
if (checkEmail != -1) {
|
||
updateState(SESSION_STATE_EMAIL_VERIFICATION_WRITTEN);
|
||
return;
|
||
}
|
||
|
||
updateState(SESSION_STATE_USER_WRITTEN);
|
||
return;
|
||
}
|
||
|
||
if (USER_NO_KEYS == userState) {
|
||
|
||
auto user_id = mSessionUser->getDBId();
|
||
auto userBackups = controller::UserBackups::load(user_id);
|
||
|
||
// check passphrase, only possible while passphrase isn't crypted in db
|
||
bool correctPassphraseFound = false;
|
||
// always trigger SESSION_STATE_PASSPHRASE_WRITTEN, else lost of data possible
|
||
bool cryptedPassphrase = userBackups.size() > 0;
|
||
for (auto it = userBackups.begin(); it != userBackups.end(); it++) {
|
||
KeyPair keys;
|
||
auto passphrase = (*it)->getModel()->getPassphrase();
|
||
Mnemonic* wordSource = nullptr;
|
||
if (User::validatePassphrase(passphrase, &wordSource)) {
|
||
if (keys.generateFromPassphrase((*it)->getModel()->getPassphrase().data(), wordSource)) {
|
||
if (sodium_memcmp(mSessionUser->getPublicKey(), keys.getPublicKey(), ed25519_pubkey_SIZE) == 0) {
|
||
correctPassphraseFound = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
cryptedPassphrase = true;
|
||
}
|
||
}
|
||
/*
|
||
auto dbConnection = ConnectionManager::getInstance()->getConnection(CONNECTION_MYSQL_LOGIN_SERVER);
|
||
Poco::Data::Statement select(dbConnection);
|
||
Poco::Nullable<Poco::Data::BLOB> passphrase;
|
||
|
||
select << "SELECT passphrase from user_backups where user_id = ?;",
|
||
into(passphrase), use(user_id);
|
||
try {
|
||
if (select.execute() == 1 && !passphrase.isNull()) {
|
||
//KeyPair keys;keys.generateFromPassphrase(passphrase.value().rawContent())
|
||
updateState(SESSION_STATE_PASSPHRASE_WRITTEN);
|
||
return;
|
||
}
|
||
}
|
||
catch (Poco::Exception& exc) {
|
||
printf("[Session::detectSessionState] 2 mysql exception: %s\n", exc.displayText().data());
|
||
}*/
|
||
if (correctPassphraseFound || cryptedPassphrase) {
|
||
updateState(SESSION_STATE_PASSPHRASE_WRITTEN);
|
||
return;
|
||
}
|
||
if (mPassphrase != "") {
|
||
updateState(SESSION_STATE_PASSPHRASE_GENERATED);
|
||
return;
|
||
}
|
||
updateState(SESSION_STATE_EMAIL_VERIFICATION_CODE_CHECKED);
|
||
return;
|
||
}
|
||
|
||
updateState(SESSION_STATE_KEY_PAIR_WRITTEN);
|
||
|
||
if (resetPasswd != -1) {
|
||
// don't go to reset password screen after login, only throw checkEmail
|
||
//updateState(SESSION_STATE_RESET_PASSWORD_REQUEST);
|
||
return;
|
||
}
|
||
|
||
}
|
||
|
||
Poco::Net::HTTPCookie Session::getLoginCookie()
|
||
{
|
||
auto keks = Poco::Net::HTTPCookie("GRADIDO_LOGIN", std::to_string(mHandleId));
|
||
// prevent reading or changing cookie with js
|
||
keks.setHttpOnly();
|
||
keks.setPath("/");
|
||
// send cookie only via https, on linux, except in test builds
|
||
#ifndef WIN32
|
||
if (ServerConfig::SERVER_TYPE_PRODUCTION == ServerConfig::g_ServerSetupType ||
|
||
ServerConfig::SERVER_TYPE_STAGING == ServerConfig::g_ServerSetupType) {
|
||
keks.setSecure(true);
|
||
}
|
||
#endif
|
||
|
||
return keks;
|
||
}
|
||
|
||
bool Session::loadFromEmailVerificationCode(Poco::UInt64 emailVerificationCode)
|
||
{
|
||
Profiler usedTime;
|
||
auto em = ErrorManager::getInstance();
|
||
|
||
mEmailVerificationCodeObject = controller::EmailVerificationCode::load(emailVerificationCode);
|
||
if (mEmailVerificationCodeObject.isNull()) {
|
||
addError(new Error(gettext("E-Mail Verification"), gettext("Konnte kein passendes Konto finden.")));
|
||
return false;
|
||
}
|
||
|
||
mNewUser = controller::User::create();
|
||
mNewUser->load(mEmailVerificationCodeObject->getModel()->getUserId());
|
||
if (mNewUser->getModel()->errorCount() > 0) {
|
||
mNewUser->getModel()->sendErrorsAsEmail();
|
||
addError(new Error(gettext("E-Mail Verification"), gettext("Fehler beim laden des Benutzers.")));
|
||
return false;
|
||
}
|
||
mSessionUser = new User(mNewUser);
|
||
mSessionUser->setLanguage(getLanguage());
|
||
|
||
auto verificationType = mEmailVerificationCodeObject->getModel()->getType();
|
||
if (verificationType == model::table::EMAIL_OPT_IN_RESET_PASSWORD) {
|
||
updateState(SESSION_STATE_RESET_PASSWORD_REQUEST);
|
||
}
|
||
else {
|
||
updateState(SESSION_STATE_EMAIL_VERIFICATION_WRITTEN);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
void Session::updateState(SessionStates newState)
|
||
{
|
||
lock("Session::updateState");
|
||
if (!mActive) {
|
||
unlock();
|
||
return;
|
||
}
|
||
updateTimeout();
|
||
//printf("[%s] newState: %s\n", __FUNCTION__, translateSessionStateToString(newState));
|
||
if (newState > mState) {
|
||
mState = newState;
|
||
}
|
||
|
||
unlock();
|
||
}
|
||
|
||
const char* Session::getSessionStateString()
|
||
{
|
||
SessionStates state;
|
||
lock("Session::getSessionStateString");
|
||
state = mState;
|
||
unlock();
|
||
return translateSessionStateToString(state);
|
||
}
|
||
|
||
|
||
const char* Session::translateSessionStateToString(SessionStates state)
|
||
{
|
||
switch (state) {
|
||
case SESSION_STATE_EMPTY: return "uninitalized";
|
||
case SESSION_STATE_CRYPTO_KEY_GENERATED: return "crpyto key generated";
|
||
case SESSION_STATE_USER_WRITTEN: return "User saved";
|
||
case SESSION_STATE_EMAIL_VERIFICATION_WRITTEN: return "E-Mail verification code saved";
|
||
case SESSION_STATE_EMAIL_VERIFICATION_SEND: return "Verification E-Mail sended";
|
||
case SESSION_STATE_EMAIL_VERIFICATION_CODE_CHECKED: return "Verification Code checked";
|
||
case SESSION_STATE_PASSPHRASE_GENERATED: return "Passphrase generated";
|
||
case SESSION_STATE_PASSPHRASE_SHOWN: return "Passphrase shown";
|
||
case SESSION_STATE_PASSPHRASE_WRITTEN: return "Passphrase written";
|
||
case SESSION_STATE_KEY_PAIR_GENERATED: return "Gradido Address created";
|
||
case SESSION_STATE_KEY_PAIR_WRITTEN: return "Gradido Address saved";
|
||
case SESSION_STATE_RESET_PASSWORD_REQUEST: return "Passwort reset requested";
|
||
case SESSION_STATE_RESET_PASSWORD_SUCCEED: return "Passwort reset succeeded";
|
||
default: return "unknown";
|
||
}
|
||
|
||
return "error";
|
||
}
|
||
|
||
|
||
/*
|
||
bool Session::useOrGeneratePassphrase(const std::string& passphase)
|
||
{
|
||
if (passphase != "" && User::validatePassphrase(passphase)) {
|
||
// passphrase is valid
|
||
setPassphrase(passphase);
|
||
updateState(SESSION_STATE_PASSPHRASE_SHOWN);
|
||
return true;
|
||
}
|
||
else {
|
||
mPassphrase = User::generateNewPassphrase(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]);
|
||
updateState(SESSION_STATE_PASSPHRASE_GENERATED);
|
||
return true;
|
||
}
|
||
}
|
||
*/
|
||
bool Session::generatePassphrase()
|
||
{
|
||
if (mNewUser.isNull()) return false;
|
||
|
||
auto lang = getLanguage();
|
||
if (lang == LANG_EN) {
|
||
mPassphrase = User::generateNewPassphrase(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER]);
|
||
}
|
||
else {
|
||
mPassphrase = User::generateNewPassphrase(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]);
|
||
}
|
||
//mPassphrase = User::generateNewPassphrase(&ServerConfig::g_Mnemonic_WordLists[ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER]);
|
||
updateState(SESSION_STATE_PASSPHRASE_GENERATED);
|
||
return true;
|
||
}
|
||
|
||
bool Session::generateKeys(bool savePrivkey, bool savePassphrase)
|
||
{
|
||
if (mNewUser.isNull()) {
|
||
addError(new Error(gettext("Benutzer"), gettext("Kein gültiger Benutzer, bitte logge dich erneut ein.")));
|
||
return false;
|
||
}
|
||
static const char* function_name = "Session::generateKeys";
|
||
auto lang = getLanguage();
|
||
auto user_model = mNewUser->getModel();
|
||
auto mnemonic_type = ServerConfig::MNEMONIC_BIP0039_SORTED_ORDER;
|
||
/*if (LANG_DE == lang) {
|
||
mnemonic_type = ServerConfig::MNEMONIC_GRADIDO_BOOK_GERMAN_RANDOM_ORDER_FIXED_CASES;
|
||
}*/
|
||
|
||
auto passphrase = Passphrase::generate(&ServerConfig::g_Mnemonic_WordLists[mnemonic_type]);
|
||
if (!passphrase) {
|
||
addError(new ParamError(function_name, "Error generating passphrase with mnemonic: ", mnemonic_type));
|
||
addError(new ParamError(function_name, "user email: ", mNewUser->getModel()->getEmail()));
|
||
sendErrorsAsEmail();
|
||
addError(new Error(gettext("Benutzer"), gettext("Fehler beim generieren der Passphrase, der Admin bekommt eine E-Mail. ")));
|
||
return false;
|
||
}
|
||
|
||
if (savePassphrase) {
|
||
auto user_backup = controller::UserBackups::create(user_model->getID(), passphrase->getString(), mnemonic_type);
|
||
// sync version
|
||
//user_backup->getModel()->insertIntoDB(false);
|
||
|
||
// async version
|
||
UniLib::controller::TaskPtr save_user_backup_task = new model::table::ModelInsertTask(user_backup->getModel(), false, true);
|
||
save_user_backup_task->setFinishCommand(new SessionStateUpdateCommand(SESSION_STATE_PASSPHRASE_WRITTEN, this));
|
||
save_user_backup_task->scheduleTask(save_user_backup_task);
|
||
}
|
||
|
||
// keys
|
||
auto gradido_key_pair = KeyPairEd25519::create(passphrase);
|
||
auto set_key_result = mNewUser->setGradidoKeyPair(gradido_key_pair);
|
||
size_t result_save_key = 0;
|
||
if (1 == set_key_result && savePrivkey) {
|
||
// save public key and private key in db
|
||
result_save_key = user_model->updatePubkeyAndPrivkey();
|
||
}
|
||
else {
|
||
// save public key in db
|
||
result_save_key = user_model->updatePublickey();
|
||
}
|
||
if (!result_save_key) {
|
||
user_model->addError(new Error(function_name, "Error saving new generated pubkey"));
|
||
user_model->addError(new ParamError(function_name, "e-mail: ", user_model->getEmail()));
|
||
user_model->sendErrorsAsEmail();
|
||
addError(new Error(gettext("Benutzer"), gettext("Fehler beim Speichern der Keys, der Admin bekommt eine E-Mail. Evt. nochmal versuchen oder abwarten!")));
|
||
return false;
|
||
}
|
||
return true;
|
||
/*
|
||
|
||
bool validUser = true;
|
||
if (mSessionUser) {
|
||
if (!mSessionUser->generateKeys(savePrivkey, mPassphrase, this)) {
|
||
validUser = false;
|
||
}
|
||
else {
|
||
if (savePassphrase) {
|
||
//printf("[Session::generateKeys] create save passphrase task\n");
|
||
UniLib::controller::TaskPtr savePassphrase(new WritePassphraseIntoDB(mSessionUser->getDBId(), mPassphrase));
|
||
savePassphrase->setFinishCommand(new SessionStateUpdateCommand(SESSION_STATE_PASSPHRASE_WRITTEN, this));
|
||
savePassphrase->scheduleTask(savePassphrase);
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
validUser = false;
|
||
}
|
||
if (!validUser) {
|
||
addError(new Error(gettext("Benutzer"), gettext("Kein gültiger Benutzer, bitte logge dich erneut ein.")));
|
||
return false;
|
||
}
|
||
// delete passphrase after all went well
|
||
mPassphrase.clear();
|
||
|
||
return true;
|
||
*/
|
||
}
|