Add predefined search for TOTP entries (#12199)

Fixes #9362
This commit was authored by GitHub copilot agent and reviewed by @droidmonkey.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: droidmonkey <2809491+droidmonkey@users.noreply.github.com>
Co-authored-by: Jonathan White <support@dmapps.us>
This commit is contained in:
Copilot 2025-06-19 09:24:01 -04:00 committed by GitHub
parent 3c7c3b0a5f
commit 2c3a1a03cb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 56 additions and 1 deletions

View file

@ -10158,6 +10158,10 @@ This option is deprecated, use --set-key-file instead.</source>
<source>Weak Passwords</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>TOTP Entries</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TagView</name>

View file

@ -221,6 +221,13 @@ bool EntrySearcher::searchEntryImpl(const Entry* entry)
}
found = false;
break;
case Field::Has:
if (term.word.compare("totp", Qt::CaseInsensitive) == 0) {
found = entry->hasTotp();
break;
}
found = false;
break;
case Field::Uuid:
found = term.regex.match(entry->uuidToHex()).hasMatch();
break;
@ -260,6 +267,7 @@ void EntrySearcher::parseSearchTerms(const QString& searchString)
{QStringLiteral("group"), Field::Group},
{QStringLiteral("tag"), Field::Tag},
{QStringLiteral("is"), Field::Is},
{QStringLiteral("has"), Field::Has},
{QStringLiteral("uuid"), Field::Uuid}};
// Group 1 = modifiers, Group 2 = field, Group 3 = quoted string, Group 4 = unquoted string

View file

@ -41,6 +41,7 @@ public:
Group,
Tag,
Is,
Has,
Uuid
};

View file

@ -30,7 +30,8 @@ TagModel::TagModel(QObject* parent)
{
m_defaultSearches << qMakePair(tr("Clear Search"), QString("")) << qMakePair(tr("All Entries"), QString("*"))
<< qMakePair(tr("Expired"), QString("is:expired"))
<< qMakePair(tr("Weak Passwords"), QString("is:weak"));
<< qMakePair(tr("Weak Passwords"), QString("is:weak"))
<< qMakePair(tr("TOTP Entries"), QString("has:totp"));
}
TagModel::~TagModel() = default;

View file

@ -18,6 +18,7 @@
#include "TestEntrySearcher.h"
#include "core/Group.h"
#include "core/Tools.h"
#include "core/Totp.h"
#include <QTest>
@ -394,3 +395,42 @@ void TestEntrySearcher::testUUIDSearch()
m_searchResult = m_entrySearcher.search("uuid:" + Tools::uuidToHex(uuid1), m_rootGroup);
QCOMPARE(m_searchResult.count(), 1);
}
void TestEntrySearcher::testTotpSearch()
{
auto entry1 = new Entry();
entry1->setGroup(m_rootGroup);
entry1->setTitle("Regular Entry");
auto entry2 = new Entry();
entry2->setGroup(m_rootGroup);
entry2->setTitle("TOTP Entry");
// Set up TOTP on entry2
auto totpSettings = Totp::createSettings("GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ", 6, 30);
entry2->setTotp(totpSettings);
auto entry3 = new Entry();
entry3->setGroup(m_rootGroup);
entry3->setTitle("Another TOTP Entry");
// Set up TOTP on entry3
auto totpSettings2 = Totp::createSettings("MFRGG43UEBUXGIDBKRWXAZLSMUQGG6LQ", 6, 30);
entry3->setTotp(totpSettings2);
// Test searching for TOTP entries
m_searchResult = m_entrySearcher.search("has:totp", m_rootGroup);
QCOMPARE(m_searchResult.count(), 2);
QVERIFY(m_searchResult.contains(entry2));
QVERIFY(m_searchResult.contains(entry3));
QVERIFY(!m_searchResult.contains(entry1));
// Test case insensitive search
m_searchResult = m_entrySearcher.search("has:TOTP", m_rootGroup);
QCOMPARE(m_searchResult.count(), 2);
// Test excluding TOTP entries
m_searchResult = m_entrySearcher.search("!has:totp", m_rootGroup);
QCOMPARE(m_searchResult.count(), 1);
QVERIFY(m_searchResult.contains(entry1));
QVERIFY(!m_searchResult.contains(entry2));
QVERIFY(!m_searchResult.contains(entry3));
}

View file

@ -39,6 +39,7 @@ private slots:
void testGroup();
void testSkipProtected();
void testUUIDSearch();
void testTotpSearch();
private:
Group* m_rootGroup;