keepassxc

Форк
0
/
DatabaseSettingsWidgetBrowser.cpp 
305 строк · 11.1 Кб
1
/*
2
 *  Copyright (C) 2022 KeePassXC Team <team@keepassxc.org>
3
 *  Copyright (C) 2018 Sami Vänttinen <sami.vanttinen@protonmail.com>
4
 *
5
 *  This program is free software: you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation, either version 2 or (at your option)
8
 *  version 3 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18

19
#include "DatabaseSettingsWidgetBrowser.h"
20
#include "ui_DatabaseSettingsWidgetBrowser.h"
21

22
#include <QProgressDialog>
23

24
#include "browser/BrowserService.h"
25
#include "browser/BrowserSettings.h"
26
#include "core/Group.h"
27
#include "core/Metadata.h"
28
#include "gui/MessageBox.h"
29

30
DatabaseSettingsWidgetBrowser::DatabaseSettingsWidgetBrowser(QWidget* parent)
31
    : DatabaseSettingsWidget(parent)
32
    , m_ui(new Ui::DatabaseSettingsWidgetBrowser())
33
    , m_customData(new CustomData(this))
34
    , m_customDataModel(new QStandardItemModel(this))
35
{
36
    m_ui->setupUi(this);
37
    m_ui->removeCustomDataButton->setEnabled(false);
38
    m_ui->customDataTable->setModel(m_customDataModel);
39

40
    settingsWarning();
41

42
    // clang-format off
43
    connect(m_ui->customDataTable->selectionModel(),
44
            SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
45
            SLOT(toggleRemoveButton(QItemSelection)));
46
    connect(m_ui->customDataTable, SIGNAL(doubleClicked(QModelIndex)), SLOT(editIndex(QModelIndex)));
47
    connect(m_customDataModel, SIGNAL(itemChanged(QStandardItem*)), SLOT(editFinished(QStandardItem*)));
48
    // clang-format on
49

50
    connect(m_ui->removeCustomDataButton, SIGNAL(clicked()), SLOT(removeSelectedKey()));
51
    connect(m_ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SLOT(removeSharedEncryptionKeys()));
52
    connect(m_ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SLOT(updateSharedKeyList()));
53
    connect(m_ui->removeStoredPermissions, SIGNAL(clicked()), this, SLOT(removeStoredPermissions()));
54
    connect(m_ui->refreshDatabaseID, SIGNAL(clicked()), this, SLOT(refreshDatabaseID()));
55
}
56

57
DatabaseSettingsWidgetBrowser::~DatabaseSettingsWidgetBrowser()
58
{
59
}
60

61
CustomData* DatabaseSettingsWidgetBrowser::customData() const
62
{
63
    // Returns the current database customData from metadata. Otherwise return an empty customData member.
64
    if (m_db) {
65
        return m_db->metadata()->customData();
66
    }
67
    return m_customData;
68
}
69

70
void DatabaseSettingsWidgetBrowser::initialize()
71
{
72
    updateModel();
73
    settingsWarning();
74
}
75

76
void DatabaseSettingsWidgetBrowser::uninitialize()
77
{
78
}
79

80
void DatabaseSettingsWidgetBrowser::showEvent(QShowEvent* event)
81
{
82
    QWidget::showEvent(event);
83
}
84

85
bool DatabaseSettingsWidgetBrowser::save()
86
{
87
    return true;
88
}
89

90
void DatabaseSettingsWidgetBrowser::removeSelectedKey()
91
{
92
    if (MessageBox::Yes
93
        != MessageBox::question(this,
94
                                tr("Delete the selected key?"),
95
                                tr("Do you really want to delete the selected key?\n"
96
                                   "This may prevent connection to the browser plugin."),
97
                                MessageBox::Yes | MessageBox::Cancel,
98
                                MessageBox::Cancel)) {
99
        return;
100
    }
101

102
    const QItemSelectionModel* itemSelectionModel = m_ui->customDataTable->selectionModel();
103
    if (itemSelectionModel) {
104
        for (const QModelIndex& index : itemSelectionModel->selectedRows(0)) {
105
            QString key = index.data().toString();
106
            key.insert(0, CustomData::BrowserKeyPrefix);
107
            customData()->remove(key);
108
        }
109
        updateModel();
110
    }
111
}
112

113
void DatabaseSettingsWidgetBrowser::toggleRemoveButton(const QItemSelection& selected)
114
{
115
    m_ui->removeCustomDataButton->setEnabled(!selected.isEmpty());
116
}
117

118
void DatabaseSettingsWidgetBrowser::updateModel()
119
{
120
    m_customDataModel->clear();
121
    m_customDataModel->setHorizontalHeaderLabels({tr("Key"), tr("Value"), tr("Created")});
122

123
    for (const QString& key : customData()->keys()) {
124
        if (key.startsWith(CustomData::BrowserKeyPrefix)) {
125
            QString strippedKey = key;
126
            strippedKey.remove(CustomData::BrowserKeyPrefix);
127
            auto created = customData()->value(QString("%1_%2").arg(CustomData::Created, strippedKey));
128
            auto createdItem = new QStandardItem(created);
129
            createdItem->setEditable(false);
130
            m_customDataModel->appendRow(QList<QStandardItem*>()
131
                                         << new QStandardItem(strippedKey)
132
                                         << new QStandardItem(customData()->value(key)) << createdItem);
133
        }
134
    }
135

136
    m_ui->removeCustomDataButton->setEnabled(false);
137
}
138

139
void DatabaseSettingsWidgetBrowser::settingsWarning()
140
{
141
    if (!browserSettings()->isEnabled()) {
142
        m_ui->removeSharedEncryptionKeys->setEnabled(false);
143
        m_ui->removeStoredPermissions->setEnabled(false);
144
        m_ui->customDataTable->setEnabled(false);
145
        m_ui->warningWidget->showMessage(tr("Enable Browser Integration to access these settings."),
146
                                         MessageWidget::Warning);
147
        m_ui->warningWidget->setCloseButtonVisible(false);
148
        m_ui->warningWidget->setAutoHideTimeout(-1);
149
    } else {
150
        m_ui->removeSharedEncryptionKeys->setEnabled(true);
151
        m_ui->removeStoredPermissions->setEnabled(true);
152
        m_ui->customDataTable->setEnabled(true);
153
        m_ui->warningWidget->hideMessage();
154
    }
155
}
156

157
void DatabaseSettingsWidgetBrowser::removeSharedEncryptionKeys()
158
{
159
    if (MessageBox::Yes
160
        != MessageBox::question(this,
161
                                tr("Disconnect all browsers"),
162
                                tr("Do you really want to disconnect all browsers?\n"
163
                                   "This may prevent connection to the browser plugin."),
164
                                MessageBox::Yes | MessageBox::Cancel,
165
                                MessageBox::Cancel)) {
166
        return;
167
    }
168

169
    QStringList keysToRemove;
170
    for (const QString& key : m_db->metadata()->customData()->keys()) {
171
        if (key.startsWith(CustomData::BrowserKeyPrefix)) {
172
            keysToRemove << key;
173
        }
174
    }
175

176
    if (keysToRemove.isEmpty()) {
177
        MessageBox::information(
178
            this, tr("No keys found"), tr("No shared encryption keys found in KeePassXC settings."), MessageBox::Ok);
179
        return;
180
    }
181

182
    for (const QString& key : keysToRemove) {
183
        m_db->metadata()->customData()->remove(key);
184
    }
185

186
    const int count = keysToRemove.count();
187
    MessageBox::information(this,
188
                            tr("Removed keys from database"),
189
                            tr("Successfully removed %n encryption key(s) from KeePassXC settings.", "", count),
190
                            MessageBox::Ok);
191
}
192

193
void DatabaseSettingsWidgetBrowser::removeStoredPermissions()
194
{
195
    if (MessageBox::Yes
196
        != MessageBox::question(this,
197
                                tr("Forget all site-specific settings on entries"),
198
                                tr("Do you really want forget all site-specific settings on every entry?\n"
199
                                   "Permissions to access entries will be revoked."),
200
                                MessageBox::Yes | MessageBox::Cancel,
201
                                MessageBox::Cancel)) {
202
        return;
203
    }
204

205
    QList<Entry*> entries = m_db->rootGroup()->entriesRecursive();
206

207
    QProgressDialog progress(tr("Removing stored permissions…"), tr("Abort"), 0, entries.count());
208
    progress.setWindowModality(Qt::WindowModal);
209

210
    uint counter = 0;
211
    for (Entry* entry : entries) {
212
        if (progress.wasCanceled()) {
213
            return;
214
        }
215

216
        if (entry->customData()->contains(BrowserService::KEEPASSXCBROWSER_NAME)) {
217
            entry->beginUpdate();
218
            entry->customData()->remove(BrowserService::KEEPASSXCBROWSER_NAME);
219
            entry->endUpdate();
220
            ++counter;
221
        }
222
        progress.setValue(progress.value() + 1);
223
    }
224
    progress.reset();
225

226
    if (counter > 0) {
227
        MessageBox::information(this,
228
                                tr("Removed permissions"),
229
                                tr("Successfully removed permissions from %n entry(s).", "", counter),
230
                                MessageBox::Ok);
231
    } else {
232
        MessageBox::information(this,
233
                                tr("No entry with permissions found!"),
234
                                tr("The active database does not contain an entry with permissions."),
235
                                MessageBox::Ok);
236
    }
237
}
238

239
void DatabaseSettingsWidgetBrowser::refreshDatabaseID()
240
{
241
    if (MessageBox::Yes
242
        != MessageBox::question(this,
243
                                tr("Refresh database ID"),
244
                                tr("Do you really want refresh the database ID?\n"
245
                                   "This is only necessary if your database is a copy of another and the "
246
                                   "browser extension cannot connect."),
247
                                MessageBox::Yes | MessageBox::Cancel,
248
                                MessageBox::Cancel)) {
249
        return;
250
    }
251

252
    m_db->rootGroup()->setUuid(QUuid::createUuid());
253
}
254

255
void DatabaseSettingsWidgetBrowser::editIndex(const QModelIndex& index)
256
{
257
    Q_ASSERT(index.isValid());
258
    if (!index.isValid()) {
259
        return;
260
    }
261

262
    m_valueInEdit = index.data().toString();
263
    m_ui->customDataTable->edit(index);
264
}
265

266
void DatabaseSettingsWidgetBrowser::editFinished(QStandardItem* item)
267
{
268
    const QItemSelectionModel* itemSelectionModel = m_ui->customDataTable->selectionModel();
269

270
    if (itemSelectionModel) {
271
        auto indexList = itemSelectionModel->selectedRows(item->column());
272
        if (indexList.length() > 0) {
273
            QString newValue = item->index().data().toString();
274

275
            // The key is edited
276
            if (item->column() == 0) {
277
                // Get the old key/value pair, remove it and replace it
278
                m_valueInEdit.insert(0, CustomData::BrowserKeyPrefix);
279
                auto tempValue = customData()->value(m_valueInEdit);
280
                newValue.insert(0, CustomData::BrowserKeyPrefix);
281

282
                m_db->metadata()->customData()->remove(m_valueInEdit);
283
                m_db->metadata()->customData()->set(newValue, tempValue);
284
            } else {
285
                // Replace just the value
286
                for (const QString& key : m_db->metadata()->customData()->keys()) {
287
                    if (key.startsWith(CustomData::BrowserKeyPrefix)) {
288
                        if (m_valueInEdit == m_db->metadata()->customData()->value(key)) {
289
                            m_db->metadata()->customData()->set(key, newValue);
290
                            break;
291
                        }
292
                    }
293
                }
294
            }
295

296
            updateModel();
297
        }
298
    }
299
}
300

301
// Updates the shared key list after the list is cleared
302
void DatabaseSettingsWidgetBrowser::updateSharedKeyList()
303
{
304
    updateModel();
305
}
306

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.