Selecting/Creating/Joining Rooms & Severs!
This commit is contained in:
@@ -57,7 +57,7 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
migrate!().run(&db_pool).await?; // TODO: Do in Docker with Sqlx-cli
|
migrate!().run(&db_pool).await?; // TODO: Do in Docker with Sqlx-cli
|
||||||
info!("Migrations complete!");
|
info!("Migrations complete!");
|
||||||
|
|
||||||
let server_addr = (IpAddr::V6(Ipv6Addr::LOCALHOST), env::var("PORT").expect("PORT must be set").parse::<u16>().unwrap());
|
let server_addr = (IpAddr::V4("0.0.0.0".parse()?), env::var("PORT").expect("PORT must be set").parse::<u16>().unwrap());
|
||||||
|
|
||||||
// JSON transport is provided by the json_transport tarpc module. It makes it easy
|
// 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.
|
// to start up a serde-powered json serialization strategy over TCP.
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
|
use tarpc::client::RpcError;
|
||||||
use tarpc::context;
|
use tarpc::context;
|
||||||
use tarpc::tokio_serde::formats::Json;
|
use tarpc::tokio_serde::formats::Json;
|
||||||
use tokio::sync::broadcast;
|
use tokio::sync::broadcast;
|
||||||
use tokio::sync::broadcast::{Receiver, Sender};
|
use tokio::sync::broadcast::{Receiver, Sender};
|
||||||
use tracing::log::*;
|
use tracing::log::*;
|
||||||
use realm_auth::types::RealmAuthClient;
|
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::stoken;
|
||||||
use realm_shared::types::ErrorCode::*;
|
use realm_shared::types::ErrorCode::*;
|
||||||
use realm_shared::types::ErrorCode;
|
use realm_shared::types::ErrorCode;
|
||||||
@@ -15,9 +16,6 @@ use crate::ui::gui;
|
|||||||
#[derive(serde::Deserialize, serde::Serialize)]
|
#[derive(serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(default)] // if we add new fields, give them default values when deserializing old state
|
#[serde(default)] // if we add new fields, give them default values when deserializing old state
|
||||||
pub struct RealmApp {
|
pub struct RealmApp {
|
||||||
// Example stuff:
|
|
||||||
pub label: String,
|
|
||||||
pub selected: bool,
|
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub selected_serverid: String,
|
pub selected_serverid: String,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
@@ -58,6 +56,15 @@ pub struct RealmApp {
|
|||||||
pub server_window_domain: String,
|
pub server_window_domain: String,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub server_window_port: String,
|
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)]
|
#[serde(skip)]
|
||||||
pub login_start_channel: (Sender<Result<(), ErrorCode>>, Receiver<Result<(), ErrorCode>>),
|
pub login_start_channel: (Sender<Result<(), ErrorCode>>, Receiver<Result<(), ErrorCode>>),
|
||||||
@@ -74,14 +81,16 @@ pub struct RealmApp {
|
|||||||
|
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub fetching_servers_channel: (Sender<Result<CServer, ErrorCode>>, Receiver<Result<CServer, ErrorCode>>),
|
pub fetching_servers_channel: (Sender<Result<CServer, ErrorCode>>, Receiver<Result<CServer, ErrorCode>>),
|
||||||
|
|
||||||
|
#[serde(skip)]
|
||||||
|
pub add_room_channel: (Sender<Result<CServer, ErrorCode>>, Receiver<Result<CServer, ErrorCode>>),
|
||||||
|
#[serde(skip)]
|
||||||
|
pub room_changes_channel: (Sender<Result<(CServer, Vec<Room>), ErrorCode>>, Receiver<Result<(CServer, Vec<Room>), ErrorCode>>)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for RealmApp {
|
impl Default for RealmApp {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
// Example stuff:
|
|
||||||
label: "Hello World!".to_owned(),
|
|
||||||
selected: false,
|
|
||||||
selected_serverid: String::new(),
|
selected_serverid: String::new(),
|
||||||
selected_roomid: String::new(),
|
selected_roomid: String::new(),
|
||||||
current_user: None,
|
current_user: None,
|
||||||
@@ -105,11 +114,18 @@ impl Default for RealmApp {
|
|||||||
server_window_open: false,
|
server_window_open: false,
|
||||||
server_window_domain: String::new(),
|
server_window_domain: String::new(),
|
||||||
server_window_port: "5051".to_string(),
|
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),
|
fetching_user_data_channel: broadcast::channel(10),
|
||||||
add_server_channel: broadcast::channel(10),
|
add_server_channel: broadcast::channel(10),
|
||||||
join_server_channel: broadcast::channel(10),
|
join_server_channel: broadcast::channel(10),
|
||||||
fetching_servers_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<Result<CUser, ErrorCode>>, server_ad
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fetch_server_data(addresses: Vec<String>, channel: Sender<Result<CServer, ErrorCode>>) {
|
pub fn fetch_server_data(channel: Sender<Result<CServer, ErrorCode>>, addresses: Vec<String>, token: String, username: String) {
|
||||||
for server_address in addresses {
|
for server_address in addresses {
|
||||||
let send_channel = channel.clone();
|
let send_channel = channel.clone();
|
||||||
|
let token = token.clone();
|
||||||
|
let userid = username.clone();
|
||||||
|
|
||||||
let _handle = tokio::spawn(async move {
|
let _handle = tokio::spawn(async move {
|
||||||
let mut transport = tarpc::serde_transport::tcp::connect(&server_address, Json::default);
|
let mut transport = tarpc::serde_transport::tcp::connect(&server_address, Json::default);
|
||||||
@@ -190,19 +208,46 @@ pub fn fetch_server_data(addresses: Vec<String>, channel: Sender<Result<CServer,
|
|||||||
|
|
||||||
let client = RealmChatClient::new(tarpc::client::Config::default(), connection).spawn();
|
let client = RealmChatClient::new(tarpc::client::Config::default(), connection).spawn();
|
||||||
let info = client.get_info(context::current()).await.unwrap();
|
let info = client.get_info(context::current()).await.unwrap();
|
||||||
let is_admin = client.is_user_admin(context::current(), info.server_id.clone()).await.unwrap();
|
let domain = server_address.split(':').collect::<Vec<&str>>()[0].to_string();
|
||||||
let is_owner = client.is_user_owner(context::current(), info.server_id.clone()).await.unwrap();
|
let port = server_address.split(':').collect::<Vec<&str>>()[1].to_string().parse::<u16>().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 {
|
send_channel.send(Ok(CServer {
|
||||||
|
tarpc_conn: client,
|
||||||
server_id: info.server_id,
|
server_id: info.server_id,
|
||||||
domain: server_address.split(':').collect::<Vec<&str>>()[0].to_string(),
|
domain,
|
||||||
port: server_address.split(':').collect::<Vec<&str>>()[1].to_string().parse::<u16>().unwrap(),
|
port,
|
||||||
is_admin,
|
is_admin,
|
||||||
is_owner,
|
is_owner,
|
||||||
|
rooms,
|
||||||
})).unwrap();
|
})).unwrap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fetch_rooms_data(send_channel: Sender<Result<(CServer, Vec<Room>), 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 {
|
impl eframe::App for RealmApp {
|
||||||
/// Called each time the UI needs repainting, which may be many times per second.
|
/// 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) {
|
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||||
@@ -225,7 +270,12 @@ impl eframe::App for RealmApp {
|
|||||||
// Fetching servers
|
// Fetching servers
|
||||||
if self.active_servers.is_none() && self.current_user.is_some() {
|
if self.active_servers.is_none() && self.current_user.is_some() {
|
||||||
self.active_servers = Some(Vec::new());
|
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
|
// 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;
|
let result = client.join_server(context::current(), stoken(&thread_token, &info.server_id, &domain, port), thread_username).await;
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => {
|
Ok(r) => {
|
||||||
info!("Joined server!");
|
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 {
|
match result {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
info!("Successfully joined a server");
|
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) => {
|
Err(code) => {
|
||||||
error!("Error joining server: {:?}", code);
|
error!("Error joining server: {:?}", code);
|
||||||
@@ -347,6 +409,40 @@ impl eframe::App for RealmApp {
|
|||||||
Err(e) => error!("Error fetching server data: {:?}", e),
|
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
|
// File -> Quit
|
||||||
gui::top_panel(self, ctx);
|
gui::top_panel(self, ctx);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use realm_server::types::{RealmChatClient, Room};
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||||
pub struct CUser {
|
pub struct CUser {
|
||||||
pub id: i64,
|
pub id: i64,
|
||||||
@@ -9,11 +11,13 @@ pub struct CUser {
|
|||||||
pub token: String,
|
pub token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CServer {
|
pub struct CServer {
|
||||||
|
pub tarpc_conn: RealmChatClient,
|
||||||
pub server_id: String,
|
pub server_id: String,
|
||||||
pub domain: String,
|
pub domain: String,
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
pub is_admin: bool,
|
pub is_admin: bool,
|
||||||
pub is_owner: bool,
|
pub is_owner: bool,
|
||||||
|
pub rooms: Vec<Room>
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,10 @@ use realm_auth::types::RealmAuthClient;
|
|||||||
use realm_shared::types::ErrorCode::RPCError;
|
use realm_shared::types::ErrorCode::RPCError;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use tracing::log::*;
|
use tracing::log::*;
|
||||||
|
use realm_server::types::Room;
|
||||||
|
use realm_shared::stoken;
|
||||||
use crate::app::RealmApp;
|
use crate::app::RealmApp;
|
||||||
|
use crate::types::CServer;
|
||||||
|
|
||||||
pub fn top_panel(app: &mut RealmApp, ctx: &Context) {
|
pub fn top_panel(app: &mut RealmApp, ctx: &Context) {
|
||||||
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
|
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_username = None;
|
||||||
app.saved_token = None;
|
app.saved_token = None;
|
||||||
app.saved_auth_address = None;
|
app.saved_auth_address = None;
|
||||||
|
|
||||||
|
app.active_servers = None;
|
||||||
|
app.selected_roomid.clear();
|
||||||
|
app.selected_serverid.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ui.button("Quit").clicked() {
|
if ui.button("Quit").clicked() {
|
||||||
@@ -72,10 +79,6 @@ pub fn servers(app: &mut RealmApp, ctx: &Context) {
|
|||||||
});
|
});
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
if ui.add(SelectableLabel::new(app.selected, "server")).clicked() {
|
|
||||||
app.selected = !app.selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(active_servers) = &mut app.active_servers {
|
if let Some(active_servers) = &mut app.active_servers {
|
||||||
for server in active_servers {
|
for server in active_servers {
|
||||||
if ui.add(SelectableLabel::new(server.server_id.eq(&app.selected_serverid), server.server_id.clone())).clicked() {
|
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 {
|
} else {
|
||||||
app.selected_serverid = server.server_id.clone();
|
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) {
|
pub fn rooms(app: &mut RealmApp, ctx: &Context) {
|
||||||
egui::SidePanel::left("rooms").show(ctx, |ui| {
|
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();
|
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) {
|
pub fn messages(app: &mut RealmApp, ctx: &Context) {
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
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 username: {:?}", app.saved_username));
|
||||||
ui.label(format!("Saved token: {:?}", app.saved_token));
|
ui.label(format!("Saved token: {:?}", app.saved_token));
|
||||||
ui.label(format!("Saved auth address: {:?}", app.saved_auth_address));
|
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 {
|
if let Some(servers) = &app.active_servers {
|
||||||
for server in servers {
|
for server in servers {
|
||||||
ui.label(format!("Active server: {:?}", server));
|
ui.heading(&server.server_id);
|
||||||
|
ui.label(format!("{:?}", server));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
ui.label(format!("Current user: {:?}", app.current_user));
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,6 @@ sqlx = { version = "0.8.2", features = [ "runtime-tokio", "tls-rustls", "sqlite"
|
|||||||
dotenvy = "0.15.7"
|
dotenvy = "0.15.7"
|
||||||
moka = { version = "0.12.8", features = ["future"] }
|
moka = { version = "0.12.8", features = ["future"] }
|
||||||
futures-util = "0.3.30"
|
futures-util = "0.3.30"
|
||||||
durian = "0.5"
|
|
||||||
|
|
||||||
realm_auth = { path = "../auth" }
|
realm_auth = { path = "../auth" }
|
||||||
realm_shared = { path = "../shared" }
|
realm_shared = { path = "../shared" }
|
||||||
|
|||||||
@@ -1,64 +1,64 @@
|
|||||||
use durian::bincode_packet;
|
// use durian::bincode_packet;
|
||||||
use crate::types::{Message, Room, User};
|
// 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,
|
|
||||||
}
|
|
||||||
|
|
||||||
// #[bincode_packet]
|
// #[bincode_packet]
|
||||||
// pub struct StartTypingEvent {
|
// pub struct Greet {
|
||||||
// pub user: User,
|
// pub id: u32
|
||||||
// pub room: String,
|
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// #[bincode_packet]
|
// #[bincode_packet]
|
||||||
// pub struct StopTypingEvent {
|
// pub struct UserJoinedEvent {
|
||||||
// pub user: User,
|
// pub user: User,
|
||||||
// pub room: String,
|
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
#[bincode_packet]
|
// #[bincode_packet]
|
||||||
pub struct NewRoomEvent {
|
// pub struct UserLeftEvent {
|
||||||
pub room: Room,
|
// pub user: User,
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
#[bincode_packet]
|
// #[bincode_packet]
|
||||||
pub struct DeleteRoomEvent {
|
// pub struct NewMessageEvent {
|
||||||
pub roomid: String,
|
// pub message: Message,
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
#[bincode_packet]
|
// // #[bincode_packet]
|
||||||
pub struct KickedUserEvent {
|
// // pub struct StartTypingEvent {
|
||||||
pub userid: String,
|
// // pub user: User,
|
||||||
}
|
// // pub room: String,
|
||||||
|
// // }
|
||||||
#[bincode_packet]
|
// //
|
||||||
pub struct BannedUserEvent {
|
// // #[bincode_packet]
|
||||||
pub userid: String,
|
// // pub struct StopTypingEvent {
|
||||||
}
|
// // pub user: User,
|
||||||
|
// // pub room: String,
|
||||||
#[bincode_packet]
|
// // }
|
||||||
pub struct PromotedUserEvent {
|
//
|
||||||
pub userid: String,
|
// #[bincode_packet]
|
||||||
}
|
// pub struct NewRoomEvent {
|
||||||
|
// pub room: Room,
|
||||||
#[bincode_packet]
|
// }
|
||||||
pub struct DemotedUserEvent {
|
//
|
||||||
pub userid: String,
|
// #[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,
|
||||||
|
// }
|
||||||
@@ -3,7 +3,6 @@ use std::future::Future;
|
|||||||
use std::net::{IpAddr, Ipv6Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv6Addr, SocketAddr};
|
||||||
use std::sync::{Arc};
|
use std::sync::{Arc};
|
||||||
use dotenvy::dotenv;
|
use dotenvy::dotenv;
|
||||||
use durian::{PacketManager, ServerConfig};
|
|
||||||
use futures::future::{self};
|
use futures::future::{self};
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use sqlx::migrate::MigrateDatabase;
|
use sqlx::migrate::MigrateDatabase;
|
||||||
@@ -18,7 +17,7 @@ use tokio::sync::Mutex;
|
|||||||
use tracing::{info, subscriber, warn};
|
use tracing::{info, subscriber, warn};
|
||||||
use realm_server::events::*;
|
use realm_server::events::*;
|
||||||
use realm_server::server::RealmChatServer;
|
use realm_server::server::RealmChatServer;
|
||||||
use realm_server::types::RealmChat;
|
use realm_server::types::{RealmChat};
|
||||||
|
|
||||||
async fn spawn(fut: impl Future<Output = ()> + Send + 'static) {
|
async fn spawn(fut: impl Future<Output = ()> + Send + 'static) {
|
||||||
tokio::spawn(fut);
|
tokio::spawn(fut);
|
||||||
@@ -57,39 +56,32 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
info!("Migrations complete!");
|
info!("Migrations complete!");
|
||||||
|
|
||||||
let port = env::var("PORT").expect("PORT must be set").parse::<u16>()?;
|
let port = env::var("PORT").expect("PORT must be set").parse::<u16>()?;
|
||||||
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();
|
// let (handler, listener) = node::split::<()>();
|
||||||
|
// handler.network().listen(Transport::FramedTcp, "0.0.0.0:"+(port-1))?;
|
||||||
inner_manager.register_receive_packet::<Greet>(GreetPacketBuilder)?;
|
// info!("Listening on port {}", port-1);
|
||||||
inner_manager.register_receive_packet::<UserJoinedEvent>(UserJoinedEventPacketBuilder)?;
|
//
|
||||||
inner_manager.register_receive_packet::<UserLeftEvent>(UserLeftEventPacketBuilder)?;
|
// // Read incoming network events.
|
||||||
inner_manager.register_receive_packet::<NewMessageEvent>(NewMessageEventPacketBuilder)?;
|
// listener.for_each(|event| match event.network() {
|
||||||
// inner_manager.register_receive_packet::<StartTypingEvent>(StartTypingEventPacketBuilder)?;
|
// NetEvent::Connected(_, _) => unreachable!(), // Used for explicit connections.
|
||||||
// inner_manager.register_receive_packet::<StopTypingEvent>(StopTypingEventPacketBuilder)?;
|
// NetEvent::Accepted(_endpoint, _listener) => println!("Client connected"), // Tcp or Ws
|
||||||
inner_manager.register_receive_packet::<NewRoomEvent>(NewRoomEventPacketBuilder)?;
|
// NetEvent::Message(endpoint, data) => {
|
||||||
inner_manager.register_receive_packet::<DeleteRoomEvent>(DeleteRoomEventPacketBuilder)?;
|
// println!("Received: {}", String::from_utf8_lossy(data));
|
||||||
inner_manager.register_receive_packet::<KickedUserEvent>(KickedUserEventPacketBuilder)?;
|
// handler.network().send(endpoint, data);
|
||||||
inner_manager.register_receive_packet::<BannedUserEvent>(BannedUserEventPacketBuilder)?;
|
// },
|
||||||
|
// NetEvent::Disconnected(_endpoint) => println!("Client disconnected"), //Tcp or Ws
|
||||||
inner_manager.register_send_packet::<Greet>()?;
|
// });
|
||||||
inner_manager.register_send_packet::<UserJoinedEvent>()?;
|
//
|
||||||
inner_manager.register_send_packet::<UserLeftEvent>()?;
|
// inner_manager.init_server(
|
||||||
inner_manager.register_send_packet::<NewMessageEvent>()?;
|
// ServerConfig::new(
|
||||||
// inner_manager.register_send_packet::<StartTypingEvent>()?;
|
// SocketAddr::from((IpAddr::V4("0.0.0.0".parse()?), port-1)).to_string(),
|
||||||
// inner_manager.register_send_packet::<StopTypingEvent>()?;
|
// 0, None, 8, 8))?;
|
||||||
inner_manager.register_send_packet::<NewRoomEvent>()?;
|
//
|
||||||
inner_manager.register_send_packet::<DeleteRoomEvent>()?;
|
// let manager = Arc::new(Mutex::new(NetIO {
|
||||||
inner_manager.register_send_packet::<KickedUserEvent>()?;
|
// handler,
|
||||||
inner_manager.register_send_packet::<BannedUserEvent>()?;
|
// listener,
|
||||||
|
// }));
|
||||||
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);
|
|
||||||
|
|
||||||
// JSON transport is provided by the json_transport tarpc module. It makes it easy
|
// 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.
|
// 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
|
// serve is generated by the service attribute. It takes as input any type implementing
|
||||||
// the generated World trait.
|
// the generated World trait.
|
||||||
.map(|channel| {
|
.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)
|
channel.execute(server.serve()).for_each(spawn)
|
||||||
})
|
})
|
||||||
// Max 10 channels.
|
// Max 10 channels.
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ use std::net::SocketAddr;
|
|||||||
use std::sync::{Arc};
|
use std::sync::{Arc};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use durian::PacketManager;
|
|
||||||
use moka::future::Cache;
|
use moka::future::Cache;
|
||||||
use sqlx::{FromRow, Pool, query_as, Sqlite};
|
use sqlx::{FromRow, Pool, query_as, Sqlite};
|
||||||
use sqlx::query;
|
use sqlx::query;
|
||||||
@@ -26,7 +25,6 @@ pub struct RealmChatServer {
|
|||||||
pub db_pool: Pool<Sqlite>,
|
pub db_pool: Pool<Sqlite>,
|
||||||
pub typing_users: Vec<(String, String)>, //NOTE: user.userid, room.roomid
|
pub typing_users: Vec<(String, String)>, //NOTE: user.userid, room.roomid
|
||||||
pub cache: Cache<String, String>,
|
pub cache: Cache<String, String>,
|
||||||
pub packet_manager: Arc<Mutex<PacketManager>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const FETCH_MESSAGE: &str = "SELECT message.*,
|
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";
|
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 {
|
impl RealmChatServer {
|
||||||
pub fn new(server_id: String, socket: SocketAddr, db_pool: Pool<Sqlite>, packet_manager: Arc<Mutex<PacketManager>>) -> RealmChatServer {
|
pub fn new(server_id: String, socket: SocketAddr, db_pool: Pool<Sqlite>) -> RealmChatServer {
|
||||||
RealmChatServer {
|
RealmChatServer {
|
||||||
server_id,
|
server_id,
|
||||||
port: env::var("PORT").unwrap().parse::<u16>().unwrap(),
|
port: env::var("PORT").unwrap().parse::<u16>().unwrap(),
|
||||||
@@ -48,7 +46,6 @@ impl RealmChatServer {
|
|||||||
.time_to_idle(Duration::from_secs(5*60))
|
.time_to_idle(Duration::from_secs(5*60))
|
||||||
.time_to_live(Duration::from_secs(60*60))
|
.time_to_live(Duration::from_secs(60*60))
|
||||||
.build(),
|
.build(),
|
||||||
packet_manager,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,36 +91,20 @@ impl RealmChatServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn internal_is_user_admin(&self, stoken: &str) -> bool {
|
pub async fn internal_is_user_admin(&self, userid: &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;
|
||||||
let result = query!("SELECT admin FROM user WHERE userid = ?", userid).fetch_one(&self.db_pool).await;
|
match result {
|
||||||
return match result {
|
Ok(record) => record.admin,
|
||||||
Ok(record) => {
|
Err(_) => false
|
||||||
if record.admin {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
Err(_) => false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn internal_is_user_owner(&self, stoken: &str) -> bool {
|
pub async fn internal_is_user_owner(&self, userid: &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;
|
||||||
let result = query!("SELECT owner FROM user WHERE userid = ?", userid).fetch_one(&self.db_pool).await;
|
match result {
|
||||||
return match result {
|
Ok(record) => record.owner,
|
||||||
Ok(record) => {
|
Err(_) => false
|
||||||
if record.owner {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
Err(_) => false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn is_user_in_server(&self, userid: &str) -> bool {
|
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<Vec<Message>, ErrorCode> {
|
async fn inner_get_all_direct_replies(&self, userid: &str, head: i64) -> Result<Vec<Message>, ErrorCode> {
|
||||||
let is_admin = self.internal_is_user_admin(stoken).await;
|
let is_admin = self.internal_is_user_admin(userid).await;
|
||||||
let result = sqlx::query(&format!("{}{}", FETCH_MESSAGE, "AND message.referencing_id = ?"))
|
let result = sqlx::query(&format!("{}{}", FETCH_MESSAGE, "AND message.referencing_id = ?"))
|
||||||
.bind(is_admin)
|
.bind(is_admin)
|
||||||
.bind(head)
|
.bind(head)
|
||||||
@@ -148,19 +129,19 @@ impl RealmChatServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn inner_get_reply_chain(&self, stoken: &str, head: Message, depth: u8) -> Result<ReplyChain, ErrorCode> {
|
async fn inner_get_reply_chain(&self, userid: &str, head: Message, depth: u8) -> Result<ReplyChain, ErrorCode> {
|
||||||
if depth > 8 {
|
if depth > 8 {
|
||||||
return Err(DepthTooLarge)
|
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 {
|
let replies = if direct_replies.is_empty() || depth == 0 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let mut chains = Vec::new();
|
let mut chains = Vec::new();
|
||||||
|
|
||||||
for reply in direct_replies {
|
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)
|
Some(chains)
|
||||||
@@ -174,8 +155,8 @@ impl RealmChatServer {
|
|||||||
Ok(chain)
|
Ok(chain)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn inner_get_room(&self, stoken: &str, roomid: &str) -> Result<Room, ErrorCode> {
|
async fn inner_get_room(&self, userid: &str, roomid: &str) -> Result<Room, ErrorCode> {
|
||||||
let is_admin = self.internal_is_user_admin(&stoken).await;
|
let is_admin = self.internal_is_user_admin(&userid).await;
|
||||||
let result = query_as!(
|
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;
|
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<Message, ErrorCode> {
|
async fn inner_get_message(&self, userid: &str, id: i64) -> Result<Message, ErrorCode> {
|
||||||
let is_admin = self.internal_is_user_admin(&stoken).await;
|
let is_admin = self.internal_is_user_admin(&userid).await;
|
||||||
let result = sqlx::query(&format!("{}{}", FETCH_MESSAGE, "AND message.id = ?"))
|
let result = sqlx::query(&format!("{}{}", FETCH_MESSAGE, "AND message.id = ?"))
|
||||||
.bind(is_admin)
|
.bind(is_admin)
|
||||||
.bind(id)
|
.bind(id)
|
||||||
@@ -228,12 +209,12 @@ impl RealmChat for RealmChatServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn is_user_admin(self, _: Context, stoken: String) -> bool {
|
async fn is_user_admin(self, _: Context, userid: String) -> bool {
|
||||||
self.internal_is_user_admin(&stoken).await
|
self.internal_is_user_admin(&userid).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn is_user_owner(self, _: Context, stoken: String) -> bool {
|
async fn is_user_owner(self, _: Context, userid: String) -> bool {
|
||||||
self.internal_is_user_owner(&stoken).await
|
self.internal_is_user_owner(&userid).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn join_server(self, _: Context, stoken: String, userid: String) -> Result<User, ErrorCode> {
|
async fn join_server(self, _: Context, stoken: String, userid: String) -> Result<User, ErrorCode> {
|
||||||
@@ -258,12 +239,12 @@ impl RealmChat for RealmChatServer {
|
|||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let new_user = self.inner_get_user(&userid).await?;
|
let new_user = self.inner_get_user(&userid).await?;
|
||||||
|
|
||||||
let result = self.packet_manager.lock().await.broadcast(UserJoinedEvent {
|
// let result = self.packet_manager.lock().await.broadcast(UserJoinedEvent {
|
||||||
user: new_user.clone(),
|
// user: new_user.clone(),
|
||||||
});
|
// });
|
||||||
if result.is_err() {
|
// if result.is_err() {
|
||||||
error!("Error broadcasting UserJoinedEvent!");
|
// error!("Error broadcasting UserJoinedEvent!");
|
||||||
}
|
// }
|
||||||
|
|
||||||
Ok(new_user)
|
Ok(new_user)
|
||||||
},
|
},
|
||||||
@@ -286,13 +267,13 @@ impl RealmChat for RealmChatServer {
|
|||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let result = self.packet_manager.lock().await.broadcast(UserLeftEvent {
|
// let result = self.packet_manager.lock().await.broadcast(UserLeftEvent {
|
||||||
user,
|
// user,
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
if result.is_err() {
|
// if result.is_err() {
|
||||||
error!("Error broadcasting UserLeftEvent!");
|
// error!("Error broadcasting UserLeftEvent!");
|
||||||
}
|
// }
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
@@ -310,21 +291,21 @@ impl RealmChat for RealmChatServer {
|
|||||||
|
|
||||||
match &message.data { // Check that the sender is the owner of the referencing msg
|
match &message.data { // Check that the sender is the owner of the referencing msg
|
||||||
MessageData::Edit(e) => {
|
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) {
|
if !ref_msg.user.userid.eq(&message.user.userid) {
|
||||||
return Err(Unauthorized)
|
return Err(Unauthorized)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MessageData::Redaction(r)=> {
|
MessageData::Redaction(r)=> {
|
||||||
let ref_msg = self.inner_get_message(&stoken, r.referencing_id).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(&stoken).await {
|
if !ref_msg.user.userid.eq(&message.user.userid) || !self.internal_is_user_admin(&message.user.userid).await {
|
||||||
return Err(Unauthorized)
|
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!(
|
let admin_only_send = query!(
|
||||||
"SELECT admin_only_send FROM room WHERE roomid = ?",
|
"SELECT admin_only_send FROM room WHERE roomid = ?",
|
||||||
message.room.roomid).fetch_one(&self.db_pool).await;
|
message.room.roomid).fetch_one(&self.db_pool).await;
|
||||||
@@ -336,7 +317,7 @@ impl RealmChat for RealmChatServer {
|
|||||||
return Err(RoomNotFound)
|
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 {
|
let result = match &message.data {
|
||||||
MessageData::Text(text) => {
|
MessageData::Text(text) => {
|
||||||
@@ -369,13 +350,13 @@ impl RealmChat for RealmChatServer {
|
|||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let result = self.packet_manager.lock().await.broadcast(NewMessageEvent {
|
// let result = self.packet_manager.lock().await.broadcast(NewMessageEvent {
|
||||||
message: message.clone(),
|
// message: message.clone(),
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
if result.is_err() {
|
// if result.is_err() {
|
||||||
error!("Error broadcasting NewMessageEvent!");
|
// error!("Error broadcasting NewMessageEvent!");
|
||||||
}
|
// }
|
||||||
|
|
||||||
Ok(message)
|
Ok(message)
|
||||||
},
|
},
|
||||||
@@ -395,8 +376,12 @@ impl RealmChat for RealmChatServer {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_message(self, _: Context, stoken: String, id: i64) -> Result<Message, ErrorCode> {
|
async fn get_message(self, _: Context, stoken: String, userid: String, id: i64) -> Result<Message, ErrorCode> {
|
||||||
let is_admin = self.internal_is_user_admin(&stoken).await;
|
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 = ?"))
|
let result = sqlx::query(&format!("{}{}", FETCH_MESSAGE, "AND message.id = ?"))
|
||||||
.bind(is_admin)
|
.bind(is_admin)
|
||||||
.bind(id)
|
.bind(id)
|
||||||
@@ -412,8 +397,12 @@ impl RealmChat for RealmChatServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_messages_since(self, _: Context, stoken: String, time: DateTime<Utc>) -> Result<Vec<Message>, ErrorCode> {
|
async fn get_messages_since(self, _: Context, stoken: String, userid: String, time: DateTime<Utc>) -> Result<Vec<Message>, ErrorCode> {
|
||||||
let is_admin = self.internal_is_user_admin(&stoken).await;
|
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 >= ?"))
|
let result = sqlx::query(&format!("{}{}", FETCH_MESSAGE, "AND message.timestamp >= ?"))
|
||||||
.bind(is_admin)
|
.bind(is_admin)
|
||||||
.bind(time)
|
.bind(time)
|
||||||
@@ -425,18 +414,30 @@ impl RealmChat for RealmChatServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_all_direct_replies(self, _: Context, stoken: String, head: i64) -> Result<Vec<Message>, ErrorCode> {
|
async fn get_all_direct_replies(self, _: Context, stoken: String, userid: String, head: i64) -> Result<Vec<Message>, ErrorCode> {
|
||||||
self.inner_get_all_direct_replies(&stoken, head).await
|
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<ReplyChain, ErrorCode> {
|
async fn get_reply_chain(self, _: Context, stoken: String, userid: String, head: Message, depth: u8) -> Result<ReplyChain, ErrorCode> {
|
||||||
|
if !self.is_stoken_valid(&userid, &stoken).await {
|
||||||
|
return Err(Unauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
self.inner_get_reply_chain(&stoken, head, depth).await
|
self.inner_get_reply_chain(&stoken, head, depth).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_rooms(self, _: Context, stoken: String) -> Result<Vec<Room>, ErrorCode> {
|
async fn get_rooms(self, _: Context, stoken: String, userid: String) -> Result<Vec<Room>, ErrorCode> {
|
||||||
let is_admin = self.internal_is_user_admin(&stoken).await;
|
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!(
|
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 {
|
match result {
|
||||||
Ok(rooms) => Ok(rooms),
|
Ok(rooms) => Ok(rooms),
|
||||||
@@ -444,8 +445,12 @@ impl RealmChat for RealmChatServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_room(self, _: Context, stoken: String, roomid: String) -> Result<Room, ErrorCode> {
|
async fn get_room(self, _: Context, stoken: String, userid: String, roomid: String) -> Result<Room, ErrorCode> {
|
||||||
self.inner_get_room(&stoken, &roomid).await
|
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<User, ErrorCode> {
|
async fn get_user(self, _: Context, userid: String) -> Result<User, ErrorCode> {
|
||||||
@@ -456,8 +461,12 @@ impl RealmChat for RealmChatServer {
|
|||||||
self.inner_get_all_users().await
|
self.inner_get_all_users().await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_room(self, _: Context, stoken: String, room: Room) -> Result<Room, ErrorCode> {
|
async fn create_room(self, _: Context, stoken: String, userid: String, room: Room) -> Result<Room, ErrorCode> {
|
||||||
if !self.internal_is_user_admin(&stoken).await {
|
if !self.is_stoken_valid(&userid, &stoken).await {
|
||||||
|
return Err(Unauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.internal_is_user_admin(&userid).await {
|
||||||
return Err(Unauthorized)
|
return Err(Unauthorized)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,13 +476,13 @@ impl RealmChat for RealmChatServer {
|
|||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let result = self.packet_manager.lock().await.broadcast(NewRoomEvent {
|
// let result = self.packet_manager.lock().await.broadcast(NewRoomEvent {
|
||||||
room: room.clone(),
|
// room: room.clone(),
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
if result.is_err() {
|
// if result.is_err() {
|
||||||
error!("Error broadcasting NewRoomEvent!");
|
// error!("Error broadcasting NewRoomEvent!");
|
||||||
}
|
// }
|
||||||
|
|
||||||
Ok(room)
|
Ok(room)
|
||||||
}
|
}
|
||||||
@@ -481,8 +490,12 @@ impl RealmChat for RealmChatServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn delete_room(self, _: Context, stoken: String, roomid: String) -> Result<(), ErrorCode> {
|
async fn delete_room(self, _: Context, stoken: String, userid: String, roomid: String) -> Result<(), ErrorCode> {
|
||||||
if !self.internal_is_user_admin(&stoken).await {
|
if !self.is_stoken_valid(&userid, &stoken).await {
|
||||||
|
return Err(Unauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.internal_is_user_admin(&userid).await {
|
||||||
return Err(Unauthorized)
|
return Err(Unauthorized)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,13 +503,13 @@ impl RealmChat for RealmChatServer {
|
|||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let result = self.packet_manager.lock().await.broadcast(DeleteRoomEvent {
|
// let result = self.packet_manager.lock().await.broadcast(DeleteRoomEvent {
|
||||||
roomid,
|
// roomid,
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
if result.is_err() {
|
// if result.is_err() {
|
||||||
error!("Error broadcasting DeleteRoomEvent!");
|
// error!("Error broadcasting DeleteRoomEvent!");
|
||||||
}
|
// }
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -504,8 +517,12 @@ impl RealmChat for RealmChatServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn promote_user(self, _: Context, stoken: String, userid: String) -> Result<(), ErrorCode> {
|
async fn promote_user(self, _: Context, stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode> {
|
||||||
if !self.internal_is_user_owner(&stoken).await {
|
if !self.is_stoken_valid(&admin_userid, &stoken).await {
|
||||||
|
return Err(Unauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.internal_is_user_owner(&admin_userid).await {
|
||||||
return Err(Unauthorized)
|
return Err(Unauthorized)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,13 +530,13 @@ impl RealmChat for RealmChatServer {
|
|||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let result = self.packet_manager.lock().await.broadcast(PromotedUserEvent {
|
// let result = self.packet_manager.lock().await.broadcast(PromotedUserEvent {
|
||||||
userid,
|
// userid,
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
if result.is_err() {
|
// if result.is_err() {
|
||||||
error!("Error broadcasting PromotedUserEvent!");
|
// error!("Error broadcasting PromotedUserEvent!");
|
||||||
}
|
// }
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -527,8 +544,12 @@ impl RealmChat for RealmChatServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn demote_user(self, _: Context, stoken: String, userid: String) -> Result<(), ErrorCode> {
|
async fn demote_user(self, _: Context, stoken: String, owner_userid: String, userid: String) -> Result<(), ErrorCode> {
|
||||||
if !self.internal_is_user_owner(&stoken).await {
|
if !self.is_stoken_valid(&owner_userid, &stoken).await {
|
||||||
|
return Err(Unauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.internal_is_user_owner(&owner_userid).await {
|
||||||
return Err(Unauthorized)
|
return Err(Unauthorized)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,13 +557,13 @@ impl RealmChat for RealmChatServer {
|
|||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let result = self.packet_manager.lock().await.broadcast(DemotedUserEvent {
|
// let result = self.packet_manager.lock().await.broadcast(DemotedUserEvent {
|
||||||
userid,
|
// userid,
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
if result.is_err() {
|
// if result.is_err() {
|
||||||
error!("Error broadcasting DemotedUserEvent!");
|
// error!("Error broadcasting DemotedUserEvent!");
|
||||||
}
|
// }
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -550,8 +571,12 @@ impl RealmChat for RealmChatServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn kick_user(self, _: Context, stoken: String, userid: String) -> Result<(), ErrorCode> {
|
async fn kick_user(self, _: Context, stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode> {
|
||||||
if !self.internal_is_user_admin(&stoken).await {
|
if !self.is_stoken_valid(&admin_userid, &stoken).await {
|
||||||
|
return Err(Unauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.internal_is_user_admin(&admin_userid).await {
|
||||||
return Err(Unauthorized)
|
return Err(Unauthorized)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,13 +584,13 @@ impl RealmChat for RealmChatServer {
|
|||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let result = self.packet_manager.lock().await.broadcast(KickedUserEvent {
|
// let result = self.packet_manager.lock().await.broadcast(KickedUserEvent {
|
||||||
userid,
|
// userid,
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
if result.is_err() {
|
// if result.is_err() {
|
||||||
error!("Error broadcasting KickedUserEvent!");
|
// error!("Error broadcasting KickedUserEvent!");
|
||||||
}
|
// }
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -573,8 +598,12 @@ impl RealmChat for RealmChatServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn ban_user(self, _: Context, stoken: String, userid: String) -> Result<(), ErrorCode> {
|
async fn ban_user(self, _: Context, stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode> {
|
||||||
if !self.internal_is_user_admin(&stoken).await {
|
if !self.is_stoken_valid(&admin_userid, &stoken).await {
|
||||||
|
return Err(Unauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.internal_is_user_admin(&admin_userid).await {
|
||||||
return Err(Unauthorized)
|
return Err(Unauthorized)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,13 +612,13 @@ impl RealmChat for RealmChatServer {
|
|||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let result = self.packet_manager.lock().await.broadcast(BannedUserEvent {
|
// let result = self.packet_manager.lock().await.broadcast(BannedUserEvent {
|
||||||
userid,
|
// userid,
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
if result.is_err() {
|
// if result.is_err() {
|
||||||
error!("Error broadcasting BannedUserEvent!");
|
// error!("Error broadcasting BannedUserEvent!");
|
||||||
}
|
// }
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -597,8 +626,8 @@ impl RealmChat for RealmChatServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn pardon_user(self, _: Context, stoken: String, userid: String) -> Result<(), ErrorCode> {
|
async fn pardon_user(self, _: Context, stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode> {
|
||||||
if !self.internal_is_user_admin(&stoken).await {
|
if !self.internal_is_user_admin(&admin_userid).await {
|
||||||
return Err(Unauthorized)
|
return Err(Unauthorized)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
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
|
//NOTE: Any user can call, if they are in the server
|
||||||
async fn get_message(stoken: String, id: i64) -> Result<Message, ErrorCode>;
|
async fn get_message(stoken: String, userid: String, id: i64) -> Result<Message, ErrorCode>;
|
||||||
async fn get_messages_since(stoken: String, time: DateTime<Utc>) -> Result<Vec<Message>, ErrorCode>;
|
async fn get_messages_since(stoken: String, userid: String, time: DateTime<Utc>) -> Result<Vec<Message>, ErrorCode>;
|
||||||
async fn get_all_direct_replies(stoken: String, head: i64) -> Result<Vec<Message>, ErrorCode>;
|
async fn get_all_direct_replies(stoken: String, userid: String, head: i64) -> Result<Vec<Message>, ErrorCode>;
|
||||||
async fn get_reply_chain(stoken: String, head: Message, depth: u8) -> Result<ReplyChain, ErrorCode>;
|
async fn get_reply_chain(stoken: String, userid: String, head: Message, depth: u8) -> Result<ReplyChain, ErrorCode>;
|
||||||
async fn get_rooms(stoken: String) -> Result<Vec<Room>, ErrorCode>;
|
async fn get_rooms(stoken: String, userid: String) -> Result<Vec<Room>, ErrorCode>;
|
||||||
async fn get_room(stoken: String, roomid: String) -> Result<Room, ErrorCode>;
|
async fn get_room(stoken: String, userid: String, roomid: String) -> Result<Room, ErrorCode>;
|
||||||
async fn get_user(userid: String) -> Result<User, ErrorCode>;
|
async fn get_user(userid: String) -> Result<User, ErrorCode>;
|
||||||
async fn get_users() -> Result<Vec<User>, ErrorCode>;
|
async fn get_users() -> Result<Vec<User>, ErrorCode>;
|
||||||
async fn create_room(stoken: String, room: Room) -> Result<Room, ErrorCode>;
|
async fn create_room(stoken: String, userid: String, room: Room) -> Result<Room, ErrorCode>;
|
||||||
async fn delete_room(stoken: String, roomid: String) -> Result<(), ErrorCode>;
|
async fn delete_room(stoken: String, userid: String, roomid: String) -> Result<(), ErrorCode>;
|
||||||
async fn promote_user(stoken: String, userid: String) -> Result<(), ErrorCode>;
|
async fn promote_user(stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode>;
|
||||||
async fn demote_user(stoken: String, userid: String) -> Result<(), ErrorCode>;
|
async fn demote_user(stoken: String, owner_userid: String, userid: String) -> Result<(), ErrorCode>;
|
||||||
async fn kick_user(stoken: String, userid: String) -> Result<(), ErrorCode>;
|
async fn kick_user(stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode>;
|
||||||
async fn ban_user(stoken: String, userid: String) -> Result<(), ErrorCode>;
|
async fn ban_user(stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode>;
|
||||||
async fn pardon_user(stoken: String, userid: String) -> Result<(), ErrorCode>;
|
async fn pardon_user(stoken: String, admin_userid: String, userid: String) -> Result<(), ErrorCode>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
|||||||
Reference in New Issue
Block a user