From bbe16f84679061f1f4af5c1ab76f519279a234c0 Mon Sep 17 00:00:00 2001
From: Nyaaori <+@nyaaori.cat>
Date: Sun, 24 Oct 2021 00:45:02 +0000
Subject: [PATCH 1/4] Update Ruma

---
 Cargo.toml                |  2 +-
 src/client_server/room.rs | 13 +++++++++----
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index dae68bf1..13a7af44 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,7 +19,7 @@ rocket = { version = "0.5.0-rc.1", features = ["tls"] } # Used to handle request
 
 # Used for matrix spec type definitions and helpers
 #ruma = { version = "0.4.0", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
-ruma = { git = "https://github.com/ruma/ruma", rev = "58cdcae1f9a8f4824bcbec1de1bb13e659c66804", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
+ruma = { git = "https://github.com/ruma/ruma", rev = "e7f01ca55a1eff437bad754bf0554cc09f44ec2a", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
 #ruma = { git = "https://github.com/timokoesters/ruma", rev = "50c1db7e0a3a21fc794b0cce3b64285a4c750c71", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
 #ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
 
diff --git a/src/client_server/room.rs b/src/client_server/room.rs
index 2d1fe237..ec09eec8 100644
--- a/src/client_server/room.rs
+++ b/src/client_server/room.rs
@@ -22,10 +22,10 @@ use ruma::{
         },
         EventType,
     },
-    serde::JsonObject,
+    serde::{JsonObject},
     RoomAliasId, RoomId, RoomVersionId,
 };
-use serde_json::value::to_raw_value;
+use serde_json::{value::to_raw_value};
 use std::{cmp::max, collections::BTreeMap, convert::TryFrom, sync::Arc};
 use tracing::{info, warn};
 
@@ -102,9 +102,14 @@ pub async fn create_room_route(
                 }
             })?;
 
+    let creation_content = match body.creation_content.clone() {
+        Some(content) => content.deserialize().expect("Invalid creation content"),
+        None => create_room::CreationContent::new(),
+    };
+
     let mut content = RoomCreateEventContent::new(sender_user.clone());
-    content.federate = body.creation_content.federate;
-    content.predecessor = body.creation_content.predecessor.clone();
+    content.federate = creation_content.federate;
+    content.predecessor = creation_content.predecessor.clone();
     content.room_version = match body.room_version.clone() {
         Some(room_version) => {
             if room_version == RoomVersionId::Version5 || room_version == RoomVersionId::Version6 {

From 8087a26a35fdcd495e28e8bff401fa3ba2afd9ef Mon Sep 17 00:00:00 2001
From: Nyaaori <+@nyaaori.cat>
Date: Sun, 24 Oct 2021 20:26:51 +0000
Subject: [PATCH 2/4] Make createRoom follow spec for m.room.create, allowing
 creation of spaces

---
 src/client_server/room.rs | 65 +++++++++++++++++++++++++++++++--------
 1 file changed, 53 insertions(+), 12 deletions(-)

diff --git a/src/client_server/room.rs b/src/client_server/room.rs
index ec09eec8..5e59e81d 100644
--- a/src/client_server/room.rs
+++ b/src/client_server/room.rs
@@ -22,11 +22,16 @@ use ruma::{
         },
         EventType,
     },
-    serde::{JsonObject},
+    serde::{CanonicalJsonObject, JsonObject, Raw},
     RoomAliasId, RoomId, RoomVersionId,
 };
-use serde_json::{value::to_raw_value};
-use std::{cmp::max, collections::BTreeMap, convert::TryFrom, sync::Arc};
+use serde_json::{json, value::to_raw_value};
+use std::{
+    cmp::max,
+    collections::BTreeMap,
+    convert::{TryFrom, TryInto},
+    sync::Arc,
+};
 use tracing::{info, warn};
 
 #[cfg(feature = "conduit_bin")]
@@ -102,15 +107,7 @@ pub async fn create_room_route(
                 }
             })?;
 
-    let creation_content = match body.creation_content.clone() {
-        Some(content) => content.deserialize().expect("Invalid creation content"),
-        None => create_room::CreationContent::new(),
-    };
-
-    let mut content = RoomCreateEventContent::new(sender_user.clone());
-    content.federate = creation_content.federate;
-    content.predecessor = creation_content.predecessor.clone();
-    content.room_version = match body.room_version.clone() {
+    let room_version = match body.room_version.clone() {
         Some(room_version) => {
             if room_version == RoomVersionId::Version5 || room_version == RoomVersionId::Version6 {
                 room_version
@@ -124,6 +121,50 @@ pub async fn create_room_route(
         None => RoomVersionId::Version6,
     };
 
+    let content = match &body.creation_content {
+        Some(content) => {
+            let mut content = content
+                .deserialize_as::<CanonicalJsonObject>()
+                .expect("Invalid creation content");
+            content.insert(
+                "creator".into(),
+                json!(sender_user.clone()).try_into().unwrap(),
+            );
+            content.insert(
+                "room_version".into(),
+                json!(room_version.as_str()).try_into().unwrap(),
+            );
+            content
+        }
+        None => {
+            let mut content = Raw::<CanonicalJsonObject>::from_json(
+                to_raw_value(&RoomCreateEventContent::new(sender_user.clone())).unwrap(),
+            )
+            .deserialize_as::<CanonicalJsonObject>()
+            .unwrap();
+            content.insert(
+                "room_version".into(),
+                json!(room_version.as_str()).try_into().unwrap(),
+            );
+            content
+        }
+    };
+
+    // Validate creation content
+    match Raw::<CanonicalJsonObject>::from_json(
+        to_raw_value(&content).expect("Invalid creation content"),
+    )
+    .deserialize_as::<RoomCreateEventContent>()
+    {
+        Ok(_t) => {}
+        Err(_e) => {
+            return Err(Error::BadRequest(
+                ErrorKind::BadJson,
+                "Invalid creation content",
+            ))
+        }
+    };
+
     // 1. The room create event
     db.rooms.build_and_append_pdu(
         PduBuilder {

From d5d25fb064449cb42a0243248e6fc2020bf77fe2 Mon Sep 17 00:00:00 2001
From: Nyaaori <+@nyaaori.cat>
Date: Sun, 24 Oct 2021 22:13:08 +0000
Subject: [PATCH 3/4] Preserve all m.room.create entries when performing room
 upgrades

---
 src/client_server/room.rs | 37 ++++++++++++++++++++++++++++---------
 1 file changed, 28 insertions(+), 9 deletions(-)

diff --git a/src/client_server/room.rs b/src/client_server/room.rs
index 5e59e81d..0c62d2d6 100644
--- a/src/client_server/room.rs
+++ b/src/client_server/room.rs
@@ -478,7 +478,7 @@ pub async fn get_room_aliases_route(
     .into())
 }
 
-/// # `GET /_matrix/client/r0/rooms/{roomId}/upgrade`
+/// # `POST /_matrix/client/r0/rooms/{roomId}/upgrade`
 ///
 /// Upgrades the room.
 ///
@@ -556,16 +556,15 @@ pub async fn upgrade_room_route(
     );
     let state_lock = mutex_state.lock().await;
 
-    // Get the old room federations status
-    let federate = serde_json::from_str::<RoomCreateEventContent>(
+    // Get the old room creation event
+    let mut create_event_content = serde_json::from_str::<CanonicalJsonObject>(
         db.rooms
             .room_state_get(&body.room_id, &EventType::RoomCreate, "")?
             .ok_or_else(|| Error::bad_database("Found room without m.room.create event."))?
             .content
             .get(),
     )
-    .map_err(|_| Error::bad_database("Invalid room event in database."))?
-    .federate;
+    .map_err(|_| Error::bad_database("Invalid room event in database."))?;
 
     // Use the m.room.tombstone event as the predecessor
     let predecessor = Some(ruma::events::room::create::PreviousRoom::new(
@@ -574,10 +573,30 @@ pub async fn upgrade_room_route(
     ));
 
     // Send a m.room.create event containing a predecessor field and the applicable room_version
-    let mut create_event_content = RoomCreateEventContent::new(sender_user.clone());
-    create_event_content.federate = federate;
-    create_event_content.room_version = body.new_version.clone();
-    create_event_content.predecessor = predecessor;
+    create_event_content.insert(
+        "creator".into(),
+        json!(sender_user.clone()).try_into().unwrap(),
+    );
+    create_event_content.insert(
+        "room_version".into(),
+        json!(body.new_version.clone()).try_into().unwrap(),
+    );
+    create_event_content.insert("predecessor".into(), json!(predecessor).try_into().unwrap());
+
+    // Validate creation event content
+    match Raw::<CanonicalJsonObject>::from_json(
+        to_raw_value(&create_event_content).expect("Error forming creation event"),
+    )
+    .deserialize_as::<RoomCreateEventContent>()
+    {
+        Ok(_t) => {}
+        Err(_e) => {
+            return Err(Error::BadRequest(
+                ErrorKind::BadJson,
+                "Error forming creation event",
+            ))
+        }
+    };
 
     db.rooms.build_and_append_pdu(
         PduBuilder {

From c4bce1d0c7ee0ba9c88fdccb11ac79112c19075b Mon Sep 17 00:00:00 2001
From: Nyaaori <+@nyaaori.cat>
Date: Tue, 9 Nov 2021 16:12:44 +0000
Subject: [PATCH 4/4] Cleanup room.rs; replace unwraps with map_err

---
 src/client_server/room.rs | 86 +++++++++++++++++++++++----------------
 1 file changed, 50 insertions(+), 36 deletions(-)

diff --git a/src/client_server/room.rs b/src/client_server/room.rs
index 0c62d2d6..47c7ee6f 100644
--- a/src/client_server/room.rs
+++ b/src/client_server/room.rs
@@ -22,7 +22,7 @@ use ruma::{
         },
         EventType,
     },
-    serde::{CanonicalJsonObject, JsonObject, Raw},
+    serde::{CanonicalJsonObject, JsonObject},
     RoomAliasId, RoomId, RoomVersionId,
 };
 use serde_json::{json, value::to_raw_value};
@@ -128,42 +128,48 @@ pub async fn create_room_route(
                 .expect("Invalid creation content");
             content.insert(
                 "creator".into(),
-                json!(sender_user.clone()).try_into().unwrap(),
+                json!(&sender_user).try_into().map_err(|_| {
+                    Error::BadRequest(ErrorKind::BadJson, "Invalid creation content")
+                })?,
             );
             content.insert(
                 "room_version".into(),
-                json!(room_version.as_str()).try_into().unwrap(),
+                json!(room_version.as_str()).try_into().map_err(|_| {
+                    Error::BadRequest(ErrorKind::BadJson, "Invalid creation content")
+                })?,
             );
             content
         }
         None => {
-            let mut content = Raw::<CanonicalJsonObject>::from_json(
-                to_raw_value(&RoomCreateEventContent::new(sender_user.clone())).unwrap(),
+            let mut content = serde_json::from_str::<CanonicalJsonObject>(
+                to_raw_value(&RoomCreateEventContent::new(sender_user.clone()))
+                    .map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Invalid creation content"))?
+                    .get(),
             )
-            .deserialize_as::<CanonicalJsonObject>()
             .unwrap();
             content.insert(
                 "room_version".into(),
-                json!(room_version.as_str()).try_into().unwrap(),
+                json!(room_version.as_str()).try_into().map_err(|_| {
+                    Error::BadRequest(ErrorKind::BadJson, "Invalid creation content")
+                })?,
             );
             content
         }
     };
 
     // Validate creation content
-    match Raw::<CanonicalJsonObject>::from_json(
-        to_raw_value(&content).expect("Invalid creation content"),
-    )
-    .deserialize_as::<RoomCreateEventContent>()
-    {
-        Ok(_t) => {}
-        Err(_e) => {
-            return Err(Error::BadRequest(
-                ErrorKind::BadJson,
-                "Invalid creation content",
-            ))
-        }
-    };
+    let de_result = serde_json::from_str::<CanonicalJsonObject>(
+        to_raw_value(&content)
+            .expect("Invalid creation content")
+            .get(),
+    );
+
+    if let Err(_) = de_result {
+        return Err(Error::BadRequest(
+            ErrorKind::BadJson,
+            "Invalid creation content",
+        ));
+    }
 
     // 1. The room create event
     db.rooms.build_and_append_pdu(
@@ -575,28 +581,36 @@ pub async fn upgrade_room_route(
     // Send a m.room.create event containing a predecessor field and the applicable room_version
     create_event_content.insert(
         "creator".into(),
-        json!(sender_user.clone()).try_into().unwrap(),
+        json!(&sender_user)
+            .try_into()
+            .map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"))?,
     );
     create_event_content.insert(
         "room_version".into(),
-        json!(body.new_version.clone()).try_into().unwrap(),
+        json!(&body.new_version)
+            .try_into()
+            .map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"))?,
+    );
+    create_event_content.insert(
+        "predecessor".into(),
+        json!(predecessor)
+            .try_into()
+            .map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"))?,
     );
-    create_event_content.insert("predecessor".into(), json!(predecessor).try_into().unwrap());
 
     // Validate creation event content
-    match Raw::<CanonicalJsonObject>::from_json(
-        to_raw_value(&create_event_content).expect("Error forming creation event"),
-    )
-    .deserialize_as::<RoomCreateEventContent>()
-    {
-        Ok(_t) => {}
-        Err(_e) => {
-            return Err(Error::BadRequest(
-                ErrorKind::BadJson,
-                "Error forming creation event",
-            ))
-        }
-    };
+    let de_result = serde_json::from_str::<CanonicalJsonObject>(
+        to_raw_value(&create_event_content)
+            .expect("Error forming creation event")
+            .get(),
+    );
+
+    if let Err(_) = de_result {
+        return Err(Error::BadRequest(
+            ErrorKind::BadJson,
+            "Error forming creation event",
+        ));
+    }
 
     db.rooms.build_and_append_pdu(
         PduBuilder {