diff --git a/src/Controller/Core/AccountManager.cc b/src/Controller/Core/AccountManager.cc index 0b0aaf30..49b2697a 100644 --- a/src/Controller/Core/AccountManager.cc +++ b/src/Controller/Core/AccountManager.cc @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -60,10 +61,15 @@ void AccountManager::performLogin() { auto data = result.unwrap(); self.userInfo = data.userInfo; - - self.setNetworkAccessToken(data.accessToken); +#ifdef EVENTO_API_V1 + self.setKeychainAccessToken(data.accessToken); + self.expiredTime = std::chrono::system_clock::now() + std::chrono::days(30); +#else self.setKeychainRefreshToken(data.refreshToken); self.scheduleRenewAccessToken(); + self.expiredTime = std::chrono::system_clock::now() + std::chrono::days(7); +#endif + self.setNetworkAccessToken(data.accessToken); self.setLoginState(true); }); } @@ -83,17 +89,15 @@ void AccountManager::performRefreshToken() { } co_return Ok(std::monostate{}); }(), - [weak_this = weak_from_this(), &self](Result result) { - if (auto alive = weak_this.lock()) { - if (result.isErr()) { - self.setLoginState(false); - self.bridge.getMessageManager().showMessage("登录过期,请重新登录", - MessageType::Info); - return; - } - self.performGetUserInfo(); - spdlog::info("refresh token success"); + [&self = *this](Result result) { + if (result.isErr()) { + self.setLoginState(false); + self.bridge.getMessageManager().showMessage("登录过期,请重新登录", + MessageType::Info); + return; } + self.performGetUserInfo(); + spdlog::info("refresh token success"); }); } @@ -108,16 +112,14 @@ void AccountManager::performGetUserInfo() { } co_return result.unwrap(); }(), - [weak_this = weak_from_this(), &self](Result result) { - if (auto alive = weak_this.lock()) { - if (result.isErr()) { - self.setLoginState(false); - return; - } - self.userInfo = result.unwrap(); - spdlog::info("get user info success"); - self.setLoginState(true); + [&self = *this](Result result) { + if (result.isErr()) { + self.setLoginState(false); + return; } + self.userInfo = result.unwrap(); + spdlog::info("get user info success"); + self.setLoginState(true); }); } @@ -146,11 +148,24 @@ void AccountManager::tryLoginDirectly() { if (isLogin()) { return; } + if (std::chrono::system_clock::now() + 15min < expiredTime) { + return; + } + +#ifdef EVENTO_API_V1 + if (auto token = getKeychainAccessToken()) { + spdlog::info("Token is found. Login directly!"); + setNetworkAccessToken(*token); + performGetUserInfo(); + } +#else spdlog::info("Try login directly, expired time: {}", expiredTime.time_since_epoch().count()); + // If the token is not expired after 15min, we don't need to login again - if (std::chrono::system_clock::now() + 15min < expiredTime) { + if (getKeychainRefreshToken()) { performRefreshToken(); } +#endif } UserInfoEntity AccountManager::getUserInfo() { @@ -182,15 +197,18 @@ void AccountManager::setKeychainRefreshToken(const std::string& refreshToken) co if (err.code != 0) { spdlog::error("Failed to save refresh token: {}", err.message); + return; } + spdlog::info("Save refresh token success"); } std::optional AccountManager::getKeychainRefreshToken() const { keychain::Error err; auto refreshToken = keychain::getPassword(package, service, userInfo.id, err); - if (err.code != 0) { - spdlog::error("Failed to save refresh token: {}", err.message); + if (err.type != keychain::ErrorType::NoError) { + spdlog::error("Failed to get refresh token: {}", err.message); + return std::nullopt; } if (refreshToken.empty()) { @@ -203,22 +221,50 @@ std::optional AccountManager::getKeychainRefreshToken() const { void AccountManager::scheduleRenewAccessToken() { auto& self = *this; renewAccessTokenTimer.expires_after(55min); - renewAccessTokenTimer.async_wait( - [weak_this = weak_from_this(), &self](const boost::system::error_code& ec) { - if (ec) { - spdlog::error("Failed to renew access token: {}", ec.message()); - return; - } - if (auto alive = weak_this.lock()) { - self.performRefreshToken(); - } - }); + renewAccessTokenTimer.async_wait([&self = *this](const boost::system::error_code& ec) { + if (ec) { + spdlog::error("Failed to renew access token: {}", ec.message()); + return; + } + self.performRefreshToken(); + }); } void AccountManager::setNetworkAccessToken(std::string accessToken) { evento::networkClient()->tokenBytes = accessToken; } +#ifdef EVENTO_API_V1 +std::optional AccountManager::getKeychainAccessToken() const { + keychain::Error err; + auto accessToken = keychain::getPassword(package, service, userInfo.id, err); + + if (err.type != keychain::ErrorType::NoError) { + debug(), (int) err.type; + spdlog::error("Failed to get access token: {}", err.message); + return std::nullopt; + } + + if (accessToken.empty()) { + return std::nullopt; + } + + return accessToken; +} + +void AccountManager::setKeychainAccessToken(const std::string& accessToken) const { + keychain::Error err; + keychain::setPassword(package, service, userInfo.id, accessToken, err); + + if (err.type != keychain::ErrorType::NoError) { + debug(), (int) err.type; + spdlog::error("Failed to save access token: {}", err.message); + return; + } + spdlog::info("Save access token success"); +} +#endif + void AccountManager::setLoginState(bool newState) { auto& self = *this; if (loginState != newState) { diff --git a/src/Controller/Core/AccountManager.h b/src/Controller/Core/AccountManager.h index ff107337..964c8b52 100644 --- a/src/Controller/Core/AccountManager.h +++ b/src/Controller/Core/AccountManager.h @@ -20,7 +20,12 @@ class AccountManager : private GlobalAgent, net::steady_timer renewAccessTokenTimer; static const inline std::string package = "org.sast.evento"; - static const inline std::string service = "refresh-token"; + static const inline std::string service = +#ifdef EVENTO_API_V1 + "access-token"; +#else + "refresh-token"; +#endif public: AccountManager(slint::ComponentHandle uiEntry, UiBridge& bridge); @@ -45,6 +50,11 @@ class AccountManager : private GlobalAgent, static void setNetworkAccessToken(std::string accessToken); +#ifdef EVENTO_API_V1 + std::optional getKeychainAccessToken() const; + void setKeychainAccessToken(const std::string& accessToken) const; +#endif + void setLoginState(bool newState); void onStateChanged(); diff --git a/src/Infrastructure/Utils/Config.h b/src/Infrastructure/Utils/Config.h index 417c72f4..d2e52991 100644 --- a/src/Infrastructure/Utils/Config.h +++ b/src/Infrastructure/Utils/Config.h @@ -126,6 +126,13 @@ inline void saveConfig() { spdlog::error("Failed to open \"{}\" for saving config.", path.string()); return; } + config.insert_or_assign("account", + toml::table{{"user-id", account.userId}, {"expire", account.expire}}); + config.insert_or_assign("setting", + toml::table{{"minimal-to-tray", settings.minimalToTray}, + {"notice-begin", settings.noticeBegin}, + {"notice-end", settings.noticeEnd}, + {"theme", settings.theme}}); ofs << config; }