aboutsummaryrefslogtreecommitdiff
path: root/src/widgets
diff options
context:
space:
mode:
authorOsmium Sorcerer <os@sof.beauty>2026-03-22 18:51:12 +0000
committerOsmium Sorcerer <os@sof.beauty>2026-03-29 22:22:25 +0000
commitb1ad938c37f4e175e5509f727d1033b074b134d4 (patch)
tree702b41a851550c14104599905907fa659c0d39b7 /src/widgets
parent4274f5036004ae6d3db0e88c8e28eb78c6e37d27 (diff)
Integrate the keyring into UI
Add "Keyring" tab to the options dialog. The tab displays the keys from the table model (notes and certificates) and lets users create and delete keys. Key generation dialog includes passphare confirmation and a note.
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/aooptionsdialog.cpp47
-rw-r--r--src/widgets/aooptionsdialog.h6
-rw-r--r--src/widgets/key_generate_dialog.cpp53
-rw-r--r--src/widgets/key_generate_dialog.h26
4 files changed, 131 insertions, 1 deletions
diff --git a/src/widgets/aooptionsdialog.cpp b/src/widgets/aooptionsdialog.cpp
index 760dccf..d9cbcb8 100644
--- a/src/widgets/aooptionsdialog.cpp
+++ b/src/widgets/aooptionsdialog.cpp
@@ -8,10 +8,13 @@
#include "networkmanager.h"
#include "options.h"
+// Hopefully temporary.
+#include "widgets/key_generate_dialog.h"
#include <QCollator>
#include <QDoubleSpinBox>
#include <QGroupBox>
+#include <QHeaderView>
#include <QResource>
#include <QUiLoader>
#include <QVBoxLayout>
@@ -594,7 +597,49 @@ void AOOptionsDialog::setupUI()
FROM_UI(QTextBrowser, privacy_policy);
ui_privacy_policy->setPlainText(tr("Getting privacy policy..."));
FROM_UI(QCheckBox, privacy_optout_cb);
- registerOption<QCheckBox, bool>("privacy_optout", &Options::playerCountOptout, &Options::setPlayerCountOptout);
+ registerOption<QCheckBox, bool>("privacy_optout_cb", &Options::playerCountOptout, &Options::setPlayerCountOptout);
+
+ // Keyring tab
+
+ FROM_UI(QPushButton, key_generate);
+ connect(ui_key_generate, &QPushButton::clicked, this, [=, this] {
+ // this should be coupled
+ KeyGenerateDialog keygen_dialog(this);
+ if (keygen_dialog.exec() == QDialog::Accepted)
+ {
+ int err = generate_key(keygen_dialog.key_name(), keygen_dialog.key_password());
+ if (err)
+ {
+ QMessageBox::warning(this, "Error", QString("Key generation failed, code %1").arg(err));
+ }
+ ao_app->keyring_model.load_keys();
+ }
+ });
+ FROM_UI(QPushButton, key_delete);
+
+ FROM_UI(QTableView, keyring_table);
+ ui_keyring_table->setModel(&ao_app->keyring_model);
+ ui_keyring_table->setSelectionMode(QAbstractItemView::SingleSelection);
+ ui_keyring_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
+
+ // This assumes something is selected, and emptiness of selection is thus
+ // unchecked.
+ connect(ui_key_delete, &QPushButton::clicked, this, [=, this] {
+ int row = ui_keyring_table->selectionModel()->selectedIndexes().first().row();
+ QString key_note = ao_app->keyring_model.data(ao_app->keyring_model.index(row, 0)).toString();
+ QString del_text = QString("Are you sure you want to delete the key pair \"%1\"? If it's an active key that you use to authenticate on a server, and you want to delete it due to suspected compromise (or otherwise want it to never be used for authentication by anyone), revoke it on the server first.").arg(key_note);
+ if (QMessageBox::question(this, "Confirm deletion", del_text, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes)
+ {
+ QByteArray key_id = ao_app->keyring_model.data(ao_app->keyring_model.index(row, 0), 0x0100).toByteArray();
+ delete_key(key_id);
+ ao_app->keyring_model.load_keys();
+ }
+ });
+
+ connect(ui_keyring_table->selectionModel(), &QItemSelectionModel::selectionChanged, this, [=, this] {
+ bool selected = !ui_keyring_table->selectionModel()->selectedIndexes().isEmpty();
+ ui_key_delete->setEnabled(selected);
+ });
updateValues();
}
diff --git a/src/widgets/aooptionsdialog.h b/src/widgets/aooptionsdialog.h
index ab59916..bc9f282 100644
--- a/src/widgets/aooptionsdialog.h
+++ b/src/widgets/aooptionsdialog.h
@@ -15,6 +15,7 @@
#include <QScrollArea>
#include <QSpinBox>
#include <QTabWidget>
+#include <QTableView>
#include <QTextBrowser>
#include <QVariant>
@@ -123,6 +124,11 @@ private:
QFrame *ui_privacy_separator;
QTextBrowser *ui_privacy_policy;
+ // The keyring tab
+ QPushButton *ui_key_generate;
+ QPushButton *ui_key_delete;
+ QTableView *ui_keyring_table;
+
bool asset_cache_dirty = false;
void populateAudioDevices();
diff --git a/src/widgets/key_generate_dialog.cpp b/src/widgets/key_generate_dialog.cpp
new file mode 100644
index 0000000..1e9790e
--- /dev/null
+++ b/src/widgets/key_generate_dialog.cpp
@@ -0,0 +1,53 @@
+#include "key_generate_dialog.h"
+
+#include <QFile>
+#include <QPushButton>
+#include <QUiLoader>
+#include <QVBoxLayout>
+
+#include "options.h"
+
+KeyGenerateDialog::KeyGenerateDialog(QWidget *parent)
+ : QDialog(parent)
+{
+ QUiLoader l_loader(this);
+ QFile l_uiFile(Options::getInstance().getUIAsset("key_generate_dialog.ui"));
+ if (!l_uiFile.open(QFile::ReadOnly))
+ {
+ qCritical() << "Unable to open file " << l_uiFile.fileName();
+ return;
+ }
+ ui_widget = l_loader.load(&l_uiFile, this);
+ auto l_layout = new QVBoxLayout(this);
+ l_layout->addWidget(ui_widget);
+ setWindowTitle("Generate key");
+
+ FROM_UI(QLineEdit, key_name);
+ FROM_UI(QLineEdit, key_password);
+ ui_key_password->setEchoMode(QLineEdit::Password);
+ connect(ui_key_password, &QLineEdit::textChanged, this, &KeyGenerateDialog::validate);
+ FROM_UI(QLineEdit, key_password_confirm);
+ ui_key_password_confirm->setEchoMode(QLineEdit::Password);
+ connect(ui_key_password_confirm, &QLineEdit::textChanged, this, &KeyGenerateDialog::validate);
+ FROM_UI(QDialogButtonBox, key_gen_buttons);
+ connect(ui_key_gen_buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(ui_key_gen_buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
+
+ validate();
+}
+
+// Empty passwords should be also checked.
+void KeyGenerateDialog::validate()
+{
+ ui_key_gen_buttons->button(QDialogButtonBox::Ok)->setEnabled(!ui_key_password->text().isEmpty() && (ui_key_password->text() == ui_key_password_confirm->text()));
+}
+
+QStringView KeyGenerateDialog::key_name()
+{
+ return ui_key_name->text();
+}
+
+QByteArray KeyGenerateDialog::key_password()
+{
+ return ui_key_password->text().toUtf8();
+}
diff --git a/src/widgets/key_generate_dialog.h b/src/widgets/key_generate_dialog.h
new file mode 100644
index 0000000..dd366fc
--- /dev/null
+++ b/src/widgets/key_generate_dialog.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <QDialog>
+#include <QDialogButtonBox>
+#include <QLineEdit>
+
+#include "gui_utils.h"
+
+class KeyGenerateDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit KeyGenerateDialog(QWidget *parent = nullptr);
+ QStringView key_name();
+ QByteArray key_password();
+
+private:
+ QWidget *ui_widget;
+ QLineEdit *ui_key_name;
+ QLineEdit *ui_key_password;
+ QLineEdit *ui_key_password_confirm;
+ QDialogButtonBox *ui_key_gen_buttons;
+
+ void validate(void);
+};