diff --git a/server/src/server.rs b/server/src/server.rs index 2abe77e..cc5496d 100644 --- a/server/src/server.rs +++ b/server/src/server.rs @@ -5,14 +5,13 @@ use chrono::{DateTime, Utc}; use moka::future::Cache; use sqlx::{FromRow, Pool, query_as, Sqlite}; use sqlx::query; -use sqlx::sqlite::SqliteQueryResult; use tarpc::context::Context; use tracing::error; use realm_auth::types::RealmAuthClient; use realm_shared::types::ErrorCode::*; use realm_shared::types::ErrorCode; -use crate::types::{Message, MessageData, RealmChat, Room, User}; +use crate::types::{Attachment, Edit, Message, MessageData, Reaction, RealmChat, Redaction, Reply, Room, User}; #[derive(Clone)] pub struct RealmChatServer { @@ -65,13 +64,7 @@ impl RealmChatServer { } } } - Some(cached_username) => { - if cached_username.eq(userid) { - true - } else { - false - } - }, + Some(cached_username) => cached_username.eq(userid), } } @@ -97,20 +90,23 @@ impl RealmChat for RealmChatServer { format!("Hello, {name}!") } - async fn send_message(self, _: Context, stoken: String, message: Message) -> Result { - if !self.is_stoken_valid(&message.user.userid, &stoken).await { + async fn send_message(self, ctx: Context, stoken: String, mut message: Message) -> Result { + if !self.is_stoken_valid(&message.user.userid, &stoken).await { // Check sender userid return Err(Unauthorized) } - match &message.data { + // Assert all the data in message is correct + message.user = self.clone().get_user(ctx, message.user.userid).await.unwrap(); + + match &message.data { // Check that the sender is the owner of the referencing msg MessageData::Edit(e) => { - let ref_msg = self.get_message_from_id(tarpc::context::current(), stoken.clone(), e.referencing_id).await?; + let ref_msg = self.clone().get_message_from_id(ctx, stoken.clone(), e.referencing_id).await?; if !ref_msg.user.userid.eq(&message.user.userid) { return Err(Unauthorized) } } MessageData::Redaction(r)=> { - let ref_msg = self.get_message_from_id(tarpc::context::current(), stoken.clone(), r.referencing_id).await?; + let ref_msg = self.clone().get_message_from_id(ctx, stoken.clone(), r.referencing_id).await?; if !ref_msg.user.userid.eq(&message.user.userid) { return Err(Unauthorized) } @@ -119,7 +115,8 @@ impl RealmChat for RealmChatServer { } let is_admin = self.is_user_admin(&stoken).await; - let admin_only_send = query!("SELECT admin_only_send FROM room WHERE roomid = ?", + let admin_only_send = query!( + "SELECT admin_only_send FROM room WHERE roomid = ?", message.room.roomid).fetch_one(&self.db_pool).await; if let Ok(record) = admin_only_send { if record.admin_only_send && !is_admin { @@ -129,6 +126,8 @@ impl RealmChat for RealmChatServer { return Err(RoomNotFound) } + message.room = self.clone().get_room(ctx, stoken.clone(), message.room.roomid).await.unwrap(); + let result = match &message.data { MessageData::Text(text) => { query!("INSERT INTO message (timestamp, user, room, msg_type, msg_text) VALUES (?, ?, ?, 'text', ?)", @@ -205,6 +204,32 @@ impl RealmChat for RealmChatServer { todo!() } + async fn get_all_direct_replies(self, _: Context, stoken: String, head: i64) -> Result, ErrorCode> { + let mut messages: Vec = Vec::new(); + + let is_admin = self.is_user_admin(&stoken).await; + let result = sqlx::query("SELECT message.*, + room.id AS 'room_id', room.roomid AS 'room_roomid', room.name AS 'room_name', room.admin_only_send AS 'room_admin_only_send', room.admin_only_view AS 'room_admin_only_view', + user.id AS 'user_id', user.userid AS 'user_userid', user.name AS 'user_name', user.online AS 'user_online', user.admin AS 'user_admin' + FROM message INNER JOIN room ON message.room = room.id INNER JOIN user ON message.user = user.id WHERE message.referencing_id = ? AND room.admin_only_view = ? OR false") + .bind(head) + .bind(is_admin) + .fetch_all(&self.db_pool).await; + + match result { + Ok(rows) => { + for row in rows { + messages.push(Message::from_row(&row).unwrap()) + } + }, + Err(_) => { + return Err(MessageNotFound) + }, + } + + Ok(messages) + } + async fn get_rooms(self, _: Context, stoken: String) -> Result, ErrorCode> { let is_admin = self.is_user_admin(&stoken).await; let result = query_as!( diff --git a/server/src/types.rs b/server/src/types.rs index 690e91e..a1c67c0 100644 --- a/server/src/types.rs +++ b/server/src/types.rs @@ -20,6 +20,7 @@ pub trait RealmChat { //NOTE: Any user can call, if they are in the server async fn get_message_from_id(stoken: String, id: i64) -> Result; async fn get_messages_since(stoken: String, time: DateTime) -> Result, ErrorCode>; + async fn get_all_direct_replies(stoken: String, head: i64) -> Result, ErrorCode>; async fn get_rooms(stoken: String) -> Result, ErrorCode>; async fn get_room(stoken: String, roomid: String) -> Result; async fn get_user(userid: String) -> Result; @@ -89,7 +90,7 @@ impl FromRow<'_, SqliteRow> for Message { } //TODO: Maybe have multipart messages -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub enum MessageData { Text(String), Attachment(Attachment), @@ -99,35 +100,35 @@ pub enum MessageData { Redaction(Redaction), //NOTE: Have to be the owner of the referencing_guid } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct Attachment { //TODO } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct Reply { pub referencing_id: i64, pub text: String, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct Edit { pub referencing_id: i64, pub text: String, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct Reaction { pub referencing_id: i64, pub emoji: String } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct Redaction { pub referencing_id: i64, } -#[derive(Debug, Clone, Serialize, Deserialize, FromRow)] +#[derive(Debug, Clone, Serialize, Deserialize, FromRow, PartialEq)] pub struct User { pub id: i64, pub userid: String, @@ -136,7 +137,7 @@ pub struct User { pub admin: bool, } -#[derive(Debug, Clone, Serialize, Deserialize, FromRow)] +#[derive(Debug, Clone, Serialize, Deserialize, FromRow, PartialEq)] pub struct Room { pub id: i64, pub roomid: String,