diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 28f8bc2e70cab671d9c7af5fb1b6c3796d3501c0..6b54663578b60be402531c52f156a88b774f8311 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -183,7 +183,7 @@ test-pages: before_script: - apk update - apk add doxygen git texlive-full py3-jinja2 py3-pygments - - git clone git://github.com/mosra/m.css + - git clone https://github.com/mosra/m.css.git script: - ./m.css/documentation/doxygen.py Doxyfile-mcss - mv generated-docs/html/ public/ @@ -201,7 +201,7 @@ pages: before_script: - apk update - apk add doxygen git texlive-full py3-jinja2 py3-pygments - - git clone git://github.com/mosra/m.css + - git clone https://github.com/mosra/m.css.git script: - ./m.css/documentation/doxygen.py Doxyfile-mcss - mv generated-docs/html/ public/ diff --git a/include/mtx/events/collections.hpp b/include/mtx/events/collections.hpp index 410eb7f73ac15a35aee250e9a20d329ac8ba2a4d..58c04ee21a4b8a29daf0b4edf33cef7af228541c 100644 --- a/include/mtx/events/collections.hpp +++ b/include/mtx/events/collections.hpp @@ -112,6 +112,7 @@ using StrippedEvents = std::variant<events::StrippedEvent<states::Aliases>, events::StrippedEvent<states::Avatar>, events::StrippedEvent<states::CanonicalAlias>, events::StrippedEvent<states::Create>, + events::StrippedEvent<states::Encryption>, events::StrippedEvent<states::GuestAccess>, events::StrippedEvent<states::HistoryVisibility>, events::StrippedEvent<states::JoinRules>, diff --git a/include/mtx/requests.hpp b/include/mtx/requests.hpp index c3b5127ef28fbe54def5944ee16294ea0ca90017..c510b97259500f03f6179534a3a92d0e04f246a0 100644 --- a/include/mtx/requests.hpp +++ b/include/mtx/requests.hpp @@ -52,6 +52,21 @@ struct CreateRoom Preset preset = Preset::PrivateChat; //! Whether or not the room will be visible by non members. common::RoomVisibility visibility = common::RoomVisibility::Private; + + //! A list of state events to set in the new room. This allows the user to override the default + //! state events set in the new room. The expected format of the state events are an object with + //! type, state_key and content keys set. + std::vector<events::collections::StrippedEvents> initial_state; + + //! The room version to set for the room. If not provided, the homeserver is to use its + //! configured default. If provided, the homeserver will return a 400 error with the errcode + //! M_UNSUPPORTED_ROOM_VERSION if it does not support the room version. + std::string room_version; + + //! Extra keys, such as m.federate, to be added to the content of the m.room.create event. The + //! server will overwrite the following keys: creator, room_version. Future versions of the + //! specification may allow the server to overwrite other keys. + std::optional<events::state::Create> creation_content; }; void diff --git a/lib/structs/requests.cpp b/lib/structs/requests.cpp index de4ab9704d42fb10d794b847135a23f01ceb2674..c907c2733e70c30ec72b250afa8f503a7cadb6e8 100644 --- a/lib/structs/requests.cpp +++ b/lib/structs/requests.cpp @@ -46,6 +46,22 @@ to_json(json &obj, const CreateRoom &request) obj["is_direct"] = request.is_direct; obj["preset"] = presetToString(request.preset); obj["visibility"] = visibilityToString(request.visibility); + + if (!request.room_version.empty()) + obj["room_version"] = request.room_version; + + if (request.creation_content) + obj["creation_content"] = *request.creation_content; + + if (!request.initial_state.empty()) { + auto arr = nlohmann::json::array(); + for (const auto &ev : request.initial_state) { + auto event_json = std::visit([](auto e) { return json(e); }, ev); + event_json.erase("sender"); + arr.push_back(std::move(event_json)); + } + obj["initial_state"] = std::move(arr); + } } void diff --git a/tests/client_api.cpp b/tests/client_api.cpp index a5c000464e8ed8cbfae5f81f39c28db1e1acd3a8..7f044cdcaf01faeb92f16c6401fb176aa840b98e 100644 --- a/tests/client_api.cpp +++ b/tests/client_api.cpp @@ -8,6 +8,7 @@ #include "mtx/events/encrypted.hpp" #include "mtx/requests.hpp" #include "mtx/responses.hpp" +#include "mtxclient/crypto/types.hpp" #include "mtxclient/http/client.hpp" #include "test_helpers.hpp" @@ -289,6 +290,58 @@ TEST(ClientAPI, CreateRoom) mtx_client->close(); } +TEST(ClientAPI, CreateRoomInitialState) +{ + mtx::requests::CreateRoom req; + + mtx::events::StrippedEvent<mtx::events::state::Encryption> enc; + enc.type = mtx::events::EventType::RoomEncryption; + enc.content.algorithm = mtx::crypto::MEGOLM_ALGO; + enc.content.rotation_period_ms = 1000ULL * 60ULL * 60ULL * 777ULL; + enc.content.rotation_period_msgs = 777; + + req.initial_state.emplace_back(enc); + + std::shared_ptr<Client> mtx_client = make_test_client(); + + mtx_client->login( + "alice", "secret", [mtx_client](const mtx::responses::Login &, RequestErr err) { + check_error(err); + }); + + while (mtx_client->access_token().empty()) + sleep(); + + mtx_client->create_room( + req, [mtx_client, enc](const mtx::responses::CreateRoom &res, RequestErr err) { + check_error(err); + ASSERT_TRUE(res.room_id.localpart().size() > 10); + EXPECT_EQ(res.room_id.hostname(), server_name()); + + mtx_client->get_state( + res.room_id.to_string(), [enc](const mtx::responses::StateEvents &res, RequestErr err) { + check_error(err); + ASSERT_TRUE(res.events.size() > 0); + bool found_enc_event = false; + + for (const auto &e : res.events) { + auto ev = + std::get_if<mtx::events::StateEvent<mtx::events::state::Encryption>>(&e); + if (ev) { + found_enc_event = true; + EXPECT_EQ(ev->content.algorithm, enc.content.algorithm); + EXPECT_EQ(ev->content.rotation_period_ms, enc.content.rotation_period_ms); + EXPECT_EQ(ev->content.rotation_period_msgs, + enc.content.rotation_period_msgs); + } + } + EXPECT_TRUE(found_enc_event); + }); + }); + + mtx_client->close(); +} + TEST(ClientAPI, Members) { std::shared_ptr<Client> mtx_client = make_test_client(); diff --git a/tests/connection.cpp b/tests/connection.cpp index 957d1ae9150144814fbb253b42b56cbc0e4326f8..c05fe10a45850a476fc1a8d41544c0b85447d0dc 100644 --- a/tests/connection.cpp +++ b/tests/connection.cpp @@ -16,7 +16,7 @@ TEST(Basic, Connection) { auto client = make_test_client(); - client->versions([](const mtx::responses::Versions &, RequestErr err) { ASSERT_FALSE(err); }); + client->versions([](const mtx::responses::Versions &, RequestErr err) { check_error(err); }); client->close(); } @@ -30,7 +30,7 @@ TEST(Basic, ServerWithPort) EXPECT_EQ(alice->server(), server); EXPECT_EQ(alice->port(), 8008); - alice->versions([](const mtx::responses::Versions &, RequestErr err) { ASSERT_FALSE(err); }); + alice->versions([](const mtx::responses::Versions &, RequestErr err) { check_error(err); }); alice->close(); }