conduit/src/client_server/message.rs

176 lines
5.6 KiB
Rust
Raw Normal View History

2021-07-14 07:07:08 +00:00
use crate::{database::DatabaseGuard, pdu::PduBuilder, utils, ConduitResult, Error, Ruma};
use ruma::{
api::client::{
error::ErrorKind,
r0::message::{get_message_events, send_message_event},
},
2021-04-22 09:26:20 +00:00
events::EventType,
2020-08-25 11:24:38 +00:00
EventId,
2020-07-30 16:14:47 +00:00
};
use std::{
collections::BTreeMap,
convert::{TryFrom, TryInto},
};
2020-07-30 16:14:47 +00:00
#[cfg(feature = "conduit_bin")]
use rocket::{get, put};
#[cfg_attr(
feature = "conduit_bin",
put("/_matrix/client/r0/rooms/<_>/send/<_>/<_>", data = "<body>")
)]
2021-02-28 11:41:03 +00:00
#[tracing::instrument(skip(db, body))]
2020-09-14 18:23:19 +00:00
pub async fn send_message_event_route(
2021-07-14 07:07:08 +00:00
db: DatabaseGuard,
2020-09-08 15:32:03 +00:00
body: Ruma<send_message_event::Request<'_>>,
2020-08-12 21:32:39 +00:00
) -> ConduitResult<send_message_event::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
let sender_device = body.sender_device.as_deref();
2020-08-25 11:24:38 +00:00
// Check if this is a new transaction id
if let Some(response) =
db.transaction_ids
.existing_txnid(sender_user, sender_device, &body.txn_id)?
2020-08-25 11:24:38 +00:00
{
// The client might have sent a txnid of the /sendToDevice endpoint
// This txnid has no response associated with it
if response.is_empty() {
return Err(Error::BadRequest(
ErrorKind::InvalidParam,
"Tried to use txn id already used for an incompatible endpoint.",
));
}
let event_id = EventId::try_from(
utils::string_from_bytes(&response)
.map_err(|_| Error::bad_database("Invalid txnid bytes in database."))?,
)
.map_err(|_| Error::bad_database("Invalid event id in txnid data."))?;
return Ok(send_message_event::Response { event_id }.into());
}
2020-07-30 16:14:47 +00:00
let mut unsigned = BTreeMap::new();
2020-07-30 16:14:47 +00:00
unsigned.insert("transaction_id".to_owned(), body.txn_id.clone().into());
2020-10-05 20:19:22 +00:00
let event_id = db.rooms.build_and_append_pdu(
PduBuilder {
2021-04-22 09:26:20 +00:00
event_type: EventType::from(&body.event_type),
content: serde_json::from_str(body.body.body.json().get())
.map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Invalid JSON body."))?,
2020-10-05 20:19:22 +00:00
unsigned: Some(unsigned),
state_key: None,
redacts: None,
},
&sender_user,
2020-10-05 20:19:22 +00:00
&body.room_id,
2021-01-15 16:05:57 +00:00
&db,
2020-10-05 20:19:22 +00:00
)?;
2020-07-30 16:14:47 +00:00
db.transaction_ids.add_txnid(
sender_user,
sender_device,
&body.txn_id,
event_id.as_bytes(),
)?;
db.flush().await?;
Ok(send_message_event::Response::new(event_id).into())
2020-07-30 16:14:47 +00:00
}
#[cfg_attr(
feature = "conduit_bin",
get("/_matrix/client/r0/rooms/<_>/messages", data = "<body>")
)]
2021-02-28 11:41:03 +00:00
#[tracing::instrument(skip(db, body))]
pub async fn get_message_events_route(
2021-07-14 07:07:08 +00:00
db: DatabaseGuard,
2020-09-08 15:32:03 +00:00
body: Ruma<get_message_events::Request<'_>>,
2020-07-30 16:14:47 +00:00
) -> ConduitResult<get_message_events::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
2020-07-30 16:14:47 +00:00
if !db.rooms.is_joined(sender_user, &body.room_id)? {
2020-07-30 16:14:47 +00:00
return Err(Error::BadRequest(
ErrorKind::Forbidden,
"You don't have permission to view this room.",
));
}
let from = body
.from
.clone()
.parse()
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid `from` value."))?;
let to = body.to.as_ref().map(|t| t.parse());
// Use limit or else 10
let limit = body
.limit
.try_into()
.map_or(Ok::<_, Error>(10_usize), |l: u32| Ok(l as usize))?;
match body.dir {
get_message_events::Direction::Forward => {
let events_after = db
.rooms
.pdus_after(&sender_user, &body.room_id, from)
2020-07-30 16:14:47 +00:00
.take(limit)
.filter_map(|r| r.ok()) // Filter out buggy events
.filter_map(|(pdu_id, pdu)| {
db.rooms
.pdu_count(&pdu_id)
.map(|pdu_count| (pdu_count, pdu))
.ok()
})
2020-07-30 16:14:47 +00:00
.take_while(|&(k, _)| Some(Ok(k)) != to) // Stop at `to`
.collect::<Vec<_>>();
let end_token = events_after.last().map(|(count, _)| count.to_string());
let events_after = events_after
.into_iter()
.map(|(_, pdu)| pdu.to_room_event())
.collect::<Vec<_>>();
let mut resp = get_message_events::Response::new();
2020-09-08 15:32:03 +00:00
resp.start = Some(body.from.to_owned());
resp.end = end_token;
resp.chunk = events_after;
resp.state = Vec::new();
Ok(resp.into())
2020-07-30 16:14:47 +00:00
}
get_message_events::Direction::Backward => {
let events_before = db
.rooms
.pdus_until(&sender_user, &body.room_id, from)
2020-07-30 16:14:47 +00:00
.take(limit)
.filter_map(|r| r.ok()) // Filter out buggy events
.filter_map(|(pdu_id, pdu)| {
db.rooms
.pdu_count(&pdu_id)
.map(|pdu_count| (pdu_count, pdu))
.ok()
})
2020-07-30 16:14:47 +00:00
.take_while(|&(k, _)| Some(Ok(k)) != to) // Stop at `to`
.collect::<Vec<_>>();
let start_token = events_before.last().map(|(count, _)| count.to_string());
let events_before = events_before
.into_iter()
.map(|(_, pdu)| pdu.to_room_event())
.collect::<Vec<_>>();
let mut resp = get_message_events::Response::new();
2020-09-08 15:32:03 +00:00
resp.start = Some(body.from.to_owned());
resp.end = start_token;
resp.chunk = events_before;
resp.state = Vec::new();
Ok(resp.into())
2020-07-30 16:14:47 +00:00
}
}
}