allow for better granularity when choosing password extension

Switches presets for quantity and unit of time pickers. Stores auto extension
on modification data as custom data for the entry to respect the spec
This commit is contained in:
Xavier Valls 2021-04-29 10:01:57 +02:00
parent fa785e1745
commit bcc81b069b
7 changed files with 101 additions and 13 deletions

View File

@ -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*> Entry::historyItems()
{
return m_history;

View File

@ -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<Totp::Settings> settings);
QList<Entry*> historyItems();

View File

@ -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;

View File

@ -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;

View File

@ -35,6 +35,7 @@
#include <QStandardPaths>
#include <QStringListModel>
#include <QTemporaryFile>
#include <tuple>
#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<TimeDelta>();
m_mainUi->extendByMagnitude->setMenu(createExtendByMenu());
connect(m_mainUi->extendByMagnitude->menu(), &QMenu::triggered, this, [&](QAction* action) {
std::get<1>(m_extensionOnPwUpdate) = action->data().value<TimeDelta>();
m_mainUi->extendByMagnitude->setText(action->text());
setModified(true);
});
connect(m_mainUi->extendByQuantity, QOverload<int>::of(&QSpinBox::valueChanged), this, [&](int n) {
std::get<0>(m_extensionOnPwUpdate) = static_cast<unsigned>(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<QString> 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;

View File

@ -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<Entry> m_entry;
QSharedPointer<Database> m_db;
TimeDelta m_extensionOnPwUpdate;
std::tuple<unsigned, TimeDelta> m_extensionOnPwUpdate;
bool m_create;
bool m_history;
#ifdef WITH_XC_SSHAGENT

View File

@ -279,8 +279,6 @@
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalautoUpdate">
<item>
<widget class="QCheckBox" name="autoExtendExpire">
<property name="toolTip">
<string>Toggle auto updating expiration</string>
@ -289,12 +287,33 @@
<string>Toggle auto updating expiration date</string>
</property>
<property name="text">
<string>Automatically extend expiration date on password modification by</string>
<string>Auto assign new password expiration after modification:</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalautoUpdate">
<property name="spacing">
<number>1</number>
</property>
<item>
<widget class="QPushButton" name="extendPresets">
<widget class="QSpinBox" name="extendByQuantity">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="FixedWidth">
<number>5</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="extendByMagnitude">
<property name="enabled">
<bool>false</bool>
</property>
@ -311,7 +330,7 @@
<string>Expiration extension presets</string>
</property>
<property name="text">
<string>Time</string>
<string>Time period</string>
</property>
</widget>
</item>