Skip to content

Commit

Permalink
Added expire entry option
Browse files Browse the repository at this point in the history
  • Loading branch information
mattesony committed Nov 2, 2022
1 parent 30c0842 commit 6fc663f
Show file tree
Hide file tree
Showing 14 changed files with 158 additions and 6 deletions.
29 changes: 29 additions & 0 deletions share/translations/keepassxc_en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2609,6 +2609,10 @@ Would you like to correct it?</source>
<numerusform></numerusform>
</translation>
</message>
<message>
<source>Now</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EditEntryWidgetAdvanced</name>
Expand Down Expand Up @@ -5458,6 +5462,10 @@ We recommend you use the AppImage available on our downloads page.</source>
<source>XML File…</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>&amp;Expire Entry…</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ManageDatabase</name>
Expand Down Expand Up @@ -8040,6 +8048,13 @@ This options is deprecated, use --set-key-file instead.</source>
<source>Exclude from reports</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<source>Expire Entry(s)…</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
</context>
<context>
<name>ReportsWidgetHealthcheck</name>
Expand Down Expand Up @@ -8129,6 +8144,13 @@ This options is deprecated, use --set-key-file instead.</source>
<source>Exclude from reports</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<source>Expire Entry(s)…</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
</context>
<context>
<name>ReportsWidgetHibp</name>
Expand Down Expand Up @@ -8227,6 +8249,13 @@ This options is deprecated, use --set-key-file instead.</source>
<source>Exclude from reports</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<source>Expire Entry(s)…</source>
<translation type="unfinished">
<numerusform></numerusform>
<numerusform></numerusform>
</translation>
</message>
</context>
<context>
<name>ReportsWidgetStatistics</name>
Expand Down
25 changes: 25 additions & 0 deletions src/gui/DatabaseWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,22 @@ void DatabaseWidget::setupTotp()
setupTotpDialog->open();
}

void DatabaseWidget::expireSelectedEntries()
{
const QModelIndexList selected = m_entryView->selectionModel()->selectedRows();
if (selected.isEmpty()) {
return;
}

// Resolve entries from the selection model
QList<Entry*> selectedEntries;
for (const QModelIndex& index : selected) {
selectedEntries.append(m_entryView->entryFromIndex(index));
}

expireEntries(std::move(selectedEntries));
}

void DatabaseWidget::deleteSelectedEntries()
{
const QModelIndexList selected = m_entryView->selectionModel()->selectedRows();
Expand Down Expand Up @@ -523,6 +539,15 @@ void DatabaseWidget::restoreSelectedEntries()
}
}

void DatabaseWidget::expireEntries(QList<Entry*> selectedEntries)
{
if (selectedEntries.isEmpty()) {
return;
}

GuiTools::expireEntries(this, selectedEntries);
}

void DatabaseWidget::deleteEntries(QList<Entry*> selectedEntries, bool confirm)
{
if (selectedEntries.isEmpty()) {
Expand Down
2 changes: 2 additions & 0 deletions src/gui/DatabaseWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,10 @@ public slots:
void replaceDatabase(QSharedPointer<Database> db);
void createEntry();
void cloneEntry();
void expireSelectedEntries();
void deleteSelectedEntries();
void restoreSelectedEntries();
void expireEntries(QList<Entry*> entries);
void deleteEntries(QList<Entry*> entries, bool confirm = true);
void focusOnEntries(bool editIfFocused = false);
void focusOnGroups(bool editIfFocused = false);
Expand Down
14 changes: 14 additions & 0 deletions src/gui/GuiTools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "GuiTools.h"

#include "core/Clock.h"
#include "core/Config.h"
#include "core/Group.h"
#include "gui/MessageBox.h"
Expand Down Expand Up @@ -66,6 +67,19 @@ namespace GuiTools
}
}

size_t expireEntries(QWidget* parent, const QList<Entry*>& entries)
{
if (!parent || entries.isEmpty()) {
return 0;
}

for (auto entry : asConst(entries)) {
entry->setExpiryTime(Clock::currentDateTimeUtc());
entry->setExpires(true);
}
return entries.size();
}

size_t deleteEntriesResolveReferences(QWidget* parent, const QList<Entry*>& entries, bool permanent)
{
if (!parent || entries.isEmpty()) {
Expand Down
1 change: 1 addition & 0 deletions src/gui/GuiTools.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class Entry;
namespace GuiTools
{
bool confirmDeleteEntries(QWidget* parent, const QList<Entry*>& entries, bool permanent);
size_t expireEntries(QWidget* parent, const QList<Entry*>& entries);
size_t deleteEntriesResolveReferences(QWidget* parent, const QList<Entry*>& entries, bool permanent);
} // namespace GuiTools
#endif // KEEPASSXC_GUITOOLS_H
9 changes: 7 additions & 2 deletions src/gui/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ MainWindow::MainWindow()
m_entryContextMenu->addAction(m_ui->actionEntryAutoType);
m_entryContextMenu->addSeparator();
m_entryContextMenu->addAction(m_ui->actionEntryEdit);
m_entryContextMenu->addAction(m_ui->actionEntryExpire);
m_entryContextMenu->addAction(m_ui->actionEntryClone);
m_entryContextMenu->addAction(m_ui->actionEntryDelete);
m_entryContextMenu->addAction(m_ui->actionEntryNew);
Expand Down Expand Up @@ -303,6 +304,7 @@ MainWindow::MainWindow()
// Unfortunately, Qt::AA_DontShowShortcutsInContextMenus is broken, have to manually enable them
m_ui->actionEntryNew->setShortcutVisibleInContextMenu(true);
m_ui->actionEntryEdit->setShortcutVisibleInContextMenu(true);
m_ui->actionEntryExpire->setShortcutVisibleInContextMenu(true);
m_ui->actionEntryDelete->setShortcutVisibleInContextMenu(true);
m_ui->actionEntryRestore->setShortcutVisibleInContextMenu(true);
m_ui->actionEntryClone->setShortcutVisibleInContextMenu(true);
Expand Down Expand Up @@ -390,6 +392,7 @@ MainWindow::MainWindow()
m_ui->actionEntryNew->setIcon(icons()->icon("entry-new"));
m_ui->actionEntryClone->setIcon(icons()->icon("entry-clone"));
m_ui->actionEntryEdit->setIcon(icons()->icon("entry-edit"));
m_ui->actionEntryExpire->setIcon(icons()->icon("entry-expire"));
m_ui->actionEntryDelete->setIcon(icons()->icon("entry-delete"));
m_ui->actionEntryRestore->setIcon(icons()->icon("entry-restore"));
m_ui->actionEntryAutoType->setIcon(icons()->icon("auto-type"));
Expand Down Expand Up @@ -493,8 +496,9 @@ MainWindow::MainWindow()
connect(m_ui->actionQuit, SIGNAL(triggered()), SLOT(appExit()));

m_actionMultiplexer.connect(m_ui->actionEntryNew, SIGNAL(triggered()), SLOT(createEntry()));
m_actionMultiplexer.connect(m_ui->actionEntryClone, SIGNAL(triggered()), SLOT(cloneEntry()));
m_actionMultiplexer.connect(m_ui->actionEntryEdit, SIGNAL(triggered()), SLOT(switchToEntryEdit()));
m_actionMultiplexer.connect(m_ui->actionEntryExpire, SIGNAL(triggered()), SLOT(expireSelectedEntries()));
m_actionMultiplexer.connect(m_ui->actionEntryClone, SIGNAL(triggered()), SLOT(cloneEntry()));
m_actionMultiplexer.connect(m_ui->actionEntryDelete, SIGNAL(triggered()), SLOT(deleteSelectedEntries()));
m_actionMultiplexer.connect(m_ui->actionEntryRestore, SIGNAL(triggered()), SLOT(restoreSelectedEntries()));

Expand Down Expand Up @@ -908,8 +912,9 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode)
int numEntries = dbWidget->currentGroup()->entries().size();

m_ui->actionEntryNew->setEnabled(true);
m_ui->actionEntryClone->setEnabled(singleEntrySelected);
m_ui->actionEntryEdit->setEnabled(singleEntrySelected);
m_ui->actionEntryExpire->setEnabled(entriesSelected);
m_ui->actionEntryClone->setEnabled(singleEntrySelected);
m_ui->actionEntryDelete->setEnabled(entriesSelected);
m_ui->actionEntryRestore->setVisible(entriesSelected && recycleBinSelected);
m_ui->actionEntryRestore->setEnabled(entriesSelected && recycleBinSelected);
Expand Down
10 changes: 10 additions & 0 deletions src/gui/MainWindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@
</widget>
<addaction name="actionEntryNew"/>
<addaction name="actionEntryEdit"/>
<addaction name="actionEntryExpire"/>
<addaction name="actionEntryClone"/>
<addaction name="actionEntryDelete"/>
<addaction name="separator"/>
Expand Down Expand Up @@ -427,6 +428,7 @@
<addaction name="separator"/>
<addaction name="actionEntryNew"/>
<addaction name="actionEntryEdit"/>
<addaction name="actionEntryExpire"/>
<addaction name="actionEntryDelete"/>
<addaction name="separator"/>
<addaction name="actionEntryCopyUsername"/>
Expand Down Expand Up @@ -521,6 +523,14 @@
<string>View or edit entry</string>
</property>
</action>
<action name="actionEntryExpire">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Expire Entry…</string>
</property>
</action>
<action name="actionEntryDelete">
<property name="enabled">
<bool>false</bool>
Expand Down
2 changes: 1 addition & 1 deletion src/gui/entry/EditEntryWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1576,7 +1576,7 @@ void EditEntryWidget::deleteAllHistoryEntries()
QMenu* EditEntryWidget::createPresetsMenu()
{
auto* expirePresetsMenu = new QMenu(this);
expirePresetsMenu->addAction(tr("Now"))->setData(QVariant::fromValue(TimeDelta(0,0,0,0)));
expirePresetsMenu->addAction(tr("Now"))->setData(QVariant::fromValue(TimeDelta(0, 0, 0, 0)));
expirePresetsMenu->addAction(tr("%n hour(s)", nullptr, 12))->setData(QVariant::fromValue(TimeDelta::fromHours(12)));
expirePresetsMenu->addAction(tr("%n hour(s)", nullptr, 24))->setData(QVariant::fromValue(TimeDelta::fromHours(24)));
expirePresetsMenu->addSeparator();
Expand Down
23 changes: 22 additions & 1 deletion src/gui/reports/ReportsWidgetBrowserStatistics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,11 @@ void ReportsWidgetBrowserStatistics::customMenuRequested(QPoint pos)
});
}

// Create the "expire entry" menu item
const auto expEntry = new QAction(icons()->icon("entry-expire"), tr("Expire Entry(s)…", "", selected.size()), this);
menu->addAction(expEntry);
connect(expEntry, &QAction::triggered, this, &ReportsWidgetBrowserStatistics::expireSelectedEntries);

// Create the "delete entry" menu item
const auto delEntry = new QAction(icons()->icon("entry-delete"), tr("Delete Entry(s)…", "", selected.size()), this);
menu->addAction(delEntry);
Expand Down Expand Up @@ -316,7 +321,7 @@ void ReportsWidgetBrowserStatistics::saveSettings()
// Nothing to do - the tab is passive
}

void ReportsWidgetBrowserStatistics::deleteSelectedEntries()
QList<Entry*> ReportsWidgetBrowserStatistics::getSelectedEntries()
{
QList<Entry*> selectedEntries;
for (auto index : m_ui->browserStatisticsTableView->selectionModel()->selectedRows()) {
Expand All @@ -326,7 +331,23 @@ void ReportsWidgetBrowserStatistics::deleteSelectedEntries()
selectedEntries << entry;
}
}
return selectedEntries;
}

void ReportsWidgetBrowserStatistics::expireSelectedEntries()
{
QList<Entry*> selectedEntries = getSelectedEntries();
if (selectedEntries.isEmpty()) {
return;
}
GuiTools::expireEntries(this, selectedEntries);

calculateHealth();
}

void ReportsWidgetBrowserStatistics::deleteSelectedEntries()
{
QList<Entry*> selectedEntries = getSelectedEntries();
bool permanent = !m_db->metadata()->recycleBinEnabled();
if (GuiTools::confirmDeleteEntries(this, selectedEntries, permanent)) {
GuiTools::deleteEntriesResolveReferences(this, selectedEntries, permanent);
Expand Down
2 changes: 2 additions & 0 deletions src/gui/reports/ReportsWidgetBrowserStatistics.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ public slots:
void calculateBrowserStatistics();
void emitEntryActivated(const QModelIndex& index);
void customMenuRequested(QPoint);
QList<Entry*> getSelectedEntries();
void expireSelectedEntries();
void deleteSelectedEntries();

private:
Expand Down
23 changes: 22 additions & 1 deletion src/gui/reports/ReportsWidgetHealthcheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,11 @@ void ReportsWidgetHealthcheck::customMenuRequested(QPoint pos)
});
}

// Create the "Expire entry" menu item
const auto expEntry = new QAction(tr("Expire Entry(s)…", "", selected.size()), this);
menu->addAction(expEntry);
connect(expEntry, &QAction::triggered, this, &ReportsWidgetHealthcheck::expireSelectedEntries);

// Create the "delete entry" menu item
const auto delEntry = new QAction(icons()->icon("entry-delete"), tr("Delete Entry(s)…", "", selected.size()), this);
menu->addAction(delEntry);
Expand Down Expand Up @@ -372,7 +377,7 @@ void ReportsWidgetHealthcheck::saveSettings()
// nothing to do - the tab is passive
}

void ReportsWidgetHealthcheck::deleteSelectedEntries()
QList<Entry*> ReportsWidgetHealthcheck::getSelectedEntries()
{
QList<Entry*> selectedEntries;
for (auto index : m_ui->healthcheckTableView->selectionModel()->selectedRows()) {
Expand All @@ -382,7 +387,23 @@ void ReportsWidgetHealthcheck::deleteSelectedEntries()
selectedEntries << entry;
}
}
return selectedEntries;
}

void ReportsWidgetHealthcheck::expireSelectedEntries()
{
QList<Entry*> selectedEntries = getSelectedEntries();
if (selectedEntries.isEmpty()) {
return;
}
GuiTools::expireEntries(this, selectedEntries);

calculateHealth();
}

void ReportsWidgetHealthcheck::deleteSelectedEntries()
{
QList<Entry*> selectedEntries = getSelectedEntries();
bool permanent = !m_db->metadata()->recycleBinEnabled();
if (GuiTools::confirmDeleteEntries(this, selectedEntries, permanent)) {
GuiTools::deleteEntriesResolveReferences(this, selectedEntries, permanent);
Expand Down
2 changes: 2 additions & 0 deletions src/gui/reports/ReportsWidgetHealthcheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ public slots:
void calculateHealth();
void emitEntryActivated(const QModelIndex& index);
void customMenuRequested(QPoint);
QList<Entry*> getSelectedEntries();
void expireSelectedEntries();
void deleteSelectedEntries();

private:
Expand Down
20 changes: 19 additions & 1 deletion src/gui/reports/ReportsWidgetHibp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,11 @@ void ReportsWidgetHibp::customMenuRequested(QPoint pos)
});
}

// Create the "Expire entry" menu item
const auto expEntry = new QAction(tr("Expire Entry(s)…", "", selected.size()), this);
menu->addAction(expEntry);
connect(expEntry, &QAction::triggered, this, &ReportsWidgetHibp::expireSelectedEntries);

// Create the "delete entry" menu item
const auto delEntry = new QAction(icons()->icon("entry-delete"), tr("Delete Entry(s)…", "", selected.size()), this);
menu->addAction(delEntry);
Expand Down Expand Up @@ -411,7 +416,7 @@ void ReportsWidgetHibp::customMenuRequested(QPoint pos)
menu->popup(m_ui->hibpTableView->viewport()->mapToGlobal(pos));
}

void ReportsWidgetHibp::deleteSelectedEntries()
QList<Entry*> ReportsWidgetHibp::getSelectedEntries()
{
QList<Entry*> selectedEntries;
for (auto index : m_ui->hibpTableView->selectionModel()->selectedRows()) {
Expand All @@ -421,7 +426,20 @@ void ReportsWidgetHibp::deleteSelectedEntries()
selectedEntries << entry;
}
}
return selectedEntries;
}

void ReportsWidgetHibp::expireSelectedEntries()
{
QList<Entry*> selectedEntries = getSelectedEntries();
GuiTools::expireEntries(this, selectedEntries);

makeHibpTable();
}

void ReportsWidgetHibp::deleteSelectedEntries()
{
QList<Entry*> selectedEntries = getSelectedEntries();
bool permanent = !m_db->metadata()->recycleBinEnabled();
if (GuiTools::confirmDeleteEntries(this, selectedEntries, permanent)) {
GuiTools::deleteEntriesResolveReferences(this, selectedEntries, permanent);
Expand Down
2 changes: 2 additions & 0 deletions src/gui/reports/ReportsWidgetHibp.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ public slots:
void fetchFailed(const QString& error);
void makeHibpTable();
void customMenuRequested(QPoint);
QList<Entry*> getSelectedEntries();
void expireSelectedEntries();
void deleteSelectedEntries();

private:
Expand Down

0 comments on commit 6fc663f

Please sign in to comment.