From a740fe128cab4a4ab63d05dd9cce34e9c5cc484f Mon Sep 17 00:00:00 2001 From: "J.M. Dana" <1109854+jmdana@users.noreply.github.com> Date: Wed, 13 Apr 2022 11:46:47 +0200 Subject: [PATCH] Add password strength indicator to PasswordEditWidget Fixes #7437 (entry edit view only) Fixes #5220 --- share/translations/keepassxc_en.ts | 96 ++++++---- src/CMakeLists.txt | 2 +- src/autotype/PickcharsDialog.ui | 7 +- src/gui/DatabaseOpenWidget.ui | 8 +- src/gui/PasswordGeneratorWidget.ui | 6 +- .../{PasswordEdit.cpp => PasswordWidget.cpp} | 168 +++++++++++++++--- src/gui/{PasswordEdit.h => PasswordWidget.h} | 50 ++++-- src/gui/PasswordWidget.ui | 66 +++++++ src/gui/databasekey/PasswordEditWidget.cpp | 3 + src/gui/databasekey/PasswordEditWidget.ui | 8 +- src/gui/entry/EditEntryWidget.cpp | 2 + src/gui/entry/EditEntryWidgetMain.ui | 14 +- src/keeshare/group/EditGroupWidgetKeeShare.ui | 6 +- tests/gui/TestGui.cpp | 109 +++++++----- tests/gui/TestGuiBrowser.cpp | 4 +- tests/gui/TestGuiFdoSecrets.cpp | 9 +- 16 files changed, 402 insertions(+), 156 deletions(-) rename src/gui/{PasswordEdit.cpp => PasswordWidget.cpp} (55%) rename src/gui/{PasswordEdit.h => PasswordWidget.h} (61%) create mode 100644 src/gui/PasswordWidget.ui diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts index 5fa8e7542..6f625f943 100644 --- a/share/translations/keepassxc_en.ts +++ b/share/translations/keepassxc_en.ts @@ -1426,10 +1426,6 @@ Backup database located at %2 Key File: - - <p>In addition to a password, you can use a secret file to enhance the security of your database. This file can be generated in your database's security settings.</p><p>This is <strong>not</strong> your *.kdbx database file!<br>If you do not have a key file, leave this field empty.</p><p>Click for more information…</p> - - Key file help @@ -1442,11 +1438,6 @@ Backup database located at %2 Hardware Key: - - <p>You can use a hardware security key such as a <strong>YubiKey</strong> or <strong>OnlyKey</strong> with slots configured for HMAC-SHA1.</p> -<p>Click for more information…</p> - - Hardware key help @@ -1581,6 +1572,15 @@ If you do not have a key file, please leave the field empty. Select hardware key… + + <p>In addition to a password, you can use a secret file to enhance the security of your database. This file can be generated in your database's security settings.</p><p>This is <strong>not</strong> your *.kdbx database file!<br>If you do not have a key file, leave this field empty.</p><p>Click for more information…</p> + + + + <p>You can use a hardware security key such as a <strong>YubiKey</strong> or <strong>OnlyKey</strong> with slots configured for HMAC-SHA1.</p> +<p>Click for more information…</p> + + DatabaseSettingWidgetMetaData @@ -5749,29 +5749,6 @@ We recommend you use the AppImage available on our downloads page. - - PasswordEdit - - Passwords do not match - - - - Passwords match so far - - - - Toggle Password (%1) - - - - Generate Password (%1) - - - - Warning: Caps Lock enabled! - - - PasswordEditWidget @@ -5950,10 +5927,6 @@ We recommend you use the AppImage available on our downloads page. Also choose from: - - Excluded characters: "0", "1", "l", "I", "O", "|", "﹒" - - Exclude look-alike characters @@ -6103,6 +6076,57 @@ Do you want to overwrite it? Password quality + + Excluded characters: "0", "1", "l", "I", "O", "|", "﹒" + + + + + PasswordWidget + + Passwords do not match + + + + Passwords match so far + + + + Toggle Password (%1) + + + + Generate Password (%1) + + + + Warning: Caps Lock enabled! + + + + Quality: %1 + + + + Poor + Password quality + + + + Weak + Password quality + + + + Good + Password quality + + + + Excellent + Password quality + + PickcharsDialog diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c4f66e713..8e6fbc425 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -121,7 +121,7 @@ set(keepassx_SOURCES gui/MessageBox.cpp gui/MessageWidget.cpp gui/OpVaultOpenWidget.cpp - gui/PasswordEdit.cpp + gui/PasswordWidget.cpp gui/PasswordGeneratorWidget.cpp gui/ApplicationSettingsWidget.cpp gui/Icons.cpp diff --git a/src/autotype/PickcharsDialog.ui b/src/autotype/PickcharsDialog.ui index de9704eb0..2ff3ac0c6 100644 --- a/src/autotype/PickcharsDialog.ui +++ b/src/autotype/PickcharsDialog.ui @@ -34,7 +34,7 @@ - + 0 @@ -74,9 +74,10 @@ - PasswordEdit + PasswordWidget QLineEdit -
gui/PasswordEdit.h
+
gui/PasswordWidget.h
+ 1
diff --git a/src/gui/DatabaseOpenWidget.ui b/src/gui/DatabaseOpenWidget.ui index 101bef632..7cd4f281e 100644 --- a/src/gui/DatabaseOpenWidget.ui +++ b/src/gui/DatabaseOpenWidget.ui @@ -145,7 +145,7 @@
- + Password field @@ -380,7 +380,7 @@ 0 - + 0 @@ -617,9 +617,9 @@ - PasswordEdit + PasswordWidget QLineEdit -
gui/PasswordEdit.h
+
gui/PasswordWidget.h
1
diff --git a/src/gui/PasswordGeneratorWidget.ui b/src/gui/PasswordGeneratorWidget.ui index 9330a983f..19cb0bef3 100644 --- a/src/gui/PasswordGeneratorWidget.ui +++ b/src/gui/PasswordGeneratorWidget.ui @@ -87,7 +87,7 @@
- + 0 @@ -990,9 +990,9 @@ QProgressBar::chunk { - PasswordEdit + PasswordWidget QLineEdit -
gui/PasswordEdit.h
+
gui/PasswordWidget.h
1
diff --git a/src/gui/PasswordEdit.cpp b/src/gui/PasswordWidget.cpp similarity index 55% rename from src/gui/PasswordEdit.cpp rename to src/gui/PasswordWidget.cpp index 5f9272b1b..f5e97ba08 100644 --- a/src/gui/PasswordEdit.cpp +++ b/src/gui/PasswordWidget.cpp @@ -16,9 +16,11 @@ * along with this program. If not, see . */ -#include "PasswordEdit.h" +#include "PasswordWidget.h" +#include "ui_PasswordWidget.h" #include "core/Config.h" +#include "core/PasswordHealth.h" #include "gui/Font.h" #include "gui/Icons.h" #include "gui/PasswordGeneratorWidget.h" @@ -26,19 +28,24 @@ #include "gui/styles/StateColorPalette.h" #include +#include #include #include -PasswordEdit::PasswordEdit(QWidget* parent) - : QLineEdit(parent) +PasswordWidget::PasswordWidget(QWidget* parent) + : QWidget(parent) + , m_ui(new Ui::PasswordWidget()) { + m_ui->setupUi(this); + setFocusProxy(m_ui->passwordEdit); + const QIcon errorIcon = icons()->icon("dialog-error"); - m_errorAction = addAction(errorIcon, QLineEdit::TrailingPosition); + m_errorAction = m_ui->passwordEdit->addAction(errorIcon, QLineEdit::TrailingPosition); m_errorAction->setVisible(false); m_errorAction->setToolTip(tr("Passwords do not match")); const QIcon correctIcon = icons()->icon("dialog-ok"); - m_correctAction = addAction(correctIcon, QLineEdit::TrailingPosition); + m_correctAction = m_ui->passwordEdit->addAction(correctIcon, QLineEdit::TrailingPosition); m_correctAction->setVisible(false); m_correctAction->setToolTip(tr("Passwords match so far")); @@ -63,8 +70,8 @@ PasswordEdit::PasswordEdit(QWidget* parent) m_toggleVisibleAction->setCheckable(true); m_toggleVisibleAction->setShortcut(modifier + Qt::Key_H); m_toggleVisibleAction->setShortcutContext(Qt::WidgetShortcut); - addAction(m_toggleVisibleAction, QLineEdit::TrailingPosition); - connect(m_toggleVisibleAction, &QAction::triggered, this, &PasswordEdit::setShowPassword); + m_ui->passwordEdit->addAction(m_toggleVisibleAction, QLineEdit::TrailingPosition); + connect(m_toggleVisibleAction, &QAction::triggered, this, &PasswordWidget::setShowPassword); m_passwordGeneratorAction = new QAction( icons()->icon("password-generator"), @@ -72,44 +79,98 @@ PasswordEdit::PasswordEdit(QWidget* parent) this); m_passwordGeneratorAction->setShortcut(modifier + Qt::Key_G); m_passwordGeneratorAction->setShortcutContext(Qt::WidgetShortcut); - addAction(m_passwordGeneratorAction, QLineEdit::TrailingPosition); + m_ui->passwordEdit->addAction(m_passwordGeneratorAction, QLineEdit::TrailingPosition); m_passwordGeneratorAction->setVisible(false); m_capslockAction = new QAction(icons()->icon("dialog-warning", true, StateColorPalette().color(StateColorPalette::Error)), tr("Warning: Caps Lock enabled!"), this); - addAction(m_capslockAction, QLineEdit::LeadingPosition); + m_ui->passwordEdit->addAction(m_capslockAction, QLineEdit::LeadingPosition); m_capslockAction->setVisible(false); + + // Reset the password strength bar, hidden by default + updatePasswordStrength(""); + m_ui->qualityProgressBar->setVisible(false); + + connect(m_ui->passwordEdit, &QLineEdit::textChanged, this, [this](const QString& pwd) { + updatePasswordStrength(pwd); + emit textChanged(pwd); + }); } -void PasswordEdit::setRepeatPartner(PasswordEdit* repeatEdit) +PasswordWidget::~PasswordWidget() +{ +} + +void PasswordWidget::setQualityVisible(bool state) +{ + m_ui->qualityProgressBar->setVisible(state); +} + +QString PasswordWidget::text() +{ + return m_ui->passwordEdit->text(); +} + +void PasswordWidget::setText(const QString& text) +{ + m_ui->passwordEdit->setText(text); +} + +void PasswordWidget::setEchoMode(QLineEdit::EchoMode mode) +{ + m_ui->passwordEdit->setEchoMode(mode); +} + +void PasswordWidget::clear() +{ + m_ui->passwordEdit->clear(); +} + +void PasswordWidget::setClearButtonEnabled(bool enabled) +{ + m_ui->passwordEdit->setClearButtonEnabled(enabled); +} + +void PasswordWidget::selectAll() +{ + m_ui->passwordEdit->selectAll(); +} + +void PasswordWidget::setReadOnly(bool state) +{ + m_ui->passwordEdit->setReadOnly(state); +} + +void PasswordWidget::setRepeatPartner(PasswordWidget* repeatEdit) { m_repeatPasswordEdit = repeatEdit; m_repeatPasswordEdit->setParentPasswordEdit(this); - connect(this, SIGNAL(textChanged(QString)), m_repeatPasswordEdit, SLOT(autocompletePassword(QString))); - connect(this, SIGNAL(textChanged(QString)), m_repeatPasswordEdit, SLOT(updateRepeatStatus())); - connect(m_repeatPasswordEdit, SIGNAL(textChanged(QString)), m_repeatPasswordEdit, SLOT(updateRepeatStatus())); + connect( + m_ui->passwordEdit, SIGNAL(textChanged(QString)), m_repeatPasswordEdit, SLOT(autocompletePassword(QString))); + connect(m_ui->passwordEdit, SIGNAL(textChanged(QString)), m_repeatPasswordEdit, SLOT(updateRepeatStatus())); } -void PasswordEdit::setParentPasswordEdit(PasswordEdit* parent) +void PasswordWidget::setParentPasswordEdit(PasswordWidget* parent) { m_parentPasswordEdit = parent; // Hide actions m_toggleVisibleAction->setVisible(false); m_passwordGeneratorAction->setVisible(false); + connect(m_ui->passwordEdit, SIGNAL(textChanged(QString)), this, SLOT(updateRepeatStatus())); } -void PasswordEdit::enablePasswordGenerator() +void PasswordWidget::enablePasswordGenerator() { if (!m_passwordGeneratorAction->isVisible()) { m_passwordGeneratorAction->setVisible(true); - connect(m_passwordGeneratorAction, &QAction::triggered, this, &PasswordEdit::popupPasswordGenerator); + connect(m_passwordGeneratorAction, &QAction::triggered, this, &PasswordWidget::popupPasswordGenerator); } } -void PasswordEdit::setShowPassword(bool show) +void PasswordWidget::setShowPassword(bool show) { setEchoMode(show ? QLineEdit::Normal : QLineEdit::Password); m_toggleVisibleAction->setIcon(icons()->onOffIcon("password-show", show)); @@ -126,12 +187,12 @@ void PasswordEdit::setShowPassword(bool show) } } -bool PasswordEdit::isPasswordVisible() const +bool PasswordWidget::isPasswordVisible() const { - return echoMode() == QLineEdit::Normal; + return m_ui->passwordEdit->echoMode() == QLineEdit::Normal; } -void PasswordEdit::popupPasswordGenerator() +void PasswordWidget::popupPasswordGenerator() { auto generator = PasswordGeneratorWidget::popupGenerator(this); generator->setPasswordVisible(isPasswordVisible()); @@ -143,7 +204,7 @@ void PasswordEdit::popupPasswordGenerator() } } -void PasswordEdit::updateRepeatStatus() +void PasswordWidget::updateRepeatStatus() { static const auto stylesheetTemplate = QStringLiteral("QLineEdit { background: %1; }"); if (!m_parentPasswordEdit) { @@ -170,24 +231,25 @@ void PasswordEdit::updateRepeatStatus() } } -void PasswordEdit::autocompletePassword(const QString& password) +void PasswordWidget::autocompletePassword(const QString& password) { - if (!config()->get(Config::Security_PasswordsRepeatVisible).toBool() && echoMode() == QLineEdit::Normal) { + if (!config()->get(Config::Security_PasswordsRepeatVisible).toBool() + && m_ui->passwordEdit->echoMode() == QLineEdit::Normal) { setText(password); } } -bool PasswordEdit::event(QEvent* event) +bool PasswordWidget::event(QEvent* event) { if (isVisible() && (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease || event->type() == QEvent::FocusIn)) { checkCapslockState(); } - return QLineEdit::event(event); + return QWidget::event(event); } -void PasswordEdit::checkCapslockState() +void PasswordWidget::checkCapslockState() { if (m_parentPasswordEdit) { return; @@ -201,8 +263,6 @@ void PasswordEdit::checkCapslockState() // Force repaint to avoid rendering glitches of QLineEdit contents repaint(); - emit capslockToggled(m_capslockState); - if (newCapslockState) { QTimer::singleShot( 150, [this] { QToolTip::showText(mapToGlobal(rect().bottomLeft()), m_capslockAction->text()); }); @@ -211,3 +271,55 @@ void PasswordEdit::checkCapslockState() } } } + +void PasswordWidget::updatePasswordStrength(const QString& password) +{ + if (password.isEmpty()) { + m_ui->qualityProgressBar->setValue(0); + m_ui->qualityProgressBar->setToolTip((tr(""))); + return; + } + + PasswordHealth health(password); + + m_ui->qualityProgressBar->setValue(std::min(int(health.entropy()), m_ui->qualityProgressBar->maximum())); + + QString style = m_ui->qualityProgressBar->styleSheet(); + QRegularExpression re("(QProgressBar::chunk\\s*\\{.*?background-color:)[^;]+;", + QRegularExpression::CaseInsensitiveOption | QRegularExpression::DotMatchesEverythingOption); + style.replace(re, "\\1 %1;"); + + StateColorPalette qualityPalette; + + switch (health.quality()) { + case PasswordHealth::Quality::Bad: + case PasswordHealth::Quality::Poor: + m_ui->qualityProgressBar->setStyleSheet( + style.arg(qualityPalette.color(StateColorPalette::HealthCritical).name())); + + m_ui->qualityProgressBar->setToolTip(tr("Quality: %1").arg(tr("Poor", "Password quality"))); + + break; + + case PasswordHealth::Quality::Weak: + m_ui->qualityProgressBar->setStyleSheet(style.arg(qualityPalette.color(StateColorPalette::HealthBad).name())); + + m_ui->qualityProgressBar->setToolTip(tr("Quality: %1").arg(tr("Weak", "Password quality"))); + + break; + case PasswordHealth::Quality::Good: + m_ui->qualityProgressBar->setStyleSheet(style.arg(qualityPalette.color(StateColorPalette::HealthOk).name())); + + m_ui->qualityProgressBar->setToolTip(tr("Quality: %1").arg(tr("Good", "Password quality"))); + + break; + case PasswordHealth::Quality::Excellent: + + m_ui->qualityProgressBar->setStyleSheet( + style.arg(qualityPalette.color(StateColorPalette::HealthExcellent).name())); + + m_ui->qualityProgressBar->setToolTip(tr("Quality: %1").arg(tr("Excellent", "Password quality"))); + + break; + } +} \ No newline at end of file diff --git a/src/gui/PasswordEdit.h b/src/gui/PasswordWidget.h similarity index 61% rename from src/gui/PasswordEdit.h rename to src/gui/PasswordWidget.h index 559394bd0..f844d7737 100644 --- a/src/gui/PasswordEdit.h +++ b/src/gui/PasswordWidget.h @@ -16,50 +16,70 @@ * along with this program. If not, see . */ -#ifndef KEEPASSX_PASSWORDEDIT_H -#define KEEPASSX_PASSWORDEDIT_H +#ifndef KEEPASSX_PASSWORDWIDGET_H +#define KEEPASSX_PASSWORDWIDGET_H #include #include #include +#include -class QDialog; +namespace Ui +{ + class PasswordWidget; +} -class PasswordEdit : public QLineEdit +class PasswordWidget : public QWidget { Q_OBJECT public: - explicit PasswordEdit(QWidget* parent = nullptr); + explicit PasswordWidget(QWidget* parent = nullptr); + ~PasswordWidget() override; void enablePasswordGenerator(); - void setRepeatPartner(PasswordEdit* repeatEdit); + void setRepeatPartner(PasswordWidget* repeatEdit); + void setQualityVisible(bool state); + bool isPasswordVisible() const; + QString text(); + +signals: + void textChanged(QString text); public slots: + void setText(const QString& text); void setShowPassword(bool show); - void updateRepeatStatus(); + + void clear(); + void selectAll(); + void setReadOnly(bool state); + void setEchoMode(QLineEdit::EchoMode mode); + void setClearButtonEnabled(bool enabled); protected: bool event(QEvent* event) override; -signals: - void capslockToggled(bool capslockOn); - private slots: void autocompletePassword(const QString& password); void popupPasswordGenerator(); - void setParentPasswordEdit(PasswordEdit* parent); - void checkCapslockState(); + void updateRepeatStatus(); + void updatePasswordStrength(const QString& password); private: + void checkCapslockState(); + void setParentPasswordEdit(PasswordWidget* parent); + + const QScopedPointer m_ui; + QPointer m_errorAction; QPointer m_correctAction; QPointer m_toggleVisibleAction; QPointer m_passwordGeneratorAction; QPointer m_capslockAction; - QPointer m_repeatPasswordEdit; - QPointer m_parentPasswordEdit; + QPointer m_repeatPasswordEdit; + QPointer m_parentPasswordEdit; + bool m_capslockState = false; }; -#endif // KEEPASSX_PASSWORDEDIT_H +#endif // KEEPASSX_PASSWORDWIDGET_H diff --git a/src/gui/PasswordWidget.ui b/src/gui/PasswordWidget.ui new file mode 100644 index 000000000..4419ad79b --- /dev/null +++ b/src/gui/PasswordWidget.ui @@ -0,0 +1,66 @@ + + + PasswordWidget + + + + 0 + 0 + 471 + 25 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + 16777215 + 4 + + + + QProgressBar { + border: none; + background-color: transparent; + } + QProgressBar::chunk { + background-color: #c0392b; + border-radius: 1px; + } + + + + 24 + + + false + + + + + + + passwordEdit + + + + diff --git a/src/gui/databasekey/PasswordEditWidget.cpp b/src/gui/databasekey/PasswordEditWidget.cpp index 5f12f7d19..5ed6b6328 100644 --- a/src/gui/databasekey/PasswordEditWidget.cpp +++ b/src/gui/databasekey/PasswordEditWidget.cpp @@ -78,6 +78,9 @@ void PasswordEditWidget::initComponentEditWidget(QWidget* widget) Q_UNUSED(widget); Q_ASSERT(m_compEditWidget); m_compUi->enterPasswordEdit->setFocus(); + + m_compUi->enterPasswordEdit->setQualityVisible(true); + m_compUi->repeatPasswordEdit->setQualityVisible(false); } void PasswordEditWidget::initComponent() diff --git a/src/gui/databasekey/PasswordEditWidget.ui b/src/gui/databasekey/PasswordEditWidget.ui index d8382ed94..e3b1679e1 100644 --- a/src/gui/databasekey/PasswordEditWidget.ui +++ b/src/gui/databasekey/PasswordEditWidget.ui @@ -31,7 +31,7 @@
- + 0 @@ -60,7 +60,7 @@ - + 0 @@ -85,9 +85,9 @@ - PasswordEdit + PasswordWidget QLineEdit -
gui/PasswordEdit.h
+
gui/PasswordWidget.h
1
diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index 6eca36a3b..b7b838d7d 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -131,6 +131,8 @@ EditEntryWidget::EditEntryWidget(QWidget* parent) connect(m_iconsWidget, SIGNAL(messageEditEntryDismiss()), SLOT(hideMessage())); m_editWidgetProperties->setCustomData(m_customData.data()); + + m_mainUi->passwordEdit->setQualityVisible(true); } EditEntryWidget::~EditEntryWidget() diff --git a/src/gui/entry/EditEntryWidgetMain.ui b/src/gui/entry/EditEntryWidgetMain.ui index 555c719fa..6b0f95178 100644 --- a/src/gui/entry/EditEntryWidgetMain.ui +++ b/src/gui/entry/EditEntryWidgetMain.ui @@ -243,7 +243,7 @@
- + Password field @@ -297,15 +297,15 @@ - TagsEdit - QWidget -
gui/tag/TagsEdit.h
+ PasswordWidget + QLineEdit +
gui/PasswordWidget.h
1
- PasswordEdit - QLineEdit -
gui/PasswordEdit.h
+ TagsEdit + QWidget +
gui/tag/TagsEdit.h
1
diff --git a/src/keeshare/group/EditGroupWidgetKeeShare.ui b/src/keeshare/group/EditGroupWidgetKeeShare.ui index 9b87f963f..4f655ee4d 100644 --- a/src/keeshare/group/EditGroupWidgetKeeShare.ui +++ b/src/keeshare/group/EditGroupWidgetKeeShare.ui @@ -51,7 +51,7 @@
- + 0 @@ -190,9 +190,9 @@ - PasswordEdit + PasswordWidget QLineEdit -
gui/PasswordEdit.h
+
gui/PasswordWidget.h
1
diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index fc3da4ea9..c00e3a10b 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -40,8 +40,8 @@ #include "gui/EntryPreviewWidget.h" #include "gui/FileDialog.h" #include "gui/MessageBox.h" -#include "gui/PasswordEdit.h" #include "gui/PasswordGeneratorWidget.h" +#include "gui/PasswordWidget.h" #include "gui/SearchWidget.h" #include "gui/TotpDialog.h" #include "gui/TotpSetupDialog.h" @@ -131,7 +131,9 @@ void TestGui::init() m_dbWidget = m_tabWidget->currentDatabaseWidget(); auto* databaseOpenWidget = m_tabWidget->currentDatabaseWidget()->findChild("databaseOpenWidget"); QVERIFY(databaseOpenWidget); - auto* editPassword = databaseOpenWidget->findChild("editPassword"); + // editPassword is not QLineEdit anymore but PasswordWidget + auto* editPassword = + databaseOpenWidget->findChild("editPassword")->findChild("passwordEdit"); QVERIFY(editPassword); editPassword->setFocus(); @@ -242,8 +244,10 @@ void TestGui::testCreateDatabase() // enter password auto* passwordWidget = wizard->currentPage()->findChild(); QCOMPARE(passwordWidget->visiblePage(), KeyFileEditWidget::Page::Edit); - auto* passwordEdit = passwordWidget->findChild("enterPasswordEdit"); - auto* passwordRepeatEdit = passwordWidget->findChild("repeatPasswordEdit"); + auto* passwordEdit = + passwordWidget->findChild("enterPasswordEdit")->findChild("passwordEdit"); + auto* passwordRepeatEdit = + passwordWidget->findChild("repeatPasswordEdit")->findChild("passwordEdit"); QTRY_VERIFY(passwordEdit->isVisible()); QTRY_VERIFY(passwordEdit->hasFocus()); QTest::keyClicks(passwordEdit, "test"); @@ -318,7 +322,7 @@ void TestGui::testMergeDatabase() fileDialog()->setNextFileName(QString(KEEPASSX_TEST_DATA_DIR).append("/MergeDatabase.kdbx")); triggerAction("actionDatabaseMerge"); - QTRY_COMPARE(QApplication::focusWidget()->objectName(), QString("editPassword")); + QTRY_COMPARE(QApplication::focusWidget()->objectName(), QString("passwordEdit")); auto* editPasswordMerge = QApplication::focusWidget(); QVERIFY(editPasswordMerge->isVisible()); @@ -518,7 +522,7 @@ void TestGui::testEditEntry() QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode); titleEdit->setText("multiline\ntitle"); editEntryWidget->findChild("usernameComboBox")->lineEdit()->setText("multiline\nusername"); - editEntryWidget->findChild("passwordEdit")->setText("multiline\npassword"); + editEntryWidget->findChild("passwordEdit")->setText("multiline\npassword"); editEntryWidget->findChild("urlEdit")->setText("multiline\nurl"); QTest::mouseClick(okButton, Qt::LeftButton); @@ -626,7 +630,8 @@ void TestGui::testAddEntry() QTest::mouseClick(usernameComboBox, Qt::LeftButton); QTest::keyClicks(usernameComboBox, "Auto"); QTest::keyPress(usernameComboBox, Qt::Key_Right); - auto* passwordEdit = editEntryWidget->findChild("passwordEdit"); + auto* passwordEdit = + editEntryWidget->findChild("passwordEdit")->findChild("passwordEdit"); QTest::keyClicks(passwordEdit, "something 2"); QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); @@ -742,7 +747,8 @@ void TestGui::testPasswordEntryEntropy() QTest::keyClicks(titleEdit, "test"); // Open the password generator - auto* passwordEdit = editEntryWidget->findChild(); + auto* passwordEdit = + editEntryWidget->findChild("passwordEdit")->findChild("passwordEdit"); QVERIFY(passwordEdit); QTest::mouseClick(passwordEdit, Qt::LeftButton); @@ -752,24 +758,26 @@ void TestGui::testPasswordEntryEntropy() QTest::keyClick(passwordEdit, Qt::Key_G, Qt::ControlModifier); #endif - TEST_MODAL(PasswordGeneratorWidget * pwGeneratorWidget; - QTRY_VERIFY(pwGeneratorWidget = m_dbWidget->findChild()); + TEST_MODAL( + PasswordGeneratorWidget * pwGeneratorWidget; + QTRY_VERIFY(pwGeneratorWidget = m_dbWidget->findChild()); - // Type in some password - auto* generatedPassword = pwGeneratorWidget->findChild("editNewPassword"); - auto* entropyLabel = pwGeneratorWidget->findChild("entropyLabel"); - auto* strengthLabel = pwGeneratorWidget->findChild("strengthLabel"); + // Type in some password + auto* generatedPassword = + pwGeneratorWidget->findChild("editNewPassword")->findChild("passwordEdit"); + auto* entropyLabel = pwGeneratorWidget->findChild("entropyLabel"); + auto* strengthLabel = pwGeneratorWidget->findChild("strengthLabel"); - QFETCH(QString, password); - QFETCH(QString, expectedEntropyLabel); - QFETCH(QString, expectedStrengthLabel); + QFETCH(QString, password); + QFETCH(QString, expectedEntropyLabel); + QFETCH(QString, expectedStrengthLabel); - generatedPassword->setText(password); - QCOMPARE(entropyLabel->text(), expectedEntropyLabel); - QCOMPARE(strengthLabel->text(), expectedStrengthLabel); + generatedPassword->setText(password); + QCOMPARE(entropyLabel->text(), expectedEntropyLabel); + QCOMPARE(strengthLabel->text(), expectedStrengthLabel); - QTest::mouseClick(generatedPassword, Qt::LeftButton); - QTest::keyClick(generatedPassword, Qt::Key_Escape);); + QTest::mouseClick(generatedPassword, Qt::LeftButton); + QTest::keyClick(generatedPassword, Qt::Key_Escape);); } void TestGui::testDicewareEntryEntropy() @@ -795,7 +803,7 @@ void TestGui::testDicewareEntryEntropy() QTest::keyClicks(titleEdit, "test"); // Open the password generator - auto* passwordEdit = editEntryWidget->findChild(); + auto* passwordEdit = editEntryWidget->findChild()->findChild("passwordEdit"); QVERIFY(passwordEdit); QTest::mouseClick(passwordEdit, Qt::LeftButton); @@ -805,34 +813,36 @@ void TestGui::testDicewareEntryEntropy() QTest::keyClick(passwordEdit, Qt::Key_G, Qt::ControlModifier); #endif - TEST_MODAL(PasswordGeneratorWidget * pwGeneratorWidget; - QTRY_VERIFY(pwGeneratorWidget = m_dbWidget->findChild()); + TEST_MODAL( + PasswordGeneratorWidget * pwGeneratorWidget; + QTRY_VERIFY(pwGeneratorWidget = m_dbWidget->findChild()); - // Select Diceware - auto* generatedPassword = pwGeneratorWidget->findChild("editNewPassword"); - auto* tabWidget = pwGeneratorWidget->findChild("tabWidget"); - auto* dicewareWidget = pwGeneratorWidget->findChild("dicewareWidget"); - tabWidget->setCurrentWidget(dicewareWidget); + // Select Diceware + auto* generatedPassword = + pwGeneratorWidget->findChild("editNewPassword")->findChild("passwordEdit"); + auto* tabWidget = pwGeneratorWidget->findChild("tabWidget"); + auto* dicewareWidget = pwGeneratorWidget->findChild("dicewareWidget"); + tabWidget->setCurrentWidget(dicewareWidget); - auto* comboBoxWordList = dicewareWidget->findChild("comboBoxWordList"); - comboBoxWordList->setCurrentText("eff_large.wordlist"); - auto* spinBoxWordCount = dicewareWidget->findChild("spinBoxWordCount"); - spinBoxWordCount->setValue(6); + auto* comboBoxWordList = dicewareWidget->findChild("comboBoxWordList"); + comboBoxWordList->setCurrentText("eff_large.wordlist"); + auto* spinBoxWordCount = dicewareWidget->findChild("spinBoxWordCount"); + spinBoxWordCount->setValue(6); - // Confirm a password was generated - QVERIFY(!pwGeneratorWidget->getGeneratedPassword().isEmpty()); + // Confirm a password was generated + QVERIFY(!pwGeneratorWidget->getGeneratedPassword().isEmpty()); - // Verify entropy and strength - auto* entropyLabel = pwGeneratorWidget->findChild("entropyLabel"); - auto* strengthLabel = pwGeneratorWidget->findChild("strengthLabel"); - auto* wordLengthLabel = pwGeneratorWidget->findChild("charactersInPassphraseLabel"); + // Verify entropy and strength + auto* entropyLabel = pwGeneratorWidget->findChild("entropyLabel"); + auto* strengthLabel = pwGeneratorWidget->findChild("strengthLabel"); + auto* wordLengthLabel = pwGeneratorWidget->findChild("charactersInPassphraseLabel"); - QTRY_COMPARE_WITH_TIMEOUT(entropyLabel->text(), QString("Entropy: 77.55 bit"), 200); - QCOMPARE(strengthLabel->text(), QString("Password Quality: Good")); - QCOMPARE(wordLengthLabel->text().toInt(), pwGeneratorWidget->getGeneratedPassword().size()); + QTRY_COMPARE_WITH_TIMEOUT(entropyLabel->text(), QString("Entropy: 77.55 bit"), 200); + QCOMPARE(strengthLabel->text(), QString("Password Quality: Good")); + QCOMPARE(wordLengthLabel->text().toInt(), pwGeneratorWidget->getGeneratedPassword().size()); - QTest::mouseClick(generatedPassword, Qt::LeftButton); - QTest::keyClick(generatedPassword, Qt::Key_Escape);); + QTest::mouseClick(generatedPassword, Qt::LeftButton); + QTest::keyClick(generatedPassword, Qt::Key_Escape);); } void TestGui::testTotp() @@ -1431,7 +1441,8 @@ void TestGui::testKeePass1Import() triggerAction("actionImportKeePass1"); auto* keepass1OpenWidget = m_tabWidget->currentDatabaseWidget()->findChild("keepass1OpenWidget"); - auto* editPassword = keepass1OpenWidget->findChild("editPassword"); + auto* editPassword = + keepass1OpenWidget->findChild("editPassword")->findChild("passwordEdit"); QVERIFY(editPassword); QTest::keyClicks(editPassword, "masterpw"); @@ -1463,7 +1474,8 @@ void TestGui::testDatabaseLocking() DatabaseWidget* dbWidget = m_tabWidget->currentDatabaseWidget(); QVERIFY(dbWidget->isLocked()); auto* unlockDatabaseWidget = dbWidget->findChild("databaseOpenWidget"); - QWidget* editPassword = unlockDatabaseWidget->findChild("editPassword"); + QWidget* editPassword = + unlockDatabaseWidget->findChild("editPassword")->findChild("passwordEdit"); QVERIFY(editPassword); QTest::keyClicks(editPassword, "a"); @@ -1798,7 +1810,8 @@ void TestGui::addCannedEntries() QWidget* entryNewWidget = toolBar->widgetForAction(m_mainWindow->findChild("actionEntryNew")); auto* editEntryWidget = m_dbWidget->findChild("editEntryWidget"); auto* titleEdit = editEntryWidget->findChild("titleEdit"); - auto* passwordEdit = editEntryWidget->findChild("passwordEdit"); + auto* passwordEdit = + editEntryWidget->findChild("passwordEdit")->findChild("passwordEdit"); // Add entry "test" and confirm added QTest::mouseClick(entryNewWidget, Qt::LeftButton); diff --git a/tests/gui/TestGuiBrowser.cpp b/tests/gui/TestGuiBrowser.cpp index bcc218240..075d49dc9 100644 --- a/tests/gui/TestGuiBrowser.cpp +++ b/tests/gui/TestGuiBrowser.cpp @@ -35,6 +35,7 @@ #include "gui/DatabaseTabWidget.h" #include "gui/FileDialog.h" #include "gui/MessageBox.h" +#include "gui/PasswordWidget.h" #include "gui/entry/EditEntryWidget.h" #include "gui/entry/EntryView.h" @@ -90,7 +91,8 @@ void TestGuiBrowser::init() auto* databaseOpenWidget = m_tabWidget->currentDatabaseWidget()->findChild("databaseOpenWidget"); QVERIFY(databaseOpenWidget); - auto* editPassword = databaseOpenWidget->findChild("editPassword"); + auto* editPassword = + databaseOpenWidget->findChild("editPassword")->findChild("passwordEdit"); QVERIFY(editPassword); editPassword->setFocus(); diff --git a/tests/gui/TestGuiFdoSecrets.cpp b/tests/gui/TestGuiFdoSecrets.cpp index 9bc3e6121..ec9a16b5c 100644 --- a/tests/gui/TestGuiFdoSecrets.cpp +++ b/tests/gui/TestGuiFdoSecrets.cpp @@ -33,6 +33,7 @@ #include "gui/FileDialog.h" #include "gui/MainWindow.h" #include "gui/MessageBox.h" +#include "gui/PasswordWidget.h" #include "gui/wizard/NewDatabaseWizard.h" #include "util/FdoSecretsProxy.h" #include "util/TemporaryFile.h" @@ -1768,8 +1769,10 @@ bool TestGuiFdoSecrets::driveNewDatabaseWizard() COMPARE(wizard->currentId(), 2); // enter password - auto* passwordEdit = wizard->findChild("enterPasswordEdit"); - auto* passwordRepeatEdit = wizard->findChild("repeatPasswordEdit"); + auto* passwordEdit = + wizard->findChild("enterPasswordEdit")->findChild("passwordEdit"); + auto* passwordRepeatEdit = + wizard->findChild("repeatPasswordEdit")->findChild("passwordEdit"); VERIFY(passwordEdit); VERIFY(passwordRepeatEdit); QTest::keyClicks(passwordEdit, "test"); @@ -1797,7 +1800,7 @@ bool TestGuiFdoSecrets::driveUnlockDialog() processEvents(); auto dbOpenDlg = m_tabWidget->findChild(); VERIFY(dbOpenDlg); - auto editPassword = dbOpenDlg->findChild("editPassword"); + auto editPassword = dbOpenDlg->findChild("editPassword")->findChild("passwordEdit"); VERIFY(editPassword); editPassword->setFocus(); QTest::keyClicks(editPassword, "a");