mirror of
https://git.citron-emu.org/Citron/Citron.git
synced 2025-01-22 08:36:32 +01:00
web: Simplify web configuration and token management
- Remove telemetry functionality and related UI elements - Add automatic token generation using UUID - Remove manual token verification process - Sync Citron username with profile username automatically - Simplify web configuration UI and improve error messages - Update host room error message for clarity This change streamlines the web service configuration by removing unnecessary complexity and automating token management. Users no longer need to manually verify tokens, and the Citron username is automatically kept in sync with their profile username.
This commit is contained in:
parent
8f5e3516fe
commit
21f94d5825
5 changed files with 40 additions and 183 deletions
|
@ -177,6 +177,9 @@ void ConfigureProfileManager::UpdateCurrentUser() {
|
||||||
scene->addPixmap(
|
scene->addPixmap(
|
||||||
GetIcon(*current_user).scaled(48, 48, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
GetIcon(*current_user).scaled(48, 48, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||||
ui->current_user_username->setText(username);
|
ui->current_user_username->setText(username);
|
||||||
|
|
||||||
|
// Set the username for the Citron profile
|
||||||
|
Settings::values.citron_username = username.toStdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureProfileManager::ApplyConfiguration() {
|
void ConfigureProfileManager::ApplyConfiguration() {
|
||||||
|
|
|
@ -5,43 +5,15 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QtConcurrent/QtConcurrentRun>
|
#include <QtConcurrent/QtConcurrentRun>
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/telemetry_session.h"
|
#include "common/uuid.h"
|
||||||
#include "ui_configure_web.h"
|
#include "ui_configure_web.h"
|
||||||
#include "citron/configuration/configure_web.h"
|
#include "citron/configuration/configure_web.h"
|
||||||
#include "citron/uisettings.h"
|
#include "citron/uisettings.h"
|
||||||
|
|
||||||
static constexpr char token_delimiter{':'};
|
|
||||||
|
|
||||||
static std::string GenerateDisplayToken(const std::string& username, const std::string& token) {
|
|
||||||
if (username.empty() || token.empty()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string unencoded_display_token{username + token_delimiter + token};
|
|
||||||
QByteArray b{unencoded_display_token.c_str()};
|
|
||||||
QByteArray b64 = b.toBase64();
|
|
||||||
return b64.toStdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string UsernameFromDisplayToken(const std::string& display_token) {
|
|
||||||
const std::string unencoded_display_token{
|
|
||||||
QByteArray::fromBase64(display_token.c_str()).toStdString()};
|
|
||||||
return unencoded_display_token.substr(0, unencoded_display_token.find(token_delimiter));
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string TokenFromDisplayToken(const std::string& display_token) {
|
|
||||||
const std::string unencoded_display_token{
|
|
||||||
QByteArray::fromBase64(display_token.c_str()).toStdString()};
|
|
||||||
return unencoded_display_token.substr(unencoded_display_token.find(token_delimiter) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigureWeb::ConfigureWeb(QWidget* parent)
|
ConfigureWeb::ConfigureWeb(QWidget* parent)
|
||||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureWeb>()) {
|
: QWidget(parent), ui(std::make_unique<Ui::ConfigureWeb>()) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
connect(ui->button_regenerate_telemetry_id, &QPushButton::clicked, this,
|
connect(ui->button_reset_token, &QPushButton::clicked, this, &ConfigureWeb::ResetToken);
|
||||||
&ConfigureWeb::RefreshTelemetryID);
|
|
||||||
connect(ui->button_verify_login, &QPushButton::clicked, this, &ConfigureWeb::VerifyLogin);
|
|
||||||
connect(&verify_watcher, &QFutureWatcher<bool>::finished, this, &ConfigureWeb::OnLoginVerified);
|
|
||||||
|
|
||||||
#ifndef USE_DISCORD_PRESENCE
|
#ifndef USE_DISCORD_PRESENCE
|
||||||
ui->discord_group->setVisible(false);
|
ui->discord_group->setVisible(false);
|
||||||
|
@ -63,115 +35,51 @@ void ConfigureWeb::changeEvent(QEvent* event) {
|
||||||
|
|
||||||
void ConfigureWeb::RetranslateUI() {
|
void ConfigureWeb::RetranslateUI() {
|
||||||
ui->retranslateUi(this);
|
ui->retranslateUi(this);
|
||||||
|
|
||||||
ui->telemetry_learn_more->setText(
|
|
||||||
tr("<a href='https://citron-emu.org/help/feature/telemetry/'><span style=\"text-decoration: "
|
|
||||||
"underline; color:#039be5;\">Learn more</span></a>"));
|
|
||||||
|
|
||||||
ui->web_signup_link->setText(
|
|
||||||
tr("<a href='https://profile.citron-emu.org/'><span style=\"text-decoration: underline; "
|
|
||||||
"color:#039be5;\">Sign up</span></a>"));
|
|
||||||
|
|
||||||
ui->web_token_info_link->setText(
|
|
||||||
tr("<a href='https://citron-emu.org/wiki/citron-web-service/'><span style=\"text-decoration: "
|
|
||||||
"underline; color:#039be5;\">What is my token?</span></a>"));
|
|
||||||
|
|
||||||
ui->label_telemetry_id->setText(
|
|
||||||
tr("Telemetry ID: 0x%1").arg(QString::number(Core::GetTelemetryId(), 16).toUpper()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureWeb::SetConfiguration() {
|
void ConfigureWeb::SetConfiguration() {
|
||||||
ui->web_credentials_disclaimer->setWordWrap(true);
|
ui->web_credentials_disclaimer->setWordWrap(true);
|
||||||
|
|
||||||
ui->telemetry_learn_more->setOpenExternalLinks(true);
|
|
||||||
ui->web_signup_link->setOpenExternalLinks(true);
|
|
||||||
ui->web_token_info_link->setOpenExternalLinks(true);
|
|
||||||
|
|
||||||
if (Settings::values.citron_username.GetValue().empty()) {
|
if (Settings::values.citron_username.GetValue().empty()) {
|
||||||
ui->username->setText(tr("Unspecified"));
|
ui->username->setText(tr("Unspecified"));
|
||||||
} else {
|
} else {
|
||||||
ui->username->setText(QString::fromStdString(Settings::values.citron_username.GetValue()));
|
ui->username->setText(QString::fromStdString(Settings::values.citron_username.GetValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->toggle_telemetry->setChecked(Settings::values.enable_telemetry.GetValue());
|
ui->edit_token->setText(QString::fromStdString(Settings::values.citron_token.GetValue()));
|
||||||
ui->edit_token->setText(QString::fromStdString(GenerateDisplayToken(
|
|
||||||
Settings::values.citron_username.GetValue(), Settings::values.citron_token.GetValue())));
|
|
||||||
|
|
||||||
// Connect after setting the values, to avoid calling OnLoginChanged now
|
|
||||||
connect(ui->edit_token, &QLineEdit::textChanged, this, &ConfigureWeb::OnLoginChanged);
|
|
||||||
|
|
||||||
user_verified = true;
|
|
||||||
|
|
||||||
ui->toggle_discordrpc->setChecked(UISettings::values.enable_discord_presence.GetValue());
|
ui->toggle_discordrpc->setChecked(UISettings::values.enable_discord_presence.GetValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureWeb::ApplyConfiguration() {
|
void ConfigureWeb::ApplyConfiguration() {
|
||||||
Settings::values.enable_telemetry = ui->toggle_telemetry->isChecked();
|
|
||||||
UISettings::values.enable_discord_presence = ui->toggle_discordrpc->isChecked();
|
UISettings::values.enable_discord_presence = ui->toggle_discordrpc->isChecked();
|
||||||
if (user_verified) {
|
if (Settings::values.citron_username.GetValue().empty()) {
|
||||||
Settings::values.citron_username =
|
// Backup: default name should already be set by ConfigureProfileManager::UpdateCurrentUser()
|
||||||
UsernameFromDisplayToken(ui->edit_token->text().toStdString());
|
Settings::values.citron_username = "torzu";
|
||||||
Settings::values.citron_token = TokenFromDisplayToken(ui->edit_token->text().toStdString());
|
|
||||||
} else {
|
} else {
|
||||||
QMessageBox::warning(
|
// If a name already exist, reassign it to itself (needed for change set with a profile switch)
|
||||||
this, tr("Token not verified"),
|
Settings::values.citron_username = Settings::values.citron_username.GetValue();
|
||||||
tr("Token was not verified. The change to your token has not been saved."));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigureWeb::RefreshTelemetryID() {
|
|
||||||
const u64 new_telemetry_id{Core::RegenerateTelemetryId()};
|
|
||||||
ui->label_telemetry_id->setText(
|
|
||||||
tr("Telemetry ID: 0x%1").arg(QString::number(new_telemetry_id, 16).toUpper()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigureWeb::OnLoginChanged() {
|
|
||||||
if (ui->edit_token->text().isEmpty()) {
|
if (ui->edit_token->text().isEmpty()) {
|
||||||
user_verified = true;
|
// If no token specified, automatically generate one
|
||||||
// Empty = no icon
|
Settings::values.citron_token = Common::UUID::MakeRandom().FormattedString();
|
||||||
ui->label_token_verified->setPixmap(QPixmap());
|
|
||||||
ui->label_token_verified->setToolTip(QString());
|
|
||||||
} else {
|
} else {
|
||||||
user_verified = false;
|
// Otherwise use user-specified value
|
||||||
|
Settings::values.citron_token = ui->edit_token->text().toStdString();
|
||||||
// Show an info icon if it's been changed, clearer than showing failure
|
|
||||||
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("info")).pixmap(16);
|
|
||||||
ui->label_token_verified->setPixmap(pixmap);
|
|
||||||
ui->label_token_verified->setToolTip(
|
|
||||||
tr("Unverified, please click Verify before saving configuration", "Tooltip"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureWeb::VerifyLogin() {
|
void ConfigureWeb::ResetToken() {
|
||||||
ui->button_verify_login->setDisabled(true);
|
// Generate and set token
|
||||||
ui->button_verify_login->setText(tr("Verifying..."));
|
const auto token = Common::UUID::MakeRandom().FormattedString();
|
||||||
ui->label_token_verified->setPixmap(QIcon::fromTheme(QStringLiteral("sync")).pixmap(16));
|
Settings::values.citron_token = token;
|
||||||
ui->label_token_verified->setToolTip(tr("Verifying..."));
|
// Just to display the label_token_icon pic and tooltip for visual confirmation
|
||||||
verify_watcher.setFuture(QtConcurrent::run(
|
ui->label_token_icon->setPixmap(QIcon::fromTheme(QStringLiteral("checked")).pixmap(16));
|
||||||
[username = UsernameFromDisplayToken(ui->edit_token->text().toStdString()),
|
ui->label_token_icon->setToolTip(tr("Token Changed", "Tooltip"));
|
||||||
token = TokenFromDisplayToken(ui->edit_token->text().toStdString())] {
|
ui->username->setText(QString::fromStdString(token));
|
||||||
return Core::VerifyLogin(username, token);
|
// Apply the changes
|
||||||
}));
|
SetConfiguration();
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigureWeb::OnLoginVerified() {
|
|
||||||
ui->button_verify_login->setEnabled(true);
|
|
||||||
ui->button_verify_login->setText(tr("Verify"));
|
|
||||||
if (verify_watcher.result()) {
|
|
||||||
user_verified = true;
|
|
||||||
|
|
||||||
ui->label_token_verified->setPixmap(QIcon::fromTheme(QStringLiteral("checked")).pixmap(16));
|
|
||||||
ui->label_token_verified->setToolTip(tr("Verified", "Tooltip"));
|
|
||||||
ui->username->setText(
|
|
||||||
QString::fromStdString(UsernameFromDisplayToken(ui->edit_token->text().toStdString())));
|
|
||||||
} else {
|
|
||||||
ui->label_token_verified->setPixmap(QIcon::fromTheme(QStringLiteral("failed")).pixmap(16));
|
|
||||||
ui->label_token_verified->setToolTip(tr("Verification failed", "Tooltip"));
|
|
||||||
ui->username->setText(tr("Unspecified"));
|
|
||||||
QMessageBox::critical(this, tr("Verification failed"),
|
|
||||||
tr("Verification failed. Check that you have entered your token "
|
|
||||||
"correctly, and that your internet connection is working."));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureWeb::SetWebServiceConfigEnabled(bool enabled) {
|
void ConfigureWeb::SetWebServiceConfigEnabled(bool enabled) {
|
||||||
|
|
|
@ -25,15 +25,9 @@ private:
|
||||||
void changeEvent(QEvent* event) override;
|
void changeEvent(QEvent* event) override;
|
||||||
void RetranslateUI();
|
void RetranslateUI();
|
||||||
|
|
||||||
void RefreshTelemetryID();
|
void ResetToken();
|
||||||
void OnLoginChanged();
|
|
||||||
void VerifyLogin();
|
|
||||||
void OnLoginVerified();
|
|
||||||
|
|
||||||
void SetConfiguration();
|
void SetConfiguration();
|
||||||
|
|
||||||
bool user_verified = true;
|
|
||||||
QFutureWatcher<bool> verify_watcher;
|
|
||||||
|
|
||||||
std::unique_ptr<Ui::ConfigureWeb> ui;
|
std::unique_ptr<Ui::ConfigureWeb> ui;
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>926</width>
|
<width>2280</width>
|
||||||
<height>561</height>
|
<height>561</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
@ -24,18 +24,18 @@
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>citron Web Service</string>
|
<string>citron Web Service</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayoutCitronWebService">
|
<layout class="QVBoxLayout" name="verticalLayoutYuzuWebService">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="web_credentials_disclaimer">
|
<widget class="QLabel" name="web_credentials_disclaimer">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>By providing your username and token, you agree to allow citron to collect additional usage data, which may include user identifying information.</string>
|
<string>This is your Citron Web Service token. It is used to authenticate your Citron account.</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayoutCitronUsername">
|
<layout class="QGridLayout" name="gridLayoutYuzuUsername">
|
||||||
<item row="2" column="3">
|
<item row="2" column="3">
|
||||||
<widget class="QPushButton" name="button_verify_login">
|
<widget class="QPushButton" name="button_reset_token">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
|
@ -46,12 +46,15 @@
|
||||||
<enum>Qt::RightToLeft</enum>
|
<enum>Qt::RightToLeft</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Verify</string>
|
<string>Reset Token</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="web_signup_link">
|
<widget class="QLabel" name="web_signup_link">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Sign up</string>
|
<string>Sign up</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -68,7 +71,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="4">
|
<item row="1" column="4">
|
||||||
<widget class="QLabel" name="label_token_verified"/>
|
<widget class="QLabel" name="label_token_icon"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label_username">
|
<widget class="QLabel" name="label_username">
|
||||||
|
@ -82,13 +85,13 @@
|
||||||
<property name="maxLength">
|
<property name="maxLength">
|
||||||
<number>80</number>
|
<number>80</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="echoMode">
|
|
||||||
<enum>QLineEdit::Password</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QLabel" name="web_token_info_link">
|
<widget class="QLabel" name="web_token_info_link">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>What is my token?</string>
|
<string>What is my token?</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -122,56 +125,6 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="groupBox">
|
|
||||||
<property name="title">
|
|
||||||
<string>Telemetry</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="toggle_telemetry">
|
|
||||||
<property name="text">
|
|
||||||
<string>Share anonymous usage data with the citron team</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="telemetry_learn_more">
|
|
||||||
<property name="text">
|
|
||||||
<string>Learn more</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QGridLayout" name="gridLayoutTelemetryId">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_telemetry_id">
|
|
||||||
<property name="text">
|
|
||||||
<string>Telemetry ID:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QPushButton" name="button_regenerate_telemetry_id">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="layoutDirection">
|
|
||||||
<enum>Qt::RightToLeft</enum>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Regenerate</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|
|
@ -183,8 +183,7 @@ void HostRoomWindow::Host() {
|
||||||
if (result.result_code != WebService::WebResult::Code::Success) {
|
if (result.result_code != WebService::WebResult::Code::Success) {
|
||||||
QMessageBox::warning(
|
QMessageBox::warning(
|
||||||
this, tr("Error"),
|
this, tr("Error"),
|
||||||
tr("Failed to announce the room to the public lobby. In order to host a "
|
tr("To host a room publicly, you must have a valid citron account configured in "
|
||||||
"room publicly, you must have a valid citron account configured in "
|
|
||||||
"Emulation -> Configure -> Web. If you do not want to publish a room in "
|
"Emulation -> Configure -> Web. If you do not want to publish a room in "
|
||||||
"the public lobby, then select Unlisted instead.\nDebug Message: ") +
|
"the public lobby, then select Unlisted instead.\nDebug Message: ") +
|
||||||
QString::fromStdString(result.result_string),
|
QString::fromStdString(result.result_string),
|
||||||
|
|
Loading…
Reference in a new issue