Show expired entries on DB unlock

* Show banner message about expired entries
* Add config option and expiration offset
* Only show expiry warning on first DB unlock
* Default to on with 3-day offset from expiration
This commit is contained in:
Balazs Gyurak 2022-01-22 18:20:41 +00:00 committed by Jonathan White
parent 3c824cb500
commit 6897787d8f
9 changed files with 145 additions and 1 deletions

View File

@ -460,6 +460,22 @@
<source>{DB_FILENAME}.old.kdbx</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>On database unlock, show entries that </source>
<translation type="unfinished"></translation>
</message>
<message>
<source> days</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>are expired</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>will expire within </source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ApplicationSettingsWidgetSecurity</name>
@ -2385,6 +2401,14 @@ Disable safe saves and try again?</translation>
<source>Database Tags</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Expired entries</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Entries expiring within %1 days</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EditEntryWidget</name>

View File

@ -111,6 +111,8 @@ static const QHash<Config::ConfigKey, ConfigDirective> configStrings = {
{Config::GUI_CheckForUpdates, {QS("GUI/CheckForUpdates"), Roaming, true}},
{Config::GUI_CheckForUpdatesNextCheck, {QS("GUI/CheckForUpdatesNextCheck"), Local, 0}},
{Config::GUI_CheckForUpdatesIncludeBetas, {QS("GUI/CheckForUpdatesIncludeBetas"), Roaming, false}},
{Config::GUI_ShowExpiredEntriesOnDatabaseUnlock, {QS("GUI/ShowExpiredEntriesOnDatabaseUnlock"), Roaming, true}},
{Config::GUI_ShowExpiredEntriesOnDatabaseUnlockOffsetDays, {QS("GUI/ShowExpiredEntriesOnDatabaseUnlockOffsetDays"), Roaming, 3}},
{Config::GUI_MainWindowGeometry, {QS("GUI/MainWindowGeometry"), Local, {}}},
{Config::GUI_MainWindowState, {QS("GUI/MainWindowState"), Local, {}}},

View File

@ -91,6 +91,8 @@ public:
GUI_CompactMode,
GUI_CheckForUpdates,
GUI_CheckForUpdatesIncludeBetas,
GUI_ShowExpiredEntriesOnDatabaseUnlock,
GUI_ShowExpiredEntriesOnDatabaseUnlockOffsetDays,
GUI_MainWindowGeometry,
GUI_MainWindowState,

View File

@ -441,7 +441,12 @@ int Entry::size() const
bool Entry::isExpired() const
{
return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Clock::currentDateTimeUtc();
return willExpireInDays(0);
}
bool Entry::willExpireInDays(int days) const
{
return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Clock::currentDateTime().addDays(days);
}
bool Entry::isRecycled() const

View File

@ -121,6 +121,7 @@ public:
bool hasTotp() const;
bool isExpired() const;
bool willExpireInDays(int days) const;
bool isRecycled() const;
bool isAttributeReference(const QString& key) const;
bool isAttributeReferenceOf(const QString& key, const QUuid& uuid) const;

View File

@ -120,6 +120,8 @@ ApplicationSettingsWidget::ApplicationSettingsWidget(QWidget* parent)
connect(m_generalUi->backupBeforeSaveCheckBox, SIGNAL(toggled(bool)),
m_generalUi->backupFilePathPicker, SLOT(setEnabled(bool)));
connect(m_generalUi->backupFilePathPicker, SIGNAL(pressed()), SLOT(selectBackupDirectory()));
connect(m_generalUi->showExpiredEntriesOnDatabaseUnlockCheckBox, SIGNAL(toggled(bool)),
SLOT(showExpiredEntriesOnDatabaseUnlockToggled(bool)));
connect(m_secUi->clearClipboardCheckBox, SIGNAL(toggled(bool)),
m_secUi->clearClipboardSpinBox, SLOT(setEnabled(bool)));
@ -251,6 +253,12 @@ void ApplicationSettingsWidget::loadSettings()
m_generalUi->checkForUpdatesIncludeBetasCheckBox->setChecked(
config()->get(Config::GUI_CheckForUpdatesIncludeBetas).toBool());
m_generalUi->showExpiredEntriesOnDatabaseUnlockCheckBox->setChecked(
config()->get(Config::GUI_ShowExpiredEntriesOnDatabaseUnlock).toBool());
m_generalUi->showExpiredEntriesOnDatabaseUnlockOffsetSpinBox->setValue(
config()->get(Config::GUI_ShowExpiredEntriesOnDatabaseUnlockOffsetDays).toInt());
showExpiredEntriesOnDatabaseUnlockToggled(m_generalUi->showExpiredEntriesOnDatabaseUnlockCheckBox->isChecked());
m_generalUi->autoTypeAskCheckBox->setChecked(config()->get(Config::Security_AutoTypeAsk).toBool());
if (autoType()->isAvailable()) {
@ -378,6 +386,11 @@ void ApplicationSettingsWidget::saveSettings()
config()->set(Config::GUI_CheckForUpdatesIncludeBetas,
m_generalUi->checkForUpdatesIncludeBetasCheckBox->isChecked());
config()->set(Config::GUI_ShowExpiredEntriesOnDatabaseUnlock,
m_generalUi->showExpiredEntriesOnDatabaseUnlockCheckBox->isChecked());
config()->set(Config::GUI_ShowExpiredEntriesOnDatabaseUnlockOffsetDays,
m_generalUi->showExpiredEntriesOnDatabaseUnlockOffsetSpinBox->value());
config()->set(Config::Security_AutoTypeAsk, m_generalUi->autoTypeAskCheckBox->isChecked());
if (autoType()->isAvailable()) {
@ -520,6 +533,11 @@ void ApplicationSettingsWidget::checkUpdatesToggled(bool checked)
m_generalUi->checkForUpdatesIncludeBetasCheckBox->setEnabled(checked);
}
void ApplicationSettingsWidget::showExpiredEntriesOnDatabaseUnlockToggled(bool checked)
{
m_generalUi->showExpiredEntriesOnDatabaseUnlockOffsetSpinBox->setEnabled(checked);
}
void ApplicationSettingsWidget::selectBackupDirectory()
{
auto backupDirectory =

View File

@ -62,6 +62,7 @@ private slots:
void systrayToggled(bool checked);
void rememberDatabasesToggled(bool checked);
void checkUpdatesToggled(bool checked);
void showExpiredEntriesOnDatabaseUnlockToggled(bool checked);
void selectBackupDirectory();
private:

View File

@ -234,6 +234,73 @@
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="showExpiredEntriesSubLayout">
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QCheckBox" name="showExpiredEntriesOnDatabaseUnlockCheckBox">
<property name="text">
<string>On database unlock, show entries that </string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="showExpiredEntriesOnDatabaseUnlockOffsetSpinBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="accessibleName">
<string>On database unlock, show entries that </string>
</property>
<property name="prefix">
<string>will expire within </string>
</property>
<property name="suffix">
<string> days</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>30</number>
</property>
<property name="value">
<number>0</number>
</property>
<property name="specialValueText">
<string>are expired</string>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="showExpiredEntriesSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
@ -1138,6 +1205,8 @@
<tabstop>rememberLastKeyFilesCheckBox</tabstop>
<tabstop>checkForUpdatesOnStartupCheckBox</tabstop>
<tabstop>checkForUpdatesIncludeBetasCheckBox</tabstop>
<tabstop>showExpiredEntriesOnDatabaseUnlockCheckBox</tabstop>
<tabstop>showExpiredEntriesOnDatabaseUnlockOffsetSpinBox</tabstop>
<tabstop>autoSaveAfterEveryChangeCheckBox</tabstop>
<tabstop>autoSaveOnExitCheckBox</tabstop>
<tabstop>autoSaveNonDataChangesCheckBox</tabstop>

View File

@ -1119,7 +1119,29 @@ void DatabaseWidget::loadDatabase(bool accepted)
replaceDatabase(openWidget->database());
switchToMainView();
processAutoOpen();
restoreGroupEntryFocus(m_groupBeforeLock, m_entryBeforeLock);
// Only show expired entries if first unlock and option is enabled
if (m_groupBeforeLock.isNull() && config()->get(Config::GUI_ShowExpiredEntriesOnDatabaseUnlock).toBool()) {
int expirationOffset = config()->get(Config::GUI_ShowExpiredEntriesOnDatabaseUnlockOffsetDays).toInt();
QList<Entry*> expiredEntries;
for (auto entry : m_db->rootGroup()->entriesRecursive()) {
if (entry->willExpireInDays(expirationOffset) && !entry->excludeFromReports() && !entry->isRecycled()) {
expiredEntries << entry;
}
}
if (!expiredEntries.isEmpty()) {
m_entryView->displaySearch(expiredEntries);
m_entryView->setFirstEntryActive();
m_searchingLabel->setText(expirationOffset == 0
? tr("Expired entries")
: tr("Entries expiring within %1 days").arg(expirationOffset));
m_searchingLabel->setVisible(true);
}
}
m_groupBeforeLock = QUuid();
m_entryBeforeLock = QUuid();
m_saveAttempts = 0;