From c86c4a99aa60a4ac1e81bd222dab8b7fba7a1ae9 Mon Sep 17 00:00:00 2001 From: Ninetime Date: Thu, 8 May 2025 18:09:14 -0400 Subject: [PATCH] Add RPCN Account Recovery Option --- rpcs3/Emu/NP/rpcn_client.cpp | 27 +++++++++++++++++- rpcs3/Emu/NP/rpcn_client.h | 1 + rpcs3/Emu/NP/rpcn_types.h | 1 + rpcs3/rpcs3qt/rpcn_settings_dialog.cpp | 38 ++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/NP/rpcn_client.cpp b/rpcs3/Emu/NP/rpcn_client.cpp index c963e85ab7..b88746b495 100644 --- a/rpcs3/Emu/NP/rpcn_client.cpp +++ b/rpcs3/Emu/NP/rpcn_client.cpp @@ -659,7 +659,7 @@ namespace rpcn command == CommandType::AddFriend || command == CommandType::RemoveFriend || command == CommandType::AddBlock || command == CommandType::RemoveBlock || command == CommandType::SendMessage || command == CommandType::SendToken || - command == CommandType::SendResetToken || command == CommandType::ResetPassword || + command == CommandType::SendResetToken || command == CommandType::ResetPassword || command == CommandType::RecoverAccount || command == CommandType::GetNetworkTime || command == CommandType::SetPresence || command == CommandType::Terminate) { std::lock_guard lock(mutex_replies_sync); @@ -1424,6 +1424,31 @@ namespace rpcn return error; } + ErrorType rpcn_client::recover_account(std::string_view email) { + std::vector data; + std::copy(email.begin(), email.end(), std::back_inserter(data)); + data.push_back(0); + + u64 req_id = rpcn_request_counter.fetch_add(1); + + std::vector packet_data; + if (!forge_send_reply(CommandType::RecoverAccount, req_id, data, packet_data)) + { + state = rpcn_state::failure_other; + return ErrorType::EmailFail; + } + + vec_stream reply(packet_data); + auto error = static_cast(reply.get()); + + if (error == rpcn::ErrorType::NoError) + { + rpcn_log.success("Account recovery email has successfully been sent!"); + } + + return error; + } + bool rpcn_client::add_friend(const std::string& friend_username) { std::vector data; diff --git a/rpcs3/Emu/NP/rpcn_client.h b/rpcs3/Emu/NP/rpcn_client.h index 2ada34b581..eb37994ce6 100644 --- a/rpcs3/Emu/NP/rpcn_client.h +++ b/rpcs3/Emu/NP/rpcn_client.h @@ -302,6 +302,7 @@ namespace rpcn ErrorType resend_token(const std::string& npid, const std::string& password); ErrorType send_reset_token(std::string_view npid, std::string_view email); ErrorType reset_password(std::string_view npid, std::string_view token, std::string_view password); + ErrorType recover_account(std::string_view email); bool add_friend(const std::string& friend_username); bool remove_friend(const std::string& friend_username); diff --git a/rpcs3/Emu/NP/rpcn_types.h b/rpcs3/Emu/NP/rpcn_types.h index 1e9fb9acf4..357ab093e3 100644 --- a/rpcs3/Emu/NP/rpcn_types.h +++ b/rpcs3/Emu/NP/rpcn_types.h @@ -12,6 +12,7 @@ namespace rpcn SendToken, SendResetToken, ResetPassword, + RecoverAccount, ResetState, AddFriend, RemoveFriend, diff --git a/rpcs3/rpcs3qt/rpcn_settings_dialog.cpp b/rpcs3/rpcs3qt/rpcn_settings_dialog.cpp index 5046435008..90131368d8 100644 --- a/rpcs3/rpcs3qt/rpcn_settings_dialog.cpp +++ b/rpcs3/rpcs3qt/rpcn_settings_dialog.cpp @@ -159,6 +159,7 @@ rpcn_account_dialog::rpcn_account_dialog(QWidget* parent) QVBoxLayout* vbox_buttons = new QVBoxLayout(); QPushButton* btn_create = new QPushButton(tr("Create Account")); QPushButton* btn_edit = new QPushButton(tr("Edit Account")); + QPushButton* btn_recover = new QPushButton(tr("Recover Account")); QPushButton* btn_test = new QPushButton(tr("Test Account")); QLabel* label_npid = new QLabel(); @@ -178,6 +179,8 @@ rpcn_account_dialog::rpcn_account_dialog(QWidget* parent) vbox_buttons->addSpacing(10); vbox_buttons->addWidget(btn_edit); vbox_buttons->addSpacing(10); + vbox_buttons->addWidget(btn_recover); + vbox_buttons->addSpacing(10); vbox_buttons->addWidget(btn_test); vbox_buttons->addSpacing(10); grp_buttons->setLayout(vbox_buttons); @@ -323,6 +326,41 @@ rpcn_account_dialog::rpcn_account_dialog(QWidget* parent) update_npid_label(); }); + connect(btn_recover, &QAbstractButton::clicked, this, [this, update_npid_label]() { + + rpcn_ask_email_dialog dlg_email(this, tr("Please enter the email associated with the RPCN account")); + dlg_email.exec(); + const auto& email = dlg_email.get_email(); + + if (!email) + 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->recover_account(*email); error != rpcn::ErrorType::NoError) + { + QString error_message; + switch (error) + { + 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 recovery your account once every 24 hours!"); break; + case rpcn::ErrorType::EmailFail: error_message = tr("The mail couldn't be sent successfully!"); break; + default: error_message = tr("Unknown error"); break; + } + QMessageBox::critical(this, tr("Error Sending Account Recovery Email!"), tr("Failed to send the account recovery email:\n%0").arg(error_message), QMessageBox::Ok); + return; + + } + QMessageBox::information(this, tr("Email Sent!"), tr("Your account information was successfully sent to the email specified!"), QMessageBox::Ok); + update_npid_label(); + }); + connect(btn_test, &QAbstractButton::clicked, this, [this]() { auto rpcn = rpcn::rpcn_client::get_instance();