#include "MasterController.h" #include "ConnectionManagerWindow.h" #include "ConnectionList.h" #include "ConnectionListModel.h" #include "PasswordManager.h" #include "DatabaseWindow.h" #include "ServerWindow.h" #include "BackupDialog.h" #include "PasswordPromptDialog.h" #include #include #include #include namespace { QString GetUserConfigDatabaseName() { QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); QDir dir(path); if (!dir.exists()) { dir.mkpath("."); } path += "/pglabuser.db"; return path; } } MasterController::MasterController(QObject *parent) : QObject(parent) {} MasterController::~MasterController() { delete m_connectionManagerWindow; delete m_connectionListModel; delete m_connectionList; } void MasterController::init() { //std::string dbfilename = QDir::toNativeSeparators(GetUserConfigDatabaseName()).toUtf8().data(); //m_userConfigDatabase = std::make_shared(dbfilename); m_userConfigDatabase = QSqlDatabase::addDatabase("QSQLITE"); m_userConfigDatabase.setDatabaseName(GetUserConfigDatabaseName()); if (!m_userConfigDatabase.open()) { qDebug() << "Error: connection with database fail"; } else { qDebug() << "Database: connection ok"; } m_passwordManager = std::make_shared(); m_connectionList = new ConnectionList; m_connectionList->load(); m_connectionListModel = new ConnectionListModel(m_connectionList, this); m_connectionManagerWindow = new ConnectionManagerWindow(this, nullptr); m_connectionManagerWindow->show(); } void MasterController::showConnectionManager() { m_connectionManagerWindow->show(); } void MasterController::openSqlWindowForConnection(size_t connection_index) { auto res = m_connectionListModel->get(connection_index); if (res.valid()) { auto cc = res.get(); if (retrieveConnectionPassword(cc)) { m_connectionListModel->save(connection_index, cc); // TODO instead of directly openening the mainwindow // do async connect and only open window when we have // working connection auto w = new DatabaseWindow(this, nullptr); w->setAttribute( Qt::WA_DeleteOnClose ); w->setConfig(cc); w->show(); } } } void MasterController::openBackupDlgForConnection(size_t connection_index) { auto res = m_connectionListModel->get(connection_index); if (res.valid()) { auto cc = res.get(); if (retrieveConnectionPassword(cc)) { m_connectionListModel->save(connection_index, cc); auto w = new BackupDialog(nullptr); //new ServerWindow(this, nullptr); w->setAttribute( Qt::WA_DeleteOnClose ); w->setConfig(cc); w->show(); } } } void MasterController::openServerWindowForConnection(size_t connection_index) { auto res = m_connectionListModel->get(connection_index); if (res.valid()) { auto cc = res.get(); if (retrieveConnectionPassword(cc)) { m_connectionListModel->save(connection_index, cc); auto w = new ServerWindow(this, nullptr); w->setAttribute( Qt::WA_DeleteOnClose ); w->setConfig(cc); w->show(); } } } bool MasterController::retrieveConnectionPassword(ConnectionConfig &cc) { auto pw_state = cc.passwordState(); if (pw_state == PasswordState::NotNeeded) { return true; } else if (pw_state == PasswordState::SavedPasswordManager) { std::string pw; bool result = getPasswordFromPskdb(getPskId(cc), pw); if (result) { cc.setPassword(pw); return true; } } // Geen else hier want als voorgaande blok niet geretourneerd heeft moeten we wachtwoord // ook aan de gebruiker vragen zoals hier gebeurd. QString str = ConnectionListModel::makeLongDescription(cc); auto dlg = std::make_unique(PasswordPromptDialog::SaveOption, nullptr); dlg->setCaption(tr("Connection password prompt")); dlg->setDescription(QString(tr("Please provide password for connection %1")).arg(str)); int exec_result = dlg->exec(); if (exec_result == QDialog::Accepted) { std::string password = dlg->password().toUtf8().data(); cc.setPassword(password); if (dlg->saveChecked()) { storePasswordInPskdb(getPskId(cc), password); cc.setPasswordState(PasswordState::SavedPasswordManager); } return true; } return false; } bool MasterController::getPasswordFromPskdb(const std::string &password_id, std::string &password) { if (!UnlockPasswordManagerIfNeeded()) return false; return m_passwordManager->get(password_id, password); } bool MasterController::storePasswordInPskdb(const std::string &password_id, const std::string password) { if (!UnlockPasswordManagerIfNeeded()) return false; m_passwordManager->set(password_id, password); return true; } bool MasterController::UnlockPasswordManagerIfNeeded() { if (m_passwordManager->initialized(m_userConfigDatabase)) { if (!m_passwordManager->locked()) return true; while (true) { // ask user for passphrase auto dlg = std::make_unique(nullptr, nullptr); dlg->setCaption(tr("Unlock password manager")); dlg->setDescription(tr("Enter password for password manager")); int exec_result = dlg->exec(); bool ok = (exec_result == QDialog::Accepted); if (!ok) { // leave this retry loop break; } // user gave OK, if succeeds return true otherwise loop a prompt for password again. if (m_passwordManager->openDatabase(m_userConfigDatabase, dlg->password())) return true; } } else { // Ask user for passphrase + confirmation, clearly instruct this is first setup // create auto dlg = std::make_unique(PasswordPromptDialog::ConfirmPassword, nullptr); dlg->setCaption(tr("Password manager setup")); dlg->setDescription(tr("Enter a strong password for password manager initialization. A strong key will be " "derived from your password and it will be impossible to recover anything from the " "password manager without the password you enter here.")); int exec_result = dlg->exec(); if (exec_result == QDialog::Accepted) { QString passphrase = dlg->password(); if (m_passwordManager->createDatabase(m_userConfigDatabase, passphrase)) return true; } } return false; } std::string MasterController::getPskId(const ConnectionConfig &cc) { std::string id = "dbpw/"; id += cc.uuid().toString().toUtf8().data(); return id; } //std::shared_ptr MasterController::getUserConfigDatabase() //{ // return m_userConfigDatabase; //}