From 4d4969862a2513c44c59149ec6cb255180a48a11 Mon Sep 17 00:00:00 2001
From: CapsizeGlimmer <>
Date: Fri, 10 Jul 2020 02:49:05 -0400
Subject: [PATCH] Implement /rooms/<room_id>/joined_members

---
 src/client_server.rs    | 35 ++++++++++++++++++++++++++++++++++-
 src/database/rooms.rs   |  2 +-
 src/main.rs             |  1 +
 sytest/sytest-whitelist |  1 +
 4 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/src/client_server.rs b/src/client_server.rs
index 79885faef..c63e8b9c0 100644
--- a/src/client_server.rs
+++ b/src/client_server.rs
@@ -34,7 +34,8 @@
             media::{create_content, get_content, get_content_thumbnail, get_media_config},
             membership::{
                 ban_user, forget_room, get_member_events, invite_user, join_room_by_id,
-                join_room_by_id_or_alias, joined_rooms, kick_user, leave_room, unban_user,
+                join_room_by_id_or_alias, joined_members, joined_rooms, kick_user, leave_room,
+                unban_user,
             },
             message::{create_message_event, get_message_events},
             presence::set_presence,
@@ -1667,6 +1668,38 @@ pub fn kick_user_route(
     Ok(kick_user::Response.into())
 }
 
+#[get("/_matrix/client/r0/rooms/<_room_id>/joined_members", data = "<body>")]
+pub fn joined_members_route(
+    db: State<'_, Database>,
+    body: Ruma<joined_members::Request>,
+    _room_id: String,
+) -> ConduitResult<joined_members::Response> {
+    let user_id = body.user_id.as_ref().expect("user is authenticated");
+
+    if !db.rooms.is_joined(&user_id, &body.room_id).unwrap_or(false) {
+        return Err(Error::BadRequest(
+            ErrorKind::Forbidden,
+            "You aren't a member of the room.",
+        ));
+    }
+
+    let mut joined = BTreeMap::new();
+    for user_id in db.rooms.room_members(&body.room_id).filter_map(|r| r.ok()) {
+        let display_name = db.users.displayname(&user_id)?;
+        let avatar_url = db.users.avatar_url(&user_id)?;
+
+        joined.insert(
+            user_id,
+            joined_members::RoomMember {
+                display_name,
+                avatar_url,
+            },
+        );
+    }
+
+    Ok(joined_members::Response { joined }.into())
+}
+
 #[post("/_matrix/client/r0/rooms/<_room_id>/ban", data = "<body>")]
 pub fn ban_user_route(
     db: State<'_, Database>,
diff --git a/src/database/rooms.rs b/src/database/rooms.rs
index 298212d48..0395cc20d 100644
--- a/src/database/rooms.rs
+++ b/src/database/rooms.rs
@@ -81,7 +81,7 @@ pub fn room_state_full(
         Ok(hashmap)
     }
 
-    /// Returns the full room state.
+    /// Returns the all state entries for this type.
     pub fn room_state_type(
         &self,
         room_id: &RoomId,
diff --git a/src/main.rs b/src/main.rs
index a530a205b..ba22b6456 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -64,6 +64,7 @@ fn setup_rocket() -> rocket::Rocket {
                 client_server::get_alias_route,
                 client_server::join_room_by_id_route,
                 client_server::join_room_by_id_or_alias_route,
+                client_server::joined_members_route,
                 client_server::leave_room_route,
                 client_server::forget_room_route,
                 client_server::joined_rooms_route,
diff --git a/sytest/sytest-whitelist b/sytest/sytest-whitelist
index ad555361a..ec2aba4eb 100644
--- a/sytest/sytest-whitelist
+++ b/sytest/sytest-whitelist
@@ -1,3 +1,4 @@
+/joined_members return joined members
 /joined_rooms returns only joined rooms
 3pid invite join valid signature but revoked keys are rejected
 3pid invite join valid signature but unreachable ID server are rejected
-- 
GitLab