Skip to content

Commit

Permalink
fix: auto login
Browse files Browse the repository at this point in the history
  • Loading branch information
Serein207 committed Sep 29, 2024
1 parent 13578c4 commit 1bd395c
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 35 deletions.
114 changes: 80 additions & 34 deletions src/Controller/Core/AccountManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <Infrastructure/Network/ResponseStruct.h>
#include <Infrastructure/Utils/Config.h>
#include <Infrastructure/Utils/Result.h>
#include <chrono>
#include <keychain/keychain.h>
#include <optional>
#include <sast_link.h>
Expand Down Expand Up @@ -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);
});
}
Expand All @@ -83,17 +89,15 @@ void AccountManager::performRefreshToken() {
}
co_return Ok(std::monostate{});
}(),
[weak_this = weak_from_this(), &self](Result<std::monostate> 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<std::monostate> result) {
if (result.isErr()) {
self.setLoginState(false);
self.bridge.getMessageManager().showMessage("登录过期,请重新登录",
MessageType::Info);
return;
}
self.performGetUserInfo();
spdlog::info("refresh token success");
});
}

Expand All @@ -108,16 +112,14 @@ void AccountManager::performGetUserInfo() {
}
co_return result.unwrap();
}(),
[weak_this = weak_from_this(), &self](Result<UserInfoEntity> 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<UserInfoEntity> result) {
if (result.isErr()) {
self.setLoginState(false);
return;
}
self.userInfo = result.unwrap();
spdlog::info("get user info success");
self.setLoginState(true);
});
}

Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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<std::string> 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()) {
Expand All @@ -203,22 +221,50 @@ std::optional<std::string> 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<std::string> 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) {
Expand Down
12 changes: 11 additions & 1 deletion src/Controller/Core/AccountManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ class AccountManager : private GlobalAgent<AccountManagerBridge>,
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<UiEntryName> uiEntry, UiBridge& bridge);
Expand All @@ -45,6 +50,11 @@ class AccountManager : private GlobalAgent<AccountManagerBridge>,

static void setNetworkAccessToken(std::string accessToken);

#ifdef EVENTO_API_V1
std::optional<std::string> getKeychainAccessToken() const;
void setKeychainAccessToken(const std::string& accessToken) const;
#endif

void setLoginState(bool newState);
void onStateChanged();

Expand Down
7 changes: 7 additions & 0 deletions src/Infrastructure/Utils/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down

0 comments on commit 1bd395c

Please sign in to comment.