From 399d1f1702a9383f27ddadc8a94096757875fe21 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Tue, 28 May 2024 22:58:23 +0200 Subject: [PATCH] refresh token timer --- src/slic3r/GUI/Plater.cpp | 4 ++ src/slic3r/GUI/UserAccount.hpp | 2 + src/slic3r/GUI/UserAccountCommunication.cpp | 49 ++++++++++++++++++--- src/slic3r/GUI/UserAccountCommunication.hpp | 9 +++- src/slic3r/GUI/UserAccountSession.cpp | 9 ++++ src/slic3r/GUI/UserAccountSession.hpp | 11 +++-- 6 files changed, 73 insertions(+), 11 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 2bb4db5293..840e34191f 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -984,6 +984,10 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) this->notification_manager->close_notification_of_type(NotificationType::SelectFilamentFromConnect); this->notification_manager->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::WarningNotificationLevel, msg); }); + + this->q->Bind(EVT_UA_REFRESH_TIME, [this](UserAccountTimeEvent& evt) { + this->user_account->set_refresh_time(evt.data); + }); } wxGetApp().other_instance_message_handler()->init(this->q); diff --git a/src/slic3r/GUI/UserAccount.hpp b/src/slic3r/GUI/UserAccount.hpp index 533fdff970..11543dc04e 100644 --- a/src/slic3r/GUI/UserAccount.hpp +++ b/src/slic3r/GUI/UserAccount.hpp @@ -78,6 +78,8 @@ public: std::string get_current_printer_uuid_from_connect(const std::string& selected_printer_id) const; void set_current_printer_data(const std::string& data) { m_current_printer_data_json_from_connect = data; } + + void set_refresh_time(int seconds) { m_communication->set_refresh_time(seconds); } private: void set_username(const std::string& username); diff --git a/src/slic3r/GUI/UserAccountCommunication.cpp b/src/slic3r/GUI/UserAccountCommunication.cpp index 2796ae525e..b6f9656d76 100644 --- a/src/slic3r/GUI/UserAccountCommunication.cpp +++ b/src/slic3r/GUI/UserAccountCommunication.cpp @@ -132,22 +132,37 @@ bool load_secret(const std::string& opt, std::string& usr, std::string& psswd) } UserAccountCommunication::UserAccountCommunication(wxEvtHandler* evt_handler, AppConfig* app_config) - : m_evt_handler(evt_handler) + : wxEvtHandler() + , m_evt_handler(evt_handler) , m_app_config(app_config) + , m_token_timer(new wxTimer(this)) { - std::string access_token, refresh_token, shared_session_key; + Bind(wxEVT_TIMER, [this](const wxTimerEvent&) { + enqueue_refresh(); + }); + + std::string access_token, refresh_token, shared_session_key, next_timeout; if (is_secret_store_ok()) { - std::string key0, key1; + std::string key0, key1, key2; load_secret("access_token", key0, access_token); load_secret("refresh_token", key1, refresh_token); + load_secret("timeout", key2, next_timeout); assert(key0 == key1); shared_session_key = key0; } else { access_token = m_app_config->get("access_token"); refresh_token = m_app_config->get("refresh_token"); shared_session_key = m_app_config->get("shared_session_key"); + next_timeout = m_app_config->get("access_token_timeout"); } - bool has_token = !access_token.empty() && !refresh_token.empty(); + long long next = next_timeout.empty() ? 0 : std::stoll(next_timeout); + long long remain_time = next - std::time(nullptr); + if (remain_time <= 0) { + access_token.clear(); + } else { + set_refresh_time((int)remain_time); + } + bool has_token = !refresh_token.empty(); m_session = std::make_unique(evt_handler, access_token, refresh_token, shared_session_key, m_app_config->get_bool("connect_polling")); init_session_thread(); // perform login at the start, but only with tokens @@ -165,7 +180,7 @@ UserAccountCommunication::~UserAccountCommunication() m_thread_stop = true; } m_thread_stop_condition.notify_all(); - // Wait for the worker thread to stop. + // Wait for the worker thread to stop m_thread.join(); } } @@ -178,11 +193,13 @@ void UserAccountCommunication::set_username(const std::string& username) if (is_secret_store_ok()) { save_secret("access_token", m_session->get_shared_session_key(), m_remember_session ? m_session->get_access_token() : std::string()); save_secret("refresh_token", m_session->get_shared_session_key(), m_remember_session ? m_session->get_refresh_token() : std::string()); + save_secret("timeout", m_session->get_shared_session_key(), m_remember_session ? GUI::format("%1%",m_session->get_next_token_timeout()) : "0"); } else { m_app_config->set("access_token", m_remember_session ? m_session->get_access_token() : std::string()); m_app_config->set("refresh_token", m_remember_session ? m_session->get_refresh_token() : std::string()); m_app_config->set("shared_session_key", m_remember_session ? m_session->get_shared_session_key() : std::string()); + m_app_config->set("access_token_timeout", m_remember_session ? GUI::format("%1%", m_session->get_next_token_timeout()) : "0"); } } } @@ -271,6 +288,7 @@ void UserAccountCommunication::do_clear() m_session->clear(); } set_username({}); + m_token_timer->Stop(); } void UserAccountCommunication::on_login_code_recieved(const std::string& url_message) @@ -346,7 +364,18 @@ void UserAccountCommunication::enqueue_printer_data_action(const std::string& uu } wakeup_session_thread(); } - +void UserAccountCommunication::enqueue_refresh() +{ + { + std::lock_guard lock(m_session_mutex); + if (!m_session->is_initialized()) { + BOOST_LOG_TRIVIAL(error) << "Connect Printers endpoint connection failed - Not Logged in."; + return; + } + m_session->enqueue_refresh({}); + } + wakeup_session_thread(); +} void UserAccountCommunication::init_session_thread() { @@ -388,6 +417,14 @@ void UserAccountCommunication::wakeup_session_thread() m_thread_stop_condition.notify_all(); } +void UserAccountCommunication::set_refresh_time(int seconds) +{ + assert(m_token_timer); + m_token_timer->Stop(); + int miliseconds = std::max(seconds * 1000 - 60000, 60000); + m_token_timer->StartOnce(miliseconds); +} + std::string CodeChalengeGenerator::generate_chalenge(const std::string& verifier) { std::string code_challenge; diff --git a/src/slic3r/GUI/UserAccountCommunication.hpp b/src/slic3r/GUI/UserAccountCommunication.hpp index b630b95ec2..9ffd39ff7c 100644 --- a/src/slic3r/GUI/UserAccountCommunication.hpp +++ b/src/slic3r/GUI/UserAccountCommunication.hpp @@ -27,7 +27,8 @@ private: std::string sha256(const std::string& input); }; -class UserAccountCommunication { +class UserAccountCommunication : public wxEvtHandler +{ public: UserAccountCommunication(wxEvtHandler* evt_handler, AppConfig* app_config); ~UserAccountCommunication(); @@ -44,6 +45,7 @@ public: void enqueue_avatar_action(const std::string& url); void enqueue_test_connection(); void enqueue_printer_data_action(const std::string& uuid); + void enqueue_refresh(); // Callbacks - called from UI after receiving Event from Session thread. Some might use Session thread. // @@ -64,6 +66,8 @@ public: void set_polling_enabled(bool enabled); // we have map of uuids and printer_models - set polling action to lightweight STATUS action void on_uuid_map_success(); + + void set_refresh_time(int seconds); private: std::unique_ptr m_session; std::thread m_thread; @@ -80,6 +84,9 @@ private: std::string m_username; bool m_remember_session { true }; // if default is true, on every login Remember me will be checked. + wxTimer* m_token_timer; + wxEvtHandler* m_timer_evt_handler; + void wakeup_session_thread(); void init_session_thread(); void login_redirect(); diff --git a/src/slic3r/GUI/UserAccountSession.cpp b/src/slic3r/GUI/UserAccountSession.cpp index 69c974001f..2f6287380a 100644 --- a/src/slic3r/GUI/UserAccountSession.cpp +++ b/src/slic3r/GUI/UserAccountSession.cpp @@ -29,6 +29,7 @@ wxDEFINE_EVENT(EVT_UA_PRUSACONNECT_PRINTER_DATA_SUCCESS, UserAccountSuccessEvent wxDEFINE_EVENT(EVT_UA_FAIL, UserAccountFailEvent); wxDEFINE_EVENT(EVT_UA_RESET, UserAccountFailEvent); wxDEFINE_EVENT(EVT_UA_PRUSACONNECT_PRINTER_DATA_FAIL, UserAccountFailEvent); +wxDEFINE_EVENT(EVT_UA_REFRESH_TIME, UserAccountTimeEvent); void UserActionPost::perform(/*UNUSED*/ wxEvtHandler* evt_handler, /*UNUSED*/ const std::string& access_token, UserActionSuccessFn success_callback, UserActionFailFn fail_callback, const std::string& input) const { @@ -124,6 +125,7 @@ void UserAccountSession::token_success_callback(const std::string& body) { // Data we need std::string access_token, refresh_token, shared_session_key; + int expires_in = 300; try { std::stringstream ss(body); pt::ptree ptree; @@ -132,6 +134,7 @@ void UserAccountSession::token_success_callback(const std::string& body) const auto access_token_optional = ptree.get_optional("access_token"); const auto refresh_token_optional = ptree.get_optional("refresh_token"); const auto shared_session_key_optional = ptree.get_optional("shared_session_key"); + const auto expires_in_optional = ptree.get_optional("expires_in"); if (access_token_optional) access_token = *access_token_optional; @@ -139,6 +142,9 @@ void UserAccountSession::token_success_callback(const std::string& body) refresh_token = *refresh_token_optional; if (shared_session_key_optional) shared_session_key = *shared_session_key_optional; + assert(expires_in_optional); + if (expires_in_optional) + expires_in = *expires_in_optional; } catch (const std::exception&) { std::string msg = "Could not parse server response after code exchange."; @@ -163,7 +169,9 @@ void UserAccountSession::token_success_callback(const std::string& body) m_access_token = access_token; m_refresh_token = refresh_token; m_shared_session_key = shared_session_key; + m_next_token_timeout = std::time(nullptr) + expires_in; enqueue_action(UserAccountActionID::USER_ACCOUNT_ACTION_USER_ID, nullptr, nullptr, {}); + wxQueueEvent(p_evt_handler, new UserAccountTimeEvent(EVT_UA_REFRESH_TIME, expires_in)); } void UserAccountSession::code_exchange_fail_callback(const std::string& body) @@ -181,6 +189,7 @@ void UserAccountSession::enqueue_test_with_refresh() m_priority_action_queue.push({ UserAccountActionID::USER_ACCOUNT_ACTION_TEST_ACCESS_TOKEN, nullptr, std::bind(&UserAccountSession::enqueue_refresh, this, std::placeholders::_1), {} }); } + void UserAccountSession::enqueue_refresh(const std::string& body) { assert(!m_refresh_token.empty()); diff --git a/src/slic3r/GUI/UserAccountSession.hpp b/src/slic3r/GUI/UserAccountSession.hpp index e465b6e17b..a48f84d0a7 100644 --- a/src/slic3r/GUI/UserAccountSession.hpp +++ b/src/slic3r/GUI/UserAccountSession.hpp @@ -16,6 +16,7 @@ namespace GUI { using OpenPrusaAuthEvent = Event; using UserAccountSuccessEvent = Event; using UserAccountFailEvent = Event; +using UserAccountTimeEvent = Event; wxDECLARE_EVENT(EVT_OPEN_PRUSAAUTH, OpenPrusaAuthEvent); wxDECLARE_EVENT(EVT_UA_LOGGEDOUT, UserAccountSuccessEvent); wxDECLARE_EVENT(EVT_UA_ID_USER_SUCCESS, UserAccountSuccessEvent); @@ -27,7 +28,7 @@ wxDECLARE_EVENT(EVT_UA_PRUSACONNECT_PRINTER_DATA_SUCCESS, UserAccountSuccessEven wxDECLARE_EVENT(EVT_UA_FAIL, UserAccountFailEvent); // Soft fail - clears only after some number of fails wxDECLARE_EVENT(EVT_UA_RESET, UserAccountFailEvent); // Hard fail - clears all wxDECLARE_EVENT(EVT_UA_PRUSACONNECT_PRINTER_DATA_FAIL, UserAccountFailEvent); // Failed to get data for printer to select, soft fail, action does not repeat - +wxDECLARE_EVENT(EVT_UA_REFRESH_TIME, UserAccountTimeEvent); typedef std::function UserActionSuccessFn; typedef std::function UserActionFailFn; @@ -144,18 +145,19 @@ public: void enqueue_action(UserAccountActionID id, UserActionSuccessFn success_callback, UserActionFailFn fail_callback, const std::string& input); // Special enques, that sets callbacks. void enqueue_test_with_refresh(); + void enqueue_refresh(const std::string& body); void process_action_queue(); bool is_initialized() { return !m_access_token.empty() || !m_refresh_token.empty(); } std::string get_access_token() const { return m_access_token; } std::string get_refresh_token() const { return m_refresh_token; } std::string get_shared_session_key() const { return m_shared_session_key; } - + long long get_next_token_timeout() const {return m_next_token_timeout; } + //void set_polling_enabled(bool enabled) {m_polling_action = enabled ? UserAccountActionID::USER_ACCOUNT_ACTION_CONNECT_PRINTER_MODELS : UserAccountActionID::USER_ACCOUNT_ACTION_DUMMY; } void set_polling_action(UserAccountActionID action) { m_polling_action = action; } private: - - void enqueue_refresh(const std::string& body); + void refresh_fail_callback(const std::string& body); void cancel_queue(); void code_exchange_fail_callback(const std::string& body); @@ -172,6 +174,7 @@ private: std::string m_access_token; std::string m_refresh_token; std::string m_shared_session_key; + long long m_next_token_timeout; std::queue m_action_queue; std::queue m_priority_action_queue;