From b10a55a547af321ebe9365ca6ca3932ecd02099b Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sat, 10 Oct 2020 19:36:00 -0400 Subject: [PATCH] Prevent data loss when drag/drop between databases * Fixes #5262 * Always reset the UUID on groups and entries moved or copied between databases. This prevents data loss when the group/entry is moved back to the original database. --- src/core/Entry.cpp | 2 ++ src/core/Entry.h | 13 ++++++----- src/core/Group.cpp | 4 +--- src/core/Group.h | 3 +-- src/gui/group/GroupModel.cpp | 43 ++++++++++++++++++++++-------------- 5 files changed, 37 insertions(+), 28 deletions(-) diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index 0322d353c..81f856ff5 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -36,6 +36,8 @@ const int Entry::ResolveMaximumDepth = 10; const QString Entry::AutoTypeSequenceUsername = "{USERNAME}{ENTER}"; const QString Entry::AutoTypeSequencePassword = "{PASSWORD}{ENTER}"; +Entry::CloneFlags Entry::DefaultCloneFlags = Entry::CloneNewUuid | Entry::CloneResetTimeInfo; + Entry::Entry() : m_attributes(new EntryAttributes(this)) , m_attachments(new EntryAttachments(this)) diff --git a/src/core/Entry.h b/src/core/Entry.h index cbaf3e2c0..27df86596 100644 --- a/src/core/Entry.h +++ b/src/core/Entry.h @@ -124,11 +124,6 @@ public: CustomData* customData(); const CustomData* customData() const; - static const int DefaultIconNumber; - static const int ResolveMaximumDepth; - static const QString AutoTypeSequenceUsername; - static const QString AutoTypeSequencePassword; - void setUuid(const QUuid& uuid); void setIcon(int iconNumber); void setIcon(const QUuid& uuid); @@ -209,13 +204,19 @@ public: DbDir }; + static const int DefaultIconNumber; + static const int ResolveMaximumDepth; + static const QString AutoTypeSequenceUsername; + static const QString AutoTypeSequencePassword; + static CloneFlags DefaultCloneFlags; + /** * Creates a duplicate of this entry except that the returned entry isn't * part of any group. * Note that you need to copy the custom icons manually when inserting the * new entry into another database. */ - Entry* clone(CloneFlags flags) const; + Entry* clone(CloneFlags flags = DefaultCloneFlags) const; void copyDataFrom(const Entry* other); QString maskPasswordPlaceholders(const QString& str) const; Entry* resolveReference(const QString& str) const; diff --git a/src/core/Group.cpp b/src/core/Group.cpp index 8be8b5f95..56e545bf6 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -37,9 +37,7 @@ const int Group::RecycleBinIconNumber = 43; const QString Group::RootAutoTypeSequence = "{USERNAME}{TAB}{PASSWORD}{ENTER}"; Group::CloneFlags Group::DefaultCloneFlags = - static_cast(Group::CloneNewUuid | Group::CloneResetTimeInfo | Group::CloneIncludeEntries); -Entry::CloneFlags Group::DefaultEntryCloneFlags = - static_cast(Entry::CloneNewUuid | Entry::CloneResetTimeInfo); + Group::CloneNewUuid | Group::CloneResetTimeInfo | Group::CloneIncludeEntries; Group::Group() : m_customData(new CustomData(this)) diff --git a/src/core/Group.h b/src/core/Group.h index 8ff33d8d0..4bea8e4eb 100644 --- a/src/core/Group.h +++ b/src/core/Group.h @@ -109,7 +109,6 @@ public: static const int DefaultIconNumber; static const int RecycleBinIconNumber; static CloneFlags DefaultCloneFlags; - static Entry::CloneFlags DefaultEntryCloneFlags; static const QString RootAutoTypeSequence; Group* findChildByName(const QString& name); @@ -158,7 +157,7 @@ public: QSet customIconsRecursive() const; QList usernamesRecursive(int topN = -1) const; - Group* clone(Entry::CloneFlags entryFlags = DefaultEntryCloneFlags, + Group* clone(Entry::CloneFlags entryFlags = Entry::DefaultCloneFlags, CloneFlags groupFlags = DefaultCloneFlags) const; void copyDataFrom(const Group* other); diff --git a/src/gui/group/GroupModel.cpp b/src/gui/group/GroupModel.cpp index beba13774..e61410334 100644 --- a/src/gui/group/GroupModel.cpp +++ b/src/gui/group/GroupModel.cpp @@ -252,19 +252,23 @@ bool GroupModel::dropMimeData(const QMimeData* data, row--; } - Group* group; - if (action == Qt::MoveAction) { - group = dragGroup; - } else { - group = dragGroup->clone(); - } - Database* sourceDb = dragGroup->database(); Database* targetDb = parentGroup->database(); + Group* group = dragGroup; + if (sourceDb != targetDb) { QSet customIcons = group->customIconsRecursive(); targetDb->metadata()->copyCustomIcons(customIcons, sourceDb->metadata()); + + // Always clone the group across db's to reset UUIDs + group = dragGroup->clone(); + if (action == Qt::MoveAction) { + // Remove the original group from the sourceDb + delete dragGroup; + } + } else if (action == Qt::CopyAction) { + group = dragGroup->clone(); } group->setParent(parentGroup, row); @@ -288,19 +292,24 @@ bool GroupModel::dropMimeData(const QMimeData* data, continue; } - Entry* entry; - if (action == Qt::MoveAction) { - entry = dragEntry; - } else { - entry = dragEntry->clone(Entry::CloneNewUuid | Entry::CloneResetTimeInfo); - } - Database* sourceDb = dragEntry->group()->database(); Database* targetDb = parentGroup->database(); - QUuid customIcon = entry->iconUuid(); - if (sourceDb != targetDb && !customIcon.isNull() && !targetDb->metadata()->hasCustomIcon(customIcon)) { - targetDb->metadata()->addCustomIcon(customIcon, sourceDb->metadata()->customIcon(customIcon)); + Entry* entry = dragEntry; + + if (sourceDb != targetDb) { + QUuid customIcon = entry->iconUuid(); + if (!customIcon.isNull() && !targetDb->metadata()->hasCustomIcon(customIcon)) { + targetDb->metadata()->addCustomIcon(customIcon, sourceDb->metadata()->customIcon(customIcon)); + } + + // Always clone the entry across db's to reset the UUID + entry = dragEntry->clone(); + if (action == Qt::MoveAction) { + delete dragEntry; + } + } else if (action == Qt::CopyAction) { + entry = dragEntry->clone(); } entry->setGroup(parentGroup);