diff options
| -rw-r--r-- | battleNetApi/include/token.hpp | 15 | ||||
| -rw-r--r-- | battleNetApi/src/token.cpp | 25 | ||||
| -rw-r--r-- | battleNetApi/tests/tests.cpp | 2 |
3 files changed, 27 insertions, 15 deletions
diff --git a/battleNetApi/include/token.hpp b/battleNetApi/include/token.hpp index 34c6d3e..1941ce5 100644 --- a/battleNetApi/include/token.hpp +++ b/battleNetApi/include/token.hpp @@ -5,6 +5,8 @@ class Token { public: Token(const std::string &iTokenFilePath); std::string text() const; + const bool hasTokenExpired() const; + void updateToken(); private: const std::string mFilePath; //!< Path to the token file @@ -13,16 +15,17 @@ class Token { std::string mToken; //!< Token value /** - * @return A token that a user can use to perform API requests. - * A new token might be computed if the current token lifetime expired. + * @return An access token that a user can use to perform API requests. + * First, the cache file is checked. + * A new token is computed if the current token lifetime expired, + * or if there is no token at all. */ std::string generateToken(); - const bool hasTokenExpired() const; - void writeNewTokenToLocalFile(const std::string &iTokenContent) const; + void writeNewTokenToLocalFile(const std::pair<std::string, std::uint64_t> &iToken) const; std::string getTokenFromLocalFile() const; - std::string getTokenWithApi() const; + std::pair<std::string, std::uint64_t> getTokenWithApi() const; std::chrono::seconds getCurrentTime() const; static size_t curlCallbackStringOutput(void *iPtr, size_t iSize, size_t iNmemb, std::string *iUserData); - friend class TokenTests; + static const std::uint16_t kTokenContentMinLength{10}; }; diff --git a/battleNetApi/src/token.cpp b/battleNetApi/src/token.cpp index de0276a..e32a946 100644 --- a/battleNetApi/src/token.cpp +++ b/battleNetApi/src/token.cpp @@ -1,10 +1,12 @@ #include "token.hpp" #include <chrono> +#include <cstdint> #include <curl/curl.h> #include <format> #include <fstream> #include <iostream> #include <nlohmann/json.hpp> +#include <utility> using json = nlohmann::json; @@ -16,8 +18,11 @@ const bool Token::hasTokenExpired() const { std::ifstream aTokenFile{mFilePath}; json aCredentialsFile = json::parse(aTokenFile); if (not aCredentialsFile.contains("Token") or not aCredentialsFile["Token"].contains("ExpirationTime") or - not aCredentialsFile["Token"].contains("Content") or aCredentialsFile["Token"]["Content"].empty()) { - return false; + not aCredentialsFile["Token"].contains("Content")) { + return true; + } + if (aCredentialsFile["Token"]["Content"].dump().length() < kTokenContentMinLength) { + return true; } const std::uint64_t kExpirationTime{aCredentialsFile["Token"]["ExpirationTime"]}; const std::uint64_t kCurrentTime{static_cast<std::uint64_t>( @@ -29,6 +34,8 @@ const bool Token::hasTokenExpired() const { return false; } +void Token::updateToken() { mToken = generateToken(); } + std::string Token::getTokenFromLocalFile() const { std::ifstream aTokenFile{mFilePath}; return json::parse(aTokenFile)["Token"]["Content"]; @@ -36,24 +43,25 @@ std::string Token::getTokenFromLocalFile() const { std::string Token::generateToken() { if (hasTokenExpired()) { - const std::string kTokenContent{getTokenWithApi()}; + const std::pair<std::string, std::uint64_t> kTokenContent{getTokenWithApi()}; writeNewTokenToLocalFile(kTokenContent); } return getTokenFromLocalFile(); } -void Token::writeNewTokenToLocalFile(const std::string &iTokenContent) const { +void Token::writeNewTokenToLocalFile(const std::pair<std::string, std::uint64_t> &iToken) const { std::ifstream aTokenFileInput{mFilePath}; json aCredentialsFile = json::parse(aTokenFileInput); - aCredentialsFile["Token"]["Content"] = iTokenContent; + aCredentialsFile["Token"]["Content"] = iToken.first; aCredentialsFile["Token"]["ExpirationTime"] = - std::chrono::duration_cast<std::chrono::seconds>(getCurrentTime() + std::chrono::hours(24)).count(); + std::chrono::duration_cast<std::chrono::seconds>(getCurrentTime() + std::chrono::seconds(iToken.second)) + .count(); std::ofstream aTokenFileOutput{mFilePath}; aTokenFileOutput << std::setw(4) << aCredentialsFile; } -std::string Token::getTokenWithApi() const { +std::pair<std::string, std::uint64_t> Token::getTokenWithApi() const { std::ifstream aCredentialsFile{mFilePath}; json aCredentials = json::parse(aCredentialsFile); if (not aCredentials.contains("Agent") or not aCredentials["Agent"].contains("Username") or @@ -80,7 +88,8 @@ std::string Token::getTokenWithApi() const { std::exit(EXIT_FAILURE); } } - return json::parse(aTokenInfo)["access_token"]; + json aTokenJson = json::parse(aTokenInfo); + return std::make_pair(aTokenJson["access_token"], aTokenJson["expires_in"]); } std::chrono::seconds Token::getCurrentTime() const { diff --git a/battleNetApi/tests/tests.cpp b/battleNetApi/tests/tests.cpp index 0831e79..550e2ca 100644 --- a/battleNetApi/tests/tests.cpp +++ b/battleNetApi/tests/tests.cpp @@ -3,7 +3,7 @@ #include <catch2/catch_test_macros.hpp> #include <utility> -TEST_CASE("Retrieve API Token", "[getApiToken]") { +TEST_CASE("Retrieve API Token", "[generateApiToken]") { const std::string kCredentialsFile{"tests/resources/credentials.json"}; Token aToken(kCredentialsFile); const std::string kTokenContent{aToken.text()}; |
