// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 #pragma once // Standard library #include #include // AWS SDK #include #include #include #include #include #include #include #include // GameKit #include #include #include #include #include #include #include #include // Boost Forward declarations namespace boost { namespace filesystem { class path; } } using namespace GameKit::Logger; namespace GameKit { class IAdminAchievementsFeature { public: IAdminAchievementsFeature() {}; virtual ~IAdminAchievementsFeature() {}; // Configuration virtual unsigned int ListAchievements(unsigned int pageSize, bool waitForAllPages, DISPATCH_RECEIVER_HANDLE dispatchReceiver, CharPtrCallback responseCallback) = 0; virtual unsigned int AddAchievements(const GameKit::Achievement* achievements, unsigned int batchSize) = 0; virtual unsigned int DeleteAchievements(const char* const* achievementIdentifiers, unsigned int batchSize) = 0; }; namespace Achievements { static const int ADMIN_SESSION_EXPIRATION_BUFFER_MILLIS = 120000; static const std::string ACHIEVEMENT_ICONS_UPLOAD_OBJECT_PATH = "uploads/"; static const std::string ACHIEVEMENT_ICONS_RESIZED_OBJECT_PATH = "icons/"; class AdminAchievements : GameKitFeature, IAdminAchievementsFeature { private: Authentication::GameKitSessionManager* m_sessionManager; std::shared_ptr m_httpClient; Aws::STS::Model::Credentials m_adminApiSessionCredentials; std::mutex m_adminCredentialsMutex; std::string m_cloudResourcesPath; AccountInfoCopy m_accountInfo; AccountCredentialsCopy m_accountCredentials; GameKit::Utils::STSUtils m_stsUtils; unsigned int processResponse(const std::shared_ptr& response, const std::string& originMethod, const DISPATCH_RECEIVER_HANDLE dispatchReceiver, const CharPtrCallback responseCallback, Aws::Utils::Json::JsonValue& outJsonValue) const; bool signRequestWithSessionCredentials(const std::shared_ptr& request); unsigned persistAchievementsData(const Achievement* achievements, const std::vector>& updatedIcons, size_t batchSize); std::string getAchievementsBucketName() const; Aws::S3::Model::PutObjectOutcome uploadToS3(const Aws::S3::S3Client* s3Client, const std::string& objectKey, const boost::filesystem::path& filePath) const; unsigned int uploadIcon(const Aws::S3::S3Client* s3Client, const Achievement& achievementCopy, const char* iconType, const std::string& iconSource, std::string& outNewKey) const; unsigned int uploadIcons(const Achievement* achievements, unsigned batchSize, std::vector>& updatedIcons) const; std::string getAdminSessionPolicy() const; std::string getAdminApiRoleArn() const; unsigned int getAdminApiSessionCredentials(bool forceCredentialsRefresh=false); std::string getShortRegionCode(const std::string& region) const; unsigned int makeAdminRequest( const Aws::Http::HttpMethod method, std::shared_ptr& response, const std::map& queryStringParams=std::map(), const Aws::String& body=""); /** * @brief Generates the suffix to the S3 object key for an achievement icon, including a UUID to uniquely identify this achievement * icon from past versions. * * @details Achievements are temporarily uploaded to the ACHIEVEMENT_ICONS_UPLOAD_OBJECT_PATH path, then resized and * stored in the ACHIEVEMENT_ICONS_RESIZED_OBJECT_PATH path in S3 by a lambda function. The suffix generated by this method * will identify a specific achievement icon in both locations. * * @param achievementId The id of the achievement whose icon is being uploaded. * @param iconType The type of icon being uploaded, either "locked" or "unlocked". * @param sourcePath The file extension for the local icon file. */ std::string generateIconObjectKeySuffix(const std::string& achievementId, const std::string& iconType, const std::string& fileExtension) const; public: /** * @brief Constructor, obtains resource handles and initializes clients. * * @param logCallback Callback function for logging information and errors. * @param sessionManager GameKitSessionManager instance that manages tokens and configuration. * @param cloudResourcesPath Root path for plugin resources to read config files. * @param accountInfo Struct containing environment and game name * @param accountCredentials Struct containing AWS access key, secret access key, region, and accountID. */ AdminAchievements(FuncLogCallback logCallback, Authentication::GameKitSessionManager* sessionManager, const std::string& cloudResourcesPath, const AccountInfo& accountInfo, const AccountCredentials& accountCredentials); /** * @brief Destructor, releases resources. */ ~AdminAchievements(); /** * @brief Passes all the metadata for every achievement for the current game and environment to a callback function. * * @param pageSize The number of dynamo records to scan before the callback is called, max 100. * @param waitForAllPages Determines if all achievements should be scanned before calling the callback. * @param dispatchReceiver Object that responseCallback is a member of. * @param responseCallback Callback method to write decoded JSON response with achievement info to. * @return GameKit status code, GAMEKIT_SUCCESS on success else non-zero value. Consult errors.h file for details. */ unsigned int ListAchievements(unsigned int pageSize, bool waitForAllPages, const DISPATCH_RECEIVER_HANDLE dispatchReceiver, const CharPtrCallback responseCallback) override; /** * @brief Adds or updates the achievements table in dynamoDB for the current game and environment to have new metadata items. * * @details Achievement icons are directly uploaded to AWS S3 from this SDK. When an icon is updated, old icon versions will * be removed automatically by the backing lambda function. * * @param achievements Array of structs containing all the fields and values of an achievements item in dynamoDB. * @param batchSize The number of items achievementsMetadata contains. * @return GameKit status code, GAMEKIT_SUCCESS on success else non-zero value. Consult errors.h file for details. */ unsigned int AddAchievements(const Achievement* achievements, unsigned int batchSize) override; /** * @brief Deletes the achievements in the table in dynamoDB for the current game and environment specified ID's * * @param achievementIdentifiers Array of unique achievement ID's * @param batchSize The number of items achievementIdentifiers contains. * @return GameKit status code, GAMEKIT_SUCCESS on success else non-zero value. Consult errors.h file for details. */ unsigned int DeleteAchievements(const char* const* achievementIdentifiers, unsigned int batchSize) override; /** * @brief Changes the credentials used to sign requests and retrieve session tokens for admin requests. * * @param accountCredentials Struct containing Aws account credentials. * @param accountInfo Struct containing information about Aws account, and your game. * @return GameKit status code, GAMEKIT_SUCCESS on success else non-zero value. Consult errors.h file for details. */ unsigned int ChangeCredentials(const AccountCredentials& accountCredentials, const AccountInfo& accountInfo); /** * @brief Getter for session manager object * * @return Pointer to session manager */ Authentication::GameKitSessionManager* GetSessionManager() const { return m_sessionManager; } /** * @brief Sets the Http client to use for this feature. Useful for injecting during tests. * * @param httpClient Shared pointer to an http client for this feature to use. */ void SetHttpClient(std::shared_ptr httpClient) { m_httpClient = httpClient; } /** * @brief Sets the Aws STS client used internally to get session tokens. Useful for injecting during tests. * * @param stsClient Shared pointer to the STS Client object you want achievements to use internally. */ void SetSTSClient(std::shared_ptr stsClient) { m_stsUtils.SetSTSClient(stsClient); } /** * @brief Sets the AdminApiSessionCredentials to use for this feature. Useful for injecting during tests. * * @param adminApiSessionCredentials AdminApiSessionCredentials to use for this feature. */ void SetAdminApiSessionCredentials(const Aws::STS::Model::Credentials& adminApiSessionCredentials) { m_adminApiSessionCredentials = adminApiSessionCredentials; } /** * @brief Gets the account credentials copy obj the feature uses internally, Useful for asserts in tests. * * @return The internal account credentials copy object */ AccountCredentialsCopy GetAccountCredentials() { return m_accountCredentials; } /** * @brief Gets the account info copy obj the feature uses internally, Useful for asserts in tests. * * @return The internal account info copy object */ AccountInfoCopy GetAccountInfo() { return m_accountInfo; } }; } }