Add action item for removing a passkey from entry (#10777)

This commit is contained in:
Sami Vänttinen 2024-05-27 23:50:35 +03:00 committed by GitHub
parent 9aa040604a
commit 5de669eb7b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 94 additions and 11 deletions

View File

@ -2505,6 +2505,14 @@ Disable safe saves and try again?</source>
<comment>Database tab name modifier</comment> <comment>Database tab name modifier</comment>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Remove passkey from entry</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Do you want to remove the passkey from this entry?</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>EditEntryWidget</name> <name>EditEntryWidget</name>
@ -3547,6 +3555,10 @@ This may cause the affected plugins to malfunction.</source>
<source>%1 - Clone</source> <source>%1 - Clone</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Passkey</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>EntryAttachments</name> <name>EntryAttachments</name>
@ -5867,6 +5879,10 @@ We recommend you use the AppImage available on our downloads page.</source>
<source>Toggle Allow Screen Capture</source> <source>Toggle Allow Screen Capture</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Remove Passkey From Entry</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>ManageDatabase</name> <name>ManageDatabase</name>

View File

@ -497,7 +497,7 @@
</layout> </layout>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<item> <item>
<widget class="QLabel" name="customBrowserLabel_2"> <widget class="QLabel" name="customBrowserLabel_2">
<property name="sizePolicy"> <property name="sizePolicy">

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2024 KeePassXC Team <team@keepassxc.org>
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de> * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -551,6 +551,12 @@ bool Entry::hasPasskey() const
return m_attributes->hasPasskey(); return m_attributes->hasPasskey();
} }
void Entry::removePasskey()
{
m_attributes->removePasskeyAttributes();
removeTag(tr("Passkey"));
}
QString Entry::totp() const QString Entry::totp() const
{ {
if (hasTotp()) { if (hasTotp()) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2024 KeePassXC Team <team@keepassxc.org>
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de> * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -120,8 +120,10 @@ public:
bool excludeFromReports() const; bool excludeFromReports() const;
void setExcludeFromReports(bool state); void setExcludeFromReports(bool state);
bool hasTotp() const;
bool hasPasskey() const; bool hasPasskey() const;
void removePasskey();
bool hasTotp() const;
bool isExpired() const; bool isExpired() const;
bool willExpireInDays(int days) const; bool willExpireInDays(int days) const;
bool isRecycled() const; bool isRecycled() const;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2024 KeePassXC Team <team@keepassxc.org>
* Copyright (C) 2012 Felix Geyer <debfx@fobos.de> * Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -65,6 +65,16 @@ bool EntryAttributes::hasPasskey() const
return false; return false;
} }
void EntryAttributes::removePasskeyAttributes()
{
const auto keyList = keys();
for (const auto& key : keyList) {
if (isPasskeyAttribute(key)) {
remove(key);
}
}
}
QList<QString> EntryAttributes::customKeys() const QList<QString> EntryAttributes::customKeys() const
{ {
QList<QString> customKeys; QList<QString> customKeys;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2024 KeePassXC Team <team@keepassxc.org>
* Copyright (C) 2012 Felix Geyer <debfx@fobos.de> * Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -34,6 +34,7 @@ public:
QList<QString> keys() const; QList<QString> keys() const;
bool hasKey(const QString& key) const; bool hasKey(const QString& key) const;
bool hasPasskey() const; bool hasPasskey() const;
void removePasskeyAttributes();
QList<QString> customKeys() const; QList<QString> customKeys() const;
QString value(const QString& key) const; QString value(const QString& key) const;
QList<QString> values(const QList<QString>& keys) const; QList<QString> values(const QList<QString>& keys) const;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2024 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -563,6 +563,11 @@ void DatabaseTabWidget::importPasskeyToEntry()
{ {
currentDatabaseWidget()->showImportPasskeyDialog(true); currentDatabaseWidget()->showImportPasskeyDialog(true);
} }
void DatabaseTabWidget::removePasskeyFromEntry()
{
currentDatabaseWidget()->removePasskeyFromEntry();
}
#endif #endif
bool DatabaseTabWidget::isModified(int index) const bool DatabaseTabWidget::isModified(int index) const

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2024 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -87,6 +87,7 @@ public slots:
void showPasskeys(); void showPasskeys();
void importPasskey(); void importPasskey();
void importPasskeyToEntry(); void importPasskeyToEntry();
void removePasskeyFromEntry();
#endif #endif
void performGlobalAutoType(const QString& search); void performGlobalAutoType(const QString& search);
void performBrowserUnlock(); void performBrowserUnlock();

View File

@ -1428,6 +1428,22 @@ void DatabaseWidget::showImportPasskeyDialog(bool isEntry)
passkeyImporter.importPasskey(m_db); 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 #endif
void DatabaseWidget::performUnlockDatabase(const QString& password, const QString& keyfile) void DatabaseWidget::performUnlockDatabase(const QString& password, const QString& keyfile)
@ -2020,6 +2036,14 @@ bool DatabaseWidget::currentEntryHasSshKey()
} }
#endif #endif
#ifdef WITH_XC_BROWSER_PASSKEYS
bool DatabaseWidget::currentEntryHasPasskey()
{
auto currentEntry = m_entryView->currentEntry();
return currentEntry && currentEntry->hasPasskey();
}
#endif
bool DatabaseWidget::currentEntryHasNotes() bool DatabaseWidget::currentEntryHasNotes()
{ {
auto currentEntry = currentSelectedEntry(); auto currentEntry = currentSelectedEntry();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2024 KeePassXC Team <team@keepassxc.org>
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de> * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -212,6 +212,8 @@ public slots:
#ifdef WITH_XC_BROWSER_PASSKEYS #ifdef WITH_XC_BROWSER_PASSKEYS
void switchToPasskeys(); void switchToPasskeys();
void showImportPasskeyDialog(bool isEntry = false); void showImportPasskeyDialog(bool isEntry = false);
void removePasskeyFromEntry();
bool currentEntryHasPasskey();
#endif #endif
void switchToOpenDatabase(); void switchToOpenDatabase();
void switchToOpenDatabase(const QString& filePath); void switchToOpenDatabase(const QString& filePath);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2023 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2024 KeePassXC Team <team@keepassxc.org>
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de> * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -139,6 +139,7 @@ MainWindow::MainWindow()
m_entryContextMenu->addSeparator(); m_entryContextMenu->addSeparator();
#ifdef WITH_XC_BROWSER_PASSKEYS #ifdef WITH_XC_BROWSER_PASSKEYS
m_entryContextMenu->addAction(m_ui->actionEntryImportPasskey); m_entryContextMenu->addAction(m_ui->actionEntryImportPasskey);
m_entryContextMenu->addAction(m_ui->actionEntryRemovePasskey);
m_entryContextMenu->addSeparator(); m_entryContextMenu->addSeparator();
#endif #endif
m_entryContextMenu->addAction(m_ui->actionEntryEdit); m_entryContextMenu->addAction(m_ui->actionEntryEdit);
@ -412,6 +413,7 @@ MainWindow::MainWindow()
m_ui->actionPasskeys->setIcon(icons()->icon("passkey")); m_ui->actionPasskeys->setIcon(icons()->icon("passkey"));
m_ui->actionImportPasskey->setIcon(icons()->icon("document-import")); m_ui->actionImportPasskey->setIcon(icons()->icon("document-import"));
m_ui->actionEntryImportPasskey->setIcon(icons()->icon("document-import")); m_ui->actionEntryImportPasskey->setIcon(icons()->icon("document-import"));
m_ui->actionEntryRemovePasskey->setIcon(icons()->icon("document-close"));
#endif #endif
m_actionMultiplexer.connect( m_actionMultiplexer.connect(
@ -463,6 +465,7 @@ MainWindow::MainWindow()
connect(m_ui->actionPasskeys, SIGNAL(triggered()), m_ui->tabWidget, SLOT(showPasskeys())); 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->actionImportPasskey, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importPasskey()));
connect(m_ui->actionEntryImportPasskey, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importPasskeyToEntry())); connect(m_ui->actionEntryImportPasskey, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importPasskeyToEntry()));
connect(m_ui->actionEntryRemovePasskey, SIGNAL(triggered()), m_ui->tabWidget, SLOT(removePasskeyFromEntry()));
#endif #endif
connect(m_ui->actionImport, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importFile())); connect(m_ui->actionImport, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importFile()));
connect(m_ui->actionExportCsv, SIGNAL(triggered()), m_ui->tabWidget, SLOT(exportToCsv())); connect(m_ui->actionExportCsv, SIGNAL(triggered()), m_ui->tabWidget, SLOT(exportToCsv()));
@ -956,9 +959,11 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode)
m_ui->actionExportXML->setEnabled(true); m_ui->actionExportXML->setEnabled(true);
m_ui->actionDatabaseMerge->setEnabled(m_ui->tabWidget->currentIndex() != -1); m_ui->actionDatabaseMerge->setEnabled(m_ui->tabWidget->currentIndex() != -1);
#ifdef WITH_XC_BROWSER_PASSKEYS #ifdef WITH_XC_BROWSER_PASSKEYS
bool singleEntryHasPasskey = singleEntrySelected && dbWidget->currentEntryHasPasskey();
m_ui->actionPasskeys->setEnabled(true); m_ui->actionPasskeys->setEnabled(true);
m_ui->actionImportPasskey->setEnabled(true); m_ui->actionImportPasskey->setEnabled(true);
m_ui->actionEntryImportPasskey->setEnabled(singleEntrySelected); m_ui->actionEntryImportPasskey->setEnabled(singleEntrySelected);
m_ui->actionEntryRemovePasskey->setEnabled(singleEntryHasPasskey);
#endif #endif
#ifdef WITH_XC_SSHAGENT #ifdef WITH_XC_SSHAGENT
bool singleEntryHasSshKey = bool singleEntryHasSshKey =
@ -1030,10 +1035,12 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode)
m_ui->actionPasskeys->setEnabled(false); m_ui->actionPasskeys->setEnabled(false);
m_ui->actionImportPasskey->setEnabled(false); m_ui->actionImportPasskey->setEnabled(false);
m_ui->actionEntryImportPasskey->setEnabled(false); m_ui->actionEntryImportPasskey->setEnabled(false);
m_ui->actionEntryRemovePasskey->setEnabled(false);
#else #else
m_ui->actionPasskeys->setVisible(false); m_ui->actionPasskeys->setVisible(false);
m_ui->actionImportPasskey->setVisible(false); m_ui->actionImportPasskey->setVisible(false);
m_ui->actionEntryImportPasskey->setVisible(false); m_ui->actionEntryImportPasskey->setVisible(false);
m_ui->actionEntryRemovePasskey->setVisible(false);
#endif #endif
m_searchWidgetAction->setEnabled(false); m_searchWidgetAction->setEnabled(false);

View File

@ -335,6 +335,7 @@
<addaction name="actionEntryAutoType"/> <addaction name="actionEntryAutoType"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionEntryImportPasskey"/> <addaction name="actionEntryImportPasskey"/>
<addaction name="actionEntryRemovePasskey"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionEntryOpenUrl"/> <addaction name="actionEntryOpenUrl"/>
<addaction name="actionEntryDownloadIcon"/> <addaction name="actionEntryDownloadIcon"/>
@ -775,6 +776,14 @@
<string>Import Passkey</string> <string>Import Passkey</string>
</property> </property>
</action> </action>
<action name="actionEntryRemovePasskey">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Remove Passkey From Entry</string>
</property>
</action>
<action name="actionEntryAutoTypeUsername"> <action name="actionEntryAutoTypeUsername">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>

View File

@ -388,7 +388,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_17"> <widget class="QLabel" name="label_26">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>