Added the capability to reset the password manager

Also some documentation about the password manager.
This commit is contained in:
eelke 2022-09-05 07:33:08 +02:00
parent f8528143ac
commit 4fa2189b27
17 changed files with 233 additions and 85 deletions

View file

@ -6,7 +6,9 @@
#include "DatabaseWindow.h"
#include "BackupDialog.h"
#include "PasswordPromptDialog.h"
#include "ScopeGuard.h"
#include "ConnectionConfigurationWidget.h"
#include <QSqlQuery>
#include <QInputDialog>
#include <QMessageBox>
#include <QTimer>
@ -156,33 +158,36 @@ std::shared_ptr<PasswordManager> ConnectionController::passwordManager()
bool ConnectionController::retrieveConnectionPassword(ConnectionConfig &cc)
{
auto enc_pwd = cc.encodedPassword();
if (!enc_pwd.isEmpty()) {
std::string pw;
auto enc_pwd = cc.encodedPassword();
if (!enc_pwd.isEmpty())
{
std::string 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;
}
}
// 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 (result)
{
cc.setPassword(QString::fromUtf8(pw.data(), pw.size()));
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) {
auto password = dlg->password();
cc.setPassword(password);
if (dlg->saveChecked()) {
if (exec_result == QDialog::Accepted)
{
auto password = dlg->password();
cc.setPassword(password);
if (dlg->saveChecked())
encryptPassword(cc);
}
return true;
}
return false;
return true;
}
return false;
}
bool ConnectionController::retrieveFromPasswordManager(const std::string &password_id, const std::string_view &enc_password, std::string &password)
@ -224,29 +229,48 @@ bool ConnectionController::decodeConnectionPassword(QUuid id, QByteArray encoded
return res;
}
void ConnectionController::resetPasswordManager()
{
auto&& user_cfg_db = m_masterController->userConfigDatabase();
user_cfg_db.transaction();
try
{
m_passwordManager->resetMasterPassword(user_cfg_db);
m_connectionTreeModel->clearAllPasswords();
user_cfg_db.commit();
}
catch (...)
{
user_cfg_db.rollback();
throw;
}
}
bool ConnectionController::UnlockPasswordManagerIfNeeded()
{
auto&& user_cfg_db = m_masterController->userConfigDatabase();
if (m_passwordManager->initialized(user_cfg_db)) {
if (!m_passwordManager->locked())
return true;
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
while (true)
{
PassphraseResult pp_result = PassphrasePrompt();
if (!pp_result.success)
break; // 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, pp_result.passphrase)) {
// user gave OK, if succeeds return true otherwise loop a prompt for password again.
if (m_passwordManager->openDatabase(user_cfg_db, pp_result.passphrase))
{
setRelockTimer(pp_result.rememberForMinutes);
return true;
}
}
}
else {
return true;
}
}
}
else
InitializePasswordManager();
}
return false;
}

View file

@ -12,6 +12,7 @@ class ConnectionTreeModel;
class ConnectionManagerWindow;
class PasswordManager;
class QTimer;
class QSqlDatabase;
class PassphraseResult {
@ -58,6 +59,7 @@ public:
bool UnlockPasswordManagerIfNeeded();
bool decodeConnectionPassword(QUuid id, QByteArray encoded, QString &out_password);
void resetPasswordManager();
private:
MasterController *m_masterController;
ConnectionList *m_connectionList = nullptr;
@ -71,7 +73,6 @@ private:
std::shared_ptr<PasswordManager> m_passwordManager;
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);
/// Expects the plaintext password to be the password that needs encoding.
bool encryptPassword(ConnectionConfig &cc);

View file

@ -351,7 +351,17 @@ void ConnectionTreeModel::save(const QString &group_name, const ConnectionConfig
void ConnectionTreeModel::save(const ConnectionConfig &cc)
{
saveToDb(cc);
saveToDb(cc);
}
void ConnectionTreeModel::clearAllPasswords()
{
for (auto group : m_groups)
for (auto cc : group->connections())
{
cc->setEncodedPassword({});
saveToDb(*cc);
}
}
std::tuple<int, int> ConnectionTreeModel::findConfig(const QUuid uuid) const

View file

@ -59,6 +59,7 @@ public:
/** Save changed config, group is not allowed to change
*/
void save(const ConnectionConfig &cc);
void clearAllPasswords();
/// Create a new group in the DB and place in the tree
std::variant<int, QSqlError> addGroup(const QString &group_name);
std::optional<QSqlError> removeGroup(int row);

View file

@ -115,3 +115,15 @@ void ConnectionManagerWindow::on_actionManual_triggered()
QDesktopServices::openUrl(QString("https://eelke.gitlab.io/pgLab/#pglab-user-manual"));
}
void ConnectionManagerWindow::on_actionReset_password_manager_triggered()
{
auto warning_response = QMessageBox::warning(this, "pgLab", tr(
"Warning you are about to reset the password manager master passwords "
"all stored passwords will be lost! Are you shure you wish to continue?"),
QMessageBox::Yes | QMessageBox::No);
if (warning_response == QMessageBox::Yes)
m_connectionController->resetPasswordManager();
}

View file

@ -43,6 +43,8 @@ private slots:
void on_actionManual_triggered();
void on_actionReset_password_manager_triggered();
private:
Ui::ConnectionManagerWindow *ui;
MasterController *m_masterController;

View file

@ -33,11 +33,18 @@
<property name="title">
<string>Fi&amp;le</string>
</property>
<addaction name="actionAbout"/>
<addaction name="actionManual"/>
<addaction name="actionReset_password_manager"/>
<addaction name="actionQuit_application"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>Help</string>
</property>
<addaction name="actionManual"/>
<addaction name="actionAbout"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="toolBar">
@ -181,6 +188,11 @@ QToolButton {
<string>Manual</string>
</property>
</action>
<action name="actionReset_password_manager">
<property name="text">
<string>Reset password manager</string>
</property>
</action>
</widget>
<resources>
<include location="resources.qrc"/>