From 6fbab254789524724886d90ba88749ae319094ef Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sun, 2 Jun 2024 07:38:03 -0400 Subject: [PATCH] Add action item for removing a passkey from entry (#10777) --- share/translations/keepassxc_en.ts | 16 ++++++++++++++++ src/browser/BrowserSettingsWidget.ui | 2 +- src/core/Entry.cpp | 8 +++++++- src/core/Entry.h | 6 ++++-- src/core/EntryAttributes.cpp | 12 +++++++++++- src/core/EntryAttributes.h | 3 ++- src/gui/DatabaseTabWidget.cpp | 7 ++++++- src/gui/DatabaseTabWidget.h | 3 ++- src/gui/DatabaseWidget.cpp | 24 ++++++++++++++++++++++++ src/gui/DatabaseWidget.h | 4 +++- src/gui/MainWindow.cpp | 9 ++++++++- src/gui/MainWindow.ui | 9 +++++++++ src/gui/SearchHelpWidget.ui | 2 +- 13 files changed, 94 insertions(+), 11 deletions(-) diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts index 0861369e5a..9521a7142e 100644 --- a/share/translations/keepassxc_en.ts +++ b/share/translations/keepassxc_en.ts @@ -2533,6 +2533,14 @@ Disable safe saves and try again? Database tab name modifier + + Remove passkey from entry + + + + Do you want to remove the passkey from this entry? + + Searches and Tags @@ -3586,6 +3594,10 @@ This may cause the affected plugins to malfunction. %1 - Clone + + Passkey + + EntryAttachments @@ -5738,6 +5750,10 @@ We recommend you use the AppImage available on our downloads page. Toggle Show Menubar + + Remove Passkey From Entry + + ManageDatabase diff --git a/src/browser/BrowserSettingsWidget.ui b/src/browser/BrowserSettingsWidget.ui index 3444b219a7..a484c2ddd1 100644 --- a/src/browser/BrowserSettingsWidget.ui +++ b/src/browser/BrowserSettingsWidget.ui @@ -487,7 +487,7 @@ - + diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index db1542c6c4..77d37dc70c 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 KeePassXC Team + * Copyright (C) 2024 KeePassXC Team * Copyright (C) 2010 Felix Geyer * * This program is free software: you can redistribute it and/or modify @@ -551,6 +551,12 @@ bool Entry::hasPasskey() const return m_attributes->hasPasskey(); } +void Entry::removePasskey() +{ + m_attributes->removePasskeyAttributes(); + removeTag(tr("Passkey")); +} + QString Entry::totp() const { if (hasTotp()) { diff --git a/src/core/Entry.h b/src/core/Entry.h index 7961705143..359ce7a300 100644 --- a/src/core/Entry.h +++ b/src/core/Entry.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 KeePassXC Team + * Copyright (C) 2024 KeePassXC Team * Copyright (C) 2010 Felix Geyer * * This program is free software: you can redistribute it and/or modify @@ -120,8 +120,10 @@ class Entry : public ModifiableObject bool excludeFromReports() const; void setExcludeFromReports(bool state); - bool hasTotp() const; bool hasPasskey() const; + void removePasskey(); + + bool hasTotp() const; bool isExpired() const; bool willExpireInDays(int days) const; bool isRecycled() const; diff --git a/src/core/EntryAttributes.cpp b/src/core/EntryAttributes.cpp index 49c243ec17..a14ae7dde8 100644 --- a/src/core/EntryAttributes.cpp +++ b/src/core/EntryAttributes.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 KeePassXC Team + * Copyright (C) 2024 KeePassXC Team * Copyright (C) 2012 Felix Geyer * * This program is free software: you can redistribute it and/or modify @@ -65,6 +65,16 @@ bool EntryAttributes::hasPasskey() const return false; } +void EntryAttributes::removePasskeyAttributes() +{ + const auto keyList = keys(); + for (const auto& key : keyList) { + if (isPasskeyAttribute(key)) { + remove(key); + } + } +} + QList EntryAttributes::customKeys() const { QList customKeys; diff --git a/src/core/EntryAttributes.h b/src/core/EntryAttributes.h index fecf6a993b..ee814b03dc 100644 --- a/src/core/EntryAttributes.h +++ b/src/core/EntryAttributes.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 KeePassXC Team + * Copyright (C) 2024 KeePassXC Team * Copyright (C) 2012 Felix Geyer * * This program is free software: you can redistribute it and/or modify @@ -34,6 +34,7 @@ class EntryAttributes : public ModifiableObject QList keys() const; bool hasKey(const QString& key) const; bool hasPasskey() const; + void removePasskeyAttributes(); QList customKeys() const; QString value(const QString& key) const; QList values(const QList& keys) const; diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index 412bc95e47..805d4eabd5 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 KeePassXC Team + * Copyright (C) 2024 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -565,6 +565,11 @@ void DatabaseTabWidget::importPasskeyToEntry() { currentDatabaseWidget()->showImportPasskeyDialog(true); } + +void DatabaseTabWidget::removePasskeyFromEntry() +{ + currentDatabaseWidget()->removePasskeyFromEntry(); +} #endif bool DatabaseTabWidget::isModified(int index) const diff --git a/src/gui/DatabaseTabWidget.h b/src/gui/DatabaseTabWidget.h index 5c995b536a..59e5554519 100644 --- a/src/gui/DatabaseTabWidget.h +++ b/src/gui/DatabaseTabWidget.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 KeePassXC Team + * Copyright (C) 2024 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -87,6 +87,7 @@ public slots: void showPasskeys(); void importPasskey(); void importPasskeyToEntry(); + void removePasskeyFromEntry(); #endif void performGlobalAutoType(const QString& search); void performBrowserUnlock(); diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 04c9e337bc..2146f1aea6 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -1428,6 +1428,22 @@ void DatabaseWidget::showImportPasskeyDialog(bool isEntry) passkeyImporter.importPasskey(m_db); } } + +void DatabaseWidget::removePasskeyFromEntry() +{ + auto currentEntry = currentSelectedEntry(); + if (!currentEntry) { + return; + } + + auto result = MessageBox::question(this, + tr("Remove passkey from entry"), + tr("Do you want to remove the passkey from this entry?"), + MessageBox::Remove | MessageBox::Cancel); + if (result == MessageBox::Remove) { + currentEntry->removePasskey(); + } +} #endif void DatabaseWidget::performUnlockDatabase(const QString& password, const QString& keyfile) @@ -2020,6 +2036,14 @@ bool DatabaseWidget::currentEntryHasSshKey() } #endif +#ifdef WITH_XC_BROWSER_PASSKEYS +bool DatabaseWidget::currentEntryHasPasskey() +{ + auto currentEntry = m_entryView->currentEntry(); + return currentEntry && currentEntry->hasPasskey(); +} +#endif + bool DatabaseWidget::currentEntryHasNotes() { auto currentEntry = currentSelectedEntry(); diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index 6812600092..0b306d91d8 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 KeePassXC Team + * Copyright (C) 2024 KeePassXC Team * Copyright (C) 2010 Felix Geyer * * This program is free software: you can redistribute it and/or modify @@ -212,6 +212,8 @@ public slots: #ifdef WITH_XC_BROWSER_PASSKEYS void switchToPasskeys(); void showImportPasskeyDialog(bool isEntry = false); + void removePasskeyFromEntry(); + bool currentEntryHasPasskey(); #endif void switchToOpenDatabase(); void switchToOpenDatabase(const QString& filePath); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index cc7673fb62..4d4f2c23ad 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 KeePassXC Team + * Copyright (C) 2024 KeePassXC Team * Copyright (C) 2010 Felix Geyer * * This program is free software: you can redistribute it and/or modify @@ -137,6 +137,7 @@ MainWindow::MainWindow() m_entryContextMenu->addSeparator(); #ifdef WITH_XC_BROWSER_PASSKEYS m_entryContextMenu->addAction(m_ui->actionEntryImportPasskey); + m_entryContextMenu->addAction(m_ui->actionEntryRemovePasskey); m_entryContextMenu->addSeparator(); #endif m_entryContextMenu->addAction(m_ui->actionEntryEdit); @@ -446,6 +447,7 @@ MainWindow::MainWindow() m_ui->actionPasskeys->setIcon(icons()->icon("passkey")); m_ui->actionImportPasskey->setIcon(icons()->icon("document-import")); m_ui->actionEntryImportPasskey->setIcon(icons()->icon("document-import")); + m_ui->actionEntryRemovePasskey->setIcon(icons()->icon("document-close")); #endif m_actionMultiplexer.connect( @@ -497,6 +499,7 @@ MainWindow::MainWindow() connect(m_ui->actionPasskeys, SIGNAL(triggered()), m_ui->tabWidget, SLOT(showPasskeys())); connect(m_ui->actionImportPasskey, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importPasskey())); connect(m_ui->actionEntryImportPasskey, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importPasskeyToEntry())); + connect(m_ui->actionEntryRemovePasskey, SIGNAL(triggered()), m_ui->tabWidget, SLOT(removePasskeyFromEntry())); #endif connect(m_ui->actionImport, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importFile())); connect(m_ui->actionExportCsv, SIGNAL(triggered()), m_ui->tabWidget, SLOT(exportToCsv())); @@ -990,9 +993,11 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionExportXML->setEnabled(true); m_ui->actionDatabaseMerge->setEnabled(m_ui->tabWidget->currentIndex() != -1); #ifdef WITH_XC_BROWSER_PASSKEYS + bool singleEntryHasPasskey = singleEntrySelected && dbWidget->currentEntryHasPasskey(); m_ui->actionPasskeys->setEnabled(true); m_ui->actionImportPasskey->setEnabled(true); m_ui->actionEntryImportPasskey->setEnabled(singleEntrySelected); + m_ui->actionEntryRemovePasskey->setEnabled(singleEntryHasPasskey); #endif #ifdef WITH_XC_SSHAGENT bool singleEntryHasSshKey = @@ -1064,10 +1069,12 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionPasskeys->setEnabled(false); m_ui->actionImportPasskey->setEnabled(false); m_ui->actionEntryImportPasskey->setEnabled(false); + m_ui->actionEntryRemovePasskey->setEnabled(false); #else m_ui->actionPasskeys->setVisible(false); m_ui->actionImportPasskey->setVisible(false); m_ui->actionEntryImportPasskey->setVisible(false); + m_ui->actionEntryRemovePasskey->setVisible(false); #endif m_searchWidgetAction->setEnabled(false); diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui index a1dc25c582..84b4b751e7 100644 --- a/src/gui/MainWindow.ui +++ b/src/gui/MainWindow.ui @@ -335,6 +335,7 @@ + @@ -733,6 +734,14 @@ Import Passkey + + + false + + + Remove Passkey From Entry + + false diff --git a/src/gui/SearchHelpWidget.ui b/src/gui/SearchHelpWidget.ui index 907b2822d9..d9778fd225 100644 --- a/src/gui/SearchHelpWidget.ui +++ b/src/gui/SearchHelpWidget.ui @@ -388,7 +388,7 @@ - + 0