pgLab/pglab/ConnectionController.cpp

224 lines
6.2 KiB
C++

#include "ConnectionController.h"
#include "MasterController.h"
#include "ConnectionManagerWindow.h"
#include "ConnectionListModel.h"
#include "PasswordManager.h"
#include "DatabaseWindow.h"
#include "ServerWindow.h"
#include "BackupDialog.h"
#include "PasswordPromptDialog.h"
#include "ConnectionConfigurationWidget.h"
ConnectionController::ConnectionController(MasterController *parent)
: QObject(parent)
, m_masterController(parent)
{}
ConnectionController::~ConnectionController()
{
delete m_connectionManagerWindow;
delete m_connectionTreeModel;
}
void ConnectionController::init()
{
//std::string dbfilename = QDir::toNativeSeparators(GetUserConfigDatabaseName()).toUtf8().data();
//m_userConfigDatabase = std::make_shared<Botan::Sqlite3_Database>(dbfilename);
m_passwordManager = std::make_shared<PasswordManager>();
m_connectionTreeModel = new ConnectionTreeModel(this, m_masterController->userConfigDatabase());
m_connectionTreeModel->load();
m_connectionManagerWindow = new ConnectionManagerWindow(m_masterController, nullptr);
m_connectionManagerWindow->show();
}
void ConnectionController::showConnectionManager()
{
m_connectionManagerWindow->show();
}
namespace {
ConnectionConfig* getConfigFromModelIndex(QModelIndex index)
{
if (!index.isValid())
return nullptr;
auto node = static_cast<ConnectionNode*>(index.internalPointer());
return dynamic_cast<ConnectionConfig*>(node);
}
}
void ConnectionController::openSqlWindowForConnection(QModelIndex index)
{
auto config = getConfigFromModelIndex(index);
if (config) {
if (retrieveConnectionPassword(*config)) {
m_connectionTreeModel->save(*config);
// TODO instead of directly openening the mainwindow
// do async connect and only open window when we have
// working connection
auto w = new DatabaseWindow(m_masterController, nullptr);
w->setAttribute( Qt::WA_DeleteOnClose );
w->setConfig(*config);
w->showMaximized();
}
}
}
void ConnectionController::openBackupDlgForConnection(QModelIndex index)
{
auto config = getConfigFromModelIndex(index);
if (config) {
if (retrieveConnectionPassword(*config)) {
m_connectionTreeModel->save(*config);
auto w = new BackupDialog(nullptr); //new ServerWindow(this, nullptr);
w->setAttribute( Qt::WA_DeleteOnClose );
w->setConfig(*config);
w->show();
}
}
}
void ConnectionController::createConnection()
{
ConnectionConfig cc;
cc.setUuid(QUuid::createUuid());
ConnectionConfigurationWidget::editExistingInWindow(this, cc);
}
void ConnectionController::editConnection(QModelIndex index)
{
auto config = getConfigFromModelIndex(index);
if (config) {
ConnectionConfigurationWidget::editExistingInWindow(this, *config);
}
}
void ConnectionController::openServerWindowForConnection(QModelIndex index)
{
auto config = getConfigFromModelIndex(index);
if (config) {
if (retrieveConnectionPassword(*config)) {
m_connectionTreeModel->save(*config);
auto w = new ServerWindow(m_masterController, nullptr);
w->setAttribute( Qt::WA_DeleteOnClose );
w->setConfig(*config);
w->show();
}
}
}
bool ConnectionController::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 = cc.makeLongDescription();
auto dlg = std::make_unique<PasswordPromptDialog>(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 ConnectionController::getPasswordFromPskdb(const std::string &password_id, std::string &password)
{
if (!UnlockPasswordManagerIfNeeded())
return false;
return m_passwordManager->get(password_id, password);
}
bool ConnectionController::storePasswordInPskdb(const std::string &password_id, const std::string password)
{
if (!UnlockPasswordManagerIfNeeded())
return false;
m_passwordManager->set(password_id, password);
return true;
}
bool ConnectionController::UnlockPasswordManagerIfNeeded()
{
auto&& user_cfg_db = m_masterController->userConfigDatabase();
if (m_passwordManager->initialized(user_cfg_db)) {
if (!m_passwordManager->locked())
return true;
while (true) {
// ask user for passphrase
auto dlg = std::make_unique<PasswordPromptDialog>(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(user_cfg_db, dlg->password()))
return true;
}
}
else {
// Ask user for passphrase + confirmation, clearly instruct this is first setup
// create
auto dlg = std::make_unique<PasswordPromptDialog>(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(user_cfg_db, passphrase))
return true;
}
}
return false;
}
std::string ConnectionController::getPskId(const ConnectionConfig &cc)
{
std::string id = "dbpw/";
id += cc.uuid().toString().toUtf8().data();
return id;
}