diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index 49beb1e9e..62d2b567b 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -23,6 +23,7 @@ #include "core/Group.h" #include "core/Metadata.h" #include "core/PasswordHealth.h" +#include "core/TimeDelta.h" #include "core/Tools.h" #include "totp/totp.h" @@ -727,6 +728,20 @@ void Entry::setExpiryTime(const QDateTime& dateTime) } } +void Entry::setExtendsExpirationOnPwdChange(const bool& value) +{ + if (m_customData->value("ExpirationExtension").toInt() != value) { + m_customData->set("ExpirationExtension", QString::number(value)); + emit entryModified(); + } +} + +void Entry::setExpirationExtension(const QString& quantity, const QString& magnitude) +{ + m_customData->set("ExpirationExtensionQuantity", quantity); + m_customData->set("ExpirationExtensionMagnitude", magnitude); +} + QList Entry::historyItems() { return m_history; diff --git a/src/core/Entry.h b/src/core/Entry.h index 88a89761a..3b7dd2018 100644 --- a/src/core/Entry.h +++ b/src/core/Entry.h @@ -151,6 +151,8 @@ public: void setDefaultAttribute(const QString& attribute, const QString& value); void setExpires(const bool& value); void setExpiryTime(const QDateTime& dateTime); + void setExtendsExpirationOnPwdChange(const bool& value); + void setExpirationExtension(const QString& quantity, const QString& magnitude); void setTotp(QSharedPointer settings); QList historyItems(); diff --git a/src/core/TimeDelta.cpp b/src/core/TimeDelta.cpp index a5331736c..0c172bc78 100644 --- a/src/core/TimeDelta.cpp +++ b/src/core/TimeDelta.cpp @@ -53,6 +53,16 @@ TimeDelta::TimeDelta(int days, int months, int years) { } +TimeDelta TimeDelta::operator*(unsigned int n) +{ + return TimeDelta(n * m_days, n * m_months, n * m_years); +} + +bool TimeDelta::operator==(const TimeDelta& tD) const +{ + return m_days == tD.getDays() && m_years == tD.getYears() && m_months == tD.getMonths(); +} + int TimeDelta::getDays() const { return m_days; diff --git a/src/core/TimeDelta.h b/src/core/TimeDelta.h index d52ba72e5..325fadc05 100644 --- a/src/core/TimeDelta.h +++ b/src/core/TimeDelta.h @@ -34,6 +34,8 @@ public: TimeDelta(); TimeDelta(int days, int months, int years); + TimeDelta operator*(unsigned n); + bool operator==(const TimeDelta& tD) const; int getDays() const; int getMonths() const; diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index 0b7f81163..8f8aa3301 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include "autotype/AutoType.h" #include "core/Clock.h" @@ -66,9 +67,18 @@ #include "gui/entry/EntryAttributesModel.h" #include "gui/entry/EntryHistoryModel.h" +QString timeDelta2Text(const TimeDelta& tD) +{ + if (tD.getDays()) { + return "day(s)"; + } + return tD.getMonths() ? "month(s)" : "year(s)"; +}; + EditEntryWidget::EditEntryWidget(QWidget* parent) : EditWidget(parent) , m_entry(nullptr) + , m_extensionOnPwUpdate(std::make_tuple(0, TimeDelta(1, 0, 0))) , m_mainUi(new Ui::EditEntryWidgetMain()) , m_advancedUi(new Ui::EditEntryWidgetAdvanced()) , m_autoTypeUi(new Ui::EditEntryWidgetAutoType()) @@ -178,16 +188,22 @@ void EditEntryWidget::setupMain() m_mainUi->expirePresets->setMenu(createPresetsMenu()); connect(m_mainUi->expirePresets->menu(), SIGNAL(triggered(QAction*)), this, SLOT(useExpiryPreset(QAction*))); - m_mainUi->extendPresets->setMenu(createPresetsMenu()); - connect(m_mainUi->extendPresets->menu(), &QMenu::triggered, this, [&](QAction* action) { - m_extensionOnPwUpdate = action->data().value(); + m_mainUi->extendByMagnitude->setMenu(createExtendByMenu()); + connect(m_mainUi->extendByMagnitude->menu(), &QMenu::triggered, this, [&](QAction* action) { + std::get<1>(m_extensionOnPwUpdate) = action->data().value(); + m_mainUi->extendByMagnitude->setText(action->text()); + setModified(true); + }); + connect(m_mainUi->extendByQuantity, QOverload::of(&QSpinBox::valueChanged), this, [&](int n) { + std::get<0>(m_extensionOnPwUpdate) = static_cast(n); }); connect(m_mainUi->autoExtendExpire, &QCheckBox::toggled, [&](bool enabled) { - m_mainUi->extendPresets->setEnabled(enabled); + m_mainUi->extendByQuantity->setEnabled(enabled); + m_mainUi->extendByMagnitude->setEnabled(enabled); }); connect(m_mainUi->passwordEdit, &QLineEdit::textChanged, this, [&]() { - if (m_mainUi->extendPresets->isEnabled()) { - TimeDelta delta = m_extensionOnPwUpdate; + if (m_mainUi->autoExtendExpire->isEnabled()) { + TimeDelta delta = std::get<1>(m_extensionOnPwUpdate) * std::get<0>(m_extensionOnPwUpdate); QDateTime now = Clock::currentDateTime(); QDateTime expiryDateTime = now + delta; m_mainUi->expireDatePicker->setDateTime(expiryDateTime); @@ -450,7 +466,9 @@ void EditEntryWidget::setupEntryUpdate() #endif connect(m_mainUi->expireCheck, SIGNAL(stateChanged(int)), this, SLOT(setModified())); connect(m_mainUi->expireDatePicker, SIGNAL(dateTimeChanged(QDateTime)), this, SLOT(setModified())); + connect(m_mainUi->autoExtendExpire, SIGNAL(stateChanged(int)), this, SLOT(setModified())); connect(m_mainUi->notesEdit, SIGNAL(textChanged()), this, SLOT(setModified())); + connect(m_mainUi->extendByQuantity, SIGNAL(valueChanged(int)), this, SLOT(setModified())); // Advanced tab connect(m_advancedUi->attributesEdit, SIGNAL(textChanged()), this, SLOT(setModified())); @@ -855,6 +873,7 @@ void EditEntryWidget::setForms(Entry* entry, bool restore) m_mainUi->passwordEdit->setReadOnly(m_history); m_mainUi->expireCheck->setEnabled(!m_history); m_mainUi->expireDatePicker->setReadOnly(m_history); + m_mainUi->autoExtendExpire->setEnabled(!m_history); m_mainUi->notesEnabled->setChecked(!config()->get(Config::Security_HideNotes).toBool()); m_mainUi->notesEdit->setReadOnly(m_history); m_mainUi->notesEdit->setVisible(!config()->get(Config::Security_HideNotes).toBool()); @@ -897,6 +916,12 @@ void EditEntryWidget::setForms(Entry* entry, bool restore) m_mainUi->expireCheck->setChecked(entry->timeInfo().expires()); m_mainUi->expireDatePicker->setDateTime(entry->timeInfo().expiryTime().toLocalTime()); m_mainUi->expirePresets->setEnabled(!m_history); + m_mainUi->autoExtendExpire->setChecked(entry->timeInfo().expires()); + m_mainUi->autoExtendExpire->setChecked(entry->customData()->value("ExpirationExtension").toInt()); + m_mainUi->extendByQuantity->setEnabled(m_mainUi->autoExtendExpire->isChecked()); + m_mainUi->extendByQuantity->setValue(entry->customData()->value("ExpirationExtensionQuantity").toInt()); + m_mainUi->extendByMagnitude->setEnabled(m_mainUi->autoExtendExpire->isChecked()); + m_mainUi->extendByMagnitude->setText(entry->customData()->value("ExpirationExtensionMagnitude")); QList commonUsernames = m_db->commonUsernames(); m_usernameCompleterModel->setStringList(commonUsernames); @@ -1137,7 +1162,9 @@ void EditEntryWidget::updateEntryData(Entry* entry) const entry->setPassword(m_mainUi->passwordEdit->text()); entry->setExpires(m_mainUi->expireCheck->isChecked()); entry->setExpiryTime(m_mainUi->expireDatePicker->dateTime().toUTC()); - + entry->setExtendsExpirationOnPwdChange(m_mainUi->autoExtendExpire->isChecked()); + entry->setExpirationExtension(QString::number(std::get<0>(m_extensionOnPwUpdate)), + timeDelta2Text(std::get<1>(m_extensionOnPwUpdate))); entry->setNotes(m_mainUi->notesEdit->toPlainText()); if (entry->excludeFromReports() != m_advancedUi->excludeReportsCheckBox->isChecked()) { @@ -1541,6 +1568,18 @@ QMenu* EditEntryWidget::createPresetsMenu() return expirePresetsMenu; } +QMenu* EditEntryWidget::createExtendByMenu() +{ + auto* expirePresetsMenu = new QMenu(this); + auto tD = TimeDelta::fromDays(1); + expirePresetsMenu->addAction(timeDelta2Text(tD))->setData(QVariant::fromValue(tD)); + tD = TimeDelta::fromMonths(1); + expirePresetsMenu->addAction(timeDelta2Text(tD))->setData(QVariant::fromValue(tD)); + tD = TimeDelta::fromYears(1); + expirePresetsMenu->addAction(timeDelta2Text(tD))->setData(QVariant::fromValue(tD)); + return expirePresetsMenu; +} + void EditEntryWidget::setupColorButton(bool foreground, const QColor& color) { QWidget* button = m_advancedUi->fgColorButton; diff --git a/src/gui/entry/EditEntryWidget.h b/src/gui/entry/EditEntryWidget.h index c0abe6cb4..af212acb3 100644 --- a/src/gui/entry/EditEntryWidget.h +++ b/src/gui/entry/EditEntryWidget.h @@ -153,6 +153,7 @@ private: bool passwordsEqual(); void setForms(Entry* entry, bool restore = false); QMenu* createPresetsMenu(); + QMenu* createExtendByMenu(); void updateEntryData(Entry* entry) const; #ifdef WITH_XC_SSHAGENT bool getOpenSSHKey(OpenSSHKey& key, bool decrypt = false); @@ -163,7 +164,7 @@ private: QPointer m_entry; QSharedPointer m_db; - TimeDelta m_extensionOnPwUpdate; + std::tuple m_extensionOnPwUpdate; bool m_create; bool m_history; #ifdef WITH_XC_SSHAGENT diff --git a/src/gui/entry/EditEntryWidgetMain.ui b/src/gui/entry/EditEntryWidgetMain.ui index e028792e0..7b05360d8 100644 --- a/src/gui/entry/EditEntryWidgetMain.ui +++ b/src/gui/entry/EditEntryWidgetMain.ui @@ -279,8 +279,6 @@ - - Toggle auto updating expiration @@ -289,12 +287,33 @@ Toggle auto updating expiration date - Automatically extend expiration date on password modification by + Auto assign new password expiration after modification: + + + + 1 + - + + + false + + + 0 + + + 1000 + + + 5 + + + + + false @@ -311,7 +330,7 @@ Expiration extension presets - Time + Time period