diff --git a/pglab/ConnectionConfigurationWidget.cpp b/pglab/ConnectionConfigurationWidget.cpp index 2230c40..00bab32 100644 --- a/pglab/ConnectionConfigurationWidget.cpp +++ b/pglab/ConnectionConfigurationWidget.cpp @@ -24,10 +24,11 @@ #define SET_OBJECT_NAME(var) var->setObjectName(#var) -void ConnectionConfigurationWidget::editExistingInWindow(ConnectionController *ctrl, const ConnectionConfig &cfg) +void ConnectionConfigurationWidget::editExistingInWindow(ConnectionController *connection_controller, const ConnectionConfig &cfg, + std::function save_func) { try { - auto w = new ConnectionConfigurationWidget(ctrl->getConnectionTreeModel()); + auto w = new ConnectionConfigurationWidget(connection_controller); w->setData(cfg); auto btn_hbox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal); @@ -41,12 +42,13 @@ void ConnectionConfigurationWidget::editExistingInWindow(ConnectionController *c win->setLayout(vbox); win->setAttribute( Qt::WA_DeleteOnClose, true ); - QObject::connect(btn_hbox, &QDialogButtonBox::accepted, [ctrl, w, win] () { - auto cc = w->data(); - auto grp = w->group(); - ctrl->getConnectionTreeModel()->save(grp, cc); - win->accept(); - }); + QObject::connect(btn_hbox, &QDialogButtonBox::accepted, [w, win, save_func] () { +// auto cc = w->data(); +// auto grp = w->group(); +// connection_controller->getConnectionTreeModel()->save(grp, cc); + save_func(*w); + win->accept(); + }); QObject::connect(btn_hbox, &QDialogButtonBox::rejected, [win] () { win->reject(); @@ -59,13 +61,14 @@ void ConnectionConfigurationWidget::editExistingInWindow(ConnectionController *c } } -ConnectionConfigurationWidget::ConnectionConfigurationWidget(ConnectionTreeModel *connection_model, QWidget *parent) +ConnectionConfigurationWidget::ConnectionConfigurationWidget(ConnectionController *connection_controller, QWidget *parent) : QWidget(parent) - , m_connectionModel(connection_model) + , m_connectionController(connection_controller) + , m_connectionModel(connection_controller->getConnectionTreeModel()) { lblGroup = new QLabel; cmbbxGroup = new QComboBox; - cmbbxGroup->setModel(connection_model); + cmbbxGroup->setModel(m_connectionModel); cmbbxGroup->setModelColumn(0); lblGroup->setBuddy(cmbbxGroup); @@ -202,12 +205,16 @@ void ConnectionConfigurationWidget::setData(const ConnectionConfig &cfg) edtHost->setText(cfg.host()); spinPort->setValue(cfg.port()); edtUser->setText(cfg.user()); + edtPassword->setText(""); + cmbDbname->setCurrentText(cfg.dbname()); cmbbxSsl->setCurrentIndex(static_cast(cfg.sslMode())); edtCert->setText(cfg.sslCert()); edtKey->setText(cfg.sslKey()); edtRootCert->setText(cfg.sslRootCert()); edtCrl->setText(cfg.sslCrl()); + + encodedPassword = cfg.encodedPassword(); } ConnectionConfig ConnectionConfigurationWidget::data() const @@ -225,6 +232,7 @@ ConnectionConfig ConnectionConfigurationWidget::data() const cfg.setSslKey(edtKey->text()); cfg.setSslRootCert(edtRootCert->text()); cfg.setSslCrl(edtCrl->text()); + cfg.setEncodedPassword(encodedPassword); // this could be old, it will be overriden later when there is a new password to save. return cfg; } @@ -233,9 +241,20 @@ QString ConnectionConfigurationWidget::group() const return cmbbxGroup->currentText(); } +bool ConnectionConfigurationWidget::savePassword() const +{ + return cbSavePassword->isChecked() && !edtPassword->text().isEmpty(); +} + void ConnectionConfigurationWidget::testConnection() { + QString password = edtPassword->text(); + if (password.isEmpty() && !encodedPassword.isEmpty()) { + m_connectionController->decodeConnectionPassword(m_uuid, encodedPassword, password); + } + auto cc = data(); + cc.setPassword(password); QFuture result = QtConcurrent::run([cc] { return TestConnection(cc); }); TestWatcher.setFuture(result); } diff --git a/pglab/ConnectionConfigurationWidget.h b/pglab/ConnectionConfigurationWidget.h index ca2b4f0..05f3b39 100644 --- a/pglab/ConnectionConfigurationWidget.h +++ b/pglab/ConnectionConfigurationWidget.h @@ -25,23 +25,27 @@ class ConnectionConfigurationWidget : public QWidget { Q_OBJECT public: - static void editExistingInWindow(ConnectionController *ctrl, const ConnectionConfig &cfg); + static void editExistingInWindow(ConnectionController *ctrl, const ConnectionConfig &cfg, + std::function save_func); - explicit ConnectionConfigurationWidget(ConnectionTreeModel *connection_model, QWidget *parent = nullptr); + explicit ConnectionConfigurationWidget(ConnectionController *connection_controller, QWidget *parent = nullptr); void retranslateUi(); void setData(const ConnectionConfig &cfg); ConnectionConfig data() const; QString group() const; + bool savePassword() const; signals: public slots: void testConnection(); private: + ConnectionController *m_connectionController; ConnectionTreeModel *m_connectionModel; QUuid m_uuid; + QByteArray encodedPassword; QLabel *lblGroup; QComboBox *cmbbxGroup; @@ -73,7 +77,9 @@ private: QLabel *lblResult; QFormLayout *formLayout; + QFutureWatcher TestWatcher; + private slots: void handleTestResult(); }; diff --git a/pglab/ConnectionController.cpp b/pglab/ConnectionController.cpp index b75358d..3fbd619 100644 --- a/pglab/ConnectionController.cpp +++ b/pglab/ConnectionController.cpp @@ -83,14 +83,14 @@ void ConnectionController::createConnection() { ConnectionConfig cc; cc.setUuid(QUuid::createUuid()); - ConnectionConfigurationWidget::editExistingInWindow(this, cc); + ConnectionConfigurationWidget::editExistingInWindow(this, cc, [this] (ConnectionConfigurationWidget &w) -> void { saveConnection(w); }); } void ConnectionController::editConnection(QModelIndex index) { auto config = ConnectionTreeModel::getConfigFromModelIndex(index); if (config) { - ConnectionConfigurationWidget::editExistingInWindow(this, *config); + ConnectionConfigurationWidget::editExistingInWindow(this, *config, [this] (ConnectionConfigurationWidget &w) -> void { saveConnection(w); }); } } @@ -100,10 +100,20 @@ void ConnectionController::editCopy(QModelIndex index) if (config) { auto cc = *config; cc.setUuid(QUuid::createUuid()); - ConnectionConfigurationWidget::editExistingInWindow(this, cc); + ConnectionConfigurationWidget::editExistingInWindow(this, cc, [this] (ConnectionConfigurationWidget &w) -> void { saveConnection(w); }); } } +void ConnectionController::saveConnection(ConnectionConfigurationWidget &w) +{ + auto cc = w.data(); + auto grp = w.group(); + if (w.savePassword()) { + encryptPassword(cc); + } + m_connectionTreeModel->save(grp, cc); +} + void ConnectionController::addGroup() { auto result = QInputDialog::getText(nullptr, tr("Add new connection group"), @@ -142,8 +152,8 @@ bool ConnectionController::retrieveConnectionPassword(ConnectionConfig &cc) auto enc_pwd = cc.encodedPassword(); if (!enc_pwd.isEmpty()) { std::string pw; - bool result = decodePassword(getPskId(cc), - std::string_view(enc_pwd.data(), enc_pwd.size()) , pw);// getPasswordFromPskdb(getPskId(cc), pw); + bool result = retrieveFromPasswordManager(getPskId(cc.uuid()), + std::string_view(enc_pwd.data(), enc_pwd.size()) , pw); if (result) { cc.setPassword(QString::fromUtf8(pw.data(), pw.size())); return true; @@ -161,19 +171,14 @@ bool ConnectionController::retrieveConnectionPassword(ConnectionConfig &cc) auto password = dlg->password(); cc.setPassword(password); if (dlg->saveChecked()) { - auto ba = password.toUtf8(); - std::string pw(ba.data(), static_cast(ba.size())); - std::string encoded_pw; - if (encodePassword(getPskId(cc), pw, encoded_pw)) { - cc.setEncodedPassword({ encoded_pw.data(), static_cast(encoded_pw.size()) }); - } + encryptPassword(cc); } return true; } return false; } -bool ConnectionController::decodePassword(const std::string &password_id, const std::string_view &enc_password, std::string &password) +bool ConnectionController::retrieveFromPasswordManager(const std::string &password_id, const std::string_view &enc_password, std::string &password) { if (!UnlockPasswordManagerIfNeeded()) return false; @@ -182,13 +187,27 @@ bool ConnectionController::decodePassword(const std::string &password_id, const return true; } -bool ConnectionController::encodePassword(const std::string &password_id, const std::string &password, std::string &enc_password) +bool ConnectionController::encryptPassword(ConnectionConfig &cc) { - if (!UnlockPasswordManagerIfNeeded()) - return false; + if (!UnlockPasswordManagerIfNeeded()) + return false; - enc_password = m_passwordManager->encrypt(password_id, password); - return true; + std::string password = cc.password().toStdString(); + std::string password_id = getPskId(cc.uuid()); + std::string enc_password = m_passwordManager->encrypt(password_id, password); + cc.setEncodedPassword({ enc_password.data(), static_cast(enc_password.size()) }); + return true; +} + +bool ConnectionController::decodeConnectionPassword(QUuid id, QByteArray encoded, QString &out_password) +{ + std::string password_id = getPskId(id); + std::string enc(encoded.data(), encoded.size()); + std::string password; + bool res = retrieveFromPasswordManager(password_id, enc, password); + if (res) + out_password = QString::fromStdString(password); + return res; } bool ConnectionController::UnlockPasswordManagerIfNeeded() @@ -236,13 +255,13 @@ bool ConnectionController::UnlockPasswordManagerIfNeeded() return true; } } - return false; + return false; } -std::string ConnectionController::getPskId(const ConnectionConfig &cc) +std::string ConnectionController::getPskId(QUuid connectionid) { std::string id = "dbpw/"; - id += cc.uuid().toString().toUtf8().data(); + id += connectionid.toString().toUtf8().data(); return id; } diff --git a/pglab/ConnectionController.h b/pglab/ConnectionController.h index 7057bdf..d19a93c 100644 --- a/pglab/ConnectionController.h +++ b/pglab/ConnectionController.h @@ -6,6 +6,7 @@ class MasterController; class ConnectionConfig; +class ConnectionConfigurationWidget; class ConnectionList; class ConnectionTreeModel; class ConnectionManagerWindow; @@ -40,6 +41,14 @@ public: void removeGroup(QModelIndex index); std::shared_ptr passwordManager(); + /** Retrieves the connection password from the user (directly or through the psk db) + * + */ + bool retrieveConnectionPassword(ConnectionConfig &cc); + + bool UnlockPasswordManagerIfNeeded(); + + bool decodeConnectionPassword(QUuid id, QByteArray encoded, QString &out_password); private: MasterController *m_masterController; ConnectionList *m_connectionList = nullptr; @@ -52,21 +61,15 @@ private: */ std::shared_ptr m_passwordManager; - /** Retrieves the connection password from the user (directly or through the psk db) - * - */ - bool retrieveConnectionPassword(ConnectionConfig &cc); + bool retrieveFromPasswordManager(const std::string &password_id, const std::string_view &enc_password, std::string &password); +// bool updatePasswordManager(const std::string &password_id, const std::string &password, std::string &enc_password); - bool decodePassword(const std::string &password_id, const std::string_view &enc_password, std::string &password); - bool encodePassword(const std::string &password_id, const std::string &password, std::string &enc_password); + /// Expects the plaintext password to be the password that needs encoding. + bool encryptPassword(ConnectionConfig &cc); - /// - /// - /// \return bool: succeeded, int: relock timeout - /// - bool UnlockPasswordManagerIfNeeded(); + static std::string getPskId(QUuid connectionid); - static std::string getPskId(const ConnectionConfig &cc); + void saveConnection(ConnectionConfigurationWidget &w); private slots: void relock(); }; diff --git a/pglablib/ConnectionConfig.cpp b/pglablib/ConnectionConfig.cpp index 808a521..be56ab7 100644 --- a/pglablib/ConnectionConfig.cpp +++ b/pglablib/ConnectionConfig.cpp @@ -133,7 +133,7 @@ void ConnectionConfig::setUser(const QString& v) { if (m_user != v) { m_dirty = true; - m_user = std::move(v); + m_user = v; } } @@ -147,7 +147,7 @@ void ConnectionConfig::setPassword(const QString& v) { if (m_password != v) { m_dirty = true; - m_password = std::move(v); + m_password = v; } } @@ -160,7 +160,7 @@ void ConnectionConfig::setDbname(const QString& v) { if (m_dbname != v) { m_dirty = true; - m_dbname = std::move(v); + m_dbname = v; } } @@ -298,15 +298,15 @@ void ConnectionConfig::setEncodedPassword(const QByteArray &encodedPassword) m_encodedPassword = encodedPassword; } -void ConnectionConfig::write(QDataStream &out) const -{ -// out << -} +//void ConnectionConfig::write(QDataStream &out) const +//{ +//// out << +//} -void ConnectionConfig::read(QDataStream &in) -{ +//void ConnectionConfig::read(QDataStream &in) +//{ -} +//} QString ConnectionConfig::escapeConnectionStringValue(const QString &value) { @@ -465,15 +465,15 @@ void ConnectionGroup::update(int idx, const ConnectionConfig &cc) node->setParent(this); } -QDataStream &operator<<(QDataStream &out, const ConnectionConfig &cc) -{ - cc.write(out); - return out; -} +//QDataStream &operator<<(QDataStream &out, const ConnectionConfig &cc) +//{ +// cc.write(out); +// return out; +//} -QDataStream &operator>>(QDataStream &in, ConnectionConfig &cc) -{ - //in>>myObj.uId>>myObj.passwd>>myObj.statusType; - cc.read(in); - return in; -} +//QDataStream &operator>>(QDataStream &in, ConnectionConfig &cc) +//{ +// //in>>myObj.uId>>myObj.passwd>>myObj.statusType; +// cc.read(in); +// return in; +//} diff --git a/pglablib/ConnectionConfig.h b/pglablib/ConnectionConfig.h index 260087b..5e5a9c4 100644 --- a/pglablib/ConnectionConfig.h +++ b/pglablib/ConnectionConfig.h @@ -121,8 +121,8 @@ public: QByteArray encodedPassword() const; void setEncodedPassword(const QByteArray &encodedPassword); - void write(QDataStream &out) const; - void read(QDataStream &in); +// void write(QDataStream &out) const; +// void read(QDataStream &in); /** Escapes a value for inclusion in a keyword value connection string. * @@ -164,9 +164,9 @@ private: Q_DECLARE_METATYPE(ConnectionConfig) -QDataStream &operator<<(QDataStream &out, const ConnectionConfig &cc); +//QDataStream &operator<<(QDataStream &out, const ConnectionConfig &cc); -QDataStream &operator>>(QDataStream &in, ConnectionConfig &cc); +//QDataStream &operator>>(QDataStream &in, ConnectionConfig &cc); #endif // CONNECTION_H