From 12b933f3cbec797bd0ff782c959722aaab063f31 Mon Sep 17 00:00:00 2001 From: Carlos Nihelton Date: Fri, 15 Sep 2023 10:12:57 -0300 Subject: [PATCH 01/12] The DLL we want to write A bit more pedantic header inclusion No coroutines --- msix/storeapi/StoreApi.cpp | 27 ++++++++++++++++++--------- msix/storeapi/StoreApi.hpp | 2 -- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/msix/storeapi/StoreApi.cpp b/msix/storeapi/StoreApi.cpp index 4cb550090..de9c891a1 100644 --- a/msix/storeapi/StoreApi.cpp +++ b/msix/storeapi/StoreApi.cpp @@ -1,11 +1,21 @@ +#include "StoreApi.hpp" + +#include +#include +#include + +#include +#include +#include +#include + +#include "framework.hpp" + #ifndef DNDEBUG #include #include #endif -#include "StoreApi.hpp" -#include "framework.hpp" - // Syntactic sugar to convert the enum [value] into a Int. constexpr Int toInt(StoreApi::ErrorCode value) { return static_cast(value); @@ -24,9 +34,9 @@ static constexpr std::size_t MaxProductIdLen = 129; StoreApi::ErrorCode validateArg(const char* input, std::size_t maxLength); void logError(std::string_view functionName, std::string_view errMsg) { - #ifndef DNDEBUG - std::cerr << std::format("storeapi: {}: {}\n", functionName , errMsg); - #endif +#ifndef DNDEBUG + std::cerr << std::format("storeapi: {}: {}\n", functionName, errMsg); +#endif } #define LOG_ERROR(msg) \ @@ -75,10 +85,9 @@ Int GenerateUserJWT(const char* accessToken, char** userJWT, } try { - auto user = StoreApi::UserInfo::Current().get(); - StoreApi::ServerStoreService service{}; - const std::string jwt = service.GenerateUserJwt(accessToken, user).get(); + auto user = service.CurrentUserInfo(); + const std::string jwt = service.GenerateUserJwt(accessToken, user); // Allocates memory using some OS API so we can free this buffer on the // other side of the ABI without assumptions on specifics of the programming diff --git a/msix/storeapi/StoreApi.hpp b/msix/storeapi/StoreApi.hpp index d863af91b..4261447b1 100644 --- a/msix/storeapi/StoreApi.hpp +++ b/msix/storeapi/StoreApi.hpp @@ -5,7 +5,6 @@ // the ABI. Zero or positive values have no special meaning other than success. #pragma once -#include #include extern "C" { @@ -37,5 +36,4 @@ DLL_EXPORT Int GetSubscriptionExpirationDate(const char* productID, DLL_EXPORT Int GenerateUserJWT(const char* accessToken, // output char** userJWT, std::uint64_t* userJWTLen); - } From e5ac0bd93b03db5057e7be6014896fc13a7ce573 Mon Sep 17 00:00:00 2001 From: Carlos Nihelton Date: Fri, 15 Sep 2023 10:17:56 -0300 Subject: [PATCH 02/12] Fix user info struct and its generation Now placed inside the service. --- storeapi/agent/ServerStoreService.hpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/storeapi/agent/ServerStoreService.hpp b/storeapi/agent/ServerStoreService.hpp index 050f01894..82122bf16 100644 --- a/storeapi/agent/ServerStoreService.hpp +++ b/storeapi/agent/ServerStoreService.hpp @@ -15,10 +15,7 @@ namespace StoreApi { // when talking to external business servers about the subscription. struct UserInfo { // The user ID that should be tracked in the Contract Server. - winrt::hstring id; - - // An asynchronous factory returning [UserInfo] of the current user. - static concurrency::task Current(); + std::string id; }; // Adds functionality on top of the [StoreService] interesting to background @@ -60,6 +57,23 @@ class ServerStoreService : public StoreService { // just need to convert the duration to seconds. return duration_cast(dur).count(); } + + // A factory returning the current user's [UserInfo]. + UserInfo CurrentUserInfo() const { + auto hashes = this->context.AllLocallyAuthenticatedUserHashes(); + + auto howManyUsers = hashes.size(); + if (howManyUsers < 1) { + throw Exception(ErrorCode::NoLocalUser); + } + + if (howManyUsers > 1) { + throw Exception(ErrorCode::TooManyLocalUsers, + std::format("Expected one but found {}", howManyUsers)); + } + + return UserInfo{.id = hashes[0]}; + } }; } // namespace StoreApi From 0812bbe8301083bd6a02693816da0be9851f6ab9 Mon Sep 17 00:00:00 2001 From: Carlos Nihelton Date: Fri, 15 Sep 2023 10:37:48 -0300 Subject: [PATCH 03/12] Implements the production version of AllLocallyAuthenticatedUserHashes --- storeapi/base/impl/StoreContext.cpp | 49 +++++++++++++++++++++++++++++ storeapi/base/impl/StoreContext.hpp | 4 +++ 2 files changed, 53 insertions(+) diff --git a/storeapi/base/impl/StoreContext.cpp b/storeapi/base/impl/StoreContext.cpp index c942d76f4..15b35d3c0 100644 --- a/storeapi/base/impl/StoreContext.cpp +++ b/storeapi/base/impl/StoreContext.cpp @@ -3,6 +3,12 @@ #include "StoreContext.hpp" #include +#include +#include +#include +#include +#include +#include #include #include @@ -29,6 +35,9 @@ std::vector to_hstrings(std::span input); // Translates a [StorePurchaseStatus] into the [PurchaseStatus] enum. PurchaseStatus translate(StorePurchaseStatus purchaseStatus) noexcept; + +// Returns a hstring representation of a SHA256 sum of the input hstring. +winrt::hstring sha256(winrt::hstring input); } // namespace std::chrono::system_clock::time_point @@ -93,6 +102,32 @@ void StoreContext::InitDialogs(Window parentWindow) { iiw->Initialize(parentWindow); } +std::vector StoreContext::AllLocallyAuthenticatedUserHashes() { + using winrt::Windows::Foundation::IInspectable; + using winrt::Windows::System::KnownUserProperties; + using winrt::Windows::System::User; + using winrt::Windows::System::UserAuthenticationStatus; + using winrt::Windows::System::UserType; + + // This should really return a single user, but the API is specified in terms + // of a collection, so let's not assume too much. + auto users = + User::FindAllAsync(UserType::LocalUser, + UserAuthenticationStatus::LocallyAuthenticated) + .get(); + + std::vector allHashes; + allHashes.reserve(users.Size()); + for (auto user : users) { + IInspectable accountName = + user.GetPropertyAsync(KnownUserProperties::AccountName()).get(); + auto name = winrt::unbox_value(accountName); + allHashes.push_back(winrt::to_string(sha256(name))); + } + + return allHashes; +} + namespace { std::vector to_hstrings(std::span input) { std::vector hStrs; @@ -119,6 +154,20 @@ PurchaseStatus translate(StorePurchaseStatus purchaseStatus) noexcept { assert(false && "Missing enum elements to translate StorePurchaseStatus."); return StoreApi::PurchaseStatus::Unknown; // To be future proof. } + +winrt::hstring sha256(winrt::hstring input) { + using winrt::Windows::Security::Cryptography::BinaryStringEncoding; + using winrt::Windows::Security::Cryptography::CryptographicBuffer; + using winrt::Windows::Security::Cryptography::Core::HashAlgorithmNames; + using winrt::Windows::Security::Cryptography::Core::HashAlgorithmProvider; + + auto inputUtf8 = CryptographicBuffer::ConvertStringToBinary( + winrt::to_hstring(input), BinaryStringEncoding::Utf8); + auto hasher = + HashAlgorithmProvider::OpenAlgorithm(HashAlgorithmNames::Sha256()); + return CryptographicBuffer::EncodeToHexString(hasher.HashData(inputUtf8)); +} + } // namespace } // namespace StoreApi::impl diff --git a/storeapi/base/impl/StoreContext.hpp b/storeapi/base/impl/StoreContext.hpp index b16b824bf..801960a91 100644 --- a/storeapi/base/impl/StoreContext.hpp +++ b/storeapi/base/impl/StoreContext.hpp @@ -81,6 +81,10 @@ class StoreContext { // render native dialogs, such as when purchase or other kinds of // authorization are required. void InitDialogs(Window parentWindow); + + // Returns a collection of hashes of all locally authenticated users running + // in this session. Most likely the collection will contain a single element. + static std::vector AllLocallyAuthenticatedUserHashes(); }; } // namespace StoreApi::impl From 69c17873342fb268ffbcfc92d1fa8e6474f62a54 Mon Sep 17 00:00:00 2001 From: Carlos Nihelton Date: Fri, 15 Sep 2023 12:23:47 -0300 Subject: [PATCH 04/12] Server service cpp no longer needed UserInfo related was moved to the context and to the header. --- msix/storeapi/storeapi.vcxproj | 3 +- storeapi/agent/ServerStoreService.cpp | 57 --------------------------- 2 files changed, 1 insertion(+), 59 deletions(-) delete mode 100644 storeapi/agent/ServerStoreService.cpp diff --git a/msix/storeapi/storeapi.vcxproj b/msix/storeapi/storeapi.vcxproj index 5e5e17d9e..c98886514 100644 --- a/msix/storeapi/storeapi.vcxproj +++ b/msix/storeapi/storeapi.vcxproj @@ -43,7 +43,7 @@ - + UP4W_TEST_WITH_MS_STORE_MOCK @@ -97,7 +97,6 @@ - diff --git a/storeapi/agent/ServerStoreService.cpp b/storeapi/agent/ServerStoreService.cpp deleted file mode 100644 index 33905a6c1..000000000 --- a/storeapi/agent/ServerStoreService.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "ServerStoreService.hpp" - -#include -#include -#include -#include - -namespace StoreApi { - -using winrt::Windows::Foundation::IInspectable; -using winrt::Windows::Security::Cryptography::BinaryStringEncoding; -using winrt::Windows::Security::Cryptography::CryptographicBuffer; -using winrt::Windows::Security::Cryptography::Core::HashAlgorithmNames; -using winrt::Windows::Security::Cryptography::Core::HashAlgorithmProvider; -using winrt::Windows::System::KnownUserProperties; -using winrt::Windows::System::User; -using winrt::Windows::System::UserAuthenticationStatus; -using winrt::Windows::System::UserType; - -using concurrency::task; - -winrt::hstring sha256(winrt::hstring input) { - auto inputUtf8 = CryptographicBuffer::ConvertStringToBinary( - input, BinaryStringEncoding::Utf8); - auto hasher = - HashAlgorithmProvider::OpenAlgorithm(HashAlgorithmNames::Sha256()); - return CryptographicBuffer::EncodeToHexString(hasher.HashData(inputUtf8)); -} - -task UserInfo::Current() { - // The preferred strategy (defined in the spec) is a plain SHA256 hash of the - // user email acquired from the runtime API, which provides the AccountName - // property of the current user. - auto users = co_await User::FindAllAsync( - UserType::LocalUser, UserAuthenticationStatus::LocallyAuthenticated); - - auto howManyUsers = users.Size(); - if (howManyUsers < 1) { - throw Exception(ErrorCode::NoLocalUser); - } - - if (howManyUsers > 1) { - throw Exception(ErrorCode::TooManyLocalUsers, - std::format("Expected one but found {}", howManyUsers)); - } - - IInspectable accountName = co_await users.GetAt(0).GetPropertyAsync( - KnownUserProperties::AccountName()); - auto name = winrt::unbox_value(accountName); - if (name.size() == 0) { - co_return {}; - } - - co_return UserInfo{.id = sha256(name)}; -} - -} // namespace StoreApi From 4e9e5e73befce2e260f45b0e4beed4962bf5afb9 Mon Sep 17 00:00:00 2001 From: Carlos Nihelton Date: Fri, 15 Sep 2023 12:32:27 -0300 Subject: [PATCH 05/12] Sync GenerateJwt --- storeapi/agent/ServerStoreService.hpp | 8 +++----- storeapi/base/impl/StoreContext.cpp | 11 ++++++++++- storeapi/base/impl/StoreContext.hpp | 12 +++--------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/storeapi/agent/ServerStoreService.hpp b/storeapi/agent/ServerStoreService.hpp index 82122bf16..9d2b2eae9 100644 --- a/storeapi/agent/ServerStoreService.hpp +++ b/storeapi/agent/ServerStoreService.hpp @@ -25,20 +25,18 @@ class ServerStoreService : public StoreService { public: // Generates the user ID key (a.k.a the JWT) provided the server AAD [token] // and the [user] info whose ID the caller wants to have encoded in the JWT. - concurrency::task GenerateUserJwt(std::string token, - UserInfo user) { + std::string GenerateUserJwt(std::string token, UserInfo user) const { if (user.id.empty()) { throw Exception(StoreApi::ErrorCode::NoLocalUser); } - auto hToken = winrt::to_hstring(token); - auto jwt = co_await this->context.GenerateUserJwt(hToken, user.id); + auto jwt = this->context.GenerateUserJwt(token, user.id); if (jwt.empty()) { throw Exception(ErrorCode::EmptyJwt, std::format("access token: {}", token)); } - co_return winrt::to_string(jwt); + return jwt; } // Returns the expiration time as the number of seconds since Unix epoch of diff --git a/storeapi/base/impl/StoreContext.cpp b/storeapi/base/impl/StoreContext.cpp index 15b35d3c0..8779dc14c 100644 --- a/storeapi/base/impl/StoreContext.cpp +++ b/storeapi/base/impl/StoreContext.cpp @@ -94,6 +94,15 @@ std::vector StoreContext::GetProducts( return products; } +std::string StoreContext::GenerateUserJwt(std::string token, + std::string userId) const { + assert(token.empty() && "Azure AD token is required"); + auto hJwt = self.GetCustomerPurchaseIdAsync(winrt::to_hstring(token), + winrt::to_hstring(userId)) + .get(); + return winrt::to_string(hJwt); +} + void StoreContext::InitDialogs(Window parentWindow) { // Apps that do not feature a [CoreWindow] must inform the runtime the parent // window handle in order to render runtime provided UI elements, such as @@ -172,4 +181,4 @@ winrt::hstring sha256(winrt::hstring input) { } // namespace StoreApi::impl -#endif // UP4W_TEST_WITH_MS_STORE_MOCK +#endif // UP4W_TEST_WITH_MS_STORE_MOCK diff --git a/storeapi/base/impl/StoreContext.hpp b/storeapi/base/impl/StoreContext.hpp index 801960a91..acfcb0447 100644 --- a/storeapi/base/impl/StoreContext.hpp +++ b/storeapi/base/impl/StoreContext.hpp @@ -11,9 +11,6 @@ // For the underlying Store API #include -// To provide the WinRT coroutine types. -#include - // For HWND and GUI-related Windows types. #include @@ -70,12 +67,9 @@ class StoreContext { std::vector GetProducts(std::span kinds, std::span ids) const; - // Generates the user ID key (a.k.a the JWT) provided the server AAD [hToken] - // and the [hUserId] the caller wants to have encoded in the JWT. - winrt::Windows::Foundation::IAsyncOperation GenerateUserJwt( - winrt::hstring hToken, winrt::hstring hUserId) { - return self.GetCustomerPurchaseIdAsync(hToken, hUserId); - } + // Generates the user ID key (a.k.a the JWT) provided the server AAD [token] + // and the [userId] the caller wants to have encoded in the JWT. + std::string GenerateUserJwt(std::string token, std::string userId) const; // Initializes the GUI "subsystem" with the [parentWindow] handle so we can // render native dialogs, such as when purchase or other kinds of From ed6b22896a67205ed4035d2d137fe67bea0124d4 Mon Sep 17 00:00:00 2001 From: Carlos Nihelton Date: Fri, 15 Sep 2023 12:35:04 -0300 Subject: [PATCH 06/12] Header cleanup: no more ppl no more coroutines --- storeapi/agent/ServerStoreService.hpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/storeapi/agent/ServerStoreService.hpp b/storeapi/agent/ServerStoreService.hpp index 9d2b2eae9..0a2e46093 100644 --- a/storeapi/agent/ServerStoreService.hpp +++ b/storeapi/agent/ServerStoreService.hpp @@ -1,13 +1,12 @@ #pragma once -#include - -#include "base/DefaultContext.hpp" -#include "base/Exception.hpp" -#include "base/StoreService.hpp" - +#include +#include +#include #include #include +#include #include +#include namespace StoreApi { From 23084ab302752826f43f4f58576fe7a3921a4795 Mon Sep 17 00:00:00 2001 From: Carlos Nihelton Date: Mon, 18 Sep 2023 13:34:15 -0300 Subject: [PATCH 07/12] Fix MSBuild PreprocessorDefinitions DefineConstants is a C# property. For C++. it must be PreprocessorDefinitions under a ClCompile item. Also, the logic was twisted --- msix/storeapi/storeapi.vcxproj | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/msix/storeapi/storeapi.vcxproj b/msix/storeapi/storeapi.vcxproj index c98886514..8c063c59d 100644 --- a/msix/storeapi/storeapi.vcxproj +++ b/msix/storeapi/storeapi.vcxproj @@ -43,9 +43,11 @@ - - UP4W_TEST_WITH_MS_STORE_MOCK - + + + UP4W_TEST_WITH_MS_STORE_MOCK;%(PreProcessorDefinitions) + + Level3 From 58d95c0a05d4f86f964ca8bb0150f233992fb39b Mon Sep 17 00:00:00 2001 From: Carlos Nihelton Date: Mon, 18 Sep 2023 22:49:00 -0300 Subject: [PATCH 08/12] Updates tests and stubs Removes coroutine and WinRT related headers, Updates stubs methods Removes no longer relevant test for user id size No test should isntantiate production Context --- storeapi/test/CMakeLists.txt | 2 +- storeapi/test/ServerStoreServiceTest.cpp | 39 ++++++++------- storeapi/test/stubs.hpp | 63 ++++++++++++++---------- 3 files changed, 57 insertions(+), 47 deletions(-) diff --git a/storeapi/test/CMakeLists.txt b/storeapi/test/CMakeLists.txt index 6acefe58e..e3cd0a0b7 100644 --- a/storeapi/test/CMakeLists.txt +++ b/storeapi/test/CMakeLists.txt @@ -15,7 +15,7 @@ set(StoreApi_SRCS "../base/Exception.hpp" "../base/Purchase.hpp" "../base/StoreService.hpp" - "../agent/ServerStoreService.cpp" + "../agent/ServerStoreService.hpp" "../gui/ClientStoreService.hpp" ) diff --git a/storeapi/test/ServerStoreServiceTest.cpp b/storeapi/test/ServerStoreServiceTest.cpp index a2e154405..2162b67ae 100644 --- a/storeapi/test/ServerStoreServiceTest.cpp +++ b/storeapi/test/ServerStoreServiceTest.cpp @@ -8,41 +8,42 @@ namespace StoreApi { using namespace ::testing; -TEST(UserInfo, PredictableSizes) { - auto user = UserInfo::Current().get(); - auto size = user.id.size(); - EXPECT_TRUE(size == 0 || size == 64) - << "User ID of unexpected size: " << size << " <" - << winrt::to_string(user.id) << '\n'; +TEST(ServerStoreService, NoUsersLikeInCI) { + auto service = ServerStoreService{}; + EXPECT_THROW({auto user = service.CurrentUserInfo();}, Exception); +} + +TEST(ServerStoreService, TooManyUsers) { + auto service = ServerStoreService{}; + EXPECT_THROW({auto user = service.CurrentUserInfo();}, Exception); +} + +TEST(ServerStoreService, FindOneUser) { + static constexpr char goodHash[] = "goodHash"; + auto service = ServerStoreService{}; + FindOneUser::goodHash = goodHash; + auto user = service.CurrentUserInfo(); + EXPECT_EQ(user.id, goodHash); } TEST(ServerStoreService, EmptyJwtThrows) { auto service = ServerStoreService{}; - UserInfo user{.id = L"my@name.com"}; + UserInfo user{.id = "my@name.com"}; EXPECT_THROW( { - auto jwt = service.GenerateUserJwt("this-is-a-web-token", user).get(); + auto jwt = service.GenerateUserJwt("this-is-a-web-token", user); }, Exception); } TEST(ServerStoreService, NonEmptyJwtNeverThrows) { auto service = ServerStoreService{}; - UserInfo user{.id = L"my@name.com"}; + UserInfo user{.id = "my@name.com"}; std::string token{"this-is-a-web-token"}; - auto jwt = service.GenerateUserJwt(token, user).get(); + auto jwt = service.GenerateUserJwt(token, user); EXPECT_EQ(token, jwt); } -TEST(ServerStoreService, RealServerFailsUnderTest) { - auto service = ServerStoreService{}; - UserInfo user{.id = L"my@name.com"}; - std::string token{"this-is-a-web-token"}; - // This fails because the test is not an app deployed through the store. - EXPECT_THROW({ auto jwt = service.GenerateUserJwt(token, user).get(); }, - Exception); -} - TEST(ServerStoreService, ExpirationDateUnsubscribed) { auto service = ServerStoreService{}; diff --git a/storeapi/test/stubs.hpp b/storeapi/test/stubs.hpp index 2a101fda4..86accbcec 100644 --- a/storeapi/test/stubs.hpp +++ b/storeapi/test/stubs.hpp @@ -4,23 +4,16 @@ #include #include -// For WinRT basic types and coroutines. -#include -// For non-WinRT coroutines -#include - -// Win32 APIs, such as the Timezone -#include - #include #include #include #include #include #include +// For timegm +#include #if defined _MSC_VER -#include #include #define timegm _mkgmtime #endif @@ -89,9 +82,8 @@ struct EmptyJwtContext { return {Product{.kind = kinds[0], .id = ids[0]}}; } - winrt::Windows::Foundation::IAsyncOperation GenerateUserJwt( - winrt::hstring hToken, winrt::hstring hUserId) { - co_return {}; + std::string GenerateUserJwt(std::string hToken, std::string hUserId) const { + return {}; } }; @@ -107,9 +99,8 @@ struct IdentityJwtContext { return {Product{.kind = kinds[0], .id = ids[0]}}; } - winrt::Windows::Foundation::IAsyncOperation GenerateUserJwt( - winrt::hstring hToken, winrt::hstring hUserId) { - co_return hToken; + std::string GenerateUserJwt(std::string hToken, std::string hUserId) const { + return hToken; } }; @@ -132,9 +123,8 @@ struct NeverSubscribedContext { return {Product{.kind = kinds[0], .id = ids[0]}}; } - winrt::Windows::Foundation::IAsyncOperation GenerateUserJwt( - winrt::hstring hToken, winrt::hstring hUserId) { - co_return hToken; + std::string GenerateUserJwt(std::string hToken, std::string hUserId) const { + return hToken; } }; @@ -158,9 +148,8 @@ struct UnixEpochContext { return {Product{.kind = kinds[0], .id = ids[0]}}; } - winrt::Windows::Foundation::IAsyncOperation GenerateUserJwt( - winrt::hstring hToken, winrt::hstring hUserId) { - co_return hToken; + std::string GenerateUserJwt(std::string hToken, std::string hUserId) const { + return hToken; } }; @@ -187,9 +176,8 @@ struct AlreadyPurchasedContext { return {Product{.kind = kinds[0], .id = ids[0]}}; } - winrt::Windows::Foundation::IAsyncOperation GenerateUserJwt( - winrt::hstring hToken, winrt::hstring hUserId) { - co_return hToken; + std::string GenerateUserJwt(std::string hToken, std::string hUserId) const { + return hToken; } // noop @@ -219,11 +207,32 @@ struct PurchaseSuccessContext { return {Product{.kind = kinds[0], .id = ids[0]}}; } - winrt::Windows::Foundation::IAsyncOperation GenerateUserJwt( - winrt::hstring hToken, winrt::hstring hUserId) { - co_return hToken; + std::string GenerateUserJwt(std::string hToken, std::string hUserId) const { + return hToken; } // noop void InitDialogs(Window window) {} }; + +struct TooManyUsersContext { + struct Product {}; + std::vector AllLocallyAuthenticatedUserHashes() const { + return {"first-user", "second-user"}; + } +}; + +struct NoUsers { + struct Product {}; + std::vector AllLocallyAuthenticatedUserHashes() const { + return {}; + } +}; + +struct FindOneUser { + struct Product {}; + static inline std::string goodHash{}; + std::vector AllLocallyAuthenticatedUserHashes() const { + return {goodHash}; + } +}; From bfbf46db06742728619c889125f27cdf67134d76 Mon Sep 17 00:00:00 2001 From: Carlos Nihelton Date: Tue, 19 Sep 2023 09:26:05 -0300 Subject: [PATCH 09/12] Fix assert on GenerateJwt Token must not be empty --- storeapi/base/impl/StoreContext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storeapi/base/impl/StoreContext.cpp b/storeapi/base/impl/StoreContext.cpp index 8779dc14c..878a62380 100644 --- a/storeapi/base/impl/StoreContext.cpp +++ b/storeapi/base/impl/StoreContext.cpp @@ -96,7 +96,7 @@ std::vector StoreContext::GetProducts( std::string StoreContext::GenerateUserJwt(std::string token, std::string userId) const { - assert(token.empty() && "Azure AD token is required"); + assert(!token.empty() && "Azure AD token is required"); auto hJwt = self.GetCustomerPurchaseIdAsync(winrt::to_hstring(token), winrt::to_hstring(userId)) .get(); From f6c004c778b95d98f327b0f9cecc4a0efe544704 Mon Sep 17 00:00:00 2001 From: Carlos Nihelton Date: Tue, 19 Sep 2023 10:17:21 -0300 Subject: [PATCH 10/12] Prevents empty account names in AllLocallyAuthenticatedUserHashes --- storeapi/base/impl/StoreContext.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/storeapi/base/impl/StoreContext.cpp b/storeapi/base/impl/StoreContext.cpp index 878a62380..3a5b35bee 100644 --- a/storeapi/base/impl/StoreContext.cpp +++ b/storeapi/base/impl/StoreContext.cpp @@ -131,7 +131,9 @@ std::vector StoreContext::AllLocallyAuthenticatedUserHashes() { IInspectable accountName = user.GetPropertyAsync(KnownUserProperties::AccountName()).get(); auto name = winrt::unbox_value(accountName); - allHashes.push_back(winrt::to_string(sha256(name))); + if (!name.empty()) { + allHashes.push_back(winrt::to_string(sha256(name))); + } } return allHashes; From f8cf3c99f0d6913835f43780ba62cf81f496e0ae Mon Sep 17 00:00:00 2001 From: Carlos Nihelton Date: Tue, 19 Sep 2023 12:40:54 -0300 Subject: [PATCH 11/12] Replaces string.h by cstring Idiomatic C++ C header inclusion :) Also fix ordering --- msix/storeapi/StoreApi.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msix/storeapi/StoreApi.cpp b/msix/storeapi/StoreApi.cpp index de9c891a1..378327ce8 100644 --- a/msix/storeapi/StoreApi.cpp +++ b/msix/storeapi/StoreApi.cpp @@ -1,13 +1,13 @@ #include "StoreApi.hpp" #include -#include #include #include #include -#include +#include // For strnlen #include +#include #include "framework.hpp" From 3cc36e3766eb7685b441b1448513033727e7b52e Mon Sep 17 00:00:00 2001 From: Carlos Nihelton Date: Tue, 19 Sep 2023 12:47:51 -0300 Subject: [PATCH 12/12] Appends 'Context' to the context stub classes --- storeapi/test/ServerStoreServiceTest.cpp | 6 +++--- storeapi/test/stubs.hpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/storeapi/test/ServerStoreServiceTest.cpp b/storeapi/test/ServerStoreServiceTest.cpp index 2162b67ae..e822b17c6 100644 --- a/storeapi/test/ServerStoreServiceTest.cpp +++ b/storeapi/test/ServerStoreServiceTest.cpp @@ -9,7 +9,7 @@ namespace StoreApi { using namespace ::testing; TEST(ServerStoreService, NoUsersLikeInCI) { - auto service = ServerStoreService{}; + auto service = ServerStoreService{}; EXPECT_THROW({auto user = service.CurrentUserInfo();}, Exception); } @@ -20,8 +20,8 @@ TEST(ServerStoreService, TooManyUsers) { TEST(ServerStoreService, FindOneUser) { static constexpr char goodHash[] = "goodHash"; - auto service = ServerStoreService{}; - FindOneUser::goodHash = goodHash; + auto service = ServerStoreService{}; + FindOneUserContext::goodHash = goodHash; auto user = service.CurrentUserInfo(); EXPECT_EQ(user.id, goodHash); } diff --git a/storeapi/test/stubs.hpp b/storeapi/test/stubs.hpp index 86accbcec..c2f46aa36 100644 --- a/storeapi/test/stubs.hpp +++ b/storeapi/test/stubs.hpp @@ -222,14 +222,14 @@ struct TooManyUsersContext { } }; -struct NoUsers { +struct NoUsersContext { struct Product {}; std::vector AllLocallyAuthenticatedUserHashes() const { return {}; } }; -struct FindOneUser { +struct FindOneUserContext { struct Product {}; static inline std::string goodHash{}; std::vector AllLocallyAuthenticatedUserHashes() const {