Page MenuHomePhorge

No OneTemporary

Size
12 KB
Referenced Files
None
Subscribers
None
diff --git a/changelogs/28.fix b/changelogs/28.fix
new file mode 100644
index 0000000..7d294c9
--- /dev/null
+++ b/changelogs/28.fix
@@ -0,0 +1 @@
+Fix joining room with room alias
diff --git a/src/client/actions/membership.cpp b/src/client/actions/membership.cpp
index cc612d1..23aece4 100644
--- a/src/client/actions/membership.cpp
+++ b/src/client/actions/membership.cpp
@@ -1,287 +1,293 @@
/*
* This file is part of libkazv.
* SPDX-FileCopyrightText: 2020 Tusooa Zhu <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <libkazv-config.hpp>
#include <csapi/create_room.hpp>
#include <csapi/inviting.hpp>
#include <csapi/joining.hpp>
#include <debug.hpp>
#include "client-model.hpp"
#include "clientutil.hpp"
#include "cursorutil.hpp"
#include "status-utils.hpp"
#include "membership.hpp"
namespace Kazv
{
static std::string visibilityToStr(CreateRoomAction::Visibility v)
{
using V = CreateRoomAction::Visibility;
switch (v) {
case V::Private:
return "private";
case V::Public:
return "public";
default:
// should not happen
return "";
}
}
static std::string presetToStr(CreateRoomAction::Preset p)
{
using P = CreateRoomAction::Preset;
switch (p) {
case P::PrivateChat:
return "private_chat";
case P::PublicChat:
return "public_chat";
case P::TrustedPrivateChat:
return "trusted_private_chat";
default:
// should not happen
return "";
}
}
ClientResult updateClient(ClientModel m, CreateRoomAction a)
{
auto visibility = visibilityToStr(a.visibility);
std::optional<std::string> preset = a.preset
? std::optional<std::string>(presetToStr(a.preset.value()))
: std::nullopt;
using StateEvT = Kazv::CreateRoomJob::StateEvent;
auto initialState = intoImmer(
immer::array<StateEvT>{},
zug::map(
[](Event e) {
return StateEvT{e.type(), e.stateKey(), e.content()};
}),
a.initialState);
auto job = m.job<CreateRoomJob>().make(
visibility,
a.roomAliasName,
a.name,
a.topic,
a.invite,
DEFVAL, // invite3pid, not supported yet
a.roomVersion,
a.creationContent,
initialState,
preset,
a.isDirect,
a.powerLevelContentOverride);
m.addJob(std::move(job));
return { std::move(m), lager::noop };
}
ClientResult processResponse(ClientModel m, CreateRoomResponse r)
{
if (! r.success()) {
kzo.client.dbg() << "Create room failed" << std::endl;
m.addTrigger(CreateRoomFailed{r.errorCode(), r.errorMessage()});
return { std::move(m), failWithResponse(r) };
}
m.addTrigger(CreateRoomSuccessful{r.roomId()});
return { std::move(m), lager::noop };
}
ClientResult updateClient(ClientModel m, InviteToRoomAction a)
{
auto job = m.job<InviteUserJob>()
.make(a.roomId, a.userId)
.withData(json{
{"roomId", a.roomId},
{"userId", a.userId},
});
m.addJob(std::move(job));
return { std::move(m), lager::noop };
}
ClientResult processResponse(ClientModel m, InviteUserResponse r)
{
auto roomId = r.dataStr("roomId");
auto userId = r.dataStr("userId");
if (! r.success()) {
// Error
kzo.client.warn() << "Error inviting user " << r.errorCode() << r.errorMessage() << std::endl;
m.addTrigger(InviteUserFailed{roomId, userId, r.errorCode(), r.errorMessage()});
return { std::move(m), failWithResponse(r) };
}
kzo.client.info() << "Inviting user successful" << std::endl;
m.addTrigger(InviteUserSuccessful{roomId, userId});
return { std::move(m), lager::noop };
}
ClientResult updateClient(ClientModel m, JoinRoomAction a)
{
+ /// HACK: wait for real boost::url
+ auto encodedId = a.roomIdOrAlias;
+ if (!encodedId.empty() && encodedId[0] == '#') {
+ encodedId.replace(0, 1, "%23");
+ }
+
auto job = m.job<JoinRoomJob>()
- .make(a.roomIdOrAlias, a.serverName)
+ .make(encodedId, a.serverName)
.withData(json{{"roomIdOrAlias", a.roomIdOrAlias}});
m.addJob(std::move(job));
return { m, lager::noop };
}
ClientResult processResponse(ClientModel m, JoinRoomResponse r)
{
auto roomIdOrAlias = r.dataStr("roomIdOrAlias");
if (! r.success()) {
m.addTrigger(JoinRoomFailed{
roomIdOrAlias,
r.errorCode(),
r.errorMessage()
});
kzo.client.warn() << "Error joining room" << r.errorCode() << r.errorMessage() << std::endl;
return { std::move(m), failWithResponse(r) };
}
kzo.client.info() << "Successfully joined room" << std::endl;
m.addTrigger(JoinRoomSuccessful{roomIdOrAlias});
return { std::move(m), lager::noop};
}
ClientResult updateClient(ClientModel m, JoinRoomByIdAction a)
{
auto job = m.job<JoinRoomByIdJob>()
.make(a.roomId)
.withData(json{{"roomIdOrAlias", a.roomId}});
m.addJob(std::move(job));
return { std::move(m), lager::noop };
}
ClientResult processResponse(ClientModel m, JoinRoomByIdResponse r)
{
auto roomIdOrAlias = r.dataStr("roomIdOrAlias");
if (! r.success()) {
m.addTrigger(JoinRoomFailed{
roomIdOrAlias,
r.errorCode(),
r.errorMessage()
});
kzo.client.warn() << "Error joining room" << r.errorCode() << r.errorMessage() << std::endl;
return { std::move(m), failWithResponse(r) };
}
kzo.client.info() << "Successfully joined room" << std::endl;
m.addTrigger(JoinRoomSuccessful{roomIdOrAlias});
return { std::move(m), lager::noop};
}
ClientResult updateClient(ClientModel m, LeaveRoomAction a)
{
auto job = m.job<LeaveRoomJob>()
.make(a.roomId)
.withData(json{{"roomId", a.roomId}});
m.addJob(std::move(job));
return { std::move(m), lager::noop };
}
ClientResult processResponse(ClientModel m, LeaveRoomResponse r)
{
auto roomId = r.dataStr("roomId");
if (! r.success()) {
m.addTrigger(LeaveRoomFailed{
roomId,
r.errorCode(),
r.errorMessage()
});
kzo.client.warn() << "Error leaving room" << r.errorCode() << r.errorMessage() << std::endl;
return { std::move(m), failWithResponse(r) };
}
kzo.client.info() << "Successfully left room" << std::endl;
m.addTrigger(LeaveRoomSuccessful{roomId});
return { std::move(m), lager::noop};
}
ClientResult updateClient(ClientModel m, ForgetRoomAction a)
{
auto job = m.job<ForgetRoomJob>()
.make(a.roomId)
.withData(json{{"roomId", a.roomId}});
m.addJob(std::move(job));
return { std::move(m), lager::noop };
}
ClientResult processResponse(ClientModel m, ForgetRoomResponse r)
{
auto roomId = r.dataStr("roomId");
if (! r.success()) {
m.addTrigger(ForgetRoomFailed{
roomId,
r.errorCode(),
r.errorMessage()
});
kzo.client.warn() << "Error forgetting room" << r.errorCode() << r.errorMessage() << std::endl;
return { std::move(m), failWithResponse(r) };
}
kzo.client.info() << "Successfully forgot room" << std::endl;
m.addTrigger(ForgetRoomSuccessful{roomId});
return { std::move(m), lager::noop};
}
ClientResult updateClient(ClientModel m, KickAction a)
{
m.addJob(m.job<KickJob>().make(a.roomId, a.userId, a.reason));
return { std::move(m), lager::noop };
}
ClientResult processResponse(ClientModel m, KickResponse r)
{
if (!r.success()) {
kzo.client.warn() << "Error kicking" << r.errorCode() << r.errorMessage() << std::endl;
return { std::move(m), failWithResponse(r) };
}
return { std::move(m), lager::noop };
}
ClientResult updateClient(ClientModel m, BanAction a)
{
m.addJob(m.job<BanJob>().make(a.roomId, a.userId, a.reason));
return { std::move(m), lager::noop };
}
ClientResult processResponse(ClientModel m, BanResponse r)
{
if (!r.success()) {
kzo.client.warn() << "Error banning" << r.errorCode() << r.errorMessage() << std::endl;
return { std::move(m), failWithResponse(r) };
}
return { std::move(m), lager::noop };
}
ClientResult updateClient(ClientModel m, UnbanAction a)
{
m.addJob(m.job<UnbanJob>().make(a.roomId, a.userId));
return { std::move(m), lager::noop };
}
ClientResult processResponse(ClientModel m, UnbanResponse r)
{
if (!r.success()) {
kzo.client.warn() << "Error unbanning" << r.errorCode() << r.errorMessage() << std::endl;
return { std::move(m), failWithResponse(r) };
}
return { std::move(m), lager::noop };
}
};
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 5bc1d5c..82922e4 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -1,55 +1,56 @@
include(CTest)
set(KAZVTEST_RESPATH ${CMAKE_CURRENT_SOURCE_DIR}/resources)
configure_file(kazvtest-respath.hpp.in kazvtest-respath.hpp)
add_executable(kazvtest
testmain.cpp
basejobtest.cpp
event-test.cpp
cursorutiltest.cpp
base/serialization-test.cpp
base/types-test.cpp
client/client-test-util.cpp
client/discovery-test.cpp
client/sync-test.cpp
client/content-test.cpp
client/paginate-test.cpp
client/util-test.cpp
client/serialization-test.cpp
client/encrypted-file-test.cpp
client/sdk-test.cpp
client/thread-safety-test.cpp
client/room-test.cpp
client/random-generator-test.cpp
client/profile-test.cpp
client/kick-test.cpp
client/ban-test.cpp
+ client/join-test.cpp
client/keys-test.cpp
client/room/room-actions-test.cpp
kazvjobtest.cpp
event-emitter-test.cpp
crypto-test.cpp
crypto/deterministic-test.cpp
promise-test.cpp
store-test.cpp
file-desc-test.cpp
)
target_include_directories(
kazvtest
PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(kazvtest
PRIVATE Catch2::Catch2WithMain
PRIVATE kazv
PRIVATE kazveventemitter
PRIVATE kazvjob
PRIVATE nlohmann_json::nlohmann_json
PRIVATE immer
PRIVATE lager
PRIVATE zug)
diff --git a/src/tests/client/join-test.cpp b/src/tests/client/join-test.cpp
new file mode 100644
index 0000000..ac17766
--- /dev/null
+++ b/src/tests/client/join-test.cpp
@@ -0,0 +1,42 @@
+/*
+ * This file is part of libkazv.
+ * SPDX-FileCopyrightText: 2021-2023 tusooa <tusooa@kazv.moe>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <libkazv-config.hpp>
+
+#include <catch2/catch_all.hpp>
+#include <boost/asio.hpp>
+#include <asio-promise-handler.hpp>
+#include <cursorutil.hpp>
+#include <sdk-model.hpp>
+#include <client/client.hpp>
+
+#include "client-test-util.hpp"
+
+TEST_CASE("Send join job with alias", "[client][membership]")
+{
+ ClientModel loggedInModel = createTestClientModel();
+ auto [resModel, dontCareEffect] = ClientModel::update(
+ loggedInModel, JoinRoomAction{"#room:example.com", {}});
+
+ assert1Job(resModel);
+ for1stJob(resModel, [] (const auto &job) {
+ REQUIRE(job.jobId() == "JoinRoom");
+ REQUIRE(job.url().find("%23room:example.com") != std::string::npos);
+ });
+}
+
+TEST_CASE("Send join job with id", "[client][membership]")
+{
+ ClientModel loggedInModel = createTestClientModel();
+ auto [resModel, dontCareEffect] = ClientModel::update(
+ loggedInModel, JoinRoomAction{"!room:example.com", {}});
+
+ assert1Job(resModel);
+ for1stJob(resModel, [] (const auto &job) {
+ REQUIRE(job.jobId() == "JoinRoom");
+ REQUIRE(job.url().find("!room:example.com") != std::string::npos);
+ });
+}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Jan 20, 12:02 AM (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55535
Default Alt Text
(12 KB)

Event Timeline