From 78c1281909bf9a3495ec744b00cb0681c875b0b2 Mon Sep 17 00:00:00 2001 From: albertywang Date: Thu, 19 Dec 2024 22:17:36 -0600 Subject: [PATCH] Add twitch_id field to authenticate response --- c_library/gamelink_c.cpp | 14 ++++++- c_library/gamelink_c.h | 5 ++- gamelink_single.hpp | 77 ++++++++++++++++++++------------------- include/gateway.h | 6 ++- schema/authentication.cpp | 12 ++++-- schema/authentication.h | 13 +++++-- src/gamelink.cpp | 4 +- src/gateway.cpp | 42 +++++++-------------- test/authentication.cpp | 44 ++++++++++++++++++++++ test/clibrary_tests.cpp | 3 +- 10 files changed, 140 insertions(+), 80 deletions(-) diff --git a/c_library/gamelink_c.cpp b/c_library/gamelink_c.cpp index 934be16..2666482 100644 --- a/c_library/gamelink_c.cpp +++ b/c_library/gamelink_c.cpp @@ -119,7 +119,7 @@ MGL_RequestId MuxyGameLink_AuthenticateWithGameIDAndRefreshToken(MuxyGameLink Ga MGL_RequestId res = SDK->AuthenticateWithGameIDAndRefreshToken(ClientId, GameId, RefreshToken, C_CALLBACK(Callback, UserData, AuthenticateResponse)); return res; - } + } else { MGL_RequestId res = SDK->AuthenticateWithRefreshToken(ClientId, RefreshToken, @@ -185,6 +185,18 @@ const char* MuxyGameLink_Schema_User_GetTwitchName(MGL_Schema_User User) return ""; } + +const char* MuxyGameLink_Schema_User_GetTwitchID(MGL_Schema_User User) +{ + const gamelink::schema::User* MGLUser = static_cast(User.Obj); + if (MGLUser) + { + return MGLUser->GetTwitchID().c_str(); + } + + return ""; +} + MGL_RequestId MuxyGameLink_SendBroadcast(MuxyGameLink GameLink, const char* Topic, const char* JsonString) { gamelink::SDK* SDK = static_cast(GameLink.SDK); diff --git a/c_library/gamelink_c.h b/c_library/gamelink_c.h index e9a1b82..b89a611 100644 --- a/c_library/gamelink_c.h +++ b/c_library/gamelink_c.h @@ -27,7 +27,7 @@ extern "C" typedef uint16_t MGL_RequestId; static const MGL_RequestId ANY_REQUEST_ID = UINT16_MAX; static const MGL_RequestId REJECTED_REQUEST_ID = UINT16_MAX-1; - + typedef struct { void* SDK; @@ -260,6 +260,7 @@ extern "C" MUXY_CLIB_API const char* MuxyGameLink_Schema_User_GetJWT(MGL_Schema_User User); MUXY_CLIB_API const char* MuxyGameLink_Schema_User_GetRefreshToken(MGL_Schema_User User); MUXY_CLIB_API const char* MuxyGameLink_Schema_User_GetTwitchName(MGL_Schema_User User); + MUXY_CLIB_API const char* MuxyGameLink_Schema_User_GetTwitchID(MGL_Schema_User User); /* State functions @@ -475,7 +476,7 @@ extern "C" MUXY_CLIB_API uint32_t MuxyGameLink_PatchList_Empty(MGL_PatchList PList); MUXY_CLIB_API void MuxyGameLink_PatchList_Clear(MGL_PatchList PList); - /* + /* Drops */ MUXY_CLIB_API MGL_RequestId MuxyGameLink_GetDrops(MuxyGameLink GameLink, const char* Status, MGL_DropsCallback Callback, void* User); diff --git a/gamelink_single.hpp b/gamelink_single.hpp index e957293..a005f0d 100644 --- a/gamelink_single.hpp +++ b/gamelink_single.hpp @@ -27025,7 +27025,7 @@ namespace gamelink /// Game ID, assigned by Muxy. string game_id; }; - + MUXY_GAMELINK_SERIALIZE_3(AuthenticateWithGameAndPINRequestBody, "pin", pin, "client_id", client_id, "game_id", game_id); struct MUXY_GAMELINK_API AuthenticateWithGameAndPINRequest : SendEnvelope @@ -27057,7 +27057,7 @@ namespace gamelink /// @param[in] RefreshToken Refresh token obtained from authorization. AuthenticateWithRefreshTokenRequest(const string& clientId, const string& refreshToken); }; - + struct MUXY_GAMELINK_API AuthenticateWithRefreshTokenAndGameRequestBody { string refresh; @@ -27104,8 +27104,11 @@ namespace gamelink /// Information about the channel the auth was done with string twitch_name; + + /// The twitch id of the user in question + string twitch_id; }; - MUXY_GAMELINK_SERIALIZE_3(AuthenticateResponseBody, "jwt", jwt, "refresh", refresh, "twitch_name", twitch_name); + MUXY_GAMELINK_SERIALIZE_4(AuthenticateResponseBody, "jwt", jwt, "refresh", refresh, "twitch_name", twitch_name, "twitch_id", twitch_id); struct MUXY_GAMELINK_API AuthenticateResponse : ReceiveEnvelope { @@ -27116,16 +27119,18 @@ namespace gamelink class MUXY_GAMELINK_API User { public: - User(string jwt, string refreshToken, string twitchName); + User(string jwt, string refreshToken, string twitchName, string twtichID); const string& GetJWT() const; const string& GetRefreshToken() const; const string& GetTwitchName() const; + const string& GetTwitchID() const; // string GetOpaqueID(); private: string jwt; string refreshToken; string twitchName; + string twitchID; }; } } @@ -30217,10 +30222,11 @@ namespace gateway class AuthenticateResponse { public: - AuthenticateResponse(string JWT, string RefreshToken, string TwitchName, bool DidError) + AuthenticateResponse(string JWT, string RefreshToken, string TwitchName, string TwitchID, bool DidError) : JWT(JWT) , RefreshToken(RefreshToken) , TwitchName(TwitchName) + , TwitchID(TwitchID) , DidError(DidError) { } @@ -30234,6 +30240,9 @@ namespace gateway /// Information about the channel the auth was done with string TwitchName; + // Information about the channel the auth was done with + string TwitchID; + bool HasError() const { return DidError; @@ -30611,7 +30620,7 @@ namespace gamelink params.target = string("authentication"); } - + AuthenticateWithPINRequest::AuthenticateWithPINRequest(const string& clientId, const string& pin) { action = string("authenticate"); @@ -30646,13 +30655,14 @@ namespace gamelink data.game_id = gameId; } - User::User(string jwt, string refreshToken, string twitchName) + User::User(string jwt, string refreshToken, string twitchName, string twitchID) : jwt(std::move(jwt)) , refreshToken(std::move(refreshToken)) , twitchName(std::move(twitchName)) + , twitchID(std::move(twitchID)) { } - + const string& User::GetJWT() const { return jwt; @@ -30667,6 +30677,11 @@ namespace gamelink { return twitchName; } + + const string& User::GetTwitchID() const + { + return twitchID; + } } } @@ -31477,7 +31492,7 @@ namespace gamelink success = schema::ParseResponse(bytes, length, authResp); if (success) { - const schema::Error * err = FirstError(authResp); + const schema::Error* err = FirstError(authResp); if (!err) { _lock.lock(); @@ -31485,7 +31500,7 @@ namespace gamelink { delete _user; } - _user = new schema::User(authResp.data.jwt, authResp.data.refresh, authResp.data.twitch_name); + _user = new schema::User(authResp.data.jwt, authResp.data.refresh, authResp.data.twitch_name, authResp.data.twitch_id); _lock.unlock(); _storedJWT = authResp.data.jwt; @@ -33238,7 +33253,7 @@ namespace gateway return Base.HasPayloads(); } - void SDK::OnDebugMessage(std::function callback) + void SDK::OnDebugMessage(std::function callback) { return Base.OnDebugMessage(std::move(callback)); } @@ -33263,17 +33278,19 @@ namespace gateway RequestID SDK::AuthenticateWithPIN(const string& PIN, std::function Callback) { - return Base.AuthenticateWithGameIDAndPIN(this->ClientID, this->GameID, PIN, [=](const gamelink::schema::AuthenticateResponse& Resp) { - gateway::AuthenticateResponse Auth(Resp.data.jwt, Resp.data.refresh, Resp.data.twitch_name, gamelink::FirstError(Resp) != NULL); - Callback(Auth); - }); + return Base.AuthenticateWithGameIDAndPIN( + this->ClientID, this->GameID, PIN, [=](const gamelink::schema::AuthenticateResponse& Resp) { + gateway::AuthenticateResponse Auth(Resp.data.jwt, Resp.data.refresh, Resp.data.twitch_name, Resp.data.twitch_id, + gamelink::FirstError(Resp) != NULL); + Callback(Auth); + }); } RequestID SDK::AuthenticateWithRefreshToken(const string& JWT, std::function Callback) { return Base.AuthenticateWithGameIDAndRefreshToken( this->ClientID, this->GameID, JWT, [=](const gamelink::schema::AuthenticateResponse& Resp) { - gateway::AuthenticateResponse Auth(Resp.data.jwt, Resp.data.refresh, Resp.data.twitch_name, + gateway::AuthenticateResponse Auth(Resp.data.jwt, Resp.data.refresh, Resp.data.twitch_name, Resp.data.twitch_id, gamelink::FirstError(Resp) != NULL); Callback(Auth); }); @@ -33310,22 +33327,12 @@ namespace gateway string SDK::GetProjectionSandboxURL(const string& projection, int major, int minor, int patch) const { - return gamelink::ProjectionWebsocketConnectionURL( - ClientID, - gamelink::ConnectionStage::Sandbox, - projection, - major, minor, patch - ); + return gamelink::ProjectionWebsocketConnectionURL(ClientID, gamelink::ConnectionStage::Sandbox, projection, major, minor, patch); } string SDK::GetProjectionProductionURL(const string& projection, int major, int minor, int patch) const { - return gamelink::ProjectionWebsocketConnectionURL( - ClientID, - gamelink::ConnectionStage::Production, - projection, - major, minor, patch - ); + return gamelink::ProjectionWebsocketConnectionURL(ClientID, gamelink::ConnectionStage::Production, projection, major, minor, patch); } void SDK::StopPoll() @@ -33369,12 +33376,8 @@ namespace gateway config.userData = cfg.UserData; Base.RunPoll( - id, - cfg.Prompt, - config, - cfg.Options, - [=](const gamelink::schema::PollUpdateResponse& response) - { + id, cfg.Prompt, config, cfg.Options, + [=](const gamelink::schema::PollUpdateResponse& response) { PollUpdate update; uint32_t idx = gamelink::GetPollWinnerIndex(response.data.results); @@ -33390,8 +33393,7 @@ namespace gateway cfg.OnUpdate(update); } }, - [=](const gamelink::schema::PollUpdateResponse& response) - { + [=](const gamelink::schema::PollUpdateResponse& response) { PollUpdate finish; uint32_t idx = gamelink::GetPollWinnerIndex(response.data.results); @@ -33411,8 +33413,7 @@ namespace gateway { cfg.OnComplete(finish); } - } - ); + }); } } diff --git a/include/gateway.h b/include/gateway.h index 65b1afc..ee1bc0c 100644 --- a/include/gateway.h +++ b/include/gateway.h @@ -35,10 +35,11 @@ namespace gateway class AuthenticateResponse { public: - AuthenticateResponse(string JWT, string RefreshToken, string TwitchName, bool DidError) + AuthenticateResponse(string JWT, string RefreshToken, string TwitchName, string TwitchID, bool DidError) : JWT(JWT) , RefreshToken(RefreshToken) , TwitchName(TwitchName) + , TwitchID(TwitchID) , DidError(DidError) { } @@ -52,6 +53,9 @@ namespace gateway /// Information about the channel the auth was done with string TwitchName; + // Information about the channel the auth was done with + string TwitchID; + bool HasError() const { return DidError; diff --git a/schema/authentication.cpp b/schema/authentication.cpp index b5d82ae..13e7838 100644 --- a/schema/authentication.cpp +++ b/schema/authentication.cpp @@ -10,7 +10,7 @@ namespace gamelink params.target = string("authentication"); } - + AuthenticateWithPINRequest::AuthenticateWithPINRequest(const string& clientId, const string& pin) { action = string("authenticate"); @@ -45,13 +45,14 @@ namespace gamelink data.game_id = gameId; } - User::User(string jwt, string refreshToken, string twitchName) + User::User(string jwt, string refreshToken, string twitchName, string twitchID) : jwt(std::move(jwt)) , refreshToken(std::move(refreshToken)) , twitchName(std::move(twitchName)) + , twitchID(std::move(twitchID)) { } - + const string& User::GetJWT() const { return jwt; @@ -66,5 +67,10 @@ namespace gamelink { return twitchName; } + + const string& User::GetTwitchID() const + { + return twitchID; + } } } \ No newline at end of file diff --git a/schema/authentication.h b/schema/authentication.h index 4fa5390..09b2fa8 100644 --- a/schema/authentication.h +++ b/schema/authentication.h @@ -40,7 +40,7 @@ namespace gamelink /// Game ID, assigned by Muxy. string game_id; }; - + MUXY_GAMELINK_SERIALIZE_3(AuthenticateWithGameAndPINRequestBody, "pin", pin, "client_id", client_id, "game_id", game_id); struct MUXY_GAMELINK_API AuthenticateWithGameAndPINRequest : SendEnvelope @@ -72,7 +72,7 @@ namespace gamelink /// @param[in] RefreshToken Refresh token obtained from authorization. AuthenticateWithRefreshTokenRequest(const string& clientId, const string& refreshToken); }; - + struct MUXY_GAMELINK_API AuthenticateWithRefreshTokenAndGameRequestBody { string refresh; @@ -119,8 +119,11 @@ namespace gamelink /// Information about the channel the auth was done with string twitch_name; + + /// The twitch id of the user in question + string twitch_id; }; - MUXY_GAMELINK_SERIALIZE_3(AuthenticateResponseBody, "jwt", jwt, "refresh", refresh, "twitch_name", twitch_name); + MUXY_GAMELINK_SERIALIZE_4(AuthenticateResponseBody, "jwt", jwt, "refresh", refresh, "twitch_name", twitch_name, "twitch_id", twitch_id); struct MUXY_GAMELINK_API AuthenticateResponse : ReceiveEnvelope { @@ -131,16 +134,18 @@ namespace gamelink class MUXY_GAMELINK_API User { public: - User(string jwt, string refreshToken, string twitchName); + User(string jwt, string refreshToken, string twitchName, string twtichID); const string& GetJWT() const; const string& GetRefreshToken() const; const string& GetTwitchName() const; + const string& GetTwitchID() const; // string GetOpaqueID(); private: string jwt; string refreshToken; string twitchName; + string twitchID; }; } } diff --git a/src/gamelink.cpp b/src/gamelink.cpp index 68984a8..bb5061a 100644 --- a/src/gamelink.cpp +++ b/src/gamelink.cpp @@ -372,7 +372,7 @@ namespace gamelink success = schema::ParseResponse(bytes, length, authResp); if (success) { - const schema::Error * err = FirstError(authResp); + const schema::Error* err = FirstError(authResp); if (!err) { _lock.lock(); @@ -380,7 +380,7 @@ namespace gamelink { delete _user; } - _user = new schema::User(authResp.data.jwt, authResp.data.refresh, authResp.data.twitch_name); + _user = new schema::User(authResp.data.jwt, authResp.data.refresh, authResp.data.twitch_name, authResp.data.twitch_id); _lock.unlock(); _storedJWT = authResp.data.jwt; diff --git a/src/gateway.cpp b/src/gateway.cpp index f84f219..1dfa9b2 100644 --- a/src/gateway.cpp +++ b/src/gateway.cpp @@ -40,7 +40,7 @@ namespace gateway return Base.HasPayloads(); } - void SDK::OnDebugMessage(std::function callback) + void SDK::OnDebugMessage(std::function callback) { return Base.OnDebugMessage(std::move(callback)); } @@ -65,17 +65,19 @@ namespace gateway RequestID SDK::AuthenticateWithPIN(const string& PIN, std::function Callback) { - return Base.AuthenticateWithGameIDAndPIN(this->ClientID, this->GameID, PIN, [=](const gamelink::schema::AuthenticateResponse& Resp) { - gateway::AuthenticateResponse Auth(Resp.data.jwt, Resp.data.refresh, Resp.data.twitch_name, gamelink::FirstError(Resp) != NULL); - Callback(Auth); - }); + return Base.AuthenticateWithGameIDAndPIN( + this->ClientID, this->GameID, PIN, [=](const gamelink::schema::AuthenticateResponse& Resp) { + gateway::AuthenticateResponse Auth(Resp.data.jwt, Resp.data.refresh, Resp.data.twitch_name, Resp.data.twitch_id, + gamelink::FirstError(Resp) != NULL); + Callback(Auth); + }); } RequestID SDK::AuthenticateWithRefreshToken(const string& JWT, std::function Callback) { return Base.AuthenticateWithGameIDAndRefreshToken( this->ClientID, this->GameID, JWT, [=](const gamelink::schema::AuthenticateResponse& Resp) { - gateway::AuthenticateResponse Auth(Resp.data.jwt, Resp.data.refresh, Resp.data.twitch_name, + gateway::AuthenticateResponse Auth(Resp.data.jwt, Resp.data.refresh, Resp.data.twitch_name, Resp.data.twitch_id, gamelink::FirstError(Resp) != NULL); Callback(Auth); }); @@ -112,22 +114,12 @@ namespace gateway string SDK::GetProjectionSandboxURL(const string& projection, int major, int minor, int patch) const { - return gamelink::ProjectionWebsocketConnectionURL( - ClientID, - gamelink::ConnectionStage::Sandbox, - projection, - major, minor, patch - ); + return gamelink::ProjectionWebsocketConnectionURL(ClientID, gamelink::ConnectionStage::Sandbox, projection, major, minor, patch); } string SDK::GetProjectionProductionURL(const string& projection, int major, int minor, int patch) const { - return gamelink::ProjectionWebsocketConnectionURL( - ClientID, - gamelink::ConnectionStage::Production, - projection, - major, minor, patch - ); + return gamelink::ProjectionWebsocketConnectionURL(ClientID, gamelink::ConnectionStage::Production, projection, major, minor, patch); } void SDK::StopPoll() @@ -171,12 +163,8 @@ namespace gateway config.userData = cfg.UserData; Base.RunPoll( - id, - cfg.Prompt, - config, - cfg.Options, - [=](const gamelink::schema::PollUpdateResponse& response) - { + id, cfg.Prompt, config, cfg.Options, + [=](const gamelink::schema::PollUpdateResponse& response) { PollUpdate update; uint32_t idx = gamelink::GetPollWinnerIndex(response.data.results); @@ -192,8 +180,7 @@ namespace gateway cfg.OnUpdate(update); } }, - [=](const gamelink::schema::PollUpdateResponse& response) - { + [=](const gamelink::schema::PollUpdateResponse& response) { PollUpdate finish; uint32_t idx = gamelink::GetPollWinnerIndex(response.data.results); @@ -213,7 +200,6 @@ namespace gateway { cfg.OnComplete(finish); } - } - ); + }); } } diff --git a/test/authentication.cpp b/test/authentication.cpp index 487bb9f..6589579 100644 --- a/test/authentication.cpp +++ b/test/authentication.cpp @@ -244,4 +244,48 @@ TEST_CASE("SDK Gateway auth", "[sdk][authentication]") } })"); } +} + + +TEST_CASE("SDK Gateway auth fills user", "[sdk][authentication]") +{ + gamelink::SDK sdk; + sdk.AuthenticateWithGameIDAndPIN("client_id", "game", "pin"); + + REQUIRE(sdk.HasPayloads()); + validateSinglePayload(sdk, R"({ + "action":"authenticate", + "data": { + "client_id":"client_id", + "pin":"pin", + "game_id": "game" + }, + + "params":{ + "request_id": 1 + } + })"); + + const char* msg = R"({ + "meta": { + "request_id": 1, + "action": "authenticate" + }, + + "data": { + "jwt": "test-jwt", + "refresh": "some-refresh", + "twitch_name": "notauser", + "twitch_id": "123456" + } + })"; + + sdk.ReceiveMessage(msg, strlen(msg)); + + const gamelink::schema::User* usr = sdk.GetUser(); + REQUIRE(usr); + REQUIRE(usr->GetJWT() == "test-jwt"); + REQUIRE(usr->GetRefreshToken() == "some-refresh"); + REQUIRE(usr->GetTwitchName() == "notauser"); + REQUIRE(usr->GetTwitchID() == "123456"); } \ No newline at end of file diff --git a/test/clibrary_tests.cpp b/test/clibrary_tests.cpp index 63fa51a..10a6c9d 100644 --- a/test/clibrary_tests.cpp +++ b/test/clibrary_tests.cpp @@ -181,11 +181,12 @@ TEST_CASE_METHOD(ParityFixture, "GameMetaData parity", "[sdk][c]") TEST_CASE_METHOD(ParityFixture, "User operations", "[sdk][c]") { - gamelink::schema::User user("jwt", "refresh", "username"); + gamelink::schema::User user("jwt", "refresh", "username", "id"); MGL_Schema_User cuser; cuser.Obj = &user; REQUIRE(ConstrainedString(MuxyGameLink_Schema_User_GetJWT(cuser)) == user.GetJWT()); REQUIRE(ConstrainedString(MuxyGameLink_Schema_User_GetRefreshToken(cuser)) == user.GetRefreshToken()); REQUIRE(ConstrainedString(MuxyGameLink_Schema_User_GetTwitchName(cuser)) == user.GetTwitchName()); + REQUIRE(ConstrainedString(MuxyGameLink_Schema_User_GetTwitchID(cuser)) == user.GetTwitchID()); } \ No newline at end of file