(m_ui->stackedWidget->currentIndex()) == Page::Edit) {
diff --git a/src/gui/databasekey/KeyComponentWidget.h b/src/gui/databasekey/KeyComponentWidget.h
index 9ea53da960..d207e494de 100644
--- a/src/gui/databasekey/KeyComponentWidget.h
+++ b/src/gui/databasekey/KeyComponentWidget.h
@@ -104,9 +104,6 @@ class KeyComponentWidget : public QWidget
void editCanceled();
void componentRemovalRequested();
-protected:
- void showEvent(QShowEvent* event) override;
-
private slots:
void updateAddStatus(bool added);
void doAdd();
diff --git a/src/gui/databasekey/PasswordEditWidget.cpp b/src/gui/databasekey/PasswordEditWidget.cpp
index 04d63c43d2..e2c34be07f 100644
--- a/src/gui/databasekey/PasswordEditWidget.cpp
+++ b/src/gui/databasekey/PasswordEditWidget.cpp
@@ -27,6 +27,9 @@ PasswordEditWidget::PasswordEditWidget(QWidget* parent)
, m_compUi(new Ui::PasswordEditWidget())
{
initComponent();
+
+ // Explicitly clear password on cancel
+ connect(this, &PasswordEditWidget::editCanceled, this, [this] { setPassword({}); });
}
PasswordEditWidget::~PasswordEditWidget() = default;
@@ -59,7 +62,7 @@ bool PasswordEditWidget::isPasswordVisible() const
bool PasswordEditWidget::isEmpty() const
{
- return (visiblePage() == Page::Edit) && m_compUi->enterPasswordEdit->text().isEmpty();
+ return visiblePage() != Page::Edit || m_compUi->enterPasswordEdit->text().isEmpty();
}
PasswordHealth::Quality PasswordEditWidget::getPasswordQuality() const
@@ -83,8 +86,7 @@ void PasswordEditWidget::initComponentEditWidget(QWidget* widget)
{
Q_UNUSED(widget);
Q_ASSERT(m_compEditWidget);
- m_compUi->enterPasswordEdit->setFocus();
-
+ setFocusProxy(m_compUi->enterPasswordEdit);
m_compUi->enterPasswordEdit->setQualityVisible(true);
m_compUi->repeatPasswordEdit->setQualityVisible(false);
}
@@ -103,16 +105,6 @@ void PasswordEditWidget::initComponent()
"Good passwords are long and unique. KeePassXC can generate one for you.
"));
}
-void PasswordEditWidget::hideEvent(QHideEvent* event)
-{
- if (!isVisible() && m_compUi->enterPasswordEdit) {
- m_compUi->enterPasswordEdit->setText("");
- m_compUi->repeatPasswordEdit->setText("");
- }
-
- QWidget::hideEvent(event);
-}
-
bool PasswordEditWidget::validate(QString& errorMessage) const
{
if (m_compUi->enterPasswordEdit->text() != m_compUi->repeatPasswordEdit->text()) {
diff --git a/src/gui/databasekey/PasswordEditWidget.h b/src/gui/databasekey/PasswordEditWidget.h
index 5e7bb28d61..14dfe1d81d 100644
--- a/src/gui/databasekey/PasswordEditWidget.h
+++ b/src/gui/databasekey/PasswordEditWidget.h
@@ -47,7 +47,6 @@ class PasswordEditWidget : public KeyComponentWidget
QWidget* componentEditWidget() override;
void initComponentEditWidget(QWidget* widget) override;
void initComponent() override;
- void hideEvent(QHideEvent* event) override;
private slots:
void setPassword(const QString& password);
diff --git a/src/gui/dbsettings/DatabaseSettingsDialog.cpp b/src/gui/dbsettings/DatabaseSettingsDialog.cpp
index 14a3032624..4a325ca425 100644
--- a/src/gui/dbsettings/DatabaseSettingsDialog.cpp
+++ b/src/gui/dbsettings/DatabaseSettingsDialog.cpp
@@ -92,36 +92,32 @@ DatabaseSettingsDialog::DatabaseSettingsDialog(QWidget* parent)
scrollArea->setSizeAdjustPolicy(QScrollArea::AdjustToContents);
scrollArea->setWidgetResizable(true);
scrollArea->setWidget(m_databaseKeyWidget);
- m_securityTabWidget->addTab(scrollArea, tr("Database Credentials"));
+ m_securityTabWidget->addTab(scrollArea, tr("Database Credentials"));
m_securityTabWidget->addTab(m_encryptionWidget, tr("Encryption Settings"));
+ m_securityTabWidget->setCurrentIndex(0);
m_ui->categoryList->addCategory(tr("Remote Sync"), icons()->icon("remote-sync"));
m_ui->stackedWidget->addWidget(m_remoteWidget);
-#if defined(WITH_XC_KEESHARE)
- addSettingsPage(new DatabaseSettingsPageKeeShare());
+#ifdef WITH_XC_BROWSER
+ m_ui->categoryList->addCategory(tr("Browser Integration"), icons()->icon("internet-web-browser"));
+ m_ui->stackedWidget->addWidget(m_browserWidget);
#endif
-#if defined(WITH_XC_FDOSECRETS)
- addSettingsPage(new DatabaseSettingsPageFdoSecrets());
+#ifdef WITH_XC_KEESHARE
+ addSettingsPage(new DatabaseSettingsPageKeeShare());
#endif
- m_ui->stackedWidget->setCurrentIndex(0);
- m_securityTabWidget->setCurrentIndex(0);
-
- connect(m_securityTabWidget, SIGNAL(currentChanged(int)), SLOT(pageChanged()));
- connect(m_ui->categoryList, SIGNAL(categoryChanged(int)), m_ui->stackedWidget, SLOT(setCurrentIndex(int)));
-
-#ifdef WITH_XC_BROWSER
- m_ui->categoryList->addCategory(tr("Browser Integration"), icons()->icon("internet-web-browser"));
- m_ui->stackedWidget->addWidget(m_browserWidget);
+#ifdef WITH_XC_FDOSECRETS
+ addSettingsPage(new DatabaseSettingsPageFdoSecrets());
#endif
m_ui->categoryList->addCategory(tr("Maintenance"), icons()->icon("hammer-wrench"));
m_ui->stackedWidget->addWidget(m_maintenanceWidget);
- pageChanged();
+ m_ui->stackedWidget->setCurrentIndex(0);
+ connect(m_ui->categoryList, SIGNAL(categoryChanged(int)), m_ui->stackedWidget, SLOT(setCurrentIndex(int)));
}
DatabaseSettingsDialog::~DatabaseSettingsDialog() = default;
@@ -171,21 +167,29 @@ void DatabaseSettingsDialog::showRemoteSettings()
void DatabaseSettingsDialog::save()
{
if (!m_generalWidget->save()) {
+ m_ui->categoryList->setCurrentCategory(0);
return;
}
if (!m_databaseKeyWidget->save()) {
+ m_ui->categoryList->setCurrentCategory(1);
+ m_securityTabWidget->setCurrentIndex(0);
return;
}
if (!m_encryptionWidget->save()) {
+ m_ui->categoryList->setCurrentCategory(1);
+ m_securityTabWidget->setCurrentIndex(1);
return;
}
if (!m_remoteWidget->save()) {
+ m_ui->categoryList->setCurrentCategory(2);
return;
}
+ // Browser settings don't have anything to save
+
for (const ExtraPage& extraPage : asConst(m_extraPages)) {
extraPage.saveSettings();
}
@@ -195,10 +199,13 @@ void DatabaseSettingsDialog::save()
void DatabaseSettingsDialog::reject()
{
- emit editFinished(false);
-}
+ m_generalWidget->discard();
+ m_databaseKeyWidget->discard();
+ m_encryptionWidget->discard();
+ m_remoteWidget->discard();
+#ifdef WITH_XC_BROWSER
+ m_browserWidget->discard();
+#endif
-void DatabaseSettingsDialog::pageChanged()
-{
- m_ui->stackedWidget->currentIndex();
+ emit editFinished(false);
}
diff --git a/src/gui/dbsettings/DatabaseSettingsDialog.h b/src/gui/dbsettings/DatabaseSettingsDialog.h
index 9f04ecf39a..a7772f329f 100644
--- a/src/gui/dbsettings/DatabaseSettingsDialog.h
+++ b/src/gui/dbsettings/DatabaseSettingsDialog.h
@@ -70,7 +70,6 @@ class DatabaseSettingsDialog : public DialogyWidget
private slots:
void save();
void reject();
- void pageChanged();
private:
enum Page
diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.cpp b/src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.cpp
index 1de8e6a9f0..f631f021d0 100644
--- a/src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.cpp
+++ b/src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.cpp
@@ -79,28 +79,30 @@ void DatabaseSettingsWidgetDatabaseKey::load(QSharedPointer db)
// database has no key, we are about to add a new one
m_passwordEditWidget->changeVisiblePage(KeyComponentWidget::Page::Edit);
m_passwordEditWidget->setPasswordVisible(true);
- }
-
- bool hasAdditionalKeys = false;
- for (const auto& key : m_db->key()->keys()) {
- if (key->uuid() == PasswordKey::UUID) {
- m_passwordEditWidget->setComponentAdded(true);
- } else if (key->uuid() == FileKey::UUID) {
- m_keyFileEditWidget->setComponentAdded(true);
- hasAdditionalKeys = true;
+ // Focus won't work until the UI settles
+ QTimer::singleShot(0, m_passwordEditWidget, SLOT(setFocus()));
+ } else {
+ bool hasAdditionalKeys = false;
+ for (const auto& key : m_db->key()->keys()) {
+ if (key->uuid() == PasswordKey::UUID) {
+ m_passwordEditWidget->setComponentAdded(true);
+ } else if (key->uuid() == FileKey::UUID) {
+ m_keyFileEditWidget->setComponentAdded(true);
+ hasAdditionalKeys = true;
+ }
}
- }
#ifdef WITH_XC_YUBIKEY
- for (const auto& key : m_db->key()->challengeResponseKeys()) {
- if (key->uuid() == ChallengeResponseKey::UUID) {
- m_yubiKeyEditWidget->setComponentAdded(true);
- hasAdditionalKeys = true;
+ for (const auto& key : m_db->key()->challengeResponseKeys()) {
+ if (key->uuid() == ChallengeResponseKey::UUID) {
+ m_yubiKeyEditWidget->setComponentAdded(true);
+ hasAdditionalKeys = true;
+ }
}
- }
#endif
- setAdditionalKeyOptionsVisible(hasAdditionalKeys);
+ setAdditionalKeyOptionsVisible(hasAdditionalKeys);
+ }
connect(m_passwordEditWidget->findChild("removeButton"), SIGNAL(clicked()), SLOT(markDirty()));
connect(m_keyFileEditWidget->findChild("removeButton"), SIGNAL(clicked()), SLOT(markDirty()));
@@ -177,31 +179,32 @@ bool DatabaseSettingsWidgetDatabaseKey::save()
return false;
}
- // Show warning if database password is weak
- if (!m_passwordEditWidget->isEmpty()
- && m_passwordEditWidget->getPasswordQuality() < PasswordHealth::Quality::Good) {
- auto dialogResult = MessageBox::warning(this,
- tr("Weak password"),
- tr("This is a weak password! For better protection of your secrets, "
- "you should choose a stronger password."),
- MessageBox::ContinueWithWeakPass | MessageBox::Cancel,
- MessageBox::Cancel);
-
- if (dialogResult == MessageBox::Cancel) {
+ if (!m_passwordEditWidget->isEmpty()) {
+ // Prevent setting password with a quality less than the minimum required
+ auto minQuality = qBound(0, config()->get(Config::Security_DatabasePasswordMinimumQuality).toInt(), 4);
+ if (m_passwordEditWidget->getPasswordQuality() < static_cast(minQuality)) {
+ MessageBox::critical(this,
+ tr("Weak password"),
+ tr("The provided password does not meet the minimum quality requirement."),
+ MessageBox::Ok,
+ MessageBox::Ok);
return false;
}
- }
- // If enforced in the config file, deny users from continuing with a weak password
- auto minQuality =
- static_cast(config()->get(Config::Security_DatabasePasswordMinimumQuality).toInt());
- if (!m_passwordEditWidget->isEmpty() && m_passwordEditWidget->getPasswordQuality() < minQuality) {
- MessageBox::critical(this,
- tr("Weak password"),
- tr("You must enter a stronger password to protect your database."),
- MessageBox::Ok,
- MessageBox::Ok);
- return false;
+ // Show warning if database password is weak or poor
+ if (m_passwordEditWidget->getPasswordQuality() < PasswordHealth::Quality::Good) {
+ auto dialogResult =
+ MessageBox::warning(this,
+ tr("Weak password"),
+ tr("This is a weak password! For better protection of your secrets, "
+ "you should choose a stronger password."),
+ MessageBox::ContinueWithWeakPass | MessageBox::Cancel,
+ MessageBox::Cancel);
+
+ if (dialogResult == MessageBox::Cancel) {
+ return false;
+ }
+ }
}
if (!addToCompositeKey(m_keyFileEditWidget, newKey, oldFileKey)) {
@@ -232,11 +235,16 @@ bool DatabaseSettingsWidgetDatabaseKey::save()
m_db->markAsModified();
}
+ // Reset fields
+ initialize();
+
return true;
}
void DatabaseSettingsWidgetDatabaseKey::discard()
{
+ // Reset fields
+ initialize();
emit editFinished(false);
}
diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp
index 2408a05de9..03cb5e347d 100644
--- a/tests/gui/TestGui.cpp
+++ b/tests/gui/TestGui.cpp
@@ -1607,12 +1607,20 @@ void TestGui::testDatabaseSettings()
passwordWidgets[0]->setText("b");
passwordWidgets[1]->setText("b");
- // Cancel password change
+ // Toggle between tabs to ensure the password remains
+ securityTabWidget->setCurrentIndex(1);
+ QApplication::processEvents();
+ securityTabWidget->setCurrentIndex(0);
+ QApplication::processEvents();
+ QCOMPARE(passwordWidgets[0]->text(), QString("b"));
+
+ // Cancel password change and confirm password is cleared
auto cancelPasswordButton = passwordEditWidget->findChild("cancelButton");
QVERIFY(cancelPasswordButton);
QTest::mouseClick(cancelPasswordButton, Qt::LeftButton);
QApplication::processEvents();
QVERIFY(!passwordWidgets[0]->isVisible());
+ QCOMPARE(passwordWidgets[0]->text(), QString(""));
QVERIFY(editPasswordButton->isVisible());
// Switch to encryption tab and interact with various settings