mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-04-04 13:07:38 +03:00
303 lines
11 KiB
C++
303 lines
11 KiB
C++
/*
|
|
* Copyright (C) 2022 KeePassXC Team <team@keepassxc.org>
|
|
* Copyright (C) 2018 Sami Vänttinen <sami.vanttinen@protonmail.com>
|
|
*
|
|
* 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
|
|
* the Free Software Foundation, either version 2 or (at your option)
|
|
* version 3 of the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "DatabaseSettingsWidgetBrowser.h"
|
|
#include "ui_DatabaseSettingsWidgetBrowser.h"
|
|
|
|
#include <QProgressDialog>
|
|
|
|
#include "browser/BrowserService.h"
|
|
#include "browser/BrowserSettings.h"
|
|
#include "core/Group.h"
|
|
#include "core/Metadata.h"
|
|
#include "gui/MessageBox.h"
|
|
|
|
DatabaseSettingsWidgetBrowser::DatabaseSettingsWidgetBrowser(QWidget* parent)
|
|
: DatabaseSettingsWidget(parent)
|
|
, m_ui(new Ui::DatabaseSettingsWidgetBrowser())
|
|
, m_customData(new CustomData(this))
|
|
, m_customDataModel(new QStandardItemModel(this))
|
|
{
|
|
m_ui->setupUi(this);
|
|
m_ui->removeCustomDataButton->setEnabled(false);
|
|
m_ui->customDataTable->setModel(m_customDataModel);
|
|
|
|
settingsWarning();
|
|
|
|
// clang-format off
|
|
connect(m_ui->customDataTable->selectionModel(),
|
|
SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
|
|
SLOT(toggleRemoveButton(QItemSelection)));
|
|
connect(m_ui->customDataTable, SIGNAL(doubleClicked(QModelIndex)), SLOT(editIndex(QModelIndex)));
|
|
connect(m_customDataModel, SIGNAL(itemChanged(QStandardItem*)), SLOT(editFinished(QStandardItem*)));
|
|
// clang-format on
|
|
|
|
connect(m_ui->removeCustomDataButton, SIGNAL(clicked()), SLOT(removeSelectedKey()));
|
|
connect(m_ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SLOT(removeSharedEncryptionKeys()));
|
|
connect(m_ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SLOT(updateSharedKeyList()));
|
|
connect(m_ui->removeStoredPermissions, SIGNAL(clicked()), this, SLOT(removeStoredPermissions()));
|
|
connect(m_ui->refreshDatabaseID, SIGNAL(clicked()), this, SLOT(refreshDatabaseID()));
|
|
}
|
|
|
|
DatabaseSettingsWidgetBrowser::~DatabaseSettingsWidgetBrowser()
|
|
{
|
|
}
|
|
|
|
CustomData* DatabaseSettingsWidgetBrowser::customData() const
|
|
{
|
|
// Returns the current database customData from metadata. Otherwise return an empty customData member.
|
|
if (m_db) {
|
|
return m_db->metadata()->customData();
|
|
}
|
|
return m_customData;
|
|
}
|
|
|
|
void DatabaseSettingsWidgetBrowser::initialize()
|
|
{
|
|
updateModel();
|
|
settingsWarning();
|
|
}
|
|
|
|
void DatabaseSettingsWidgetBrowser::uninitialize()
|
|
{
|
|
}
|
|
|
|
void DatabaseSettingsWidgetBrowser::showEvent(QShowEvent* event)
|
|
{
|
|
QWidget::showEvent(event);
|
|
}
|
|
|
|
bool DatabaseSettingsWidgetBrowser::saveSettings()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
void DatabaseSettingsWidgetBrowser::removeSelectedKey()
|
|
{
|
|
if (MessageBox::Yes
|
|
!= MessageBox::question(this,
|
|
tr("Delete the selected key?"),
|
|
tr("Do you really want to delete the selected key?\n"
|
|
"This may prevent connection to the browser plugin."),
|
|
MessageBox::Yes | MessageBox::Cancel,
|
|
MessageBox::Cancel)) {
|
|
return;
|
|
}
|
|
|
|
const QItemSelectionModel* itemSelectionModel = m_ui->customDataTable->selectionModel();
|
|
if (itemSelectionModel) {
|
|
for (const QModelIndex& index : itemSelectionModel->selectedRows(0)) {
|
|
QString key = index.data().toString();
|
|
key.insert(0, CustomData::BrowserKeyPrefix);
|
|
customData()->remove(key);
|
|
}
|
|
updateModel();
|
|
}
|
|
}
|
|
|
|
void DatabaseSettingsWidgetBrowser::toggleRemoveButton(const QItemSelection& selected)
|
|
{
|
|
m_ui->removeCustomDataButton->setEnabled(!selected.isEmpty());
|
|
}
|
|
|
|
void DatabaseSettingsWidgetBrowser::updateModel()
|
|
{
|
|
m_customDataModel->clear();
|
|
m_customDataModel->setHorizontalHeaderLabels({tr("Key"), tr("Value"), tr("Created")});
|
|
|
|
for (const QString& key : customData()->keys()) {
|
|
if (key.startsWith(CustomData::BrowserKeyPrefix)) {
|
|
QString strippedKey = key;
|
|
strippedKey.remove(CustomData::BrowserKeyPrefix);
|
|
auto created = customData()->value(QString("%1_%2").arg(CustomData::Created, strippedKey));
|
|
auto createdItem = new QStandardItem(created);
|
|
createdItem->setEditable(false);
|
|
m_customDataModel->appendRow(QList<QStandardItem*>()
|
|
<< new QStandardItem(strippedKey)
|
|
<< new QStandardItem(customData()->value(key)) << createdItem);
|
|
}
|
|
}
|
|
|
|
m_ui->removeCustomDataButton->setEnabled(false);
|
|
}
|
|
|
|
void DatabaseSettingsWidgetBrowser::settingsWarning()
|
|
{
|
|
if (!browserSettings()->isEnabled()) {
|
|
m_ui->removeSharedEncryptionKeys->setEnabled(false);
|
|
m_ui->removeStoredPermissions->setEnabled(false);
|
|
m_ui->customDataTable->setEnabled(false);
|
|
m_ui->warningWidget->showMessage(tr("Enable Browser Integration to access these settings."),
|
|
MessageWidget::Warning);
|
|
m_ui->warningWidget->setCloseButtonVisible(false);
|
|
m_ui->warningWidget->setAutoHideTimeout(-1);
|
|
} else {
|
|
m_ui->removeSharedEncryptionKeys->setEnabled(true);
|
|
m_ui->removeStoredPermissions->setEnabled(true);
|
|
m_ui->customDataTable->setEnabled(true);
|
|
m_ui->warningWidget->hideMessage();
|
|
}
|
|
}
|
|
|
|
void DatabaseSettingsWidgetBrowser::removeSharedEncryptionKeys()
|
|
{
|
|
if (MessageBox::Yes
|
|
!= MessageBox::question(this,
|
|
tr("Disconnect all browsers"),
|
|
tr("Do you really want to disconnect all browsers?\n"
|
|
"This may prevent connection to the browser plugin."),
|
|
MessageBox::Yes | MessageBox::Cancel,
|
|
MessageBox::Cancel)) {
|
|
return;
|
|
}
|
|
|
|
QStringList keysToRemove;
|
|
for (const QString& key : m_db->metadata()->customData()->keys()) {
|
|
if (key.startsWith(CustomData::BrowserKeyPrefix)) {
|
|
keysToRemove << key;
|
|
}
|
|
}
|
|
|
|
if (keysToRemove.isEmpty()) {
|
|
MessageBox::information(
|
|
this, tr("No keys found"), tr("No shared encryption keys found in KeePassXC settings."), MessageBox::Ok);
|
|
return;
|
|
}
|
|
|
|
for (const QString& key : keysToRemove) {
|
|
m_db->metadata()->customData()->remove(key);
|
|
}
|
|
|
|
const int count = keysToRemove.count();
|
|
MessageBox::information(this,
|
|
tr("Removed keys from database"),
|
|
tr("Successfully removed %n encryption key(s) from KeePassXC settings.", "", count),
|
|
MessageBox::Ok);
|
|
}
|
|
|
|
void DatabaseSettingsWidgetBrowser::removeStoredPermissions()
|
|
{
|
|
if (MessageBox::Yes
|
|
!= MessageBox::question(this,
|
|
tr("Forget all site-specific settings on entries"),
|
|
tr("Do you really want forget all site-specific settings on every entry?\n"
|
|
"Permissions to access entries will be revoked."),
|
|
MessageBox::Yes | MessageBox::Cancel,
|
|
MessageBox::Cancel)) {
|
|
return;
|
|
}
|
|
|
|
QList<Entry*> entries = m_db->rootGroup()->entriesRecursive();
|
|
|
|
QProgressDialog progress(tr("Removing stored permissions…"), tr("Abort"), 0, entries.count());
|
|
progress.setWindowModality(Qt::WindowModal);
|
|
|
|
uint counter = 0;
|
|
for (Entry* entry : entries) {
|
|
if (progress.wasCanceled()) {
|
|
return;
|
|
}
|
|
|
|
if (entry->customData()->contains(BrowserService::KEEPASSXCBROWSER_NAME)) {
|
|
browserService()->removePluginData(entry);
|
|
++counter;
|
|
}
|
|
progress.setValue(progress.value() + 1);
|
|
}
|
|
progress.reset();
|
|
|
|
if (counter > 0) {
|
|
MessageBox::information(this,
|
|
tr("Removed permissions"),
|
|
tr("Successfully removed permissions from %n entry(s).", "", counter),
|
|
MessageBox::Ok);
|
|
} else {
|
|
MessageBox::information(this,
|
|
tr("No entry with permissions found!"),
|
|
tr("The active database does not contain an entry with permissions."),
|
|
MessageBox::Ok);
|
|
}
|
|
}
|
|
|
|
void DatabaseSettingsWidgetBrowser::refreshDatabaseID()
|
|
{
|
|
if (MessageBox::Yes
|
|
!= MessageBox::question(this,
|
|
tr("Refresh database ID"),
|
|
tr("Do you really want refresh the database ID?\n"
|
|
"This is only necessary if your database is a copy of another and the "
|
|
"browser extension cannot connect."),
|
|
MessageBox::Yes | MessageBox::Cancel,
|
|
MessageBox::Cancel)) {
|
|
return;
|
|
}
|
|
|
|
m_db->rootGroup()->setUuid(QUuid::createUuid());
|
|
}
|
|
|
|
void DatabaseSettingsWidgetBrowser::editIndex(const QModelIndex& index)
|
|
{
|
|
Q_ASSERT(index.isValid());
|
|
if (!index.isValid()) {
|
|
return;
|
|
}
|
|
|
|
m_valueInEdit = index.data().toString();
|
|
m_ui->customDataTable->edit(index);
|
|
}
|
|
|
|
void DatabaseSettingsWidgetBrowser::editFinished(QStandardItem* item)
|
|
{
|
|
const QItemSelectionModel* itemSelectionModel = m_ui->customDataTable->selectionModel();
|
|
|
|
if (itemSelectionModel) {
|
|
auto indexList = itemSelectionModel->selectedRows(item->column());
|
|
if (indexList.length() > 0) {
|
|
QString newValue = item->index().data().toString();
|
|
|
|
// The key is edited
|
|
if (item->column() == 0) {
|
|
// Get the old key/value pair, remove it and replace it
|
|
m_valueInEdit.insert(0, CustomData::BrowserKeyPrefix);
|
|
auto tempValue = customData()->value(m_valueInEdit);
|
|
newValue.insert(0, CustomData::BrowserKeyPrefix);
|
|
|
|
m_db->metadata()->customData()->remove(m_valueInEdit);
|
|
m_db->metadata()->customData()->set(newValue, tempValue);
|
|
} else {
|
|
// Replace just the value
|
|
for (const QString& key : m_db->metadata()->customData()->keys()) {
|
|
if (key.startsWith(CustomData::BrowserKeyPrefix)) {
|
|
if (m_valueInEdit == m_db->metadata()->customData()->value(key)) {
|
|
m_db->metadata()->customData()->set(key, newValue);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
updateModel();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Updates the shared key list after the list is cleared
|
|
void DatabaseSettingsWidgetBrowser::updateSharedKeyList()
|
|
{
|
|
updateModel();
|
|
}
|