From 9203ec1268612e5b7163cf9eda20325c660c31e8 Mon Sep 17 00:00:00 2001 From: LDA Date: Sat, 8 Jun 2024 11:57:52 +0200 Subject: [PATCH] [MOD] Join rooms via alias --- src/Routes.c | 2 + src/Routes/RouteJoinRoomAlias.c | 190 ++++++++++++++++++++++++++++++++ src/include/Routes.h | 1 + 3 files changed, 193 insertions(+) create mode 100644 src/Routes/RouteJoinRoomAlias.c diff --git a/src/Routes.c b/src/Routes.c index c5d58dd..b6d4980 100644 --- a/src/Routes.c +++ b/src/Routes.c @@ -80,6 +80,8 @@ RouterBuild(void) R("/_matrix/client/v3/rooms/(.*)/event/(.*)", RouteFetchEvent); R("/_matrix/client/v3/rooms/(.*)/join", RouteJoinRoom); + R("/_matrix/client/v3/join/(.*)", RouteJoinRoomAlias); + R("/_matrix/client/v3/createRoom", RouteCreateRoom); R("/_matrix/client/v3/directory/room/(.*)", RouteAliasDirectory); diff --git a/src/Routes/RouteJoinRoomAlias.c b/src/Routes/RouteJoinRoomAlias.c new file mode 100644 index 0000000..c074f01 --- /dev/null +++ b/src/Routes/RouteJoinRoomAlias.c @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2022-2024 Jordan Bancino <@jordan:bancino.net> with + * other valuable contributors. See CONTRIBUTORS.txt for the full list. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include + + +#include +#include +#include +#include + +#include +#include +#include + +#include + +static char * +GetServerName(Db * db) +{ + char *name; + + Config config; + + ConfigLock(db, &config); + if (!config.ok) + { + return NULL; + } + + name = StrDuplicate(config.serverName); + + ConfigUnlock(&config); + + return name; +} + +ROUTE_IMPL(RouteJoinRoomAlias, path, argp) +{ + RouteArgs *args = argp; + Db *db = args->matrixArgs->db; + + HashMap *request = NULL; + HashMap *response = NULL; + + User *user = NULL; + char *token = NULL; + CommonID *id = NULL; + + char *roomId = ArrayGet(path, 0); + char *sender = NULL, *serverName = NULL; + + Room *room = NULL; + + char *err; + + if (!roomId) + { + /* Should be impossible */ + HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR); + return MatrixErrorCreate(M_UNKNOWN, NULL); + } + if (*roomId != '!') + { + roomId = RoomResolveAlias(db, roomId); + } + else + { + roomId = StrDuplicate(roomId); + } + if (!roomId) + { + HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR); + response = MatrixErrorCreate(M_UNKNOWN, NULL); + goto finish; + } + + if (HttpRequestMethodGet(args->context) != HTTP_POST) + { + err = "Unknown request method."; + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_UNRECOGNIZED, err); + goto finish; + } + + request = JsonDecode(HttpServerStream(args->context)); + if (!request) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_NOT_JSON, NULL); + goto finish; + } + + serverName = GetServerName(db); + if (!serverName) + { + HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR); + response = MatrixErrorCreate(M_UNKNOWN, NULL); + goto finish; + } + + response = MatrixGetAccessToken(args->context, &token); + if (response) + { + goto finish; + } + + user = UserAuthenticate(db, token); + if (!user) + { + HttpResponseStatus(args->context, HTTP_UNAUTHORIZED); + response = MatrixErrorCreate(M_UNKNOWN_TOKEN, NULL); + goto finish; + } + id = UserIdParse(UserGetName(user), serverName); + id->sigil = '@'; + sender = ParserRecomposeCommonID(*id); + + room = RoomLock(db, roomId); + if (!room) + { + + err = "Room ID does not exist."; + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_UNKNOWN, err); + goto finish; + } + if (RoomContainsUser(room, sender)) + { + err = "User is already in the room."; + HttpResponseStatus(args->context, HTTP_UNAUTHORIZED); + response = MatrixErrorCreate(M_FORBIDDEN, err); + goto finish; + } + if (!RoomCanJoin(room, sender)) + { + err = "User cannot be in the room."; + HttpResponseStatus(args->context, HTTP_UNAUTHORIZED); + response = MatrixErrorCreate(M_FORBIDDEN, err); + goto finish; + } + /* TODO: Custom reason parameter. */ + if (!RoomJoin(room, user)) + { + err = "User could not be the room due to unknown reasons."; + HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR); + response = MatrixErrorCreate(M_UNKNOWN, err); + goto finish; + } + + response = HashMapCreate(); + JsonSet(response, JsonValueString(roomId), 1, "room_id"); + +finish: + Free(roomId); + UserIdFree(id); + JsonFree(request); + if (sender) + { + Free(sender); + } + if (serverName) + { + Free(serverName); + } + RoomUnlock(room); + UserUnlock(user); + return response; +} diff --git a/src/include/Routes.h b/src/include/Routes.h index 0c90b69..f307add 100644 --- a/src/include/Routes.h +++ b/src/include/Routes.h @@ -103,6 +103,7 @@ ROUTE(RouteCreateRoom); ROUTE(RouteFetchEvent); ROUTE(RouteSendEvent); ROUTE(RouteJoinRoom); +ROUTE(RouteJoinRoomAlias); ROUTE(RouteAliasDirectory); ROUTE(RouteRoomAliases);