Lot of password related changes all over the place.
Password is no longer saved with the connection list. Password is not entered along with other connection credentials. Password is now asked for when required. Still working on saving the password and auto retrieving it from the password manager.
This commit is contained in:
parent
6b9b602c64
commit
2230a4bd61
21 changed files with 508 additions and 195 deletions
|
|
@ -16,7 +16,7 @@ class BackupDialog : public QDialog
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BackupDialog(QWidget *parent = 0);
|
||||
explicit BackupDialog(QWidget *parent = nullptr);
|
||||
~BackupDialog();
|
||||
|
||||
void ConnectTo(QProcess *process);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "ConnectionList.h"
|
||||
#include "ScopeGuard.h"
|
||||
#include "util.h"
|
||||
#include "PasswordManager.h"
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
#include <QSettings>
|
||||
|
|
@ -19,31 +20,38 @@ namespace {
|
|||
settings.setValue("hostaddr", stdStrToQ(cc.hostAddr()));
|
||||
settings.setValue("port", cc.port());
|
||||
settings.setValue("user", stdStrToQ(cc.user()));
|
||||
settings.setValue("password", stdStrToQ(cc.password()));
|
||||
//settings.setValue("password", stdStrToQ(cc.password()));
|
||||
settings.setValue("dbname", stdStrToQ(cc.dbname()));
|
||||
settings.setValue("sslmode", (int)cc.sslMode());
|
||||
settings.setValue("sslmode", static_cast<int>(cc.sslMode()));
|
||||
settings.setValue("sslcert", stdStrToQ(cc.sslCert()));
|
||||
settings.setValue("sslkey", stdStrToQ(cc.sslKey()));
|
||||
settings.setValue("sslrootcert", stdStrToQ(cc.sslRootCert()));
|
||||
settings.setValue("sslcrl", stdStrToQ(cc.sslCrl()));
|
||||
}
|
||||
|
||||
template <typename S, typename T>
|
||||
bool in_range(T value)
|
||||
{
|
||||
return value >= std::numeric_limits<S>::min() && value <= std::numeric_limits<S>::max();
|
||||
}
|
||||
|
||||
void LoadConnectionConfig(QSettings &settings, ConnectionConfig &cc)
|
||||
{
|
||||
cc.setName(qvarToStdStr(settings.value("name")));
|
||||
cc.setHost(qvarToStdStr(settings.value("host")));
|
||||
cc.setHostAddr(qvarToStdStr(settings.value("hostaddr")));
|
||||
cc.setPort(settings.value("port", 5432).toInt());
|
||||
int p = settings.value("port", 5432).toInt();
|
||||
if (!in_range<uint16_t>(p)) {
|
||||
p = 0; // let the user re-enter a valid value
|
||||
}
|
||||
|
||||
cc.setPort(static_cast<uint16_t>(p));
|
||||
cc.setUser(qvarToStdStr(settings.value("user")));
|
||||
// std::string encpw = qvarToStdStr(settings.value("encryptedpw"));
|
||||
// if (encpw.empty()) {
|
||||
cc.setPassword(qvarToStdStr(settings.value("password")));
|
||||
// }
|
||||
// else {
|
||||
// cc.setEncryptedPassword(encpw);
|
||||
// }
|
||||
|
||||
//cc.setPassword(qvarToStdStr(settings.value("password")));
|
||||
|
||||
cc.setDbname(qvarToStdStr(settings.value("dbname")));
|
||||
cc.setSslMode((SslMode)settings.value("sslmode").toInt());
|
||||
cc.setSslMode(static_cast<SslMode>(settings.value("sslmode").toInt()));
|
||||
cc.setSslCert(qvarToStdStr(settings.value("sslcert")));
|
||||
cc.setSslKey(qvarToStdStr(settings.value("sslkey")));
|
||||
cc.setSslRootCert(qvarToStdStr(settings.value("sslrootcert")));
|
||||
|
|
@ -69,19 +77,20 @@ QString ConnectionList::iniFileName()
|
|||
|
||||
ConnectionList::ConnectionList()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int ConnectionList::createNew()
|
||||
size_t ConnectionList::createNew()
|
||||
{
|
||||
m_connections.emplace_back(QUuid::createUuid(), ConnectionConfig());
|
||||
ConnectionConfig cc;
|
||||
cc.setUuid(QUuid::createUuid());
|
||||
m_connections.push_back(cc);
|
||||
return m_connections.size()-1;
|
||||
}
|
||||
|
||||
void ConnectionList::remove(int idx, int count)
|
||||
void ConnectionList::remove(size_t idx, size_t count)
|
||||
{
|
||||
auto f = m_connections.begin() + idx;
|
||||
auto l = f + count;
|
||||
auto f = m_connections.begin() + static_cast<int>(idx);
|
||||
auto l = f + static_cast<int>(count);
|
||||
deleteFromIni(f, l);
|
||||
m_connections.erase(f, l);
|
||||
}
|
||||
|
|
@ -91,7 +100,7 @@ void ConnectionList::deleteFromIni(t_Connections::iterator begin, t_Connections:
|
|||
QString file_name = iniFileName();
|
||||
QSettings settings(file_name, QSettings::IniFormat);
|
||||
for (auto i = begin; i != end; ++i) {
|
||||
settings.remove(i->m_uuid.toString());
|
||||
settings.remove(i->uuid().toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -111,8 +120,9 @@ void ConnectionList::load()
|
|||
SCOPE_EXIT { settings.endGroup(); };
|
||||
|
||||
ConnectionConfig cc;
|
||||
cc.setUuid(uuid);
|
||||
LoadConnectionConfig(settings, cc);
|
||||
m_connections.emplace_back(uuid, cc);
|
||||
m_connections.push_back(cc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -123,26 +133,24 @@ void ConnectionList::save()
|
|||
QString file_name = iniFileName();
|
||||
QSettings settings(file_name, QSettings::IniFormat);
|
||||
for (auto& e : m_connections) {
|
||||
settings.beginGroup(e.m_uuid.toString());
|
||||
settings.beginGroup(e.uuid().toString());
|
||||
SCOPE_EXIT { settings.endGroup(); };
|
||||
|
||||
SaveConnectionConfig(settings, e.m_config);
|
||||
e.m_config.clean();
|
||||
SaveConnectionConfig(settings, e);
|
||||
e.clean();
|
||||
}
|
||||
settings.sync();
|
||||
}
|
||||
|
||||
void ConnectionList::save(int index)
|
||||
void ConnectionList::save(size_t index)
|
||||
{
|
||||
if (index >= 0 && index < (int)m_connections.size()) {
|
||||
auto& e = m_connections[index];
|
||||
if (e.m_config.dirty()) {
|
||||
auto& e = m_connections.at(index);
|
||||
if (e.dirty()) {
|
||||
QString file_name = iniFileName();
|
||||
QSettings settings(file_name, QSettings::IniFormat);
|
||||
settings.beginGroup(e.m_uuid.toString());
|
||||
SaveConnectionConfig(settings, e.m_config);
|
||||
e.m_config.clean();
|
||||
settings.beginGroup(e.uuid().toString());
|
||||
SaveConnectionConfig(settings, e);
|
||||
e.clean();
|
||||
settings.sync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,47 +8,42 @@
|
|||
#include <vector>
|
||||
#include "Expected.h"
|
||||
|
||||
|
||||
class ConnectionList {
|
||||
private:
|
||||
static QString iniFileName();
|
||||
|
||||
public:
|
||||
|
||||
ConnectionList();
|
||||
int size() const { return m_connections.size(); }
|
||||
size_t size() const { return m_connections.size(); }
|
||||
|
||||
ConnectionConfig& getConfigByIdx(int idx)
|
||||
ConnectionConfig& getConfigByIdx(size_t idx)
|
||||
{
|
||||
return m_connections.at(idx).m_config;
|
||||
return m_connections.at(idx);
|
||||
}
|
||||
|
||||
int createNew();
|
||||
size_t createNew();
|
||||
|
||||
void remove(int idx, int count);
|
||||
void remove(size_t idx, size_t count);
|
||||
|
||||
void load();
|
||||
void save();
|
||||
void save(int index);
|
||||
|
||||
void save(size_t index);
|
||||
|
||||
private:
|
||||
class LijstElem {
|
||||
public:
|
||||
QUuid m_uuid;
|
||||
ConnectionConfig m_config;
|
||||
// class LijstElem {
|
||||
// public:
|
||||
// QUuid m_uuid; ///< Unique identifier, used as a key for storing password in psk db.
|
||||
// ConnectionConfig m_config;
|
||||
|
||||
LijstElem(const QUuid id, const ConnectionConfig &cfg)
|
||||
: m_uuid(id), m_config(cfg)
|
||||
{}
|
||||
};
|
||||
// LijstElem(const QUuid id, const ConnectionConfig &cfg)
|
||||
// : m_uuid(id), m_config(cfg)
|
||||
// {}
|
||||
// };
|
||||
|
||||
using t_Connections = std::vector<LijstElem>;
|
||||
using t_Connections = std::vector<ConnectionConfig>;
|
||||
t_Connections m_connections;
|
||||
|
||||
void deleteFromIni(t_Connections::iterator begin, t_Connections::iterator end);
|
||||
|
||||
|
||||
static QString iniFileName();
|
||||
};
|
||||
|
||||
#endif // CONNECTIONLIST_H
|
||||
|
|
|
|||
|
|
@ -150,6 +150,27 @@ Expected<ConnectionConfig> ConnectionListModel::get(int row)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
template <typename T>
|
||||
size_t as_size_t(T t);
|
||||
|
||||
template <>
|
||||
size_t as_size_t(int t)
|
||||
{
|
||||
BOOST_ASSERT(t >= 0);
|
||||
return static_cast<size_t>(t);
|
||||
}
|
||||
|
||||
template <>
|
||||
size_t as_size_t(long t)
|
||||
{
|
||||
BOOST_ASSERT(t >= 0);
|
||||
return static_cast<size_t>(t);
|
||||
}
|
||||
|
||||
|
||||
//void ConnectionListModel::del(const int idx)
|
||||
bool ConnectionListModel::removeRows(int row, int count, const QModelIndex &parent)
|
||||
{
|
||||
|
|
@ -159,7 +180,7 @@ bool ConnectionListModel::removeRows(int row, int count, const QModelIndex &pare
|
|||
beginRemoveRows(parent, row, row + count -1);
|
||||
SCOPE_EXIT { endRemoveRows(); };
|
||||
|
||||
m_connections->remove(row, count);
|
||||
m_connections->remove(as_size_t(row), as_size_t(count));
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
|
|
@ -176,7 +197,12 @@ void ConnectionListModel::save()
|
|||
m_connections->save();
|
||||
}
|
||||
|
||||
void ConnectionListModel::save(int index)
|
||||
void ConnectionListModel::save(size_t index)
|
||||
{
|
||||
m_connections->save(index);
|
||||
}
|
||||
|
||||
void ConnectionListModel::save(size_t index, const ConnectionConfig &cc)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,13 +34,14 @@ public:
|
|||
virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
|
||||
void save();
|
||||
void save(int index);
|
||||
void save(size_t index);
|
||||
void save(size_t index, const ConnectionConfig &cc);
|
||||
static QString makeLongDescription(const ConnectionConfig &cfg);
|
||||
private:
|
||||
|
||||
ConnectionList *m_connections;
|
||||
|
||||
|
||||
static QString makeLongDescription(const ConnectionConfig &cfg);
|
||||
};
|
||||
|
||||
#endif // CONNECTIONLISTMODEL_H
|
||||
|
|
|
|||
|
|
@ -7,6 +7,21 @@
|
|||
#include <QStandardItemModel>
|
||||
#include "ConnectionListModel.h"
|
||||
|
||||
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
|
||||
QString pskFileName()
|
||||
{
|
||||
QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
QDir dir(path);
|
||||
if (!dir.exists()) {
|
||||
dir.mkpath(".");
|
||||
}
|
||||
path += "/psk.ini";
|
||||
return path;
|
||||
}
|
||||
|
||||
ConnectionManagerWindow::ConnectionManagerWindow(MasterController *master, QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
, ui(new Ui::ConnectionManagerWindow)
|
||||
|
|
@ -53,9 +68,13 @@ void ConnectionManagerWindow::on_currentChanged(const QModelIndex ¤t,
|
|||
{
|
||||
int currow = current.row();
|
||||
auto clm = m_masterController->getConnectionListModel();
|
||||
clm->save(prevSelection);
|
||||
if (prevSelection)
|
||||
clm->save(*prevSelection);
|
||||
m_mapper->setCurrentIndex(currow);
|
||||
prevSelection = currow;
|
||||
if (currow >= 0)
|
||||
prevSelection = static_cast<size_t>(currow);
|
||||
else
|
||||
prevSelection.reset();
|
||||
}
|
||||
|
||||
void ConnectionManagerWindow::on_actionDelete_connection_triggered()
|
||||
|
|
@ -82,7 +101,6 @@ void ConnectionManagerWindow::setupWidgetMappings()
|
|||
m_mapper->addMapping(ui->edtHost, 2);
|
||||
m_mapper->addMapping(ui->spinPort, 3);
|
||||
m_mapper->addMapping(ui->edtUser, 4);
|
||||
m_mapper->addMapping(ui->edtPassword, 5);
|
||||
m_mapper->addMapping(ui->edtDbname, 6);
|
||||
m_mapper->toFirst();
|
||||
}
|
||||
|
|
@ -90,7 +108,13 @@ void ConnectionManagerWindow::setupWidgetMappings()
|
|||
void ConnectionManagerWindow::on_actionConnect_triggered()
|
||||
{
|
||||
auto ci = ui->listView->selectionModel()->currentIndex();
|
||||
m_masterController->openSqlWindowForConnection(ci.row());
|
||||
if (ci.isValid()) {
|
||||
auto r = static_cast<size_t>(ci.row());
|
||||
m_masterController->openSqlWindowForConnection(r);
|
||||
}
|
||||
else {
|
||||
// TODO can we give unobtrusive message why it didn't work?
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionManagerWindow::on_actionQuit_application_triggered()
|
||||
|
|
@ -117,68 +141,3 @@ void ConnectionManagerWindow::on_actionManage_server_triggered()
|
|||
}
|
||||
|
||||
|
||||
|
||||
#include <botan/botan.h>
|
||||
//#include <botan/base64.h>
|
||||
//#include <botan/pbkdf.h>
|
||||
//#include <botan/block_cipher.h>
|
||||
//#include <botan/hex.h>
|
||||
#include <botan/cryptobox.h>
|
||||
|
||||
|
||||
void ConnectionManagerWindow::on_testButton_clicked()
|
||||
{
|
||||
std::string error = Botan::runtime_version_check(BOTAN_VERSION_MAJOR,
|
||||
BOTAN_VERSION_MINOR,
|
||||
BOTAN_VERSION_PATCH);
|
||||
if (error.empty()) {
|
||||
// Botan::AutoSeeded_RNG rng;
|
||||
// Botan::secure_vector<Botan::byte> salt =
|
||||
// //{ 0x3f, 0x0a, 0xb0, 0x11, 0x44, 0xfe, 0x9d, 0xf7, 0x85, 0xd3, 0x11, 0x38, 0xe2, 0xdf, 0x31, 0x42 };
|
||||
// rng.random_vec(16);
|
||||
// // salt should be random and saved with encrypted data so it can be used when we decrypt
|
||||
|
||||
// std::string password = "Hello kitty";
|
||||
// std::unique_ptr<Botan::PBKDF> pbkdf(Botan::get_pbkdf("PBKDF2(SHA-256)"));
|
||||
// Botan::OctetString aes256_key = pbkdf->derive_key(32, password, salt.data(), salt.size(), 10000);
|
||||
|
||||
// std::string plaintext("Your great-grandfather gave this watch to your granddad for good luck. Unfortunately, Dane's luck wasn't as good as his old man's.");
|
||||
// Botan::secure_vector<uint8_t> pt(plaintext.data(),plaintext.data()+plaintext.length());
|
||||
|
||||
// std::unique_ptr<Botan::Cipher_Mode> enc(Botan::get_cipher_mode("AES-256/CBC/PKCS7", Botan::ENCRYPTION));
|
||||
// enc->set_key(aes256_key);
|
||||
|
||||
// //generate fresh nonce (IV)
|
||||
// //std::unique_ptr<Botan::RandomNumberGenerator> rng(new Botan::AutoSeeded_RNG);
|
||||
// std::vector<uint8_t> iv(enc->default_nonce_length());
|
||||
// rng.randomize(iv.data(), iv.size());
|
||||
// enc->start(iv);
|
||||
// enc->finish(pt);
|
||||
// //std::cout << std::endl << enc->name() << " with iv " << Botan::hex_encode(iv) << std::endl << Botan::hex_encode(pt);
|
||||
|
||||
|
||||
//std::string s = aes256_key.as_string();// + "\n" + t.format_string();
|
||||
|
||||
std::string passphrase = "my passphrase";
|
||||
std::string plaintext("password1234");
|
||||
try {
|
||||
Botan::AutoSeeded_RNG rng;
|
||||
std::string encrypted = Botan::CryptoBox::encrypt((const uint8_t*)plaintext.data(), plaintext.length(), passphrase, rng);
|
||||
|
||||
std::string decrypted = Botan::CryptoBox::decrypt(encrypted, passphrase);
|
||||
|
||||
std::string s = encrypted + "\n" + decrypted;
|
||||
QMessageBox::information(this, "pglab",
|
||||
QString::fromUtf8(s.c_str()), QMessageBox::Yes);
|
||||
}
|
||||
catch (Botan::Decoding_Error &/*e*/) {
|
||||
QMessageBox::information(this, "pglab",
|
||||
tr("Failure to decrypt"), QMessageBox::Yes);
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
QMessageBox ::information(this, "pglab",
|
||||
QString::fromUtf8(error.c_str()), QMessageBox::Yes);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define CONNECTIONMANAGERWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
namespace Ui {
|
||||
class ConnectionManagerWindow;
|
||||
|
|
@ -30,14 +31,12 @@ private slots:
|
|||
void on_actionBackup_database_triggered();
|
||||
void on_actionManage_server_triggered();
|
||||
|
||||
void on_testButton_clicked();
|
||||
|
||||
private:
|
||||
Ui::ConnectionManagerWindow *ui;
|
||||
QDataWidgetMapper *m_mapper = nullptr;
|
||||
MasterController *m_masterController;
|
||||
|
||||
int prevSelection = -1;
|
||||
boost::optional<size_t> prevSelection;
|
||||
|
||||
void setupWidgetMappings();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -75,30 +75,23 @@
|
|||
<widget class="QLineEdit" name="edtUser"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="edtPassword">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Database</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="edtDbname"/>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>SSL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="cmbbxSsl">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
|
|
@ -136,53 +129,46 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>SSL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Certificate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="6" column="1">
|
||||
<widget class="QLineEdit" name="edtCert"/>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Key</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="7" column="1">
|
||||
<widget class="QLineEdit" name="edtKey"/>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Root cert.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<item row="8" column="1">
|
||||
<widget class="QLineEdit" name="edtRootCert"/>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Revocation list</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<item row="9" column="1">
|
||||
<widget class="QLineEdit" name="edtCrl"/>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<item row="10" column="0">
|
||||
<widget class="QPushButton" name="testButton">
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
|
|
@ -201,7 +187,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>25</height>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "MainWindow.h"
|
||||
#include "ServerWindow.h"
|
||||
#include "BackupDialog.h"
|
||||
#include "PasswordPromptDialog.h"
|
||||
|
||||
|
||||
MasterController::MasterController(QObject *parent) : QObject(parent)
|
||||
|
|
@ -33,39 +34,103 @@ void MasterController::showConnectionManager()
|
|||
m_connectionManagerWindow->show();
|
||||
}
|
||||
|
||||
void MasterController::openSqlWindowForConnection(int connection_index)
|
||||
void MasterController::openSqlWindowForConnection(size_t connection_index)
|
||||
{
|
||||
auto cc = m_connectionListModel->get(connection_index);
|
||||
m_connectionListModel->save(connection_index);
|
||||
if (cc.valid()) {
|
||||
|
||||
auto res = m_connectionListModel->get(connection_index);
|
||||
if (res.valid()) {
|
||||
auto cc = res.get();
|
||||
|
||||
m_connectionListModel->save(connection_index, cc);
|
||||
if (retrieveConnectionPassword(cc)) {
|
||||
// TODO instead of directly openening the mainwindow
|
||||
// do async connect and only open window when we have
|
||||
// working connection
|
||||
auto w = new MainWindow(this, nullptr);
|
||||
w->setAttribute( Qt::WA_DeleteOnClose );
|
||||
w->setConfig(cc.get());
|
||||
w->setConfig(cc);
|
||||
w->show();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MasterController::openBackupDlgForConnection(int connection_index)
|
||||
{
|
||||
auto cc = m_connectionListModel->get(connection_index);
|
||||
m_connectionListModel->save(connection_index);
|
||||
if (cc.valid()) {
|
||||
auto res = m_connectionListModel->get(connection_index);
|
||||
if (res.valid()) {
|
||||
auto cc = res.get();
|
||||
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.get());
|
||||
w->setConfig(cc);
|
||||
w->show();
|
||||
}
|
||||
}
|
||||
|
||||
void MasterController::openServerWindowForConnection(int connection_index)
|
||||
{
|
||||
auto cc = m_connectionListModel->get(connection_index);
|
||||
m_connectionListModel->save(connection_index);
|
||||
if (cc.valid()) {
|
||||
auto res = m_connectionListModel->get(connection_index);
|
||||
if (res.valid()) {
|
||||
auto cc = res.get();
|
||||
retrieveConnectionPassword(cc);
|
||||
m_connectionListModel->save(connection_index, cc);
|
||||
|
||||
auto w = new ServerWindow(this, nullptr);
|
||||
w->setAttribute( Qt::WA_DeleteOnClose );
|
||||
w->setConfig(cc.get());
|
||||
w->setConfig(cc);
|
||||
w->show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool MasterController::retrieveConnectionPassword(ConnectionConfig &cc)
|
||||
{
|
||||
// Look at config
|
||||
// - is password required, how do we know?
|
||||
// - IF is password stored in pskdb
|
||||
// - ask pskdb for password
|
||||
// - ELSE
|
||||
// - ask user for password
|
||||
QString str = ConnectionListModel::makeLongDescription(cc);
|
||||
auto dlg = std::make_unique<PasswordPromptDialog>(nullptr);
|
||||
dlg->setConnectionDescription(str);
|
||||
int exec_result = dlg->exec();
|
||||
|
||||
if (exec_result == QDialog::Accepted) {
|
||||
cc.setPassword(dlg->password().toUtf8().data());
|
||||
// - IF user checked remember password
|
||||
// - ask pskdb to store password
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool MasterController::getPasswordFromPskdb(const std::string &password_id, std::string &password)
|
||||
{
|
||||
// func: getPasswordFromPskdb
|
||||
// IF pskdb locked
|
||||
// prompt user for pskdb passphrase
|
||||
// unlock pskdb
|
||||
// get pwd
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool MasterController::storePasswordInPskdb(const std::string &password_id, const std::string password)
|
||||
{
|
||||
// func: storePasswordInPskdb
|
||||
// IF pskdb not setup
|
||||
// notify user and ask for passphrase
|
||||
// init pskdb
|
||||
// ELSE
|
||||
// IF pskdb locked
|
||||
// ask for passphrase
|
||||
// unlock
|
||||
// store pwd
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class ConnectionManagerWindow;
|
|||
class MasterController : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MasterController(QObject *parent = 0);
|
||||
explicit MasterController(QObject *parent = nullptr);
|
||||
MasterController(const MasterController&) = delete;
|
||||
MasterController &operator=(const MasterController&) = delete;
|
||||
~MasterController();
|
||||
|
|
@ -29,7 +29,7 @@ public:
|
|||
}
|
||||
|
||||
void showConnectionManager();
|
||||
void openSqlWindowForConnection(int connection_index);
|
||||
void openSqlWindowForConnection(size_t connection_index);
|
||||
void openServerWindowForConnection(int connection_index);
|
||||
void openBackupDlgForConnection(int connection_index);
|
||||
|
||||
|
|
@ -42,6 +42,14 @@ private:
|
|||
ConnectionListModel *m_connectionListModel = nullptr;
|
||||
ConnectionManagerWindow *m_connectionManagerWindow = nullptr;
|
||||
|
||||
/** Retrieves the connection password from the user (directly or through the psk db)
|
||||
*
|
||||
*/
|
||||
bool retrieveConnectionPassword(ConnectionConfig &cc);
|
||||
|
||||
bool getPasswordFromPskdb(const std::string &password_id, std::string &password);
|
||||
|
||||
bool storePasswordInPskdb(const std::string &password_id, const std::string password);
|
||||
};
|
||||
|
||||
#endif // MASTERCONTROLLER_H
|
||||
|
|
|
|||
45
pglab/PassPhraseForm.cpp
Normal file
45
pglab/PassPhraseForm.cpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#include "PassPhraseForm.h"
|
||||
#include "ui_PassPhraseForm.h"
|
||||
|
||||
PassPhraseForm::PassPhraseForm(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::PassPhraseForm)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
PassPhraseForm::~PassPhraseForm()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Password strength calculation:
|
||||
seperate characters in couple of groups
|
||||
|
||||
For the use of characters from each group a certain value is added to the base value
|
||||
which is meant to signify the size of the set of characters the password is based on.
|
||||
|
||||
Some analysis of relative positions might be required! Predictable placement of special charachters and uppercase/lowercase or numbers
|
||||
should be penalized.
|
||||
|
||||
These calculations should result in a search space size per character
|
||||
|
||||
the base to the power of the length of the password gives the resulting strength
|
||||
from this result we take the 10 log to get the magnitude of the value.
|
||||
|
||||
a-z 1:3 2:7 3:13 4:26
|
||||
A-Z 1:3 2:7 3:13 4:26
|
||||
0-9 1:4 2:10
|
||||
`~!@#$%^&*()_-=+[{]};:'",<.>/?\| 1:4 2:8 3:16 4:32
|
||||
space +1
|
||||
|
||||
Straf punten
|
||||
alleen speciaal karakter aan eind van string -8
|
||||
alleen hoofdletter aan begin van wachtwoord -6
|
||||
|
||||
la-~ZDv4E-O*y]C
|
||||
bYGWlDyeKKbcZBjoWX
|
||||
|
||||
*/
|
||||
22
pglab/PassPhraseForm.h
Normal file
22
pglab/PassPhraseForm.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef PASSPHRASEFORM_H
|
||||
#define PASSPHRASEFORM_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class PassPhraseForm;
|
||||
}
|
||||
|
||||
class PassPhraseForm : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PassPhraseForm(QWidget *parent = nullptr);
|
||||
~PassPhraseForm();
|
||||
|
||||
private:
|
||||
Ui::PassPhraseForm *ui;
|
||||
};
|
||||
|
||||
#endif // PASSPHRASEFORM_H
|
||||
75
pglab/PassPhraseForm.ui
Normal file
75
pglab/PassPhraseForm.ui
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PassPhraseForm</class>
|
||||
<widget class="QWidget" name="PassPhraseForm">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>397</width>
|
||||
<height>228</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="horizontalSpacing">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Enter passphrase:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit">
|
||||
<property name="maxLength">
|
||||
<number>32767</number>
|
||||
</property>
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::NoEcho</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Repeat passphrase:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_2">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
<number>67</number>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
70
pglab/PasswordPromptDialog.cpp
Normal file
70
pglab/PasswordPromptDialog.cpp
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#include "PasswordPromptDialog.h"
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QCheckBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLabel>
|
||||
#include <QLayout>
|
||||
#include <QLineEdit>
|
||||
|
||||
PasswordPromptDialog::PasswordPromptDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
m_connectionLabel = new QLabel(this);
|
||||
auto dialog_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
|
||||
|
||||
m_passwordLabel = new QLabel(this);
|
||||
m_passwordInput = new QLineEdit(this);
|
||||
m_passwordInput->setEchoMode(QLineEdit::Password);
|
||||
|
||||
m_saveCheck = new QCheckBox(this);
|
||||
|
||||
|
||||
auto mainLayout = new QGridLayout;
|
||||
int row = 0;
|
||||
mainLayout->addWidget(m_connectionLabel, row, 0, 1, 2);
|
||||
++row;
|
||||
mainLayout->addWidget(m_passwordLabel, row, 0);
|
||||
mainLayout->addWidget(m_passwordInput, row, 1);
|
||||
++row;
|
||||
mainLayout->addWidget(m_saveCheck, row, 1);
|
||||
++row;
|
||||
mainLayout->addWidget(dialog_buttons, row, 0, 1 ,2);
|
||||
setLayout(mainLayout);
|
||||
|
||||
m_passwordInput->setFocus();
|
||||
retranslateUi();
|
||||
|
||||
// QMetaObject::connectSlotsByName(BackupDialog);
|
||||
connect(dialog_buttons, &QDialogButtonBox::accepted, this, &PasswordPromptDialog::accept);
|
||||
connect(dialog_buttons, &QDialogButtonBox::rejected, this, &PasswordPromptDialog::reject);
|
||||
}
|
||||
|
||||
void PasswordPromptDialog::retranslateUi()
|
||||
{
|
||||
const char * context = "PasswordPromptDialog";
|
||||
setWindowTitle(QApplication::translate(context, "Connection password", nullptr));
|
||||
m_passwordLabel->setText(QApplication::translate(context, "Password", nullptr));
|
||||
m_passwordInput->setPlaceholderText(QApplication::translate(context, "Enter password", nullptr));
|
||||
m_saveCheck->setText(QApplication::translate(context, "Save password", nullptr));
|
||||
}
|
||||
|
||||
void PasswordPromptDialog::setConnectionDescription(const QString &description)
|
||||
{
|
||||
m_connectionLabel->setText(QString(tr("Please provide password for connection %1")).arg(description));
|
||||
|
||||
}
|
||||
|
||||
QString PasswordPromptDialog::password() const
|
||||
{
|
||||
return m_passwordInput->text();
|
||||
}
|
||||
|
||||
//void PasswordPromptDialog::accept()
|
||||
//{
|
||||
|
||||
//}
|
||||
|
||||
//void PasswordPromptDialog::reject()
|
||||
//{
|
||||
|
||||
//}
|
||||
32
pglab/PasswordPromptDialog.h
Normal file
32
pglab/PasswordPromptDialog.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef PASSWORDPROMPTDIALOG_H
|
||||
#define PASSWORDPROMPTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class QCheckBox;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
|
||||
class PasswordPromptDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PasswordPromptDialog(QWidget *parent = nullptr);
|
||||
|
||||
void setConnectionDescription(const QString &description);
|
||||
|
||||
QString password() const;
|
||||
private:
|
||||
QLabel *m_connectionLabel = nullptr;
|
||||
QLabel *m_passwordLabel = nullptr;
|
||||
QLineEdit *m_passwordInput = nullptr;
|
||||
QCheckBox *m_saveCheck = nullptr;
|
||||
|
||||
void retranslateUi();
|
||||
|
||||
private slots:
|
||||
// void accept();
|
||||
// void reject();
|
||||
};
|
||||
|
||||
#endif // PASSWORDPROMPTDIALOG_H
|
||||
|
|
@ -26,14 +26,10 @@ TablesPage::TablesPage(MainWindow *parent)
|
|||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
// WARNING delegates should NOT be shared!!!
|
||||
auto pglab_delegate = new PgLabItemDelegate(this);
|
||||
auto icon_delegate = new IconColumnDelegate(this);
|
||||
|
||||
SetTableViewDefault(ui->tableListTable);
|
||||
m_tablesModel = new TablesTableModel(this);
|
||||
ui->tableListTable->setModel(m_tablesModel);
|
||||
ui->tableListTable->setItemDelegate(pglab_delegate);
|
||||
ui->tableListTable->setItemDelegate(new PgLabItemDelegate(this));
|
||||
ui->tableListTable->setSortingEnabled(true);
|
||||
ui->tableListTable->sortByColumn(0, Qt::AscendingOrder);
|
||||
ui->tableListTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
|
|
@ -47,14 +43,14 @@ TablesPage::TablesPage(MainWindow *parent)
|
|||
SetTableViewDefault(ui->constraintsTable);
|
||||
m_constraintModel = new ConstraintModel(this);
|
||||
ui->constraintsTable->setModel(m_constraintModel);
|
||||
ui->constraintsTable->setItemDelegateForColumn(0, icon_delegate);
|
||||
ui->constraintsTable->setItemDelegateForColumn(0, new IconColumnDelegate(this));
|
||||
|
||||
// Indexes
|
||||
SetTableViewDefault(ui->indexesTable);
|
||||
m_indexModel = new IndexModel(this);
|
||||
ui->indexesTable->setModel(m_indexModel);
|
||||
ui->indexesTable->setItemDelegate(pglab_delegate);
|
||||
ui->indexesTable->setItemDelegateForColumn(0, icon_delegate);
|
||||
ui->indexesTable->setItemDelegate(new PgLabItemDelegate(this));
|
||||
ui->indexesTable->setItemDelegateForColumn(0, new IconColumnDelegate(this));
|
||||
|
||||
// Set code editor fonts
|
||||
QFont code_font = UserConfiguration::instance()->codeFont();
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ DEFINES += _WIN32_WINNT=0x0501
|
|||
#LIBS += -LC:\VSproj\boost32\lib -LC:/PROG/LIB -lws2_32 -llibpq
|
||||
|
||||
#debug {
|
||||
LIBS += c:/prog/lib/botand_imp.lib
|
||||
LIBS += c:/prog/lib/botan_imp.lib
|
||||
#}
|
||||
|
||||
#release {
|
||||
|
|
@ -83,7 +83,9 @@ PropertyProxyModel.cpp \
|
|||
TriggerPage.cpp \
|
||||
SqlCodePreview.cpp \
|
||||
CustomFilterSortModel.cpp \
|
||||
PropertiesPage.cpp
|
||||
PropertiesPage.cpp \
|
||||
PassPhraseForm.cpp \
|
||||
PasswordPromptDialog.cpp
|
||||
|
||||
HEADERS += \
|
||||
QueryResultModel.h \
|
||||
|
|
@ -137,7 +139,9 @@ CustomDataRole.h \
|
|||
TriggerPage.h \
|
||||
SqlCodePreview.h \
|
||||
CustomFilterSortModel.h \
|
||||
PropertiesPage.h
|
||||
PropertiesPage.h \
|
||||
PassPhraseForm.h \
|
||||
PasswordPromptDialog.h
|
||||
|
||||
FORMS += mainwindow.ui \
|
||||
ConnectionManagerWindow.ui \
|
||||
|
|
@ -151,7 +155,8 @@ FORMS += mainwindow.ui \
|
|||
NamespaceFilterWidget.ui \
|
||||
ApplicationWindow.ui \
|
||||
CrudTab.ui \
|
||||
CodeGenerator.ui
|
||||
CodeGenerator.ui \
|
||||
PassPhraseForm.ui
|
||||
|
||||
RESOURCES += \
|
||||
resources.qrc
|
||||
|
|
|
|||
|
|
@ -57,6 +57,22 @@ ConnectionConfig::ConnectionConfig()
|
|||
: m_applicationName(QCoreApplication::applicationName().toUtf8().data())
|
||||
{}
|
||||
|
||||
|
||||
void ConnectionConfig::setUuid(const QUuid &uuid)
|
||||
{
|
||||
if (uuid != m_uuid) {
|
||||
m_dirty = true;
|
||||
m_uuid = uuid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const QUuid &ConnectionConfig::uuid() const
|
||||
{
|
||||
return m_uuid;
|
||||
}
|
||||
|
||||
|
||||
void ConnectionConfig::setName(std::string desc)
|
||||
{
|
||||
if (m_name != desc) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef CONNECTION_H
|
||||
#define CONNECTION_H
|
||||
|
||||
#include <QUuid>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -27,6 +28,9 @@ class ConnectionConfig {
|
|||
public:
|
||||
ConnectionConfig();
|
||||
|
||||
void setUuid(const QUuid &uuid);
|
||||
const QUuid &uuid() const;
|
||||
|
||||
void setName(std::string desc);
|
||||
const std::string& name() const;
|
||||
|
||||
|
|
@ -73,6 +77,7 @@ public:
|
|||
bool dirty() const;
|
||||
void clean();
|
||||
private:
|
||||
QUuid m_uuid;
|
||||
std::string m_name;
|
||||
std::string m_host;
|
||||
std::string m_hostaddr;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += widgets
|
||||
QT += widgets core
|
||||
|
||||
TARGET = pglablib
|
||||
TEMPLATE = lib
|
||||
|
|
|
|||
0
readme.md
Normal file
0
readme.md
Normal file
Loading…
Add table
Add a link
Reference in a new issue