From 92b30ae7ecb05cae43e6ffdbcdd965fa7deb7eb6 Mon Sep 17 00:00:00 2001 From: varjolintu Date: Tue, 12 Mar 2024 19:44:46 +0200 Subject: [PATCH] Passkeys: Register to an existing entry --- share/translations/keepassxc_en.ts | 114 ++++++++++-------- src/browser/BrowserMessageBuilder.cpp | 2 +- .../BrowserPasskeysConfirmationDialog.cpp | 17 +-- src/browser/BrowserService.cpp | 39 ++++-- src/browser/BrowserSettingsWidget.ui | 4 +- src/gui/DatabaseWidget.cpp | 4 +- src/gui/passkeys/PasskeyExportDialog.ui | 2 +- src/gui/passkeys/PasskeyExporter.cpp | 11 +- src/gui/passkeys/PasskeyExporter.h | 9 +- src/gui/passkeys/PasskeyImportDialog.cpp | 23 +++- src/gui/passkeys/PasskeyImportDialog.h | 7 +- src/gui/passkeys/PasskeyImportDialog.ui | 2 +- src/gui/passkeys/PasskeyImporter.cpp | 50 +++++--- src/gui/passkeys/PasskeyImporter.h | 22 ++-- src/gui/reports/ReportsWidgetPasskeys.cpp | 8 +- 15 files changed, 199 insertions(+), 115 deletions(-) diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts index bdc31f13e5..126deb41b0 100644 --- a/share/translations/keepassxc_en.ts +++ b/share/translations/keepassxc_en.ts @@ -871,32 +871,36 @@ Please select the correct database for saving credentials. - Do you want to register Passkey for: + Relying Party: %1 - Existing Passkey found. -Do you want to register a new Passkey for: + Username: %1 - Select the existing Passkey and press Update to replace it. + KeePassXC - Passkey credentials - Authenticate Passkey credentials for: + Add to existing entry - Relying Party: %1 + Existing passkey found. +Do you want to register a new passkey for: - Username: %1 + Select the existing passkey and press Update to replace it. - KeePassXC - Passkey credentials + Authenticate passkey credentials for: + + + + Do you want to register a passkey for: @@ -939,11 +943,6 @@ Do you want to delete the entry? %1 (Passkey) - - Entry already has a Passkey. -Do you want to overwrite the Passkey in %1 - %2? - - KeePassXC - Create a new group @@ -956,10 +955,6 @@ Do you want to overwrite the Passkey in %1 - %2? KeePassXC - Overwrite existing key? - - KeePassXC - Update Passkey - - KeePassXC - Update Entry @@ -976,6 +971,27 @@ Do you want to overwrite the Passkey in %1 - %2? Passkey + + KeePassXC - Passkey credentials + + + + Register a new passkey to this entry: + + + + KeePassXC - Update passkey + + + + Entry already has a passkey. +Do you want to overwrite the passkey in %1 - %2? + + + + Register + + BrowserSettingsWidget @@ -1223,11 +1239,11 @@ Do you want to overwrite the Passkey in %1 - %2? - Allows using insecure http://localhost with Passkeys for testing purposes. + Allows using insecure http://localhost with passkeys for testing purposes. - Allow using localhost with Passkeys + Allow using localhost with passkeys @@ -6214,10 +6230,6 @@ We recommend you use the AppImage available on our downloads page. KeePassXC - Passkey Export - - Export the following Passkey entries. - - Filenames will be generated with title and .passkey file extension. @@ -6238,6 +6250,10 @@ We recommend you use the AppImage available on our downloads page. Export to folder + + Export the following passkey entries. + + PasskeyExporter @@ -6295,27 +6311,27 @@ Do you want to overwrite it? - Import the following Passkey: + Entry - Entry + Create new entry - Import the following Passkey to this entry: + Relying Party: %1 - Create new entry + Import the following passkey: - Default Passkeys group (Imported Passkeys) + Import the following passkey to this entry: - Relying Party: %1 + Default passkeys group (Imported Passkeys) @@ -6329,10 +6345,6 @@ Do you want to overwrite it? All files - - Open Passkey file - - Cannot open file @@ -6342,23 +6354,27 @@ Do you want to overwrite it? - Cannot import Passkey + Open passkey file - Cannot import Passkey file "%1". Data is missing. + Cannot import passkey - Cannot import Passkey file "%1". Private key is missing or malformed. + Cannot import passkey file "%1". Data is missing. - Cannot import Passkey file "%1". + Cannot import passkey file "%1". The following data is missing: %2 + + Cannot import passkey file "%1". Private key is missing or malformed. + + PasswordEditWidget @@ -8584,10 +8600,6 @@ This option is deprecated, use --set-key-file instead. Wait for timer to expire - - Unknown Passkeys error - - Challenge is shorter than required minimum length @@ -8682,6 +8694,10 @@ This option is deprecated, use --set-key-file instead. Unsupported KDF type, cannot decrypt json file + + Unknown passkeys error + + QtIOCompressor @@ -9008,14 +9024,6 @@ This option is deprecated, use --set-key-file instead. List of entry URLs - - Please wait, list of entries with Passkeys is being updated… - - - - No entries with Passkeys. - - Title @@ -9063,6 +9071,14 @@ This option is deprecated, use --set-key-file instead. The passkey file will be vulnerable to theft and unauthorized use, if left unsecured. Are you sure you want to continue? + + Please wait, list of entries with passkeys is being updated… + + + + No entries with passkeys. + + ReportsWidgetStatistics diff --git a/src/browser/BrowserMessageBuilder.cpp b/src/browser/BrowserMessageBuilder.cpp index 317c161bd2..e7b398c6a0 100644 --- a/src/browser/BrowserMessageBuilder.cpp +++ b/src/browser/BrowserMessageBuilder.cpp @@ -151,7 +151,7 @@ QString BrowserMessageBuilder::getErrorMessage(const int errorCode) const case ERROR_PASSKEYS_WAIT_FOR_LIFETIMER: return QObject::tr("Wait for timer to expire"); case ERROR_PASSKEYS_UNKNOWN_ERROR: - return QObject::tr("Unknown Passkeys error"); + return QObject::tr("Unknown passkeys error"); case ERROR_PASSKEYS_INVALID_CHALLENGE: return QObject::tr("Challenge is shorter than required minimum length"); case ERROR_PASSKEYS_INVALID_USER_ID: diff --git a/src/browser/BrowserPasskeysConfirmationDialog.cpp b/src/browser/BrowserPasskeysConfirmationDialog.cpp index 644bec599d..50bdfbc49f 100644 --- a/src/browser/BrowserPasskeysConfirmationDialog.cpp +++ b/src/browser/BrowserPasskeysConfirmationDialog.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 @@ -32,7 +32,6 @@ BrowserPasskeysConfirmationDialog::BrowserPasskeysConfirmationDialog(QWidget* pa setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); m_ui->setupUi(this); - m_ui->updateButton->setVisible(false); m_ui->verticalLayout->setAlignment(Qt::AlignTop); connect(m_ui->credentialsTable, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(accept())); @@ -53,21 +52,22 @@ void BrowserPasskeysConfirmationDialog::registerCredential(const QString& userna const QList& existingEntries, int timeout) { - m_ui->firstLabel->setText(tr("Do you want to register Passkey for:")); + m_ui->firstLabel->setText(tr("Do you want to register a passkey for:")); m_ui->relyingPartyLabel->setText(tr("Relying Party: %1").arg(relyingParty)); m_ui->usernameLabel->setText(tr("Username: %1").arg(username)); + m_ui->updateButton->setVisible(true); m_ui->secondLabel->setText(""); if (!existingEntries.isEmpty()) { - m_ui->firstLabel->setText(tr("Existing Passkey found.\nDo you want to register a new Passkey for:")); - m_ui->secondLabel->setText(tr("Select the existing Passkey and press Update to replace it.")); - - m_ui->updateButton->setVisible(true); + m_ui->firstLabel->setText(tr("Existing passkey found.\nDo you want to register a new passkey for:")); + m_ui->secondLabel->setText(tr("Select the existing passkey and press Update to replace it.")); + m_ui->updateButton->setText(tr("Update")); m_ui->confirmButton->setText(tr("Register new")); updateEntriesToTable(existingEntries); } else { m_ui->verticalLayout->setSizeConstraint(QLayout::SetFixedSize); m_ui->confirmButton->setText(tr("Register")); + m_ui->updateButton->setText(tr("Add to existing entry")); m_ui->credentialsTable->setVisible(false); } @@ -78,9 +78,10 @@ void BrowserPasskeysConfirmationDialog::authenticateCredential(const QListfirstLabel->setText(tr("Authenticate Passkey credentials for:")); + m_ui->firstLabel->setText(tr("Authenticate passkey credentials for:")); m_ui->relyingPartyLabel->setText(tr("Relying Party: %1").arg(relyingParty)); m_ui->usernameLabel->setVisible(false); + m_ui->updateButton->setVisible(false); m_ui->secondLabel->setText(""); updateEntriesToTable(entries); startCounter(timeout); diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp index 173800fb53..2b5a8bf199 100644 --- a/src/browser/BrowserService.cpp +++ b/src/browser/BrowserService.cpp @@ -34,6 +34,7 @@ #include "BrowserPasskeysClient.h" #include "BrowserPasskeysConfirmationDialog.h" #include "PasskeyUtils.h" +#include "gui/passkeys/PasskeyImporter.h" #endif #ifdef Q_OS_MACOS #include "gui/osutils/macutils/MacUtils.h" @@ -658,13 +659,33 @@ QJsonObject BrowserService::showPasskeysRegisterPrompt(const QJsonObject& public const auto rpName = publicKeyOptions["rp"]["name"].toString(); if (confirmDialog.isPasskeyUpdated()) { - addPasskeyToEntry(confirmDialog.getSelectedEntry(), - rpId, - rpName, - username, - publicKeyCredentials.credentialId, - userId, - publicKeyCredentials.key); + // If no entry is selected, show the import dialog for manual entry selection + auto selectedEntry = confirmDialog.getSelectedEntry(); + if (!selectedEntry) { + PasskeyImporter passkeyImporter(m_currentDatabaseWidget); + const auto result = passkeyImporter.showImportDialog(db, + nullptr, + origin, + rpId, + username, + publicKeyCredentials.credentialId, + userId, + publicKeyCredentials.key, + tr("KeePassXC - Passkey credentials"), + tr("Register a new passkey to this entry:"), + tr("Register")); + if (!result) { + return getPasskeyError(ERROR_PASSKEYS_REQUEST_CANCELED); + } + } else { + addPasskeyToEntry(selectedEntry, + rpId, + rpName, + username, + publicKeyCredentials.credentialId, + userId, + publicKeyCredentials.key); + } } else { addPasskeyToGroup(db, nullptr, @@ -790,8 +811,8 @@ void BrowserService::addPasskeyToEntry(Entry* entry, // Ask confirmation if entry already contains a Passkey if (entry->hasPasskey()) { if (MessageBox::question(m_currentDatabaseWidget, - tr("KeePassXC - Update Passkey"), - tr("Entry already has a Passkey.\nDo you want to overwrite the Passkey in %1 - %2?") + tr("KeePassXC - Update passkey"), + tr("Entry already has a passkey.\nDo you want to overwrite the passkey in %1 - %2?") .arg(entry->title(), passkeyUtils()->getUsernameFromEntry(entry)), MessageBox::Overwrite | MessageBox::Cancel, MessageBox::Cancel) diff --git a/src/browser/BrowserSettingsWidget.ui b/src/browser/BrowserSettingsWidget.ui index 8f69c6d2c3..facabfa4a9 100644 --- a/src/browser/BrowserSettingsWidget.ui +++ b/src/browser/BrowserSettingsWidget.ui @@ -313,10 +313,10 @@ - Allows using insecure http://localhost with Passkeys for testing purposes. + Allows using insecure http://localhost with passkeys for testing purposes. - Allow using localhost with Passkeys + Allow using localhost with passkeys diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 250463d3f0..5e7f0c4b0a 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.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 @@ -1415,7 +1415,7 @@ void DatabaseWidget::switchToPasskeys() void DatabaseWidget::showImportPasskeyDialog(bool isEntry) { - PasskeyImporter passkeyImporter; + PasskeyImporter passkeyImporter(this); if (isEntry) { auto currentEntry = currentSelectedEntry(); diff --git a/src/gui/passkeys/PasskeyExportDialog.ui b/src/gui/passkeys/PasskeyExportDialog.ui index c974ebaac4..bf9f4c42d8 100755 --- a/src/gui/passkeys/PasskeyExportDialog.ui +++ b/src/gui/passkeys/PasskeyExportDialog.ui @@ -23,7 +23,7 @@ - Export the following Passkey entries. + Export the following passkey entries. Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter diff --git a/src/gui/passkeys/PasskeyExporter.cpp b/src/gui/passkeys/PasskeyExporter.cpp index 2585c76e04..315825b4bb 100644 --- a/src/gui/passkeys/PasskeyExporter.cpp +++ b/src/gui/passkeys/PasskeyExporter.cpp @@ -27,13 +27,18 @@ #include #include +PasskeyExporter::PasskeyExporter(QWidget* parent) + : m_parent(parent) +{ +} + void PasskeyExporter::showExportDialog(const QList& items) { if (items.isEmpty()) { return; } - PasskeyExportDialog passkeyExportDialog; + PasskeyExportDialog passkeyExportDialog(m_parent); passkeyExportDialog.setEntries(items); auto ret = passkeyExportDialog.exec(); @@ -69,7 +74,7 @@ void PasskeyExporter::exportSelectedEntry(const Entry* entry, const QString& fol { const auto fullPath = QString("%1/%2.passkey").arg(folder, Tools::cleanFilename(entry->title())); if (QFile::exists(fullPath)) { - auto dialogResult = MessageBox::warning(nullptr, + auto dialogResult = MessageBox::warning(m_parent, tr("KeePassXC: Passkey Export"), tr("File \"%1.passkey\" already exists.\n" "Do you want to overwrite it?\n") @@ -84,7 +89,7 @@ void PasskeyExporter::exportSelectedEntry(const Entry* entry, const QString& fol QFile passkeyFile(fullPath); if (!passkeyFile.open(QIODevice::WriteOnly)) { MessageBox::information( - nullptr, tr("Cannot open file"), tr("Cannot open file \"%1\" for writing.").arg(fullPath)); + m_parent, tr("Cannot open file"), tr("Cannot open file \"%1\" for writing.").arg(fullPath)); return; } diff --git a/src/gui/passkeys/PasskeyExporter.h b/src/gui/passkeys/PasskeyExporter.h index 4214cbea33..ca59ea4b34 100644 --- a/src/gui/passkeys/PasskeyExporter.h +++ b/src/gui/passkeys/PasskeyExporter.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 @@ -20,6 +20,8 @@ #include #include +#include +#include class Entry; @@ -28,12 +30,15 @@ class PasskeyExporter : public QObject Q_OBJECT public: - explicit PasskeyExporter() = default; + explicit PasskeyExporter(QWidget* parent = nullptr); void showExportDialog(const QList& items); private: void exportSelectedEntry(const Entry* entry, const QString& folder); + +private: + QPointer m_parent; }; #endif // KEEPASSXC_PASSKEYEXPORTER_H diff --git a/src/gui/passkeys/PasskeyImportDialog.cpp b/src/gui/passkeys/PasskeyImportDialog.cpp index 2762df510d..179b2ed96d 100644 --- a/src/gui/passkeys/PasskeyImportDialog.cpp +++ b/src/gui/passkeys/PasskeyImportDialog.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 @@ -48,14 +48,17 @@ PasskeyImportDialog::~PasskeyImportDialog() void PasskeyImportDialog::setInfo(const QString& relyingParty, const QString& username, const QSharedPointer& database, - bool isEntry) + bool isEntry, + const QString& titleText, + const QString& infoText, + const QString& importButtonText) { m_ui->relyingPartyLabel->setText(tr("Relying Party: %1").arg(relyingParty)); m_ui->usernameLabel->setText(tr("Username: %1").arg(username)); if (isEntry) { m_ui->verticalLayout->setSizeConstraint(QLayout::SetFixedSize); - m_ui->infoLabel->setText(tr("Import the following Passkey to this entry:")); + m_ui->infoLabel->setText(tr("Import the following passkey to this entry:")); m_ui->groupBox->setVisible(false); } @@ -70,6 +73,18 @@ void PasskeyImportDialog::setInfo(const QString& relyingParty, } } m_ui->selectDatabaseCombobBox->setEnabled(openDatabaseCount > 1); + + if (!titleText.isEmpty()) { + setWindowTitle(titleText); + } + + if (!infoText.isEmpty()) { + m_ui->infoLabel->setText(infoText); + } + + if (!importButtonText.isEmpty()) { + m_ui->importButton->setText(importButtonText); + } } QSharedPointer PasskeyImportDialog::getSelectedDatabase() const @@ -155,7 +170,7 @@ void PasskeyImportDialog::addGroups() } m_ui->selectGroupComboBox->clear(); - m_ui->selectGroupComboBox->addItem(tr("Default Passkeys group (Imported Passkeys)"), {}); + m_ui->selectGroupComboBox->addItem(tr("Default passkeys group (Imported Passkeys)"), {}); for (const auto& group : m_selectedDatabase->rootGroup()->groupsRecursive(true)) { if (!group || group->isRecycled() || group == m_selectedDatabase->metadata()->recycleBin()) { diff --git a/src/gui/passkeys/PasskeyImportDialog.h b/src/gui/passkeys/PasskeyImportDialog.h index 9a7c4437ca..920a6a020a 100644 --- a/src/gui/passkeys/PasskeyImportDialog.h +++ b/src/gui/passkeys/PasskeyImportDialog.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 @@ -39,7 +39,10 @@ class PasskeyImportDialog : public QDialog void setInfo(const QString& relyingParty, const QString& username, const QSharedPointer& database, - bool isEntry); + bool isEntry, + const QString& titleText = {}, + const QString& infoText = {}, + const QString& importButtonText = {}); QSharedPointer getSelectedDatabase() const; QUuid getSelectedEntryUuid() const; QUuid getSelectedGroupUuid() const; diff --git a/src/gui/passkeys/PasskeyImportDialog.ui b/src/gui/passkeys/PasskeyImportDialog.ui index ecca97b14a..3b00809970 100755 --- a/src/gui/passkeys/PasskeyImportDialog.ui +++ b/src/gui/passkeys/PasskeyImportDialog.ui @@ -36,7 +36,7 @@ - Import the following Passkey: + Import the following passkey: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter diff --git a/src/gui/passkeys/PasskeyImporter.cpp b/src/gui/passkeys/PasskeyImporter.cpp index da7e07dc74..22435b99ea 100644 --- a/src/gui/passkeys/PasskeyImporter.cpp +++ b/src/gui/passkeys/PasskeyImporter.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 @@ -30,11 +30,16 @@ static const QString IMPORTED_PASSKEYS_GROUP = QStringLiteral("Imported Passkeys"); +PasskeyImporter::PasskeyImporter(QWidget* parent) + : m_parent(parent) +{ +} + void PasskeyImporter::importPasskey(QSharedPointer& database, Entry* entry) { auto filter = QString("%1 (*.passkey);;%2 (*)").arg(tr("Passkey file"), tr("All files")); auto fileName = - fileDialog()->getOpenFileName(nullptr, tr("Open Passkey file"), FileDialog::getLastDir("passkey"), filter); + fileDialog()->getOpenFileName(nullptr, tr("Open passkey file"), FileDialog::getLastDir("passkey"), filter); if (fileName.isEmpty()) { return; } @@ -56,9 +61,9 @@ void PasskeyImporter::importSelectedFile(QFile& file, QSharedPointer& const auto fileData = file.readAll(); const auto passkeyObject = browserMessageBuilder()->getJsonObject(fileData); if (passkeyObject.isEmpty()) { - MessageBox::information(nullptr, - tr("Cannot import Passkey"), - tr("Cannot import Passkey file \"%1\". Data is missing.").arg(file.fileName())); + MessageBox::information(m_parent, + tr("Cannot import passkey"), + tr("Cannot import passkey file \"%1\". Data is missing.").arg(file.fileName())); return; } @@ -70,43 +75,46 @@ void PasskeyImporter::importSelectedFile(QFile& file, QSharedPointer& << "credentialId" << "userHandle" << "privateKey"); - if (!missingKeys.isEmpty()) { - MessageBox::information(nullptr, - tr("Cannot import Passkey"), - tr("Cannot import Passkey file \"%1\".\nThe following data is missing:\n%2") + MessageBox::information(m_parent, + tr("Cannot import passkey"), + tr("Cannot import passkey file \"%1\".\nThe following data is missing:\n%2") .arg(file.fileName(), missingKeys.join(", "))); } else if (!privateKey.startsWith("-----BEGIN PRIVATE KEY-----") || !privateKey.trimmed().endsWith("-----END PRIVATE KEY-----")) { MessageBox::information( - nullptr, - tr("Cannot import Passkey"), - tr("Cannot import Passkey file \"%1\". Private key is missing or malformed.").arg(file.fileName())); + m_parent, + tr("Cannot import passkey"), + tr("Cannot import passkey file \"%1\". Private key is missing or malformed.").arg(file.fileName())); } else { const auto relyingParty = passkeyObject["relyingParty"].toString(); const auto url = passkeyObject["url"].toString(); const auto username = passkeyObject["username"].toString(); const auto credentialId = passkeyObject["credentialId"].toString(); const auto userHandle = passkeyObject["userHandle"].toString(); - showImportDialog(database, url, relyingParty, username, credentialId, userHandle, privateKey, entry); + showImportDialog(database, entry, url, relyingParty, username, credentialId, userHandle, privateKey); } } -void PasskeyImporter::showImportDialog(QSharedPointer& database, +bool PasskeyImporter::showImportDialog(QSharedPointer& database, + Entry* entry, const QString& url, const QString& relyingParty, const QString& username, const QString& credentialId, const QString& userHandle, const QString& privateKey, - Entry* entry) + const QString& titleText, + const QString& infoText, + const QString& importButtonText) { - PasskeyImportDialog passkeyImportDialog; - passkeyImportDialog.setInfo(relyingParty, username, database, entry != nullptr); + PasskeyImportDialog passkeyImportDialog(m_parent); + passkeyImportDialog.setInfo( + relyingParty, username, database, entry != nullptr, titleText, infoText, importButtonText); auto ret = passkeyImportDialog.exec(); if (ret != QDialog::Accepted) { - return; + return false; } auto db = passkeyImportDialog.getSelectedDatabase(); @@ -118,7 +126,7 @@ void PasskeyImporter::showImportDialog(QSharedPointer& database, if (entry) { browserService()->addPasskeyToEntry( entry, relyingParty, relyingParty, username, credentialId, userHandle, privateKey); - return; + return true; } // Import to entry selected instead of creating a new one @@ -134,7 +142,7 @@ void PasskeyImporter::showImportDialog(QSharedPointer& database, } } - return; + return true; } // Group settings. Use default group "Imported Passkeys" if user did not select a specific one. @@ -153,6 +161,8 @@ void PasskeyImporter::showImportDialog(QSharedPointer& database, browserService()->addPasskeyToGroup( db, group, url, relyingParty, relyingParty, username, credentialId, userHandle, privateKey); + + return true; } Group* PasskeyImporter::getDefaultGroup(QSharedPointer& database) const diff --git a/src/gui/passkeys/PasskeyImporter.h b/src/gui/passkeys/PasskeyImporter.h index 9cc7fab48f..9fd7097d5c 100644 --- a/src/gui/passkeys/PasskeyImporter.h +++ b/src/gui/passkeys/PasskeyImporter.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 @@ -21,7 +21,9 @@ #include "core/Database.h" #include #include +#include #include +#include class Entry; @@ -30,21 +32,27 @@ class PasskeyImporter : public QObject Q_OBJECT public: - explicit PasskeyImporter() = default; + explicit PasskeyImporter(QWidget* parent = nullptr); void importPasskey(QSharedPointer& database, Entry* entry = nullptr); - -private: - void importSelectedFile(QFile& file, QSharedPointer& database, Entry* entry); - void showImportDialog(QSharedPointer& database, + bool showImportDialog(QSharedPointer& database, + Entry* entry, const QString& url, const QString& relyingParty, const QString& username, const QString& credentialId, const QString& userHandle, const QString& privateKey, - Entry* entry); + const QString& titleText = {}, + const QString& infoText = {}, + const QString& importButtonText = {}); + +private: + void importSelectedFile(QFile& file, QSharedPointer& database, Entry* entry); Group* getDefaultGroup(QSharedPointer& database) const; + +private: + QPointer m_parent; }; #endif // KEEPASSXC_PASSKEYIMPORTER_H diff --git a/src/gui/reports/ReportsWidgetPasskeys.cpp b/src/gui/reports/ReportsWidgetPasskeys.cpp index f14b092a94..696fcd832c 100644 --- a/src/gui/reports/ReportsWidgetPasskeys.cpp +++ b/src/gui/reports/ReportsWidgetPasskeys.cpp @@ -152,7 +152,7 @@ void ReportsWidgetPasskeys::loadSettings(QSharedPointer db) m_rowToEntry.clear(); auto row = QList(); - row << new QStandardItem(tr("Please wait, list of entries with Passkeys is being updated…")); + row << new QStandardItem(tr("Please wait, list of entries with passkeys is being updated…")); m_referencesModel->appendRow(row); } @@ -188,7 +188,7 @@ void ReportsWidgetPasskeys::updateEntries() // Set the table header if (m_referencesModel->rowCount() == 0) { - m_referencesModel->setHorizontalHeaderLabels(QStringList() << tr("No entries with Passkeys.")); + m_referencesModel->setHorizontalHeaderLabels(QStringList() << tr("No entries with passkeys.")); } else { m_referencesModel->setHorizontalHeaderLabels(QStringList() << tr("Title") << tr("Path") << tr("Username") << tr("Relying Party") << tr("URLs")); @@ -282,7 +282,7 @@ void ReportsWidgetPasskeys::selectionChanged() void ReportsWidgetPasskeys::importPasskey() { - PasskeyImporter passkeyImporter; + PasskeyImporter passkeyImporter(this); passkeyImporter.importPasskey(m_db); updateEntries(); @@ -300,6 +300,6 @@ void ReportsWidgetPasskeys::exportPasskey() return; } - PasskeyExporter passkeyExporter; + PasskeyExporter passkeyExporter(this); passkeyExporter.showExportDialog(getSelectedEntries()); }