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.
This commit is contained in:
Jonathan White 2020-10-10 19:36:00 -04:00
parent 389899e0c6
commit b10a55a547
5 changed files with 37 additions and 28 deletions

View file

@ -36,6 +36,8 @@ const int Entry::ResolveMaximumDepth = 10;
const QString Entry::AutoTypeSequenceUsername = "{USERNAME}{ENTER}"; const QString Entry::AutoTypeSequenceUsername = "{USERNAME}{ENTER}";
const QString Entry::AutoTypeSequencePassword = "{PASSWORD}{ENTER}"; const QString Entry::AutoTypeSequencePassword = "{PASSWORD}{ENTER}";
Entry::CloneFlags Entry::DefaultCloneFlags = Entry::CloneNewUuid | Entry::CloneResetTimeInfo;
Entry::Entry() Entry::Entry()
: m_attributes(new EntryAttributes(this)) : m_attributes(new EntryAttributes(this))
, m_attachments(new EntryAttachments(this)) , m_attachments(new EntryAttachments(this))

View file

@ -124,11 +124,6 @@ public:
CustomData* customData(); CustomData* customData();
const CustomData* customData() const; 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 setUuid(const QUuid& uuid);
void setIcon(int iconNumber); void setIcon(int iconNumber);
void setIcon(const QUuid& uuid); void setIcon(const QUuid& uuid);
@ -209,13 +204,19 @@ public:
DbDir 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 * Creates a duplicate of this entry except that the returned entry isn't
* part of any group. * part of any group.
* Note that you need to copy the custom icons manually when inserting the * Note that you need to copy the custom icons manually when inserting the
* new entry into another database. * new entry into another database.
*/ */
Entry* clone(CloneFlags flags) const; Entry* clone(CloneFlags flags = DefaultCloneFlags) const;
void copyDataFrom(const Entry* other); void copyDataFrom(const Entry* other);
QString maskPasswordPlaceholders(const QString& str) const; QString maskPasswordPlaceholders(const QString& str) const;
Entry* resolveReference(const QString& str) const; Entry* resolveReference(const QString& str) const;

View file

@ -37,9 +37,7 @@ const int Group::RecycleBinIconNumber = 43;
const QString Group::RootAutoTypeSequence = "{USERNAME}{TAB}{PASSWORD}{ENTER}"; const QString Group::RootAutoTypeSequence = "{USERNAME}{TAB}{PASSWORD}{ENTER}";
Group::CloneFlags Group::DefaultCloneFlags = Group::CloneFlags Group::DefaultCloneFlags =
static_cast<Group::CloneFlags>(Group::CloneNewUuid | Group::CloneResetTimeInfo | Group::CloneIncludeEntries); Group::CloneNewUuid | Group::CloneResetTimeInfo | Group::CloneIncludeEntries;
Entry::CloneFlags Group::DefaultEntryCloneFlags =
static_cast<Entry::CloneFlags>(Entry::CloneNewUuid | Entry::CloneResetTimeInfo);
Group::Group() Group::Group()
: m_customData(new CustomData(this)) : m_customData(new CustomData(this))

View file

@ -109,7 +109,6 @@ public:
static const int DefaultIconNumber; static const int DefaultIconNumber;
static const int RecycleBinIconNumber; static const int RecycleBinIconNumber;
static CloneFlags DefaultCloneFlags; static CloneFlags DefaultCloneFlags;
static Entry::CloneFlags DefaultEntryCloneFlags;
static const QString RootAutoTypeSequence; static const QString RootAutoTypeSequence;
Group* findChildByName(const QString& name); Group* findChildByName(const QString& name);
@ -158,7 +157,7 @@ public:
QSet<QUuid> customIconsRecursive() const; QSet<QUuid> customIconsRecursive() const;
QList<QString> usernamesRecursive(int topN = -1) const; QList<QString> usernamesRecursive(int topN = -1) const;
Group* clone(Entry::CloneFlags entryFlags = DefaultEntryCloneFlags, Group* clone(Entry::CloneFlags entryFlags = Entry::DefaultCloneFlags,
CloneFlags groupFlags = DefaultCloneFlags) const; CloneFlags groupFlags = DefaultCloneFlags) const;
void copyDataFrom(const Group* other); void copyDataFrom(const Group* other);

View file

@ -252,19 +252,23 @@ bool GroupModel::dropMimeData(const QMimeData* data,
row--; row--;
} }
Group* group;
if (action == Qt::MoveAction) {
group = dragGroup;
} else {
group = dragGroup->clone();
}
Database* sourceDb = dragGroup->database(); Database* sourceDb = dragGroup->database();
Database* targetDb = parentGroup->database(); Database* targetDb = parentGroup->database();
Group* group = dragGroup;
if (sourceDb != targetDb) { if (sourceDb != targetDb) {
QSet<QUuid> customIcons = group->customIconsRecursive(); QSet<QUuid> customIcons = group->customIconsRecursive();
targetDb->metadata()->copyCustomIcons(customIcons, sourceDb->metadata()); 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); group->setParent(parentGroup, row);
@ -288,21 +292,26 @@ bool GroupModel::dropMimeData(const QMimeData* data,
continue; continue;
} }
Entry* entry;
if (action == Qt::MoveAction) {
entry = dragEntry;
} else {
entry = dragEntry->clone(Entry::CloneNewUuid | Entry::CloneResetTimeInfo);
}
Database* sourceDb = dragEntry->group()->database(); Database* sourceDb = dragEntry->group()->database();
Database* targetDb = parentGroup->database(); Database* targetDb = parentGroup->database();
QUuid customIcon = entry->iconUuid();
if (sourceDb != targetDb && !customIcon.isNull() && !targetDb->metadata()->hasCustomIcon(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)); 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); entry->setGroup(parentGroup);
} }
} }