refresh token timer

This commit is contained in:
David Kocik 2024-05-28 22:58:23 +02:00 committed by Lukas Matena
parent 1dd8e64009
commit 399d1f1702
6 changed files with 73 additions and 11 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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<UserAccountSession>(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<std::mutex> 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;

View File

@ -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<UserAccountSession> 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();

View File

@ -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<std::string>("access_token");
const auto refresh_token_optional = ptree.get_optional<std::string>("refresh_token");
const auto shared_session_key_optional = ptree.get_optional<std::string>("shared_session_key");
const auto expires_in_optional = ptree.get_optional<int>("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());

View File

@ -16,6 +16,7 @@ namespace GUI {
using OpenPrusaAuthEvent = Event<wxString>;
using UserAccountSuccessEvent = Event<std::string>;
using UserAccountFailEvent = Event<std::string>;
using UserAccountTimeEvent = Event<int>;
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<void(const std::string& body)> UserActionSuccessFn;
typedef std::function<void(const std::string& body)> 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<ActionQueueData> m_action_queue;
std::queue<ActionQueueData> m_priority_action_queue;