[fix] synchronize authenticated password changes

This commit is contained in:
dijunkun
2026-08-16 16:57:36 +08:00
parent 1709eb0efb
commit 092664784e
5 changed files with 152 additions and 26 deletions
+105 -25
View File
@@ -1342,33 +1342,42 @@ void GuiApplication::BindMainCallbacks() {
if (password.size() != 6) {
return false;
}
std::memset(password_saved_, 0, sizeof(password_saved_));
std::strncpy(password_saved_, password.c_str(),
sizeof(password_saved_) - 1);
if (config_center_->IsSelfHosted()) {
std::string identity = self_hosted_id_;
if (const auto at = identity.find('@'); at != std::string::npos) {
identity.resize(at);
}
if (identity.empty()) {
identity = client_id_;
}
identity += "@" + password;
std::memset(self_hosted_id_, 0, sizeof(self_hosted_id_));
std::strncpy(self_hosted_id_, identity.c_str(),
sizeof(self_hosted_id_) - 1);
} else {
const std::string identity = std::string(client_id_) + "@" + password;
std::memset(client_id_with_password_, 0,
sizeof(client_id_with_password_));
std::strncpy(client_id_with_password_, identity.c_str(),
sizeof(client_id_with_password_) - 1);
if (!peer_ || !signal_connected_) {
offline_warning_text_ =
localization::signal_disconnected[localization_language_index_];
show_offline_warning_window_ = true;
return true;
}
settings_.Save();
if (peer_) {
LeaveConnection(peer_, client_id_);
DestroyPeer(&peer_);
std::string request_id;
{
std::lock_guard<std::mutex> lock(password_change_mutex_);
if (password_change_pending_) {
return true;
}
request_id = std::to_string(++next_password_change_request_id_);
password_change_pending_ = true;
password_change_result_ready_ = false;
password_change_succeeded_ = false;
password_change_requested_at_ = std::chrono::steady_clock::now();
pending_password_change_request_id_ = request_id;
pending_local_password_ = password;
password_change_error_.clear();
}
const nlohmann::json request = {{"type", "change_password"},
{"request_id", request_id},
{"new_password", password}};
const std::string message = request.dump();
if (SendSignalMessage(peer_, message.data(), message.size()) != 0) {
std::lock_guard<std::mutex> lock(password_change_mutex_);
password_change_pending_ = false;
pending_password_change_request_id_.clear();
pending_local_password_.clear();
offline_warning_text_ =
localization::signal_disconnected[localization_language_index_];
show_offline_warning_window_ = true;
}
return true;
});
@@ -1778,6 +1787,7 @@ void GuiApplication::Tick() {
slint::quit_event_loop();
return;
}
HandlePasswordChangeResult();
if (!peer_) {
CreateConnectionPeer();
}
@@ -1852,6 +1862,76 @@ void GuiApplication::Tick() {
SyncServerWindow();
}
void GuiApplication::HandlePasswordChangeResult() {
bool succeeded = false;
std::string new_password;
std::string error;
{
std::lock_guard<std::mutex> lock(password_change_mutex_);
if (password_change_pending_ && !password_change_result_ready_ &&
std::chrono::steady_clock::now() - password_change_requested_at_ >=
std::chrono::seconds(10)) {
password_change_result_ready_ = true;
password_change_succeeded_ = false;
password_change_error_ = "Server did not respond";
}
if (!password_change_result_ready_) {
return;
}
succeeded = password_change_succeeded_;
new_password = pending_local_password_;
error = password_change_error_;
password_change_pending_ = false;
password_change_result_ready_ = false;
password_change_succeeded_ = false;
pending_password_change_request_id_.clear();
pending_local_password_.clear();
password_change_error_.clear();
}
if (!succeeded) {
LOG_WARN("Password change failed: {}", error);
offline_warning_text_ = localization::failed[localization_language_index_];
if (!error.empty()) {
offline_warning_text_ += ": " + error;
}
show_offline_warning_window_ = true;
return;
}
std::memset(password_saved_, 0, sizeof(password_saved_));
std::strncpy(password_saved_, new_password.c_str(),
sizeof(password_saved_) - 1);
const std::string identity = std::string(client_id_) + "@" + new_password;
if (config_center_->IsSelfHosted()) {
std::memset(self_hosted_id_, 0, sizeof(self_hosted_id_));
std::strncpy(self_hosted_id_, identity.c_str(),
sizeof(self_hosted_id_) - 1);
} else {
std::memset(client_id_with_password_, 0,
sizeof(client_id_with_password_));
std::strncpy(client_id_with_password_, identity.c_str(),
sizeof(client_id_with_password_) - 1);
}
if (settings_.Save() != 0) {
LOG_ERROR("Password changed on server but could not be saved locally");
offline_warning_text_ = localization::failed[localization_language_index_];
show_offline_warning_window_ = true;
return;
}
LOG_INFO("Password changed successfully for [{}]", client_id_);
if (peer_) {
LeaveConnection(peer_, client_id_);
DestroyPeer(&peer_);
}
}
void GuiApplication::UpdateLocalization() {
const int language =
localization::detail::ClampLanguageIndex(localization_language_index_);
+1
View File
@@ -31,6 +31,7 @@ private:
void BindStreamCallbacks();
void BindServerCallbacks();
void Tick();
void HandlePasswordChangeResult();
void SyncMainWindow();
void SyncConnectionDialog();
void SyncPlatformDialogs();
+32
View File
@@ -85,6 +85,38 @@ void PeerEventHandler::OnSignalMessage(const char* message, size_t size,
}
}
}
} else if (type == "change_password") {
std::lock_guard<std::mutex> lock(runtime->password_change_mutex_);
if (!runtime->password_change_pending_) {
LOG_WARN("Ignore unexpected password change response");
return;
}
if (!j.contains("request_id") || !j["request_id"].is_string() ||
j["request_id"].get<std::string>() !=
runtime->pending_password_change_request_id_) {
LOG_WARN("Ignore password change response with unexpected request id");
return;
}
if (j.contains("user_id") && j["user_id"].is_string()) {
const std::string response_user_id = j["user_id"].get<std::string>();
if (!response_user_id.empty() &&
response_user_id != runtime->client_id_) {
LOG_WARN("Ignore password change response for unexpected id [{}]",
response_user_id);
return;
}
}
runtime->password_change_succeeded_ =
j.contains("status") && j["status"].is_string() &&
j["status"].get<std::string>() == "success";
runtime->password_change_error_ =
j.contains("reason") && j["reason"].is_string()
? j["reason"].get<std::string>()
: "Password change failed";
runtime->password_change_result_ready_ = true;
}
}
+13
View File
@@ -152,6 +152,18 @@ struct UserSettingsState {
bool show_file_browser_ = true;
};
struct PasswordChangeState {
std::mutex password_change_mutex_;
uint64_t next_password_change_request_id_ = 0;
bool password_change_pending_ = false;
bool password_change_result_ready_ = false;
bool password_change_succeeded_ = false;
std::chrono::steady_clock::time_point password_change_requested_at_;
std::string pending_password_change_request_id_;
std::string pending_local_password_;
std::string password_change_error_;
};
struct ConnectionState {
using RemoteSessionMap =
std::unordered_map<std::string, RemoteSessionPtr>;
@@ -180,6 +192,7 @@ struct RuntimeState : InfrastructureState,
PeerState,
PlatformIntegrationState,
UserSettingsState,
PasswordChangeState,
ConnectionState {};
} // namespace crossdesk::gui_detail