diff --git a/auth/src/main.rs b/auth/src/main.rs index 80a43a5..97c718e 100644 --- a/auth/src/main.rs +++ b/auth/src/main.rs @@ -57,7 +57,7 @@ async fn main() -> anyhow::Result<()> { migrate!().run(&db_pool).await?; // TODO: Do in Docker with Sqlx-cli info!("Migrations complete!"); - let server_addr = (IpAddr::V6(Ipv6Addr::LOCALHOST), env::var("PORT").expect("PORT must be set").parse::().unwrap()); + let server_addr = (IpAddr::V4("0.0.0.0".parse()?), env::var("PORT").expect("PORT must be set").parse::().unwrap()); // JSON transport is provided by the json_transport tarpc module. It makes it easy // to start up a serde-powered json serialization strategy over TCP. diff --git a/client/src/app.rs b/client/src/app.rs index 318594a..75e4fba 100644 --- a/client/src/app.rs +++ b/client/src/app.rs @@ -1,10 +1,11 @@ +use tarpc::client::RpcError; use tarpc::context; use tarpc::tokio_serde::formats::Json; use tokio::sync::broadcast; use tokio::sync::broadcast::{Receiver, Sender}; use tracing::log::*; use realm_auth::types::RealmAuthClient; -use realm_server::types::{RealmChatClient, User}; +use realm_server::types::{RealmChatClient, Room, User}; use realm_shared::stoken; use realm_shared::types::ErrorCode::*; use realm_shared::types::ErrorCode; @@ -15,9 +16,6 @@ use crate::ui::gui; #[derive(serde::Deserialize, serde::Serialize)] #[serde(default)] // if we add new fields, give them default values when deserializing old state pub struct RealmApp { - // Example stuff: - pub label: String, - pub selected: bool, #[serde(skip)] pub selected_serverid: String, #[serde(skip)] @@ -58,6 +56,15 @@ pub struct RealmApp { pub server_window_domain: String, #[serde(skip)] pub server_window_port: String, + + #[serde(skip)] + pub room_window_open: bool, + #[serde(skip)] + pub room_window_name: String, + #[serde(skip)] + pub room_window_admin_only_send: bool, + #[serde(skip)] + pub room_window_admin_only_view: bool, #[serde(skip)] pub login_start_channel: (Sender>, Receiver>), @@ -74,14 +81,16 @@ pub struct RealmApp { #[serde(skip)] pub fetching_servers_channel: (Sender>, Receiver>), + + #[serde(skip)] + pub add_room_channel: (Sender>, Receiver>), + #[serde(skip)] + pub room_changes_channel: (Sender), ErrorCode>>, Receiver), ErrorCode>>) } impl Default for RealmApp { fn default() -> Self { Self { - // Example stuff: - label: "Hello World!".to_owned(), - selected: false, selected_serverid: String::new(), selected_roomid: String::new(), current_user: None, @@ -105,11 +114,18 @@ impl Default for RealmApp { server_window_open: false, server_window_domain: String::new(), server_window_port: "5051".to_string(), + + room_window_open: false, + room_window_name: String::new(), + room_window_admin_only_send: false, + room_window_admin_only_view: false, fetching_user_data_channel: broadcast::channel(10), add_server_channel: broadcast::channel(10), join_server_channel: broadcast::channel(10), fetching_servers_channel: broadcast::channel(10), + add_room_channel: broadcast::channel(10), + room_changes_channel: broadcast::channel(10), } } } @@ -171,9 +187,11 @@ pub fn fetch_user_data(send_channel: Sender>, server_ad }); } -pub fn fetch_server_data(addresses: Vec, channel: Sender>) { +pub fn fetch_server_data(channel: Sender>, addresses: Vec, token: String, username: String) { for server_address in addresses { let send_channel = channel.clone(); + let token = token.clone(); + let userid = username.clone(); let _handle = tokio::spawn(async move { let mut transport = tarpc::serde_transport::tcp::connect(&server_address, Json::default); @@ -190,19 +208,46 @@ pub fn fetch_server_data(addresses: Vec, channel: Sender>()[0].to_string(); + let port = server_address.split(':').collect::>()[1].to_string().parse::().unwrap(); + let stoken = stoken(&token, &info.server_id, &domain, port); + let is_admin = client.is_user_admin(context::current(), userid.clone()).await.unwrap(); + let is_owner = client.is_user_owner(context::current(), userid.clone()).await.unwrap(); + let rooms = client.get_rooms(context::current(), stoken.clone(), userid.clone()).await.unwrap().unwrap(); send_channel.send(Ok(CServer { + tarpc_conn: client, server_id: info.server_id, - domain: server_address.split(':').collect::>()[0].to_string(), - port: server_address.split(':').collect::>()[1].to_string().parse::().unwrap(), + domain, + port, is_admin, is_owner, + rooms, })).unwrap(); }); } } +pub fn fetch_rooms_data(send_channel: Sender), ErrorCode>>, server: CServer, token: String, userid: String) { + let _handle = tokio::spawn(async move { + let result = server.tarpc_conn.get_rooms( + context::current(), + stoken(&token, &server.server_id, &server.domain, server.port), + userid + ).await; + + match result { + Ok(r) => { + if let Ok(rooms) = r { + send_channel.send(Ok((server, rooms))).unwrap(); + } else { + send_channel.send(Err(r.unwrap_err())).unwrap(); + } + } + Err(_) => { send_channel.send(Err(RPCError)).unwrap(); } + } + }); +} + impl eframe::App for RealmApp { /// Called each time the UI needs repainting, which may be many times per second. fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { @@ -225,7 +270,12 @@ impl eframe::App for RealmApp { // Fetching servers if self.active_servers.is_none() && self.current_user.is_some() { self.active_servers = Some(Vec::new()); - fetch_server_data(self.current_user.clone().unwrap().server_addresses.clone(), self.fetching_servers_channel.0.clone()); + fetch_server_data( + self.fetching_servers_channel.0.clone(), + self.current_user.as_ref().unwrap().server_addresses.clone(), + self.current_user.as_ref().unwrap().token.clone(), + self.current_user.as_ref().unwrap().username.clone() + ); } // Starting the login flow @@ -309,10 +359,17 @@ impl eframe::App for RealmApp { let result = client.join_server(context::current(), stoken(&thread_token, &info.server_id, &domain, port), thread_username).await; match result { - Ok(_) => { + Ok(r) => { info!("Joined server!"); + match r { + Ok(_) => { send_channel.send(Ok(())).unwrap(); }, + Err(e) => { send_channel.send(Err(e)).unwrap(); }, + } + }, + Err(_) => { + error!("Error joining server"); + send_channel.send(Err(RPCError)).unwrap(); }, - Err(e) => error!("Error joining server: {:?}", e), } }); @@ -327,7 +384,12 @@ impl eframe::App for RealmApp { match result { Ok(_) => { info!("Successfully joined a server"); - fetch_server_data(self.current_user.clone().unwrap().server_addresses.clone(), self.fetching_servers_channel.0.clone()); + fetch_server_data( + self.fetching_servers_channel.0.clone(), + self.current_user.as_ref().unwrap().server_addresses.clone(), + self.current_user.as_ref().unwrap().token.clone(), + self.current_user.as_ref().unwrap().username.clone() + ); }, Err(code) => { error!("Error joining server: {:?}", code); @@ -347,6 +409,40 @@ impl eframe::App for RealmApp { Err(e) => error!("Error fetching server data: {:?}", e), } } + + // Added Room + while let Ok(result) = self.add_room_channel.1.try_recv() { + match result { + Ok(server) => { + info!("Got room add! Fetching them..."); + fetch_rooms_data( + self.room_changes_channel.0.clone(), + server, + self.current_user.as_ref().unwrap().token.clone(), + self.current_user.as_ref().unwrap().username.clone() + ); + self.room_window_open = false; + } + Err(e) => error!("Error adding room: {:?}", e), + } + } + + // Fetching rooms + while let Ok(result) = self.room_changes_channel.1.try_recv() { + match result { + Ok(tuple) => { + info!("Got room data for a server: {:?}", tuple); + if let Some(servers) = &mut self.active_servers { + for server in servers { + if server.server_id.eq(&tuple.0.server_id) { + server.rooms = tuple.1.clone(); + } + } + } + } + Err(e) => error!("Error fetching room data: {:?}", e), + } + } // File -> Quit gui::top_panel(self, ctx); diff --git a/client/src/types.rs b/client/src/types.rs index 6da2e26..68316f3 100644 --- a/client/src/types.rs +++ b/client/src/types.rs @@ -1,3 +1,5 @@ +use realm_server::types::{RealmChatClient, Room}; + #[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] pub struct CUser { pub id: i64, @@ -9,11 +11,13 @@ pub struct CUser { pub token: String, } -#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)] +#[derive(Clone, Debug)] pub struct CServer { + pub tarpc_conn: RealmChatClient, pub server_id: String, pub domain: String, pub port: u16, pub is_admin: bool, pub is_owner: bool, + pub rooms: Vec } \ No newline at end of file diff --git a/client/src/ui/gui.rs b/client/src/ui/gui.rs index 799d6d5..7daa653 100644 --- a/client/src/ui/gui.rs +++ b/client/src/ui/gui.rs @@ -5,7 +5,10 @@ use realm_auth::types::RealmAuthClient; use realm_shared::types::ErrorCode::RPCError; use regex::Regex; use tracing::log::*; +use realm_server::types::Room; +use realm_shared::stoken; use crate::app::RealmApp; +use crate::types::CServer; pub fn top_panel(app: &mut RealmApp, ctx: &Context) { egui::TopBottomPanel::top("top_panel").show(ctx, |ui| { @@ -49,6 +52,10 @@ pub fn top_panel(app: &mut RealmApp, ctx: &Context) { app.saved_username = None; app.saved_token = None; app.saved_auth_address = None; + + app.active_servers = None; + app.selected_roomid.clear(); + app.selected_serverid.clear(); } if ui.button("Quit").clicked() { @@ -72,10 +79,6 @@ pub fn servers(app: &mut RealmApp, ctx: &Context) { }); ui.separator(); - if ui.add(SelectableLabel::new(app.selected, "server")).clicked() { - app.selected = !app.selected; - } - if let Some(active_servers) = &mut app.active_servers { for server in active_servers { if ui.add(SelectableLabel::new(server.server_id.eq(&app.selected_serverid), server.server_id.clone())).clicked() { @@ -84,6 +87,7 @@ pub fn servers(app: &mut RealmApp, ctx: &Context) { } else { app.selected_serverid = server.server_id.clone(); } + app.selected_roomid.clear(); } } } @@ -92,32 +96,43 @@ pub fn servers(app: &mut RealmApp, ctx: &Context) { pub fn rooms(app: &mut RealmApp, ctx: &Context) { egui::SidePanel::left("rooms").show(ctx, |ui| { - ui.heading("Rooms"); + let mut current_server: Option<&CServer> = None; + if let Some(servers) = &app.active_servers { + for server in servers { + if server.server_id.eq(&app.selected_serverid) { + current_server = Some(server); + } + } + } + + ui.horizontal(|ui| { + ui.heading("Rooms"); + if let Some(server) = current_server { + if server.is_admin && ui.button("+").clicked() { + app.room_window_open = true; + } + } + }); + ui.separator(); - if ui.add(SelectableLabel::new(app.selected, "room")).clicked() { - app.selected = !app.selected; + + if let Some(server) = current_server { + for room in &server.rooms { + if ui.add(SelectableLabel::new(room.roomid.eq(&app.selected_roomid), room.roomid.clone())).clicked() { + if app.selected_roomid.eq(&room.roomid) { + app.selected_roomid.clear(); + } else { + app.selected_roomid = room.roomid.clone(); + } + } + } } }); } pub fn messages(app: &mut RealmApp, ctx: &Context) { egui::CentralPanel::default().show(ctx, |ui| { - // The central panel the region left after adding TopPanel's and SidePanel's - ui.heading("eframe template"); - - ui.horizontal(|ui| { - ui.label("Write something: "); - ui.text_edit_singleline(&mut app.label); - }); - - ui.add(egui::Slider::new(&mut app.value, 0.0..=10.0).text("value")); - if ui.button("Increment").clicked() { - app.value += 1.0; - } - - ui.separator(); - ui.label(format!("Saved username: {:?}", app.saved_username)); ui.label(format!("Saved token: {:?}", app.saved_token)); ui.label(format!("Saved auth address: {:?}", app.saved_auth_address)); @@ -126,12 +141,13 @@ pub fn messages(app: &mut RealmApp, ctx: &Context) { if let Some(servers) = &app.active_servers { for server in servers { - ui.label(format!("Active server: {:?}", server)); + ui.heading(&server.server_id); + ui.label(format!("{:?}", server)); } } - + ui.separator(); - + ui.label(format!("Current user: {:?}", app.current_user)); }); } @@ -339,4 +355,55 @@ pub fn modals(app: &mut RealmApp, ctx: &Context) { }); } }); + + egui::Window::new("Add Room") + .open(&mut app.room_window_open) + .min_size((500.0, 200.0)) + .show(ctx, |ui| { + ui.horizontal(|ui| { + ui.label("Name: "); + ui.text_edit_singleline(&mut app.room_window_name); + }); + + ui.checkbox(&mut app.room_window_admin_only_send, "Only admins can send"); + ui.checkbox(&mut app.room_window_admin_only_view, "Only admins can view"); + + if ui.button("Add Room").clicked() { + for server in app.active_servers.clone().unwrap() { + if server.server_id.eq(&app.selected_serverid) { + let token = app.current_user.as_ref().unwrap().token.clone(); + let roomid = app.room_window_name.clone(); + let admin_only_send = app.room_window_admin_only_send; + let admin_only_view = app.room_window_admin_only_view; + let userid = app.current_user.as_ref().unwrap().username.clone(); + let send_channel = app.add_room_channel.0.clone(); + let _handle = tokio::spawn(async move { + let result = server.tarpc_conn.create_room( + context::current(), + stoken(&token, &server.server_id, &server.domain, server.port), + userid, + Room { + id: 0, + roomid, + admin_only_send, + admin_only_view, + } + ).await; + + match result { + Ok(r) => { + match r { + Ok(_) => { send_channel.send(Ok(server)).unwrap(); } + Err(e) => { send_channel.send(Err(e)).unwrap(); } + } + } + Err(_) => { + send_channel.send(Err(RPCError)).unwrap(); + } + } + }); + } + } + } + }); } \ No newline at end of file diff --git a/server/Cargo.toml b/server/Cargo.toml index d300ebc..43b260f 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -17,7 +17,6 @@ sqlx = { version = "0.8.2", features = [ "runtime-tokio", "tls-rustls", "sqlite" dotenvy = "0.15.7" moka = { version = "0.12.8", features = ["future"] } futures-util = "0.3.30" -durian = "0.5" realm_auth = { path = "../auth" } realm_shared = { path = "../shared" } diff --git a/server/src/events.rs b/server/src/events.rs index da3bb7f..b39d95e 100644 --- a/server/src/events.rs +++ b/server/src/events.rs @@ -1,64 +1,64 @@ -use durian::bincode_packet; -use crate::types::{Message, Room, User}; - -#[bincode_packet] -pub struct Greet { - pub id: u32 -} - -#[bincode_packet] -pub struct UserJoinedEvent { - pub user: User, -} - -#[bincode_packet] -pub struct UserLeftEvent { - pub user: User, -} - -#[bincode_packet] -pub struct NewMessageEvent { - pub message: Message, -} - +// use durian::bincode_packet; +// use crate::types::{Message, Room, User}; +// // #[bincode_packet] -// pub struct StartTypingEvent { -// pub user: User, -// pub room: String, +// pub struct Greet { +// pub id: u32 // } // // #[bincode_packet] -// pub struct StopTypingEvent { +// pub struct UserJoinedEvent { // pub user: User, -// pub room: String, // } - -#[bincode_packet] -pub struct NewRoomEvent { - pub room: Room, -} - -#[bincode_packet] -pub struct DeleteRoomEvent { - pub roomid: String, -} - -#[bincode_packet] -pub struct KickedUserEvent { - pub userid: String, -} - -#[bincode_packet] -pub struct BannedUserEvent { - pub userid: String, -} - -#[bincode_packet] -pub struct PromotedUserEvent { - pub userid: String, -} - -#[bincode_packet] -pub struct DemotedUserEvent { - pub userid: String, -} \ No newline at end of file +// +// #[bincode_packet] +// pub struct UserLeftEvent { +// pub user: User, +// } +// +// #[bincode_packet] +// pub struct NewMessageEvent { +// pub message: Message, +// } +// +// // #[bincode_packet] +// // pub struct StartTypingEvent { +// // pub user: User, +// // pub room: String, +// // } +// // +// // #[bincode_packet] +// // pub struct StopTypingEvent { +// // pub user: User, +// // pub room: String, +// // } +// +// #[bincode_packet] +// pub struct NewRoomEvent { +// pub room: Room, +// } +// +// #[bincode_packet] +// pub struct DeleteRoomEvent { +// pub roomid: String, +// } +// +// #[bincode_packet] +// pub struct KickedUserEvent { +// pub userid: String, +// } +// +// #[bincode_packet] +// pub struct BannedUserEvent { +// pub userid: String, +// } +// +// #[bincode_packet] +// pub struct PromotedUserEvent { +// pub userid: String, +// } +// +// #[bincode_packet] +// pub struct DemotedUserEvent { +// pub userid: String, +// } \ No newline at end of file diff --git a/server/src/main.rs b/server/src/main.rs index c96158a..5c308c7 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -3,7 +3,6 @@ use std::future::Future; use std::net::{IpAddr, Ipv6Addr, SocketAddr}; use std::sync::{Arc}; use dotenvy::dotenv; -use durian::{PacketManager, ServerConfig}; use futures::future::{self}; use futures::StreamExt; use sqlx::migrate::MigrateDatabase; @@ -18,7 +17,7 @@ use tokio::sync::Mutex; use tracing::{info, subscriber, warn}; use realm_server::events::*; use realm_server::server::RealmChatServer; -use realm_server::types::RealmChat; +use realm_server::types::{RealmChat}; async fn spawn(fut: impl Future + Send + 'static) { tokio::spawn(fut); @@ -57,39 +56,32 @@ async fn main() -> anyhow::Result<()> { info!("Migrations complete!"); let port = env::var("PORT").expect("PORT must be set").parse::()?; - let server_addr = (IpAddr::V6(Ipv6Addr::LOCALHOST), port); + let server_addr = (IpAddr::V4("0.0.0.0".parse()?), port); - let mut inner_manager = PacketManager::new(); - - inner_manager.register_receive_packet::(GreetPacketBuilder)?; - inner_manager.register_receive_packet::(UserJoinedEventPacketBuilder)?; - inner_manager.register_receive_packet::(UserLeftEventPacketBuilder)?; - inner_manager.register_receive_packet::(NewMessageEventPacketBuilder)?; - // inner_manager.register_receive_packet::(StartTypingEventPacketBuilder)?; - // inner_manager.register_receive_packet::(StopTypingEventPacketBuilder)?; - inner_manager.register_receive_packet::(NewRoomEventPacketBuilder)?; - inner_manager.register_receive_packet::(DeleteRoomEventPacketBuilder)?; - inner_manager.register_receive_packet::(KickedUserEventPacketBuilder)?; - inner_manager.register_receive_packet::(BannedUserEventPacketBuilder)?; - - inner_manager.register_send_packet::()?; - inner_manager.register_send_packet::()?; - inner_manager.register_send_packet::()?; - inner_manager.register_send_packet::()?; - // inner_manager.register_send_packet::()?; - // inner_manager.register_send_packet::()?; - inner_manager.register_send_packet::()?; - inner_manager.register_send_packet::()?; - inner_manager.register_send_packet::()?; - inner_manager.register_send_packet::()?; - - inner_manager.init_server( - ServerConfig::new( - SocketAddr::from((IpAddr::V6(Ipv6Addr::LOCALHOST), port-1)).to_string(), - 0, None, 8, 8))?; - - let manager = Arc::new(Mutex::new(inner_manager)); - info!("Listening on port {}", port-1); + // let (handler, listener) = node::split::<()>(); + // handler.network().listen(Transport::FramedTcp, "0.0.0.0:"+(port-1))?; + // info!("Listening on port {}", port-1); + // + // // Read incoming network events. + // listener.for_each(|event| match event.network() { + // NetEvent::Connected(_, _) => unreachable!(), // Used for explicit connections. + // NetEvent::Accepted(_endpoint, _listener) => println!("Client connected"), // Tcp or Ws + // NetEvent::Message(endpoint, data) => { + // println!("Received: {}", String::from_utf8_lossy(data)); + // handler.network().send(endpoint, data); + // }, + // NetEvent::Disconnected(_endpoint) => println!("Client disconnected"), //Tcp or Ws + // }); + // + // inner_manager.init_server( + // ServerConfig::new( + // SocketAddr::from((IpAddr::V4("0.0.0.0".parse()?), port-1)).to_string(), + // 0, None, 8, 8))?; + // + // let manager = Arc::new(Mutex::new(NetIO { + // handler, + // listener, + // })); // JSON transport is provided by the json_transport tarpc module. It makes it easy // to start up a serde-powered json serialization strategy over TCP. @@ -105,7 +97,7 @@ async fn main() -> anyhow::Result<()> { // serve is generated by the service attribute. It takes as input any type implementing // the generated World trait. .map(|channel| { - let server = RealmChatServer::new(env::var("SERVER_ID").expect("SERVER_ID must be set"), channel.transport().peer_addr().unwrap(), db_pool.clone(), manager.clone()); + let server = RealmChatServer::new(env::var("SERVER_ID").expect("SERVER_ID must be set"), channel.transport().peer_addr().unwrap(), db_pool.clone()); channel.execute(server.serve()).for_each(spawn) }) // Max 10 channels. diff --git a/server/src/server.rs b/server/src/server.rs index 5b9f9b8..4141886 100644 --- a/server/src/server.rs +++ b/server/src/server.rs @@ -3,7 +3,6 @@ use std::net::SocketAddr; use std::sync::{Arc}; use std::time::Duration; use chrono::{DateTime, Utc}; -use durian::PacketManager; use moka::future::Cache; use sqlx::{FromRow, Pool, query_as, Sqlite}; use sqlx::query; @@ -26,7 +25,6 @@ pub struct RealmChatServer { pub db_pool: Pool, pub typing_users: Vec<(String, String)>, //NOTE: user.userid, room.roomid pub cache: Cache, - pub packet_manager: Arc>, } const FETCH_MESSAGE: &str = "SELECT message.*, @@ -35,7 +33,7 @@ const FETCH_MESSAGE: &str = "SELECT message.*, FROM message INNER JOIN room ON message.room = room.id INNER JOIN user ON message.user = user.id WHERE room.admin_only_view = ? OR false"; impl RealmChatServer { - pub fn new(server_id: String, socket: SocketAddr, db_pool: Pool, packet_manager: Arc>) -> RealmChatServer { + pub fn new(server_id: String, socket: SocketAddr, db_pool: Pool) -> RealmChatServer { RealmChatServer { server_id, port: env::var("PORT").unwrap().parse::().unwrap(), @@ -48,7 +46,6 @@ impl RealmChatServer { .time_to_idle(Duration::from_secs(5*60)) .time_to_live(Duration::from_secs(60*60)) .build(), - packet_manager, } } @@ -94,36 +91,20 @@ impl RealmChatServer { } } - pub async fn internal_is_user_admin(&self, stoken: &str) -> bool { - if let Some(userid) = self.cache.get(stoken).await { - let result = query!("SELECT admin FROM user WHERE userid = ?", userid).fetch_one(&self.db_pool).await; - return match result { - Ok(record) => { - if record.admin { - return true - } - false - } - Err(_) => false - } + pub async fn internal_is_user_admin(&self, userid: &str) -> bool { + let result = query!("SELECT admin FROM user WHERE userid = ?", userid).fetch_one(&self.db_pool).await; + match result { + Ok(record) => record.admin, + Err(_) => false } - false } - pub async fn internal_is_user_owner(&self, stoken: &str) -> bool { - if let Some(userid) = self.cache.get(stoken).await { - let result = query!("SELECT owner FROM user WHERE userid = ?", userid).fetch_one(&self.db_pool).await; - return match result { - Ok(record) => { - if record.owner { - return true - } - false - } - Err(_) => false - } + pub async fn internal_is_user_owner(&self, userid: &str) -> bool { + let result = query!("SELECT owner FROM user WHERE userid = ?", userid).fetch_one(&self.db_pool).await; + match result { + Ok(record) => record.owner, + Err(_) => false } - false } async fn is_user_in_server(&self, userid: &str) -> bool { @@ -135,8 +116,8 @@ impl RealmChatServer { } } - async fn inner_get_all_direct_replies(&self, stoken: &str, head: i64) -> Result, ErrorCode> { - let is_admin = self.internal_is_user_admin(stoken).await; + async fn inner_get_all_direct_replies(&self, userid: &str, head: i64) -> Result, ErrorCode> { + let is_admin = self.internal_is_user_admin(userid).await; let result = sqlx::query(&format!("{}{}", FETCH_MESSAGE, "AND message.referencing_id = ?")) .bind(is_admin) .bind(head) @@ -148,19 +129,19 @@ impl RealmChatServer { } } - async fn inner_get_reply_chain(&self, stoken: &str, head: Message, depth: u8) -> Result { + async fn inner_get_reply_chain(&self, userid: &str, head: Message, depth: u8) -> Result { if depth > 8 { return Err(DepthTooLarge) } - let direct_replies = self.inner_get_all_direct_replies(stoken, head.id).await?; + let direct_replies = self.inner_get_all_direct_replies(userid, head.id).await?; let replies = if direct_replies.is_empty() || depth == 0 { None } else { let mut chains = Vec::new(); for reply in direct_replies { - chains.push(Box::pin(self.inner_get_reply_chain(stoken, reply, depth - 1)).await?); + chains.push(Box::pin(self.inner_get_reply_chain(userid, reply, depth - 1)).await?); } Some(chains) @@ -174,8 +155,8 @@ impl RealmChatServer { Ok(chain) } - async fn inner_get_room(&self, stoken: &str, roomid: &str) -> Result { - let is_admin = self.internal_is_user_admin(&stoken).await; + async fn inner_get_room(&self, userid: &str, roomid: &str) -> Result { + let is_admin = self.internal_is_user_admin(&userid).await; let result = query_as!( Room, "SELECT * FROM room WHERE roomid = ? AND admin_only_view = ? OR false", is_admin, roomid).fetch_one(&self.db_pool).await; @@ -203,8 +184,8 @@ impl RealmChatServer { } } - async fn inner_get_message(&self, stoken: &str, id: i64) -> Result { - let is_admin = self.internal_is_user_admin(&stoken).await; + async fn inner_get_message(&self, userid: &str, id: i64) -> Result { + let is_admin = self.internal_is_user_admin(&userid).await; let result = sqlx::query(&format!("{}{}", FETCH_MESSAGE, "AND message.id = ?")) .bind(is_admin) .bind(id) @@ -228,12 +209,12 @@ impl RealmChat for RealmChatServer { } } - async fn is_user_admin(self, _: Context, stoken: String) -> bool { - self.internal_is_user_admin(&stoken).await + async fn is_user_admin(self, _: Context, userid: String) -> bool { + self.internal_is_user_admin(&userid).await } - async fn is_user_owner(self, _: Context, stoken: String) -> bool { - self.internal_is_user_owner(&stoken).await + async fn is_user_owner(self, _: Context, userid: String) -> bool { + self.internal_is_user_owner(&userid).await } async fn join_server(self, _: Context, stoken: String, userid: String) -> Result { @@ -258,12 +239,12 @@ impl RealmChat for RealmChatServer { Ok(_) => { let new_user = self.inner_get_user(&userid).await?; - let result = self.packet_manager.lock().await.broadcast(UserJoinedEvent { - user: new_user.clone(), - }); - if result.is_err() { - error!("Error broadcasting UserJoinedEvent!"); - } + // let result = self.packet_manager.lock().await.broadcast(UserJoinedEvent { + // user: new_user.clone(), + // }); + // if result.is_err() { + // error!("Error broadcasting UserJoinedEvent!"); + // } Ok(new_user) }, @@ -286,13 +267,13 @@ impl RealmChat for RealmChatServer { match result { Ok(_) => { - let result = self.packet_manager.lock().await.broadcast(UserLeftEvent { - user, - }); - - if result.is_err() { - error!("Error broadcasting UserLeftEvent!"); - } + // let result = self.packet_manager.lock().await.broadcast(UserLeftEvent { + // user, + // }); + // + // if result.is_err() { + // error!("Error broadcasting UserLeftEvent!"); + // } Ok(()) }, @@ -310,21 +291,21 @@ impl RealmChat for RealmChatServer { match &message.data { // Check that the sender is the owner of the referencing msg MessageData::Edit(e) => { - let ref_msg = self.inner_get_message(&stoken, e.referencing_id).await?; + let ref_msg = self.inner_get_message(&message.user.userid, e.referencing_id).await?; if !ref_msg.user.userid.eq(&message.user.userid) { return Err(Unauthorized) } } MessageData::Redaction(r)=> { - let ref_msg = self.inner_get_message(&stoken, r.referencing_id).await?; - if !ref_msg.user.userid.eq(&message.user.userid) || !self.internal_is_user_admin(&stoken).await { + let ref_msg = self.inner_get_message(&message.user.userid, r.referencing_id).await?; + if !ref_msg.user.userid.eq(&message.user.userid) || !self.internal_is_user_admin(&message.user.userid).await { return Err(Unauthorized) } } _ => {} } - let is_admin = self.internal_is_user_admin(&stoken).await; + let is_admin = self.internal_is_user_admin(&message.user.userid).await; let admin_only_send = query!( "SELECT admin_only_send FROM room WHERE roomid = ?", message.room.roomid).fetch_one(&self.db_pool).await; @@ -336,7 +317,7 @@ impl RealmChat for RealmChatServer { return Err(RoomNotFound) } - message.room = self.inner_get_room(&stoken, &message.room.roomid).await?; + message.room = self.inner_get_room(&message.user.userid, &message.room.roomid).await?; let result = match &message.data { MessageData::Text(text) => { @@ -369,13 +350,13 @@ impl RealmChat for RealmChatServer { match result { Ok(_) => { - let result = self.packet_manager.lock().await.broadcast(NewMessageEvent { - message: message.clone(), - }); - - if result.is_err() { - error!("Error broadcasting NewMessageEvent!"); - } + // let result = self.packet_manager.lock().await.broadcast(NewMessageEvent { + // message: message.clone(), + // }); + // + // if result.is_err() { + // error!("Error broadcasting NewMessageEvent!"); + // } Ok(message) }, @@ -395,8 +376,12 @@ impl RealmChat for RealmChatServer { todo!() } - async fn get_message(self, _: Context, stoken: String, id: i64) -> Result { - let is_admin = self.internal_is_user_admin(&stoken).await; + async fn get_message(self, _: Context, stoken: String, userid: String, id: i64) -> Result { + if !self.is_stoken_valid(&userid, &stoken).await { + return Err(Unauthorized) + } + + let is_admin = self.internal_is_user_admin(&userid).await; let result = sqlx::query(&format!("{}{}", FETCH_MESSAGE, "AND message.id = ?")) .bind(is_admin) .bind(id) @@ -412,8 +397,12 @@ impl RealmChat for RealmChatServer { } } - async fn get_messages_since(self, _: Context, stoken: String, time: DateTime) -> Result, ErrorCode> { - let is_admin = self.internal_is_user_admin(&stoken).await; + async fn get_messages_since(self, _: Context, stoken: String, userid: String, time: DateTime) -> Result, ErrorCode> { + if !self.is_stoken_valid(&userid, &stoken).await { + return Err(Unauthorized) + } + + let is_admin = self.internal_is_user_admin(&userid).await; let result = sqlx::query(&format!("{}{}", FETCH_MESSAGE, "AND message.timestamp >= ?")) .bind(is_admin) .bind(time) @@ -425,18 +414,30 @@ impl RealmChat for RealmChatServer { } } - async fn get_all_direct_replies(self, _: Context, stoken: String, head: i64) -> Result, ErrorCode> { - self.inner_get_all_direct_replies(&stoken, head).await + async fn get_all_direct_replies(self, _: Context, stoken: String, userid: String, head: i64) -> Result, ErrorCode> { + if !self.is_stoken_valid(&userid, &stoken).await { + return Err(Unauthorized) + } + + self.inner_get_all_direct_replies(&userid, head).await } - async fn get_reply_chain(self, _: Context, stoken: String, head: Message, depth: u8) -> Result { + async fn get_reply_chain(self, _: Context, stoken: String, userid: String, head: Message, depth: u8) -> Result { + if !self.is_stoken_valid(&userid, &stoken).await { + return Err(Unauthorized) + } + self.inner_get_reply_chain(&stoken, head, depth).await } - async fn get_rooms(self, _: Context, stoken: String) -> Result, ErrorCode> { - let is_admin = self.internal_is_user_admin(&stoken).await; + async fn get_rooms(self, _: Context, stoken: String, userid: String) -> Result, ErrorCode> { + if !self.is_stoken_valid(&userid, &stoken).await { + return Err(Unauthorized) + } + + let is_admin = self.internal_is_user_admin(&userid).await; let result = query_as!( - Room, "SELECT * FROM room WHERE admin_only_view = ? OR false", is_admin).fetch_all(&self.db_pool).await; + Room, "SELECT * FROM room WHERE admin_only_view LIKE false or ?", is_admin).fetch_all(&self.db_pool).await; match result { Ok(rooms) => Ok(rooms), @@ -444,8 +445,12 @@ impl RealmChat for RealmChatServer { } } - async fn get_room(self, _: Context, stoken: String, roomid: String) -> Result { - self.inner_get_room(&stoken, &roomid).await + async fn get_room(self, _: Context, stoken: String, userid: String, roomid: String) -> Result { + if !self.is_stoken_valid(&userid, &stoken).await { + return Err(Unauthorized) + } + + self.inner_get_room(&userid, &roomid).await } async fn get_user(self, _: Context, userid: String) -> Result { @@ -456,8 +461,12 @@ impl RealmChat for RealmChatServer { self.inner_get_all_users().await } - async fn create_room(self, _: Context, stoken: String, room: Room) -> Result { - if !self.internal_is_user_admin(&stoken).await { + async fn create_room(self, _: Context, stoken: String, userid: String, room: Room) -> Result { + if !self.is_stoken_valid(&userid, &stoken).await { + return Err(Unauthorized) + } + + if !self.internal_is_user_admin(&userid).await { return Err(Unauthorized) } @@ -467,13 +476,13 @@ impl RealmChat for RealmChatServer { match result { Ok(_) => { - let result = self.packet_manager.lock().await.broadcast(NewRoomEvent { - room: room.clone(), - }); - - if result.is_err() { - error!("Error broadcasting NewRoomEvent!"); - } + // let result = self.packet_manager.lock().await.broadcast(NewRoomEvent { + // room: room.clone(), + // }); + // + // if result.is_err() { + // error!("Error broadcasting NewRoomEvent!"); + // } Ok(room) } @@ -481,8 +490,12 @@ impl RealmChat for RealmChatServer { } } - async fn delete_room(self, _: Context, stoken: String, roomid: String) -> Result<(), ErrorCode> { - if !self.internal_is_user_admin(&stoken).await { + async fn delete_room(self, _: Context, stoken: String, userid: String, roomid: String) -> Result<(), ErrorCode> { + if !self.is_stoken_valid(&userid, &stoken).await { + return Err(Unauthorized) + } + + if !self.internal_is_user_admin(&userid).await { return Err(Unauthorized) } @@ -490,13 +503,13 @@ impl RealmChat for RealmChatServer { match result { Ok(_) => { - let result = self.packet_manager.lock().await.broadcast(DeleteRoomEvent { - roomid, - }); - - if result.is_err() { - error!("Error broadcasting DeleteRoomEvent!"); - } + // let result = self.packet_manager.lock().await.broadcast(DeleteRoomEvent { + // roomid, + // }); + // + // if result.is_err() { + // error!("Error broadcasting DeleteRoomEvent!"); + // } Ok(()) } @@ -504,8 +517,12 @@ impl RealmChat for RealmChatServer { } } - async fn promote_user(self, _: Context, stoken: String, userid: String) -> Result<(), ErrorCode> { - if !self.internal_is_user_owner(&stoken).await { + async fn promote_user(self, _: Context, stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode> { + if !self.is_stoken_valid(&admin_userid, &stoken).await { + return Err(Unauthorized) + } + + if !self.internal_is_user_owner(&admin_userid).await { return Err(Unauthorized) } @@ -513,13 +530,13 @@ impl RealmChat for RealmChatServer { match result { Ok(_) => { - let result = self.packet_manager.lock().await.broadcast(PromotedUserEvent { - userid, - }); - - if result.is_err() { - error!("Error broadcasting PromotedUserEvent!"); - } + // let result = self.packet_manager.lock().await.broadcast(PromotedUserEvent { + // userid, + // }); + // + // if result.is_err() { + // error!("Error broadcasting PromotedUserEvent!"); + // } Ok(()) } @@ -527,8 +544,12 @@ impl RealmChat for RealmChatServer { } } - async fn demote_user(self, _: Context, stoken: String, userid: String) -> Result<(), ErrorCode> { - if !self.internal_is_user_owner(&stoken).await { + async fn demote_user(self, _: Context, stoken: String, owner_userid: String, userid: String) -> Result<(), ErrorCode> { + if !self.is_stoken_valid(&owner_userid, &stoken).await { + return Err(Unauthorized) + } + + if !self.internal_is_user_owner(&owner_userid).await { return Err(Unauthorized) } @@ -536,13 +557,13 @@ impl RealmChat for RealmChatServer { match result { Ok(_) => { - let result = self.packet_manager.lock().await.broadcast(DemotedUserEvent { - userid, - }); - - if result.is_err() { - error!("Error broadcasting DemotedUserEvent!"); - } + // let result = self.packet_manager.lock().await.broadcast(DemotedUserEvent { + // userid, + // }); + // + // if result.is_err() { + // error!("Error broadcasting DemotedUserEvent!"); + // } Ok(()) } @@ -550,8 +571,12 @@ impl RealmChat for RealmChatServer { } } - async fn kick_user(self, _: Context, stoken: String, userid: String) -> Result<(), ErrorCode> { - if !self.internal_is_user_admin(&stoken).await { + async fn kick_user(self, _: Context, stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode> { + if !self.is_stoken_valid(&admin_userid, &stoken).await { + return Err(Unauthorized) + } + + if !self.internal_is_user_admin(&admin_userid).await { return Err(Unauthorized) } @@ -559,13 +584,13 @@ impl RealmChat for RealmChatServer { match result { Ok(_) => { - let result = self.packet_manager.lock().await.broadcast(KickedUserEvent { - userid, - }); - - if result.is_err() { - error!("Error broadcasting KickedUserEvent!"); - } + // let result = self.packet_manager.lock().await.broadcast(KickedUserEvent { + // userid, + // }); + // + // if result.is_err() { + // error!("Error broadcasting KickedUserEvent!"); + // } Ok(()) } @@ -573,8 +598,12 @@ impl RealmChat for RealmChatServer { } } - async fn ban_user(self, _: Context, stoken: String, userid: String) -> Result<(), ErrorCode> { - if !self.internal_is_user_admin(&stoken).await { + async fn ban_user(self, _: Context, stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode> { + if !self.is_stoken_valid(&admin_userid, &stoken).await { + return Err(Unauthorized) + } + + if !self.internal_is_user_admin(&admin_userid).await { return Err(Unauthorized) } @@ -583,13 +612,13 @@ impl RealmChat for RealmChatServer { match result { Ok(_) => { - let result = self.packet_manager.lock().await.broadcast(BannedUserEvent { - userid, - }); - - if result.is_err() { - error!("Error broadcasting BannedUserEvent!"); - } + // let result = self.packet_manager.lock().await.broadcast(BannedUserEvent { + // userid, + // }); + // + // if result.is_err() { + // error!("Error broadcasting BannedUserEvent!"); + // } Ok(()) } @@ -597,8 +626,8 @@ impl RealmChat for RealmChatServer { } } - async fn pardon_user(self, _: Context, stoken: String, userid: String) -> Result<(), ErrorCode> { - if !self.internal_is_user_admin(&stoken).await { + async fn pardon_user(self, _: Context, stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode> { + if !self.internal_is_user_admin(&admin_userid).await { return Err(Unauthorized) } diff --git a/server/src/types.rs b/server/src/types.rs index 5efcec2..4cd9e01 100644 --- a/server/src/types.rs +++ b/server/src/types.rs @@ -25,21 +25,21 @@ pub trait RealmChat { async fn keep_typing(stoken: String, userid: String, roomid: String) -> ErrorCode; //NOTE: If a keep alive hasn't been received in 5 seconds, stop typing //NOTE: Any user can call, if they are in the server - async fn get_message(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_reply_chain(stoken: String, head: Message, depth: u8) -> Result; - async fn get_rooms(stoken: String) -> Result, ErrorCode>; - async fn get_room(stoken: String, roomid: String) -> Result; + async fn get_message(stoken: String, userid: String, id: i64) -> Result; + async fn get_messages_since(stoken: String, userid: String, time: DateTime) -> Result, ErrorCode>; + async fn get_all_direct_replies(stoken: String, userid: String, head: i64) -> Result, ErrorCode>; + async fn get_reply_chain(stoken: String, userid: String, head: Message, depth: u8) -> Result; + async fn get_rooms(stoken: String, userid: String) -> Result, ErrorCode>; + async fn get_room(stoken: String, userid: String, roomid: String) -> Result; async fn get_user(userid: String) -> Result; async fn get_users() -> Result, ErrorCode>; - async fn create_room(stoken: String, room: Room) -> Result; - async fn delete_room(stoken: String, roomid: String) -> Result<(), ErrorCode>; - async fn promote_user(stoken: String, userid: String) -> Result<(), ErrorCode>; - async fn demote_user(stoken: String, userid: String) -> Result<(), ErrorCode>; - async fn kick_user(stoken: String, userid: String) -> Result<(), ErrorCode>; - async fn ban_user(stoken: String, userid: String) -> Result<(), ErrorCode>; - async fn pardon_user(stoken: String, userid: String) -> Result<(), ErrorCode>; + async fn create_room(stoken: String, userid: String, room: Room) -> Result; + async fn delete_room(stoken: String, userid: String, roomid: String) -> Result<(), ErrorCode>; + async fn promote_user(stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode>; + async fn demote_user(stoken: String, owner_userid: String, userid: String) -> Result<(), ErrorCode>; + async fn kick_user(stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode>; + async fn ban_user(stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode>; + async fn pardon_user(stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode>; } #[derive(Debug, Clone, Serialize, Deserialize)]