Fix cross-database reference resolution to handle unresolvable references correctly

Co-authored-by: droidmonkey <2809491+droidmonkey@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-06-19 14:41:05 +00:00
parent b0f90f3705
commit af5261d093
2 changed files with 22 additions and 9 deletions

View File

@@ -1423,22 +1423,34 @@ void Entry::resolveReferencesBeforeDatabaseMove()
// Resolve references in all default attributes // Resolve references in all default attributes
for (const QString& key : EntryAttributes::DefaultAttributes) { for (const QString& key : EntryAttributes::DefaultAttributes) {
if (m_attributes->contains(key) && m_attributes->isReference(key)) { if (m_attributes->contains(key) && m_attributes->isReference(key)) {
QString resolvedValue = resolveMultiplePlaceholdersRecursive(m_attributes->value(key), 10); QString originalValue = m_attributes->value(key);
QString resolvedValue = resolveMultiplePlaceholdersRecursive(originalValue, 10);
// Only replace if the resolution produced a different value and it's not empty
// Empty resolution means the reference couldn't be resolved, so keep original
if (!resolvedValue.isEmpty() && resolvedValue != originalValue) {
bool isProtected = m_attributes->isProtected(key); bool isProtected = m_attributes->isProtected(key);
m_attributes->set(key, resolvedValue, isProtected); m_attributes->set(key, resolvedValue, isProtected);
} }
} }
}
// Resolve references in custom attributes // Resolve references in custom attributes
const QList<QString> customKeys = m_attributes->customKeys(); const QList<QString> customKeys = m_attributes->customKeys();
for (const QString& key : customKeys) { for (const QString& key : customKeys) {
if (m_attributes->isReference(key)) { if (m_attributes->isReference(key)) {
QString resolvedValue = resolveMultiplePlaceholdersRecursive(m_attributes->value(key), 10); QString originalValue = m_attributes->value(key);
QString resolvedValue = resolveMultiplePlaceholdersRecursive(originalValue, 10);
// Only replace if the resolution produced a different value and it's not empty
// Empty resolution means the reference couldn't be resolved, so keep original
if (!resolvedValue.isEmpty() && resolvedValue != originalValue) {
bool isProtected = m_attributes->isProtected(key); bool isProtected = m_attributes->isProtected(key);
m_attributes->set(key, resolvedValue, isProtected); m_attributes->set(key, resolvedValue, isProtected);
} }
} }
} }
}
QString Entry::maskPasswordPlaceholders(const QString& str) const QString Entry::maskPasswordPlaceholders(const QString& str) const
{ {

View File

@@ -712,7 +712,8 @@ void TestEntry::testCrossDatabaseReferences()
QCOMPARE(refEntry->resolveMultiplePlaceholders(refEntry->password()), QString("OriginalPassword")); QCOMPARE(refEntry->resolveMultiplePlaceholders(refEntry->password()), QString("OriginalPassword"));
QCOMPARE(refEntry->resolveMultiplePlaceholders(refEntry->url()), QString("http://original.com")); QCOMPARE(refEntry->resolveMultiplePlaceholders(refEntry->url()), QString("http://original.com"));
QCOMPARE(refEntry->resolveMultiplePlaceholders(refEntry->notes()), QString("OriginalNotes")); QCOMPARE(refEntry->resolveMultiplePlaceholders(refEntry->notes()), QString("OriginalNotes"));
QCOMPARE(refEntry->resolveMultiplePlaceholders(refEntry->attributes()->value("CustomRef")), QString("OriginalTitle")); QCOMPARE(refEntry->resolveMultiplePlaceholders(refEntry->attributes()->value("CustomRef")),
QString("OriginalTitle"));
// Verify the attributes still contain references (not yet resolved) // Verify the attributes still contain references (not yet resolved)
QVERIFY(refEntry->attributes()->isReference(EntryAttributes::TitleKey)); QVERIFY(refEntry->attributes()->isReference(EntryAttributes::TitleKey));