mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-04 14:08:37 +00:00
RPCN v0.6
This commit is contained in:
parent
67c02e3522
commit
eea73deab3
39 changed files with 3461 additions and 758 deletions
|
|
@ -6,11 +6,13 @@
|
|||
#include <QInputDialog>
|
||||
#include <QGroupBox>
|
||||
#include <QMenu>
|
||||
#include <QDialogButtonBox>
|
||||
#include <thread>
|
||||
|
||||
#include "qt_utils.h"
|
||||
|
||||
#include "rpcn_settings_dialog.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/NP/rpcn_config.h"
|
||||
|
||||
#include <wolfssl/ssl.h>
|
||||
|
|
@ -18,13 +20,50 @@
|
|||
|
||||
LOG_CHANNEL(rpcn_settings_log, "rpcn settings dlg");
|
||||
|
||||
bool validate_rpcn_username(const std::string& input)
|
||||
bool validate_rpcn_username(std::string_view username)
|
||||
{
|
||||
if (input.length() < 3 || input.length() > 16)
|
||||
if (username.length() < 3 || username.length() > 16)
|
||||
return false;
|
||||
|
||||
return std::all_of(input.cbegin(), input.cend(), [](const char c)
|
||||
{ return std::isalnum(c) || c == '-' || c == '_'; });
|
||||
return std::all_of(username.cbegin(), username.cend(), [](const char c)
|
||||
{
|
||||
return std::isalnum(static_cast<unsigned char>(c)) || c == '-' || c == '_';
|
||||
});
|
||||
}
|
||||
|
||||
bool validate_email(std::string_view email)
|
||||
{
|
||||
const QRegularExpressionValidator simple_email_validator(QRegularExpression("^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$"));
|
||||
QString qstr_email = QString::fromStdString(std::string(email));
|
||||
int pos = 0;
|
||||
|
||||
if (qstr_email.isEmpty() || qstr_email.contains(' ') || qstr_email.contains('\t') || simple_email_validator.validate(qstr_email, pos) != QValidator::Acceptable)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validate_token(std::string_view token)
|
||||
{
|
||||
return token.size() == 16 && std::all_of(token.cbegin(), token.cend(), [](const char c) { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z'); });
|
||||
}
|
||||
|
||||
std::string derive_password(std::string_view user_password)
|
||||
{
|
||||
std::string_view salt_str = "No matter where you go, everybody's connected.";
|
||||
|
||||
u8 derived_password_digest[SHA3_256_DIGEST_LENGTH];
|
||||
ensure(!wc_PBKDF2(derived_password_digest, reinterpret_cast<const u8*>(user_password.data()), user_password.size(), reinterpret_cast<const u8*>(salt_str.data()), salt_str.size(), 200'000, SHA3_256_DIGEST_LENGTH, WC_SHA3_256));
|
||||
|
||||
std::string derived_password("0000000000000000000000000000000000000000000000000000000000000000");
|
||||
for (u32 i = 0; i < SHA3_256_DIGEST_LENGTH; i++)
|
||||
{
|
||||
constexpr auto pal = "0123456789ABCDEF";
|
||||
derived_password[i * 2] = pal[derived_password_digest[i] >> 4];
|
||||
derived_password[(i * 2) + 1] = pal[derived_password_digest[i] & 15];
|
||||
}
|
||||
|
||||
return derived_password;
|
||||
}
|
||||
|
||||
rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
||||
|
|
@ -51,6 +90,11 @@ rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
|||
|
||||
connect(btn_account, &QPushButton::clicked, this, [this]()
|
||||
{
|
||||
if (!Emu.IsStopped())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error: Emulation Running"), tr("You need to stop the emulator before editing RPCN account information!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
rpcn_account_dialog dlg(this);
|
||||
dlg.exec();
|
||||
});
|
||||
|
|
@ -66,8 +110,509 @@ rpcn_settings_dialog::rpcn_settings_dialog(QWidget* parent)
|
|||
rpcn_account_dialog::rpcn_account_dialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("RPCN: Configuration"));
|
||||
setWindowTitle(tr("RPCN: Account"));
|
||||
setObjectName("rpcn_account_dialog");
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
||||
QGroupBox* grp_server = new QGroupBox(tr("Server:"));
|
||||
QVBoxLayout* vbox_server = new QVBoxLayout();
|
||||
|
||||
QHBoxLayout* hbox_lbl_combo = new QHBoxLayout();
|
||||
QLabel* lbl_server = new QLabel(tr("Server:"));
|
||||
cbx_servers = new QComboBox();
|
||||
|
||||
refresh_combobox();
|
||||
|
||||
hbox_lbl_combo->addWidget(lbl_server);
|
||||
hbox_lbl_combo->addWidget(cbx_servers);
|
||||
|
||||
QHBoxLayout* hbox_buttons = new QHBoxLayout();
|
||||
QPushButton* btn_add_server = new QPushButton(tr("Add"));
|
||||
QPushButton* btn_del_server = new QPushButton(tr("Del"));
|
||||
hbox_buttons->addStretch();
|
||||
hbox_buttons->addWidget(btn_add_server);
|
||||
hbox_buttons->addWidget(btn_del_server);
|
||||
|
||||
vbox_server->addLayout(hbox_lbl_combo);
|
||||
vbox_server->addLayout(hbox_buttons);
|
||||
|
||||
grp_server->setLayout(vbox_server);
|
||||
vbox_global->addWidget(grp_server);
|
||||
|
||||
QGroupBox* grp_buttons = new QGroupBox();
|
||||
QVBoxLayout* vbox_buttons = new QVBoxLayout();
|
||||
QPushButton* btn_create = new QPushButton(tr("Create Account"));
|
||||
QPushButton* btn_edit = new QPushButton(tr("Edit Account"));
|
||||
QPushButton* btn_test = new QPushButton(tr("Test Account"));
|
||||
|
||||
vbox_buttons->addSpacing(10);
|
||||
vbox_buttons->addWidget(btn_create);
|
||||
vbox_buttons->addSpacing(10);
|
||||
vbox_buttons->addWidget(btn_edit);
|
||||
vbox_buttons->addSpacing(10);
|
||||
vbox_buttons->addWidget(btn_test);
|
||||
vbox_buttons->addSpacing(10);
|
||||
grp_buttons->setLayout(vbox_buttons);
|
||||
|
||||
vbox_global->addWidget(grp_buttons);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(cbx_servers, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index)
|
||||
{
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
QVariant host = cbx_servers->itemData(index);
|
||||
|
||||
if (!host.isValid() || !host.canConvert<QString>())
|
||||
return;
|
||||
|
||||
g_cfg_rpcn.set_host(host.toString().toStdString());
|
||||
g_cfg_rpcn.save();
|
||||
});
|
||||
|
||||
connect(btn_add_server, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
rpcn_add_server_dialog dlg(this);
|
||||
dlg.exec();
|
||||
const auto new_server = dlg.get_new_server();
|
||||
if (new_server)
|
||||
{
|
||||
if (!g_cfg_rpcn.add_host(new_server->first, new_server->second))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Existing Server"), tr("You already have a server with this description & hostname in the list."), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
g_cfg_rpcn.save();
|
||||
refresh_combobox();
|
||||
}
|
||||
});
|
||||
|
||||
connect(btn_del_server, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
const int index = cbx_servers->currentIndex();
|
||||
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
const auto desc = cbx_servers->itemText(index).toStdString();
|
||||
const auto host = cbx_servers->itemData(index).toString().toStdString();
|
||||
|
||||
ensure(g_cfg_rpcn.del_host(desc, host));
|
||||
g_cfg_rpcn.save();
|
||||
refresh_combobox();
|
||||
});
|
||||
|
||||
connect(btn_create, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
rpcn_ask_username_dialog dlg_username(this, tr("Please enter your username.\n\n"
|
||||
"Note that these restrictions apply:\n"
|
||||
"- Username must be between 3 and 16 characters\n"
|
||||
"- Username can only contain a-z A-Z 0-9 '-' '_'\n"
|
||||
"- Username is case sensitive\n"));
|
||||
dlg_username.exec();
|
||||
auto username = dlg_username.get_username();
|
||||
|
||||
if (!username)
|
||||
return;
|
||||
|
||||
rpcn_ask_password_dialog dlg_password(this, tr("Please choose your password:\n\n"));
|
||||
dlg_password.exec();
|
||||
auto password = dlg_password.get_password();
|
||||
|
||||
if (!password)
|
||||
return;
|
||||
|
||||
rpcn_ask_email_dialog dlg_email(this, tr("An email address is required, please note:\n"
|
||||
"- A valid email is needed to receive the token that validates your account.\n"
|
||||
"- Your email won't be used for anything beyond sending you this token or the password reset token.\n\n"));
|
||||
dlg_email.exec();
|
||||
auto email = dlg_email.get_email();
|
||||
|
||||
if (!email)
|
||||
return;
|
||||
|
||||
if (QMessageBox::question(this, tr("RPCN: Account Creation"), tr("You are about to create an account with:\n-Username:%0\n-Email:%1\n\nIs this correct?").arg(QString::fromStdString(*username)).arg(QString::fromStdString(*email))) != QMessageBox::Yes)
|
||||
return;
|
||||
|
||||
{
|
||||
const auto rpcn = rpcn::rpcn_client::get_instance();
|
||||
const auto avatar_url = "https://rpcs3.net/cdn/netplay/DefaultAvatar.png";
|
||||
|
||||
if (auto result = rpcn->wait_for_connection(); result != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
const QString error_message = tr("Failed to connect to RPCN server:\n%0").arg(QString::fromStdString(rpcn::rpcn_state_to_string(result)));
|
||||
QMessageBox::critical(this, tr("Error Connecting"), error_message, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto error = rpcn->create_user(*username, *password, *username, avatar_url, *email); error != rpcn::ErrorType::NoError)
|
||||
{
|
||||
QString error_message;
|
||||
switch (error)
|
||||
{
|
||||
case rpcn::ErrorType::CreationExistingUsername: error_message = tr("An account with that username already exists!"); break;
|
||||
case rpcn::ErrorType::CreationBannedEmailProvider: error_message = tr("This email provider is banned!"); break;
|
||||
case rpcn::ErrorType::CreationExistingEmail: error_message = tr("An account with that email already exists!"); break;
|
||||
case rpcn::ErrorType::CreationError: error_message = tr("Unknown creation error"); break;
|
||||
default: error_message = tr("Unknown error"); break;
|
||||
}
|
||||
QMessageBox::critical(this, tr("Error Creating Account"), tr("Failed to create the account:\n%0").arg(error_message), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
g_cfg_rpcn.set_npid(*username);
|
||||
g_cfg_rpcn.set_password(*password);
|
||||
g_cfg_rpcn.save();
|
||||
|
||||
rpcn_ask_token_dialog token_dlg(this, tr("Your account has been created successfully!\n"
|
||||
"Your account authentification was saved.\n"
|
||||
"Now all you need is to enter the token that was sent to your email.\n"
|
||||
"You can skip this step by leaving it empty and entering it later in the Edit Account section too.\n"));
|
||||
token_dlg.exec();
|
||||
auto token = token_dlg.get_token();
|
||||
|
||||
if (!token)
|
||||
return;
|
||||
|
||||
g_cfg_rpcn.set_token(*token);
|
||||
g_cfg_rpcn.save();
|
||||
});
|
||||
|
||||
connect(btn_edit, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
rpcn_account_edit_dialog dlg_edit(this);
|
||||
dlg_edit.exec();
|
||||
});
|
||||
|
||||
connect(btn_test, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
auto rpcn = rpcn::rpcn_client::get_instance();
|
||||
|
||||
if (auto res = rpcn->wait_for_connection(); res != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
const QString error_msg = tr("Failed to connect to RPCN:\n%0").arg(QString::fromStdString(rpcn::rpcn_state_to_string(res)));
|
||||
QMessageBox::warning(this, tr("Error connecting to RPCN!"), error_msg, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
if (auto res = rpcn->wait_for_authentified(); res != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
const QString error_msg = tr("Failed to authentify to RPCN:\n%0").arg(QString::fromStdString(rpcn::rpcn_state_to_string(res)));
|
||||
QMessageBox::warning(this, tr("Error authentifying to RPCN!"), error_msg, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
QMessageBox::information(this, tr("RPCN Account Valid!"), tr("Your account is valid!"), QMessageBox::Ok);
|
||||
});
|
||||
}
|
||||
|
||||
void rpcn_account_dialog::refresh_combobox()
|
||||
{
|
||||
g_cfg_rpcn.load();
|
||||
const auto vec_hosts = g_cfg_rpcn.get_hosts();
|
||||
auto cur_host = g_cfg_rpcn.get_host();
|
||||
int i = 0, index = 0;
|
||||
|
||||
cbx_servers->clear();
|
||||
|
||||
for (const auto& [desc, host] : vec_hosts)
|
||||
{
|
||||
cbx_servers->addItem(QString::fromStdString(desc), QString::fromStdString(host));
|
||||
if (cur_host == host)
|
||||
index = i;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
cbx_servers->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
rpcn_add_server_dialog::rpcn_add_server_dialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("RPCN: Add Server"));
|
||||
setObjectName("rpcn_add_server_dialog");
|
||||
setMinimumSize(QSize(400, 200));
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
||||
QLabel* lbl_description = new QLabel(tr("Description:"));
|
||||
QLineEdit* edt_description = new QLineEdit();
|
||||
QLabel* lbl_host = new QLabel(tr("Host:"));
|
||||
QLineEdit* edt_host = new QLineEdit();
|
||||
QDialogButtonBox* btn_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
|
||||
vbox_global->addWidget(lbl_description);
|
||||
vbox_global->addWidget(edt_description);
|
||||
vbox_global->addWidget(lbl_host);
|
||||
vbox_global->addWidget(edt_host);
|
||||
vbox_global->addWidget(btn_box);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(btn_box, &QDialogButtonBox::accepted, this, [this, edt_description, edt_host]()
|
||||
{
|
||||
auto description = edt_description->text();
|
||||
auto host = edt_host->text();
|
||||
|
||||
if (description.isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Missing Description"), tr("You must enter a description!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
if (host.isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Missing Hostname"), tr("You must enter a hostname for the server!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
m_new_server = std::make_pair(description.toStdString(), host.toStdString());
|
||||
QDialog::accept();
|
||||
});
|
||||
connect(btn_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
const std::optional<std::pair<std::string, std::string>>& rpcn_add_server_dialog::get_new_server() const
|
||||
{
|
||||
return m_new_server;
|
||||
}
|
||||
|
||||
rpcn_ask_username_dialog::rpcn_ask_username_dialog(QWidget* parent, const QString& description)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("RPCN: Username"));
|
||||
setObjectName("rpcn_ask_username_dialog");
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
||||
QLabel* lbl_username = new QLabel(description);
|
||||
|
||||
QGroupBox* grp_username = new QGroupBox(tr("Username:"));
|
||||
QHBoxLayout* hbox_grp_username = new QHBoxLayout();
|
||||
QLineEdit* edt_username = new QLineEdit(QString::fromStdString(g_cfg_rpcn.get_npid()));
|
||||
edt_username->setMaxLength(16);
|
||||
edt_username->setValidator(new QRegularExpressionValidator(QRegularExpression("^[a-zA-Z0-9_\\-]*$"), this));
|
||||
hbox_grp_username->addWidget(edt_username);
|
||||
grp_username->setLayout(hbox_grp_username);
|
||||
|
||||
QDialogButtonBox* btn_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
|
||||
vbox_global->addWidget(lbl_username);
|
||||
vbox_global->addWidget(grp_username);
|
||||
vbox_global->addWidget(btn_box);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(btn_box, &QDialogButtonBox::accepted, this, [this, edt_username]()
|
||||
{
|
||||
const auto username = edt_username->text().toStdString();
|
||||
|
||||
if (username.empty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Missing Username"), tr("You must enter a username!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
if (!validate_rpcn_username(username))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid Username"), tr("Please enter a valid username!"), QMessageBox::Ok);
|
||||
}
|
||||
|
||||
m_username = username;
|
||||
QDialog::accept();
|
||||
});
|
||||
connect(btn_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
const std::optional<std::string>& rpcn_ask_username_dialog::get_username() const
|
||||
{
|
||||
return m_username;
|
||||
}
|
||||
|
||||
rpcn_ask_password_dialog::rpcn_ask_password_dialog(QWidget* parent, const QString& description)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("RPCN: Password"));
|
||||
setObjectName("rpcn_ask_password_dialog");
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
||||
QLabel* lbl_description = new QLabel(description);
|
||||
|
||||
QGroupBox* gbox_password = new QGroupBox();
|
||||
QVBoxLayout* vbox_gbox = new QVBoxLayout();
|
||||
|
||||
QLabel* lbl_pass1 = new QLabel(tr("Enter your password:"));
|
||||
QLineEdit* m_edit_pass1 = new QLineEdit();
|
||||
m_edit_pass1->setEchoMode(QLineEdit::Password);
|
||||
QLabel* lbl_pass2 = new QLabel(tr("Enter your password a second time:"));
|
||||
QLineEdit* m_edit_pass2 = new QLineEdit();
|
||||
m_edit_pass2->setEchoMode(QLineEdit::Password);
|
||||
|
||||
vbox_gbox->addWidget(lbl_pass1);
|
||||
vbox_gbox->addWidget(m_edit_pass1);
|
||||
vbox_gbox->addWidget(lbl_pass2);
|
||||
vbox_gbox->addWidget(m_edit_pass2);
|
||||
gbox_password->setLayout(vbox_gbox);
|
||||
|
||||
QDialogButtonBox* btn_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
|
||||
vbox_global->addWidget(lbl_description);
|
||||
vbox_global->addWidget(gbox_password);
|
||||
vbox_global->addWidget(btn_box);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(btn_box, &QDialogButtonBox::accepted, this, [this, m_edit_pass1, m_edit_pass2]()
|
||||
{
|
||||
if (m_edit_pass1->text() != m_edit_pass2->text())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Wrong Input"), tr("The two passwords you entered don't match!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_edit_pass1->text().isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Missing Password"), tr("You need to enter a password!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
m_password = derive_password(m_edit_pass1->text().toStdString());
|
||||
QDialog::accept();
|
||||
});
|
||||
connect(btn_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
const std::optional<std::string>& rpcn_ask_password_dialog::get_password() const
|
||||
{
|
||||
return m_password;
|
||||
}
|
||||
|
||||
rpcn_ask_email_dialog::rpcn_ask_email_dialog(QWidget* parent, const QString& description)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("RPCN: Email"));
|
||||
setObjectName("rpcn_ask_email_dialog");
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
||||
QLabel* lbl_emailinfo = new QLabel(description);
|
||||
|
||||
QGroupBox* gbox_password = new QGroupBox();
|
||||
QVBoxLayout* vbox_gbox = new QVBoxLayout();
|
||||
|
||||
QLabel* lbl_pass1 = new QLabel(tr("Enter your email:"));
|
||||
QLineEdit* m_edit_pass1 = new QLineEdit();
|
||||
QLabel* lbl_pass2 = new QLabel(tr("Enter your email a second time:"));
|
||||
QLineEdit* m_edit_pass2 = new QLineEdit();
|
||||
|
||||
vbox_gbox->addWidget(lbl_pass1);
|
||||
vbox_gbox->addWidget(m_edit_pass1);
|
||||
vbox_gbox->addWidget(lbl_pass2);
|
||||
vbox_gbox->addWidget(m_edit_pass2);
|
||||
gbox_password->setLayout(vbox_gbox);
|
||||
|
||||
QDialogButtonBox* btn_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
|
||||
vbox_global->addWidget(lbl_emailinfo);
|
||||
vbox_global->addWidget(gbox_password);
|
||||
vbox_global->addWidget(btn_box);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(btn_box, &QDialogButtonBox::accepted, this, [this, m_edit_pass1, m_edit_pass2]()
|
||||
{
|
||||
if (m_edit_pass1->text() != m_edit_pass2->text())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Wrong Input"), tr("The two emails you entered don't match!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_edit_pass1->text().isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Missing Email"), tr("You need to enter an email!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
auto email = m_edit_pass1->text().toStdString();
|
||||
if (!validate_email(email))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid Email"), tr("You need to enter a valid email!"), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
m_email = email;
|
||||
QDialog::accept();
|
||||
});
|
||||
connect(btn_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
}
|
||||
|
||||
const std::optional<std::string>& rpcn_ask_email_dialog::get_email() const
|
||||
{
|
||||
return m_email;
|
||||
}
|
||||
|
||||
rpcn_ask_token_dialog::rpcn_ask_token_dialog(QWidget* parent, const QString& description)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("RPCN: Username"));
|
||||
setObjectName("rpcn_ask_token_dialog");
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
||||
QLabel* lbl_token = new QLabel(description);
|
||||
|
||||
QGroupBox* grp_token = new QGroupBox(tr("Token:"));
|
||||
QHBoxLayout* hbox_grp_token = new QHBoxLayout();
|
||||
QLineEdit* edt_token = new QLineEdit();
|
||||
edt_token->setMaxLength(16);
|
||||
hbox_grp_token->addWidget(edt_token);
|
||||
grp_token->setLayout(hbox_grp_token);
|
||||
|
||||
QDialogButtonBox* btn_box = new QDialogButtonBox(QDialogButtonBox::Ok);
|
||||
|
||||
vbox_global->addWidget(lbl_token);
|
||||
vbox_global->addWidget(grp_token);
|
||||
vbox_global->addWidget(btn_box);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(btn_box, &QDialogButtonBox::accepted, this, [this, edt_token]()
|
||||
{
|
||||
const auto token = edt_token->text().toStdString();
|
||||
|
||||
if (!token.empty())
|
||||
{
|
||||
if (!validate_token(token))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid Token"), tr("The token appears to be invalid:\n"
|
||||
"-Token should be 16 characters long\n"
|
||||
"-Token should only contain 0-9 and A-F"),
|
||||
QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
m_token = token;
|
||||
}
|
||||
|
||||
QDialog::accept();
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
const std::optional<std::string>& rpcn_ask_token_dialog::get_token() const
|
||||
{
|
||||
return m_token;
|
||||
}
|
||||
|
||||
rpcn_account_edit_dialog::rpcn_account_edit_dialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("RPCN: Edit Account"));
|
||||
setObjectName("rpcn_account_edit_dialog");
|
||||
setMinimumSize(QSize(400, 200));
|
||||
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
|
|
@ -76,37 +621,30 @@ rpcn_account_dialog::rpcn_account_dialog(QWidget* parent)
|
|||
QVBoxLayout* vbox_edits = new QVBoxLayout();
|
||||
QHBoxLayout* hbox_buttons = new QHBoxLayout();
|
||||
|
||||
QLabel* label_host = new QLabel(tr("Host:"));
|
||||
m_edit_host = new QLineEdit();
|
||||
QLabel* label_npid = new QLabel(tr("NPID (username):"));
|
||||
m_edit_npid = new QLineEdit();
|
||||
m_edit_npid->setMaxLength(16);
|
||||
m_edit_npid->setValidator(new QRegularExpressionValidator(QRegularExpression("^[a-zA-Z0-9_\\-]*$"), this));
|
||||
QLabel* label_pass = new QLabel(tr("Password:"));
|
||||
QLabel* lbl_username = new QLabel(tr("Username:"));
|
||||
m_edit_username = new QLineEdit();
|
||||
m_edit_username->setMaxLength(16);
|
||||
m_edit_username->setValidator(new QRegularExpressionValidator(QRegularExpression("^[a-zA-Z0-9_\\-]*$"), this));
|
||||
QLabel* lbl_pass = new QLabel(tr("Password:"));
|
||||
QPushButton* btn_chg_pass = new QPushButton(tr("Set Password"));
|
||||
QLabel* label_token = new QLabel(tr("Token:"));
|
||||
QLabel* lbl_token = new QLabel(tr("Token:"));
|
||||
m_edit_token = new QLineEdit();
|
||||
m_edit_token->setMaxLength(16);
|
||||
|
||||
QPushButton* btn_create = new QPushButton(tr("Create Account"), this);
|
||||
QPushButton* btn_resendtoken = new QPushButton(tr("Resend Token"), this);
|
||||
QPushButton* btn_changepass = new QPushButton(tr("Change Password"), this);
|
||||
btn_changepass->setEnabled(false);
|
||||
QPushButton* btn_save = new QPushButton(tr("Save"), this);
|
||||
QPushButton* btn_resendtoken = new QPushButton(tr("Resend Token"), this);
|
||||
QPushButton* btn_change_password = new QPushButton(tr("Change Password"), this);
|
||||
QPushButton* btn_save = new QPushButton(tr("Save"), this);
|
||||
|
||||
vbox_labels->addWidget(label_host);
|
||||
vbox_labels->addWidget(label_npid);
|
||||
vbox_labels->addWidget(label_pass);
|
||||
vbox_labels->addWidget(label_token);
|
||||
vbox_labels->addWidget(lbl_username);
|
||||
vbox_labels->addWidget(lbl_pass);
|
||||
vbox_labels->addWidget(lbl_token);
|
||||
|
||||
vbox_edits->addWidget(m_edit_host);
|
||||
vbox_edits->addWidget(m_edit_npid);
|
||||
vbox_edits->addWidget(m_edit_username);
|
||||
vbox_edits->addWidget(btn_chg_pass);
|
||||
vbox_edits->addWidget(m_edit_token);
|
||||
|
||||
hbox_buttons->addWidget(btn_create);
|
||||
hbox_buttons->addWidget(btn_resendtoken);
|
||||
hbox_buttons->addWidget(btn_changepass);
|
||||
hbox_buttons->addWidget(btn_change_password);
|
||||
hbox_buttons->addStretch();
|
||||
hbox_buttons->addWidget(btn_save);
|
||||
|
||||
|
|
@ -120,29 +658,14 @@ rpcn_account_dialog::rpcn_account_dialog(QWidget* parent)
|
|||
|
||||
connect(btn_chg_pass, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
rpcn_ask_password_dialog ask_pass;
|
||||
rpcn_ask_password_dialog ask_pass(this, tr("Please enter your password:"));
|
||||
ask_pass.exec();
|
||||
|
||||
auto password = ask_pass.get_password();
|
||||
if (!password)
|
||||
return;
|
||||
|
||||
const std::string pass_str = password.value();
|
||||
const std::string salt_str = "No matter where you go, everybody's connected.";
|
||||
|
||||
u8 salted_pass[SHA_DIGEST_SIZE];
|
||||
|
||||
wolfSSL_PKCS5_PBKDF2_HMAC_SHA1(pass_str.c_str(), pass_str.size(), reinterpret_cast<const u8*>(salt_str.c_str()), salt_str.size(), 1000, SHA_DIGEST_SIZE, salted_pass);
|
||||
|
||||
std::string hash("0000000000000000000000000000000000000000");
|
||||
for (u32 i = 0; i < 20; i++)
|
||||
{
|
||||
constexpr auto pal = "0123456789abcdef";
|
||||
hash[i * 2] = pal[salted_pass[i] >> 4];
|
||||
hash[1 + i * 2] = pal[salted_pass[i] & 15];
|
||||
}
|
||||
|
||||
g_cfg_rpcn.set_password(hash);
|
||||
g_cfg_rpcn.set_password(*password);
|
||||
g_cfg_rpcn.save();
|
||||
|
||||
QMessageBox::information(this, tr("RPCN Password Saved"), tr("Your password was saved successfully!"), QMessageBox::Ok);
|
||||
|
|
@ -153,48 +676,39 @@ rpcn_account_dialog::rpcn_account_dialog(QWidget* parent)
|
|||
if (save_config())
|
||||
close();
|
||||
});
|
||||
connect(btn_create, &QAbstractButton::clicked, this, &rpcn_account_dialog::create_account);
|
||||
connect(btn_resendtoken, &QAbstractButton::clicked, this, &rpcn_account_dialog::resend_token);
|
||||
connect(btn_resendtoken, &QAbstractButton::clicked, this, &rpcn_account_edit_dialog::resend_token);
|
||||
connect(btn_change_password, &QAbstractButton::clicked, this, &rpcn_account_edit_dialog::change_password);
|
||||
|
||||
g_cfg_rpcn.load();
|
||||
|
||||
m_edit_host->setText(QString::fromStdString(g_cfg_rpcn.get_host()));
|
||||
m_edit_npid->setText(QString::fromStdString(g_cfg_rpcn.get_npid()));
|
||||
m_edit_username->setText(QString::fromStdString(g_cfg_rpcn.get_npid()));
|
||||
m_edit_token->setText(QString::fromStdString(g_cfg_rpcn.get_token()));
|
||||
}
|
||||
|
||||
bool rpcn_account_dialog::save_config()
|
||||
bool rpcn_account_edit_dialog::save_config()
|
||||
{
|
||||
const auto host = m_edit_host->text().toStdString();
|
||||
const auto npid = m_edit_npid->text().toStdString();
|
||||
const auto token = m_edit_token->text().toStdString();
|
||||
const auto username = m_edit_username->text().toStdString();
|
||||
const auto token = m_edit_token->text().toStdString();
|
||||
|
||||
if (host.empty())
|
||||
if (username.empty() || g_cfg_rpcn.get_password().empty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Missing host"), tr("You need to enter a host for rpcn!"), QMessageBox::Ok);
|
||||
QMessageBox::critical(this, tr("Missing Input"), tr("You need to enter a username and a password!"), QMessageBox::Ok);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (npid.empty() || g_cfg_rpcn.get_password().empty())
|
||||
if (!validate_rpcn_username(username))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Wrong input"), tr("You need to enter a username and a password!"), QMessageBox::Ok);
|
||||
QMessageBox::critical(this, tr("Invalid Username"), tr("Username must be between 3 and 16 characters and can only contain '-', '_' or alphanumeric characters."), QMessageBox::Ok);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!validate_rpcn_username(npid))
|
||||
if (!token.empty() && !validate_token(token))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid character"), tr("NPID must be between 3 and 16 characters and can only contain '-', '_' or alphanumeric characters."), QMessageBox::Ok);
|
||||
QMessageBox::critical(this, tr("Invalid Token"), tr("The token you have received should be 16 characters long and contain only 0-9 A-F."), QMessageBox::Ok);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!token.empty() && token.size() != 16)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid token"), tr("The token you have received should be 16 characters long."), QMessageBox::Ok);
|
||||
return false;
|
||||
}
|
||||
|
||||
g_cfg_rpcn.set_host(host);
|
||||
g_cfg_rpcn.set_npid(npid);
|
||||
g_cfg_rpcn.set_npid(username);
|
||||
g_cfg_rpcn.set_token(token);
|
||||
|
||||
g_cfg_rpcn.save();
|
||||
|
|
@ -202,66 +716,7 @@ bool rpcn_account_dialog::save_config()
|
|||
return true;
|
||||
}
|
||||
|
||||
void rpcn_account_dialog::create_account()
|
||||
{
|
||||
// Validate and save
|
||||
if (!save_config())
|
||||
return;
|
||||
|
||||
QString email;
|
||||
const QRegularExpressionValidator simple_email_validator(QRegularExpression("^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$"));
|
||||
|
||||
while (true)
|
||||
{
|
||||
bool clicked_ok = false;
|
||||
email = QInputDialog::getText(this, tr("Email address"), tr("An email address is required, please note:\n*A valid email is needed to validate your account.\n*Your email won't be used for anything beyond sending you the token.\n*Upon successful creation a token will be sent to your email which you'll need to login.\n\n"), QLineEdit::Normal, "", &clicked_ok);
|
||||
if (!clicked_ok)
|
||||
return;
|
||||
|
||||
int pos = 0;
|
||||
if (email.isEmpty() || simple_email_validator.validate(email, pos) != QValidator::Acceptable)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Wrong input"), tr("You need to enter a valid email!"), QMessageBox::Ok);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const auto rpcn = rpcn::rpcn_client::get_instance();
|
||||
|
||||
const auto npid = g_cfg_rpcn.get_npid();
|
||||
const auto online_name = npid;
|
||||
const auto avatar_url = "https://rpcs3.net/cdn/netplay/DefaultAvatar.png";
|
||||
const auto password = g_cfg_rpcn.get_password();
|
||||
|
||||
if (auto result = rpcn->wait_for_connection(); result != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
const QString error_message = tr("Failed to connect to RPCN server:\n%0").arg(QString::fromStdString(rpcn::rpcn_state_to_string(result)));
|
||||
QMessageBox::critical(this, tr("Error Connecting"), error_message, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto error = rpcn->create_user(npid, password, online_name, avatar_url, email.toStdString()); error != rpcn::ErrorType::NoError)
|
||||
{
|
||||
QString error_message;
|
||||
switch (error)
|
||||
{
|
||||
case rpcn::ErrorType::CreationExistingUsername: error_message = tr("An account with that username already exists!"); break;
|
||||
case rpcn::ErrorType::CreationBannedEmailProvider: error_message = tr("This email provider is banned!"); break;
|
||||
case rpcn::ErrorType::CreationExistingEmail: error_message = tr("An account with that email already exists!"); break;
|
||||
case rpcn::ErrorType::CreationError: error_message = tr("Unknown creation error"); break;
|
||||
default: error_message = tr("Unknown error"); break;
|
||||
}
|
||||
QMessageBox::critical(this, tr("Error Creating Account"), tr("Failed to create the account:\n%0").arg(error_message), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
QMessageBox::information(this, tr("Account created!"), tr("Your account has been created successfully!\nCheck your email for your token!"), QMessageBox::Ok);
|
||||
}
|
||||
|
||||
void rpcn_account_dialog::resend_token()
|
||||
void rpcn_account_edit_dialog::resend_token()
|
||||
{
|
||||
if (!save_config())
|
||||
return;
|
||||
|
|
@ -284,11 +739,10 @@ void rpcn_account_dialog::resend_token()
|
|||
switch (error)
|
||||
{
|
||||
case rpcn::ErrorType::Invalid: error_message = tr("The server has no email verification and doesn't need a token!"); break;
|
||||
case rpcn::ErrorType::LoginAlreadyLoggedIn: error_message = tr("You can't ask for your token while authentified!"); break;
|
||||
case rpcn::ErrorType::DbFail: error_message = tr("A database related error happened on the server!"); break;
|
||||
case rpcn::ErrorType::TooSoon: error_message = tr("You can only ask for a token mail once every 24 hours!"); break;
|
||||
case rpcn::ErrorType::EmailFail: error_message = tr("The mail couldn't be sent successfully!"); break;
|
||||
case rpcn::ErrorType::LoginError: error_message = tr("The login/password pair is invalid!"); break;
|
||||
case rpcn::ErrorType::LoginError: error_message = tr("The username/password pair is invalid!"); break;
|
||||
default: error_message = tr("Unknown error"); break;
|
||||
}
|
||||
QMessageBox::critical(this, tr("Error Sending Token"), tr("Failed to send the token:\n%0").arg(error_message), QMessageBox::Ok);
|
||||
|
|
@ -298,64 +752,102 @@ void rpcn_account_dialog::resend_token()
|
|||
QMessageBox::information(this, tr("Token Sent!"), tr("Your token was successfully resent to the email associated with your account!"), QMessageBox::Ok);
|
||||
}
|
||||
|
||||
rpcn_ask_password_dialog::rpcn_ask_password_dialog(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
void rpcn_account_edit_dialog::change_password()
|
||||
{
|
||||
QVBoxLayout* vbox_global = new QVBoxLayout();
|
||||
QHBoxLayout* hbox_buttons = new QHBoxLayout();
|
||||
rpcn_ask_username_dialog dlg_username(this, tr("Please confirm your username:"));
|
||||
dlg_username.exec();
|
||||
auto username = dlg_username.get_username();
|
||||
|
||||
QGroupBox* gbox_password = new QGroupBox();
|
||||
QVBoxLayout* vbox_gbox = new QVBoxLayout();
|
||||
if (!username)
|
||||
return;
|
||||
|
||||
QLabel* label_pass1 = new QLabel(tr("Enter your password:"));
|
||||
m_edit_pass1 = new QLineEdit();
|
||||
m_edit_pass1->setEchoMode(QLineEdit::Password);
|
||||
QLabel* label_pass2 = new QLabel(tr("Enter your password a second time:"));
|
||||
m_edit_pass2 = new QLineEdit();
|
||||
m_edit_pass2->setEchoMode(QLineEdit::Password);
|
||||
switch (QMessageBox::question(this, tr("RPCN: Change Password"), tr("Do you already have a reset password token?\n"
|
||||
"Note that the reset password token is different from the email verification token.")))
|
||||
{
|
||||
case QMessageBox::No:
|
||||
{
|
||||
rpcn_ask_email_dialog dlg_email(this, tr("Please enter the email you used to create the account:"));
|
||||
dlg_email.exec();
|
||||
const auto email = dlg_email.get_email();
|
||||
|
||||
vbox_gbox->addWidget(label_pass1);
|
||||
vbox_gbox->addWidget(m_edit_pass1);
|
||||
vbox_gbox->addWidget(label_pass2);
|
||||
vbox_gbox->addWidget(m_edit_pass2);
|
||||
gbox_password->setLayout(vbox_gbox);
|
||||
if (!email)
|
||||
return;
|
||||
|
||||
QPushButton* btn_ok = new QPushButton(tr("Ok"));
|
||||
QPushButton* btn_cancel = new QPushButton(tr("Cancel"));
|
||||
|
||||
hbox_buttons->addStretch();
|
||||
hbox_buttons->addWidget(btn_ok);
|
||||
hbox_buttons->addWidget(btn_cancel);
|
||||
|
||||
vbox_global->addWidget(gbox_password);
|
||||
vbox_global->addLayout(hbox_buttons);
|
||||
|
||||
setLayout(vbox_global);
|
||||
|
||||
connect(btn_ok, &QAbstractButton::clicked, this, [this]()
|
||||
{
|
||||
if (m_edit_pass1->text() != m_edit_pass2->text())
|
||||
const auto rpcn = rpcn::rpcn_client::get_instance();
|
||||
if (auto result = rpcn->wait_for_connection(); result != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Wrong input"), tr("The two passwords you entered don't match!"), QMessageBox::Ok);
|
||||
const QString error_message = tr("Failed to connect to RPCN server:\n%0").arg(QString::fromStdString(rpcn::rpcn_state_to_string(result)));
|
||||
QMessageBox::critical(this, tr("Error Connecting"), error_message, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_edit_pass1->text().isEmpty())
|
||||
if (auto error = rpcn->send_reset_token(*username, *email); error != rpcn::ErrorType::NoError)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Wrong input"), tr("You need to enter a password!"), QMessageBox::Ok);
|
||||
QString error_message;
|
||||
switch (error)
|
||||
{
|
||||
case rpcn::ErrorType::Invalid: error_message = tr("The server has no email verification and doesn't support password changes!"); break;
|
||||
case rpcn::ErrorType::DbFail: error_message = tr("A database related error happened on the server!"); break;
|
||||
case rpcn::ErrorType::TooSoon: error_message = tr("You can only ask for a reset password token once every 24 hours!"); break;
|
||||
case rpcn::ErrorType::EmailFail: error_message = tr("The mail couldn't be sent successfully!"); break;
|
||||
case rpcn::ErrorType::LoginError: error_message = tr("The username/email pair is invalid!"); break;
|
||||
default: error_message = tr("Unknown error"); break;
|
||||
}
|
||||
QMessageBox::critical(this, tr("Error Sending Password Reset Token"), tr("Failed to send the password reset token:\n%0").arg(error_message), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
m_password = m_edit_pass1->text().toStdString();
|
||||
close();
|
||||
});
|
||||
connect(btn_cancel, &QAbstractButton::clicked, this, [this]()
|
||||
{ this->close(); });
|
||||
}
|
||||
QMessageBox::information(this, tr("Password Reset Token Sent!"), tr("The reset password token has successfully been sent!"), QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
case QMessageBox::Yes:
|
||||
{
|
||||
rpcn_ask_token_dialog dlg_token(this, tr("Please enter the password reset token you received:"));
|
||||
dlg_token.exec();
|
||||
const auto token = dlg_token.get_token();
|
||||
|
||||
std::optional<std::string> rpcn_ask_password_dialog::get_password()
|
||||
{
|
||||
return m_password;
|
||||
if (!token)
|
||||
return;
|
||||
|
||||
rpcn_ask_password_dialog dlg_password(this, tr("Please enter your new password:"));
|
||||
dlg_password.exec();
|
||||
const auto password = dlg_password.get_password();
|
||||
|
||||
if (!password)
|
||||
return;
|
||||
|
||||
{
|
||||
const auto rpcn = rpcn::rpcn_client::get_instance();
|
||||
if (auto result = rpcn->wait_for_connection(); result != rpcn::rpcn_state::failure_no_failure)
|
||||
{
|
||||
const QString error_message = tr("Failed to connect to RPCN server:\n%0").arg(QString::fromStdString(rpcn::rpcn_state_to_string(result)));
|
||||
QMessageBox::critical(this, tr("Error Connecting"), error_message, QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto error = rpcn->reset_password(*username, *token, *password); error != rpcn::ErrorType::NoError)
|
||||
{
|
||||
QString error_message;
|
||||
switch (error)
|
||||
{
|
||||
case rpcn::ErrorType::Invalid: error_message = tr("The server has no email verification and doesn't support password changes!"); break;
|
||||
case rpcn::ErrorType::DbFail: error_message = tr("A database related error happened on the server!"); break;
|
||||
case rpcn::ErrorType::TooSoon: error_message = tr("You can only ask for a reset password token once every 24 hours!"); break;
|
||||
case rpcn::ErrorType::EmailFail: error_message = tr("The mail couldn't be sent successfully!"); break;
|
||||
case rpcn::ErrorType::LoginError: error_message = tr("The username/token pair is invalid!"); break;
|
||||
default: error_message = tr("Unknown error"); break;
|
||||
}
|
||||
QMessageBox::critical(this, tr("Error Sending Password Reset Token"), tr("Failed to change the password:\n%0").arg(error_message), QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
QMessageBox::information(this, tr("Password Successfully Changed!"), tr("Your password has been successfully changed!"), QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void friend_callback(void* param, rpcn::NotificationType ntype, const std::string& username, bool status)
|
||||
|
|
@ -636,7 +1128,7 @@ void rpcn_friends_dialog::callback_handler(rpcn::NotificationType ntype, std::st
|
|||
}
|
||||
default:
|
||||
{
|
||||
rpcn_settings_log.fatal("An unhandled notification type was received by the rpcn friends dialog callback!");
|
||||
rpcn_settings_log.fatal("An unhandled notification type was received by the RPCN friends dialog callback!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue