From 4da58d0f0f9df6d9f1438a8701fedbf54edf7e46 Mon Sep 17 00:00:00 2001 From: ajberchek <ajberchek@gmail.com> Date: Sat, 3 Mar 2018 11:08:43 -0800 Subject: [PATCH] Implements Logout Functionality (#16) fixes #6 --- src/client.cpp | 21 +++++++++ src/client.hpp | 2 + tests/client_api.cpp | 101 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+) diff --git a/src/client.cpp b/src/client.cpp index ca0b49d59..8a930b5af 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -237,6 +237,27 @@ Client::login( false); } +void +Client::logout( + std::function<void(const mtx::responses::Logout &response, + std::experimental::optional<mtx::client::errors::ClientError>)> callback) +{ + mtx::requests::Logout req; + + post<mtx::requests::Logout, mtx::responses::Logout>( + "/logout", + req, + [this, callback](const mtx::responses::Logout &res, + std::experimental::optional<mtx::client::errors::ClientError> err) { + if (!err) { + // Clear the now invalid access token when logout is successful + access_token_.clear(); + } + // Pass up response and error to supplied callback + callback(res, err); + }); +} + void Client::create_room(const mtx::requests::CreateRoom &room_options, std::function<void(const mtx::responses::CreateRoom &, RequestErr)> callback) diff --git a/src/client.hpp b/src/client.hpp index cffe55518..acb076bf0 100644 --- a/src/client.hpp +++ b/src/client.hpp @@ -47,6 +47,8 @@ public: void login(const std::string &username, const std::string &password, std::function<void(const mtx::responses::Login &response, RequestErr err)>); + //! Perform logout. + void logout(std::function<void(const mtx::responses::Logout &response, RequestErr err)>); //! Create a room with the given options. void create_room( const mtx::requests::CreateRoom &room_options, diff --git a/tests/client_api.cpp b/tests/client_api.cpp index 27049c434..1b8f913d2 100644 --- a/tests/client_api.cpp +++ b/tests/client_api.cpp @@ -107,6 +107,107 @@ TEST(ClientAPI, CreateRoom) mtx_client->close(); } +TEST(ClientAPI, LogoutSuccess) +{ + std::shared_ptr<Client> mtx_client = std::make_shared<Client>("localhost"); + std::string token; + + // Login and prove that login was successful by creating a room + mtx_client->login( + "alice", "secret", [&token](const mtx::responses::Login &res, ErrType err) { + ASSERT_FALSE(err); + validate_login("@alice:localhost", res); + token = res.access_token; + }); + while (token.empty()) { + // Block while we are logging in + std::this_thread::sleep_for(std::chrono::milliseconds(300)); + } + mtx_client->set_access_token(token); + mtx::requests::CreateRoom req; + req.name = "Test1"; + req.topic = "Topic1"; + mtx_client->create_room(req, [](const mtx::responses::CreateRoom &res, ErrType err) { + boost::ignore_unused(res); + ASSERT_FALSE(err); + }); + + // Logout and prove that logout was successful and deleted the access_token_ for the client + mtx_client->logout([mtx_client, &token](const mtx::responses::Logout &res, ErrType err) { + boost::ignore_unused(res); + ASSERT_FALSE(err); + token.clear(); + }); + while (token.size()) { + // Block while we are logging out + std::this_thread::sleep_for(std::chrono::milliseconds(300)); + } + // Verify that sending requests with this mtx_client fails after logout + mtx::requests::CreateRoom failReq; + failReq.name = "42"; + failReq.topic = "LifeUniverseEverything"; + mtx_client->create_room(failReq, [](const mtx::responses::CreateRoom &res, ErrType err) { + boost::ignore_unused(res); + ASSERT_TRUE(err); + EXPECT_EQ(mtx::errors::to_string(err->matrix_error.errcode), "M_MISSING_TOKEN"); + EXPECT_EQ(err->status_code, boost::beast::http::status::forbidden); + + }); + + mtx_client->close(); +} + +TEST(ClientAPI, LogoutInvalidatesTokenOnServer) +{ + std::shared_ptr<Client> mtx_client = std::make_shared<Client>("localhost"); + std::string token; + + // Login and prove that login was successful by creating a room + mtx_client->login( + "alice", "secret", [&token](const mtx::responses::Login &res, ErrType err) { + ASSERT_FALSE(err); + validate_login("@alice:localhost", res); + token = res.access_token; + }); + while (token.empty()) { + // Block while we are logging in + std::this_thread::sleep_for(std::chrono::milliseconds(300)); + } + mtx_client->set_access_token(token); + mtx::requests::CreateRoom req; + req.name = "Test1"; + req.topic = "Topic1"; + mtx_client->create_room(req, [](const mtx::responses::CreateRoom &res, ErrType err) { + boost::ignore_unused(res); + ASSERT_FALSE(err); + }); + + // Logout and prove that logout was successful by verifying the old access_token_ is no + // longer valid + mtx_client->logout([mtx_client, &token](const mtx::responses::Logout &res, ErrType err) { + boost::ignore_unused(res); + ASSERT_FALSE(err); + mtx_client->set_access_token(token); + token.clear(); + }); + while (token.size()) { + // Block while we are logging out + std::this_thread::sleep_for(std::chrono::milliseconds(300)); + } + // Verify that creating a room with the old access_token_ no longer succeeds after logout + mtx::requests::CreateRoom failReq; + failReq.name = "42"; + failReq.topic = "LifeUniverseEverything"; + mtx_client->create_room(failReq, [](const mtx::responses::CreateRoom &res, ErrType err) { + boost::ignore_unused(res); + ASSERT_TRUE(err); + EXPECT_EQ(mtx::errors::to_string(err->matrix_error.errcode), "M_UNKNOWN_TOKEN"); + EXPECT_EQ(err->status_code, boost::beast::http::status::forbidden); + }); + + mtx_client->close(); +} + TEST(ClientAPI, CreateRoomInvites) { auto alice = std::make_shared<Client>("localhost"); -- GitLab