diff --git a/src/auth/crypto_helper.rs b/src/auth/crypto_helper.rs index f1486b9..4f7d17a 100644 --- a/src/auth/crypto_helper.rs +++ b/src/auth/crypto_helper.rs @@ -1,12 +1,11 @@ use aes_gcm::{ - Aes256Gcm, // AES‑256 GCM - Nonce, + Aes256Gcm, Nonce, aead::{Aead, KeyInit, OsRng}, }; use base64::{Engine as _, engine::general_purpose::STANDARD}; use rand_core::RngCore; use sha2::{Digest, Sha256}; -use x448::{PublicKey, Secret, SharedSecret}; // from the `x448` crate +use x448::{PublicKey, Secret, SharedSecret}; /// Errors for crypto operations #[derive(Debug)] diff --git a/src/communities/community.rs b/src/communities/community.rs index 2d1d453..0429502 100644 --- a/src/communities/community.rs +++ b/src/communities/community.rs @@ -1,5 +1,6 @@ use crate::communities::interactables::category::Category; use crate::communities::interactables::registry; +use crate::communities::perms::permission::Permission; use crate::communities::{ community_connection::CommunityConnection, interactables::interactable::Interactable, }; @@ -27,8 +28,8 @@ pub struct Community { name: String, owner_id: Uuid, members: Vec, - permissions: HashMap>, - roles: HashMap>, + permissions: HashMap>, + roles: HashMap>, private_key: Secret, public_key: PublicKey, pub interactables: Arc>>>>, @@ -148,6 +149,13 @@ impl Community { .await .retain(|i| !Arc::ptr_eq(i, &interactable)); } + pub async fn broadcast_message(&self, message: &CommunicationValue) { + for (_, conns) in self.connections.read().await.clone().iter() { + for user in conns.iter() { + user.send_message(message).await; + } + } + } pub async fn run_function( self: &mut Arc, user_id: Uuid, @@ -240,7 +248,7 @@ pub async fn load(name: &String) -> Option> { let user_data = file_util::load_file(&format!("communities/{}/", name), "users.json"); let user_json: JsonValue = json::parse(&user_data).unwrap(); let mut users = Vec::new(); - let mut permissions: HashMap> = HashMap::new(); + let mut permissions: HashMap> = HashMap::new(); for user in user_json.entries() { let (str, json): (&str, &JsonValue) = user; @@ -258,7 +266,7 @@ pub async fn load(name: &String) -> Option> { } let role_data = file_util::load_file(&format!("communities/{}/", name), "roles.json"); - let roles: HashMap> = HashMap::new(); + let roles: HashMap> = HashMap::new(); if let Ok(_) = json::parse(&role_data) { // Fill roles } else { diff --git a/src/communities/interactables/category.rs b/src/communities/interactables/category.rs index 9fac8b6..4958735 100644 --- a/src/communities/interactables/category.rs +++ b/src/communities/interactables/category.rs @@ -6,8 +6,10 @@ use async_trait::async_trait; use json::JsonValue; use std::any::Any; use std::sync::Arc; +use uuid::Uuid; pub struct Category { + id: Uuid, name: String, path: String, community: Arc, @@ -16,6 +18,7 @@ pub struct Category { impl Category { pub fn new() -> Category { Category { + id: Uuid::new_v4(), name: String::new(), path: String::new(), community: Arc::new(Community::new()), @@ -50,6 +53,9 @@ impl Category { #[async_trait] impl Interactable for Category { + fn get_id(&self) -> &Uuid { + &self.id + } fn as_any(&self) -> &dyn Any { self } @@ -90,7 +96,7 @@ impl Interactable for Category { } v } - async fn run_function(&self, cv: CommunicationValue) -> CommunicationValue { + async fn run_function(&self, _cv: CommunicationValue) -> CommunicationValue { CommunicationValue::new(CommunicationType::error) } fn to_json(&self) -> JsonValue { @@ -101,8 +107,16 @@ impl Interactable for Category { } v } - fn load(&mut self, community: Arc, path: String, name: String, _json: &JsonValue) { + fn load( + &mut self, + community: Arc, + id: Uuid, + path: String, + name: String, + _json: &JsonValue, + ) { self.community = community; + self.id = id; self.name = name; self.path = path; } diff --git a/src/communities/interactables/interactable.rs b/src/communities/interactables/interactable.rs index 72f5252..9c9805c 100644 --- a/src/communities/interactables/interactable.rs +++ b/src/communities/interactables/interactable.rs @@ -3,6 +3,7 @@ use async_trait::async_trait; use json::JsonValue; use std::any::Any; use std::sync::Arc; +use uuid::Uuid; pub type InteractableFactory = fn() -> Box; @@ -20,6 +21,14 @@ pub trait Interactable: Send + Sync + Any { fn set_community(&mut self, community: Arc); async fn run_function(&self, cv: CommunicationValue) -> CommunicationValue; fn get_data(&self) -> JsonValue; + fn get_id(&self) -> &Uuid; fn to_json(&self) -> JsonValue; - fn load(&mut self, community: Arc, path: String, name: String, json: &JsonValue); + fn load( + &mut self, + community: Arc, + id: Uuid, + path: String, + name: String, + json: &JsonValue, + ); } diff --git a/src/communities/interactables/registry.rs b/src/communities/interactables/registry.rs index 67ecf3a..47fce92 100644 --- a/src/communities/interactables/registry.rs +++ b/src/communities/interactables/registry.rs @@ -9,6 +9,7 @@ use once_cell::sync::Lazy; use std::collections::HashMap; use std::sync::Arc; use tokio::sync::Mutex; +use uuid::Uuid; pub static INTERACTABLE_REGISTRY: Lazy>>> = Lazy::new(|| Arc::new(Mutex::new(HashMap::new()))); @@ -45,6 +46,7 @@ pub async fn get_interactable(name: &str) -> Box { pub async fn save(interactable: &Arc>) { let mut json_object: JsonValue = interactable.to_json().clone(); json_object["codec"] = JsonValue::String(interactable.get_codec()); + json_object["id"] = JsonValue::String(interactable.get_id().to_string()); file_util::save_file( &format!( "communities/{}/interactables/{}", @@ -66,7 +68,8 @@ pub async fn load( ); let json_object: JsonValue = json::parse(&s).unwrap(); let codec: String = json_object["codec"].as_str().unwrap().to_string(); + let id: String = json_object["id"].as_str().unwrap().to_string(); let mut interactable = get_interactable(&codec).await; - interactable.load(c, path, name, &json_object); + interactable.load(c, Uuid::parse_str(&id).unwrap(), path, name, &json_object); interactable } diff --git a/src/communities/interactables/text_chat.rs b/src/communities/interactables/text_chat.rs index b61b9c0..2978876 100644 --- a/src/communities/interactables/text_chat.rs +++ b/src/communities/interactables/text_chat.rs @@ -14,6 +14,7 @@ use std::sync::Arc; use std::{any::Any, collections::HashMap}; use uuid::Uuid; pub struct TextChat { + id: Uuid, name: String, path: String, community: Arc, @@ -21,6 +22,7 @@ pub struct TextChat { impl TextChat { pub fn new() -> TextChat { TextChat { + id: Uuid::new_v4(), name: String::new(), path: String::new(), community: Arc::new(Community::new()), @@ -152,6 +154,9 @@ impl TextChat { } #[async_trait] impl Interactable for TextChat { + fn get_id(&self) -> &Uuid { + &self.id + } fn as_any(&self) -> &dyn Any { self } @@ -242,8 +247,16 @@ impl Interactable for TextChat { fn to_json(&self) -> JsonValue { JsonValue::new_object() } - fn load(&mut self, community: Arc, path: String, name: String, _: &JsonValue) { + fn load( + &mut self, + community: Arc, + id: Uuid, + path: String, + name: String, + _json: &JsonValue, + ) { self.community = community; + self.id = id; self.name = name; self.path = path; } diff --git a/src/communities/interactables/voice_chat.rs b/src/communities/interactables/voice_chat.rs index c77134c..ad0b6ab 100644 --- a/src/communities/interactables/voice_chat.rs +++ b/src/communities/interactables/voice_chat.rs @@ -37,6 +37,7 @@ pub struct CallUser { } pub struct VoiceChat { + id: Uuid, name: String, path: String, community: Arc, @@ -45,6 +46,7 @@ pub struct VoiceChat { impl VoiceChat { pub fn new() -> VoiceChat { VoiceChat { + id: Uuid::new_v4(), name: String::new(), path: String::new(), community: Arc::new(Community::new()), @@ -71,6 +73,9 @@ impl VoiceChat { } #[async_trait] impl Interactable for VoiceChat { + fn get_id(&self) -> &Uuid { + &self.id + } fn as_any(&self) -> &dyn Any { self } @@ -102,25 +107,6 @@ impl Interactable for VoiceChat { String::new() + &self.path + "/" + &self.name } fn get_data(&self) -> JsonValue { - /* - * "data": { - "active_users": { - "user_id": { - "state": "", - "streaming": boolean - }, - "user_id": { - "state": "", - "streaming": boolean - }, - "user_id": { - "state": "", - "streaming": boolean - } - } - } - }, - */ let mut data = JsonValue::new_object(); let mut active_users = JsonValue::new_object(); for user in self.users.read().unwrap().iter() { @@ -188,8 +174,16 @@ impl Interactable for VoiceChat { let v = JsonValue::new_object(); v } - fn load(&mut self, community: Arc, path: String, name: String, _json: &JsonValue) { + fn load( + &mut self, + community: Arc, + id: Uuid, + path: String, + name: String, + _json: &JsonValue, + ) { self.community = community; + self.id = id; self.name = name; self.path = path; } diff --git a/src/communities/mod.rs b/src/communities/mod.rs index 3da58e3..237b709 100644 --- a/src/communities/mod.rs +++ b/src/communities/mod.rs @@ -8,3 +8,6 @@ pub mod interactables { } pub mod community; pub mod community_connection; +pub mod perms { + pub mod permission; +} diff --git a/src/communities/perms/permission.rs b/src/communities/perms/permission.rs new file mode 100644 index 0000000..50d1b27 --- /dev/null +++ b/src/communities/perms/permission.rs @@ -0,0 +1,27 @@ +use json::JsonValue; +use uuid::Uuid; + +pub struct Permission { + pub id: Uuid, + pub name: String, +} +impl Permission { + pub fn new(id: Uuid, name: String) -> Self { + Permission { id, name } + } + pub fn to_json(&self) -> JsonValue { + json::object! { + "id" => self.id.to_string(), + "name" => self.name.clone() + } + } + pub fn from_json(json: JsonValue) -> Self { + Permission { + id: Uuid::parse_str(json["id"].as_str().unwrap()).unwrap(), + name: json["name"].as_str().unwrap().to_string(), + } + } + pub fn to_string(&self) -> String { + self.to_json().as_str().unwrap().to_string() + } +} diff --git a/src/eula/eula_checker.rs b/src/eula/eula_checker.rs index b5237de..8e1798f 100644 --- a/src/eula/eula_checker.rs +++ b/src/eula/eula_checker.rs @@ -10,9 +10,9 @@ pub fn check_eula() -> bool { return false; } - if (file.contains("eula=false")) { + if file.contains("eula=false") { false - } else if (file.contains("eula=true")) { + } else if file.contains("eula=true") { true } else { false diff --git a/src/gui/log_panel.rs b/src/gui/log_panel.rs index 34c8b30..037bdf5 100644 --- a/src/gui/log_panel.rs +++ b/src/gui/log_panel.rs @@ -138,7 +138,7 @@ pub fn render() { .draw(|f| { let sys = System::new_all(); - let size = f.size(); + let size = f.area(); let chunks = Layout::default() .direction(Direction::Horizontal) .constraints([Constraint::Percentage(40), Constraint::Percentage(60)]) diff --git a/src/users/mod.rs b/src/users/mod.rs index 1623ca2..7e16bb5 100644 --- a/src/users/mod.rs +++ b/src/users/mod.rs @@ -2,4 +2,3 @@ pub mod contact; pub mod user_community_util; pub mod user_manager; pub mod user_profile; -pub mod user_profile_full; diff --git a/src/users/user_manager.rs b/src/users/user_manager.rs index 518003b..5703335 100644 --- a/src/users/user_manager.rs +++ b/src/users/user_manager.rs @@ -1,10 +1,9 @@ use crate::auth::auth_connector; use crate::users::user_profile::UserProfile; -use crate::users::user_profile_full::UserProfileFull; use crate::util::config_util::CONFIG; use crate::util::file_util::{load_file, save_file}; use base64::{Engine as _, engine::general_purpose::STANDARD}; -use hex; +use hex::{self}; use json::JsonValue; use once_cell::sync::Lazy; use rand::Rng; @@ -19,7 +18,7 @@ use x448::{PublicKey, Secret}; static USERS: Lazy>> = Lazy::new(|| Mutex::new(Vec::new())); static UNIQUE: Lazy> = Lazy::new(|| Mutex::new(false)); -pub async fn create_user(username: &str) -> Option { +pub async fn create_user(username: &str) -> (Option, Option) { let user_id = auth_connector::get_register().await.unwrap(); let mut buf = [0u8; 56]; let mut rng = OsRng; @@ -45,11 +44,6 @@ pub async fn create_user(username: &str) -> Option { reset_token, ); - let up_full = UserProfileFull { - user_profile: up.clone(), - private_key: STANDARD.encode(&private_key.as_bytes()), - }; - auth_connector::complete_register(&up, &CONFIG.lock().unwrap().get_iota_id().to_string()).await; save_file( "", @@ -57,9 +51,9 @@ pub async fn create_user(username: &str) -> Option { &format!("{}::{}", user_id, STANDARD.encode(&private_key.as_bytes())), ); - USERS.lock().unwrap().push(up); + USERS.lock().unwrap().push(up.clone()); save_users().ok(); - Some(up_full) + (Some(up), Some(STANDARD.encode(&private_key.as_bytes()))) } pub fn get_user(user_id: Uuid) -> Option { diff --git a/src/users/user_profile_full.rs b/src/users/user_profile_full.rs deleted file mode 100644 index f08f7d7..0000000 --- a/src/users/user_profile_full.rs +++ /dev/null @@ -1,8 +0,0 @@ -use crate::users::user_profile::UserProfile; - -// --- UserProfileFull --- -#[derive(Clone, Debug)] -pub struct UserProfileFull { - pub user_profile: UserProfile, - pub private_key: String, -}