Client auth, Encryption module
This commit is contained in:
parent
a1b93f1cb7
commit
5b5fbce22f
15 changed files with 2008 additions and 1003 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1 +1 @@
|
||||||
target
|
target
|
||||||
|
|
|
||||||
|
|
@ -1,123 +1,123 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
communities::{community::Community, interactables::interactable::Interactable},
|
communities::{community::Community, interactables::interactable::Interactable},
|
||||||
data::communication::{CommunicationType, CommunicationValue},
|
data::communication::{CommunicationType, CommunicationValue},
|
||||||
};
|
};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub struct Category {
|
pub struct Category {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
name: String,
|
name: String,
|
||||||
path: String,
|
path: String,
|
||||||
community: Arc<Community>,
|
community: Arc<Community>,
|
||||||
children: Vec<Arc<Box<dyn Interactable>>>,
|
children: Vec<Arc<Box<dyn Interactable>>>,
|
||||||
}
|
}
|
||||||
impl Category {
|
impl Category {
|
||||||
pub fn new() -> Category {
|
pub fn new() -> Category {
|
||||||
Category {
|
Category {
|
||||||
id: Uuid::new_v4(),
|
id: Uuid::new_v4(),
|
||||||
name: String::new(),
|
name: String::new(),
|
||||||
path: String::new(),
|
path: String::new(),
|
||||||
community: Arc::new(Community::new()),
|
community: Arc::new(Community::new()),
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn get_child(&self, path: String, name: String) -> Option<Arc<Box<dyn Interactable>>> {
|
pub fn get_child(&self, path: String, name: String) -> Option<Arc<Box<dyn Interactable>>> {
|
||||||
if path.is_empty() {
|
if path.is_empty() {
|
||||||
self.children
|
self.children
|
||||||
.iter()
|
.iter()
|
||||||
.find(|child| child.get_name() == &name)
|
.find(|child| child.get_name() == &name)
|
||||||
.cloned()
|
.cloned()
|
||||||
} else {
|
} else {
|
||||||
let sub_module = path.split("/").next().unwrap();
|
let sub_module = path.split("/").next().unwrap();
|
||||||
let next = self
|
let next = self
|
||||||
.children
|
.children
|
||||||
.iter()
|
.iter()
|
||||||
.find(|child| child.get_name() == sub_module)
|
.find(|child| child.get_name() == sub_module)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if next.get_codec() == "category" {
|
if next.get_codec() == "category" {
|
||||||
let next_cat = next.as_any().downcast_ref::<Category>().unwrap();
|
let next_cat = next.as_any().downcast_ref::<Category>().unwrap();
|
||||||
next_cat.get_child(path, name)
|
next_cat.get_child(path, name)
|
||||||
} else {
|
} else {
|
||||||
Some(next.clone())
|
Some(next.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn get_children(&self) -> Vec<Arc<Box<dyn Interactable>>> {
|
pub fn get_children(&self) -> Vec<Arc<Box<dyn Interactable>>> {
|
||||||
self.children.iter().map(|child| child.clone()).collect()
|
self.children.iter().map(|child| child.clone()).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Interactable for Category {
|
impl Interactable for Category {
|
||||||
fn get_id(&self) -> &Uuid {
|
fn get_id(&self) -> &Uuid {
|
||||||
&self.id
|
&self.id
|
||||||
}
|
}
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
fn get_codec(&self) -> String {
|
fn get_codec(&self) -> String {
|
||||||
"category".to_string()
|
"category".to_string()
|
||||||
}
|
}
|
||||||
fn set_name(&mut self, name: String) {
|
fn set_name(&mut self, name: String) {
|
||||||
self.name = name;
|
self.name = name;
|
||||||
}
|
}
|
||||||
fn set_path(&mut self, path: String) {
|
fn set_path(&mut self, path: String) {
|
||||||
self.path = path;
|
self.path = path;
|
||||||
}
|
}
|
||||||
fn get_community(&self) -> &Arc<Community> {
|
fn get_community(&self) -> &Arc<Community> {
|
||||||
&self.community
|
&self.community
|
||||||
}
|
}
|
||||||
fn set_community(&mut self, community: Arc<Community>) {
|
fn set_community(&mut self, community: Arc<Community>) {
|
||||||
self.community = community;
|
self.community = community;
|
||||||
}
|
}
|
||||||
fn get_name(&self) -> &String {
|
fn get_name(&self) -> &String {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
fn get_path(&self) -> &String {
|
fn get_path(&self) -> &String {
|
||||||
&self.path
|
&self.path
|
||||||
}
|
}
|
||||||
fn get_total_path(&self) -> String {
|
fn get_total_path(&self) -> String {
|
||||||
String::new() + &self.path + "/" + &self.name
|
String::new() + &self.path + "/" + &self.name
|
||||||
}
|
}
|
||||||
fn get_data(&self) -> JsonValue {
|
fn get_data(&self) -> JsonValue {
|
||||||
let mut v = JsonValue::new_object();
|
let mut v = JsonValue::new_object();
|
||||||
for child in &self.children {
|
for child in &self.children {
|
||||||
let mut subject = JsonValue::new_object();
|
let mut subject = JsonValue::new_object();
|
||||||
subject["codec"] = JsonValue::String(child.get_codec());
|
subject["codec"] = JsonValue::String(child.get_codec());
|
||||||
subject["data"] = child.get_data();
|
subject["data"] = child.get_data();
|
||||||
v[child.get_name()] = subject;
|
v[child.get_name()] = subject;
|
||||||
}
|
}
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
async fn run_function(&self, _cv: CommunicationValue) -> CommunicationValue {
|
async fn run_function(&self, _cv: CommunicationValue) -> CommunicationValue {
|
||||||
CommunicationValue::new(CommunicationType::error)
|
CommunicationValue::new(CommunicationType::error)
|
||||||
}
|
}
|
||||||
fn to_json(&self) -> JsonValue {
|
fn to_json(&self) -> JsonValue {
|
||||||
let mut v = JsonValue::new_object();
|
let mut v = JsonValue::new_object();
|
||||||
v["children"] = JsonValue::new_array();
|
v["children"] = JsonValue::new_array();
|
||||||
for child in &self.children {
|
for child in &self.children {
|
||||||
let _ = v["children"].push(child.to_json());
|
let _ = v["children"].push(child.to_json());
|
||||||
}
|
}
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
fn load(
|
fn load(
|
||||||
&mut self,
|
&mut self,
|
||||||
community: Arc<Community>,
|
community: Arc<Community>,
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
path: String,
|
path: String,
|
||||||
name: String,
|
name: String,
|
||||||
_json: &JsonValue,
|
_json: &JsonValue,
|
||||||
) {
|
) {
|
||||||
self.community = community;
|
self.community = community;
|
||||||
self.id = id;
|
self.id = id;
|
||||||
self.name = name;
|
self.name = name;
|
||||||
self.path = path;
|
self.path = path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,34 @@
|
||||||
use crate::{communities::community::Community, data::communication::CommunicationValue};
|
use crate::{communities::community::Community, data::communication::CommunicationValue};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub type InteractableFactory = fn() -> Box<dyn Interactable>;
|
pub type InteractableFactory = fn() -> Box<dyn Interactable>;
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait Interactable: Send + Sync + Any {
|
pub trait Interactable: Send + Sync + Any {
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||||
fn get_codec(&self) -> String;
|
fn get_codec(&self) -> String;
|
||||||
fn get_name(&self) -> &String;
|
fn get_name(&self) -> &String;
|
||||||
fn get_path(&self) -> &String;
|
fn get_path(&self) -> &String;
|
||||||
fn get_total_path(&self) -> String;
|
fn get_total_path(&self) -> String;
|
||||||
fn set_name(&mut self, name: String);
|
fn set_name(&mut self, name: String);
|
||||||
fn set_path(&mut self, path: String);
|
fn set_path(&mut self, path: String);
|
||||||
fn get_community(&self) -> &Arc<Community>;
|
fn get_community(&self) -> &Arc<Community>;
|
||||||
fn set_community(&mut self, community: Arc<Community>);
|
fn set_community(&mut self, community: Arc<Community>);
|
||||||
async fn run_function(&self, cv: CommunicationValue) -> CommunicationValue;
|
async fn run_function(&self, cv: CommunicationValue) -> CommunicationValue;
|
||||||
fn get_data(&self) -> JsonValue;
|
fn get_data(&self) -> JsonValue;
|
||||||
fn get_id(&self) -> &Uuid;
|
fn get_id(&self) -> &Uuid;
|
||||||
fn to_json(&self) -> JsonValue;
|
fn to_json(&self) -> JsonValue;
|
||||||
fn load(
|
fn load(
|
||||||
&mut self,
|
&mut self,
|
||||||
community: Arc<Community>,
|
community: Arc<Community>,
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
path: String,
|
path: String,
|
||||||
name: String,
|
name: String,
|
||||||
json: &JsonValue,
|
json: &JsonValue,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,75 +1,75 @@
|
||||||
use crate::communities::community::Community;
|
use crate::communities::community::Community;
|
||||||
use crate::communities::interactables::category::Category;
|
use crate::communities::interactables::category::Category;
|
||||||
use crate::communities::interactables::interactable::{Interactable, InteractableFactory};
|
use crate::communities::interactables::interactable::{Interactable, InteractableFactory};
|
||||||
use crate::communities::interactables::text_chat::TextChat;
|
use crate::communities::interactables::text_chat::TextChat;
|
||||||
use crate::communities::interactables::voice_chat::VoiceChat;
|
use crate::communities::interactables::voice_chat::VoiceChat;
|
||||||
use crate::util::file_util;
|
use crate::util::file_util;
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub static INTERACTABLE_REGISTRY: Lazy<Arc<Mutex<HashMap<String, InteractableFactory>>>> =
|
pub static INTERACTABLE_REGISTRY: Lazy<Arc<Mutex<HashMap<String, InteractableFactory>>>> =
|
||||||
Lazy::new(|| Arc::new(Mutex::new(HashMap::new())));
|
Lazy::new(|| Arc::new(Mutex::new(HashMap::new())));
|
||||||
pub async fn load_interactables() {
|
pub async fn load_interactables() {
|
||||||
INTERACTABLE_REGISTRY
|
INTERACTABLE_REGISTRY
|
||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
.insert(TextChat::new().get_codec(), || {
|
.insert(TextChat::new().get_codec(), || {
|
||||||
Box::new(TextChat::new()) as Box<dyn Interactable>
|
Box::new(TextChat::new()) as Box<dyn Interactable>
|
||||||
});
|
});
|
||||||
INTERACTABLE_REGISTRY
|
INTERACTABLE_REGISTRY
|
||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
.insert(VoiceChat::new().get_codec(), || {
|
.insert(VoiceChat::new().get_codec(), || {
|
||||||
Box::new(VoiceChat::new()) as Box<dyn Interactable>
|
Box::new(VoiceChat::new()) as Box<dyn Interactable>
|
||||||
});
|
});
|
||||||
INTERACTABLE_REGISTRY
|
INTERACTABLE_REGISTRY
|
||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
.insert(Category::new().get_codec(), || {
|
.insert(Category::new().get_codec(), || {
|
||||||
Box::new(Category::new()) as Box<dyn Interactable>
|
Box::new(Category::new()) as Box<dyn Interactable>
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
pub async fn register_interactable(name: String, interactable: InteractableFactory) {
|
pub async fn register_interactable(name: String, interactable: InteractableFactory) {
|
||||||
INTERACTABLE_REGISTRY
|
INTERACTABLE_REGISTRY
|
||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
.insert(name.to_string(), interactable)
|
.insert(name.to_string(), interactable)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
pub async fn get_interactable(name: &str) -> Box<dyn Interactable> {
|
pub async fn get_interactable(name: &str) -> Box<dyn Interactable> {
|
||||||
INTERACTABLE_REGISTRY.lock().await.get(name).unwrap()()
|
INTERACTABLE_REGISTRY.lock().await.get(name).unwrap()()
|
||||||
}
|
}
|
||||||
pub async fn save(interactable: &Arc<Box<dyn Interactable>>) {
|
pub async fn save(interactable: &Arc<Box<dyn Interactable>>) {
|
||||||
let mut json_object: JsonValue = interactable.to_json().clone();
|
let mut json_object: JsonValue = interactable.to_json().clone();
|
||||||
json_object["codec"] = JsonValue::String(interactable.get_codec());
|
json_object["codec"] = JsonValue::String(interactable.get_codec());
|
||||||
json_object["id"] = JsonValue::String(interactable.get_id().to_string());
|
json_object["id"] = JsonValue::String(interactable.get_id().to_string());
|
||||||
file_util::save_file(
|
file_util::save_file(
|
||||||
&format!(
|
&format!(
|
||||||
"communities/{}/interactables/{}",
|
"communities/{}/interactables/{}",
|
||||||
interactable.get_community().get_name(),
|
interactable.get_community().get_name(),
|
||||||
interactable.get_path()
|
interactable.get_path()
|
||||||
),
|
),
|
||||||
&format!("{}.json", interactable.get_name()),
|
&format!("{}.json", interactable.get_name()),
|
||||||
&json_object.to_string(),
|
&json_object.to_string(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
pub async fn load(
|
pub async fn load(
|
||||||
c: Arc<Community>,
|
c: Arc<Community>,
|
||||||
path: String,
|
path: String,
|
||||||
name: String,
|
name: String,
|
||||||
) -> Box<dyn Interactable + 'static> {
|
) -> Box<dyn Interactable + 'static> {
|
||||||
let s = file_util::load_file(
|
let s = file_util::load_file(
|
||||||
&format!("communities/{}/interactables/{}", c.get_name(), path),
|
&format!("communities/{}/interactables/{}", c.get_name(), path),
|
||||||
&format!("{}.json", name),
|
&format!("{}.json", name),
|
||||||
);
|
);
|
||||||
let json_object: JsonValue = json::parse(&s).unwrap();
|
let json_object: JsonValue = json::parse(&s).unwrap();
|
||||||
let codec: String = json_object["codec"].as_str().unwrap().to_string();
|
let codec: String = json_object["codec"].as_str().unwrap().to_string();
|
||||||
let id: String = json_object["id"].as_str().unwrap().to_string();
|
let id: String = json_object["id"].as_str().unwrap().to_string();
|
||||||
let mut interactable = get_interactable(&codec).await;
|
let mut interactable = get_interactable(&codec).await;
|
||||||
interactable.load(c, Uuid::parse_str(&id).unwrap(), path, name, &json_object);
|
interactable.load(c, Uuid::parse_str(&id).unwrap(), path, name, &json_object);
|
||||||
interactable
|
interactable
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,262 +1,262 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
communities::{
|
communities::{
|
||||||
community::Community, community_connection::CommunityConnection,
|
community::Community, community_connection::CommunityConnection,
|
||||||
interactables::interactable::Interactable,
|
interactables::interactable::Interactable,
|
||||||
},
|
},
|
||||||
data::communication::{CommunicationType, CommunicationValue, DataTypes},
|
data::communication::{CommunicationType, CommunicationValue, DataTypes},
|
||||||
gui::log_panel::log_message,
|
gui::log_panel::log_message,
|
||||||
util::file_util::{get_children, load_file, save_file},
|
util::file_util::{get_children, load_file, save_file},
|
||||||
};
|
};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use json::{JsonValue, array, object};
|
use json::{JsonValue, array, object};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{any::Any, collections::HashMap};
|
use std::{any::Any, collections::HashMap};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
pub struct TextChat {
|
pub struct TextChat {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
name: String,
|
name: String,
|
||||||
path: String,
|
path: String,
|
||||||
community: Arc<Community>,
|
community: Arc<Community>,
|
||||||
}
|
}
|
||||||
impl TextChat {
|
impl TextChat {
|
||||||
pub fn new() -> TextChat {
|
pub fn new() -> TextChat {
|
||||||
TextChat {
|
TextChat {
|
||||||
id: Uuid::new_v4(),
|
id: Uuid::new_v4(),
|
||||||
name: String::new(),
|
name: String::new(),
|
||||||
path: String::new(),
|
path: String::new(),
|
||||||
community: Arc::new(Community::new()),
|
community: Arc::new(Community::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn add_message(&self, send_time: u128, sender: i64, message: &str) {
|
pub fn add_message(&self, send_time: u128, sender: i64, message: &str) {
|
||||||
let user_dir = &format!(
|
let user_dir = &format!(
|
||||||
"communities/{}/interactables/{}/{}",
|
"communities/{}/interactables/{}/{}",
|
||||||
self.get_community().get_name(),
|
self.get_community().get_name(),
|
||||||
self.get_path(),
|
self.get_path(),
|
||||||
self.get_name()
|
self.get_name()
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Err(e) = fs::create_dir_all(user_dir) {
|
if let Err(e) = fs::create_dir_all(user_dir) {
|
||||||
log_message(format!("Failed to create chat directory: {}", e));
|
log_message(format!("Failed to create chat directory: {}", e));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut chunk_index = 0;
|
let mut chunk_index = 0;
|
||||||
let mut message_chunk = array![];
|
let mut message_chunk = array![];
|
||||||
|
|
||||||
// find latest chunk not full (max 800 msgs)
|
// find latest chunk not full (max 800 msgs)
|
||||||
loop {
|
loop {
|
||||||
let file_name = format!("msgs_{}.json", chunk_index);
|
let file_name = format!("msgs_{}.json", chunk_index);
|
||||||
let file_content = load_file(&user_dir, &file_name);
|
let file_content = load_file(&user_dir, &file_name);
|
||||||
|
|
||||||
if !file_content.is_empty() {
|
if !file_content.is_empty() {
|
||||||
if let Ok(current_chunk) = json::parse(&file_content) {
|
if let Ok(current_chunk) = json::parse(&file_content) {
|
||||||
if current_chunk.is_array() && current_chunk.len() < 800 {
|
if current_chunk.is_array() && current_chunk.len() < 800 {
|
||||||
message_chunk = current_chunk;
|
message_chunk = current_chunk;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log_message(format!("Failed to parse existing JSON file: {}", file_name));
|
log_message(format!("Failed to parse existing JSON file: {}", file_name));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// New file, use empty array
|
// New file, use empty array
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_index += 1;
|
chunk_index += 1;
|
||||||
if chunk_index > 1000 {
|
if chunk_index > 1000 {
|
||||||
log_message(format!("Too many message chunks. Aborting add."));
|
log_message(format!("Too many message chunks. Aborting add."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let json_obj = object! {
|
let json_obj = object! {
|
||||||
"timestamp" => send_time as i64,
|
"timestamp" => send_time as i64,
|
||||||
"content" => message,
|
"content" => message,
|
||||||
"sender" => sender.to_string(),
|
"sender" => sender.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(e) = message_chunk.push(json_obj) {
|
if let Err(e) = message_chunk.push(json_obj) {
|
||||||
log_message(format!("Failed to push new message into JSON array: {}", e));
|
log_message(format!("Failed to push new message into JSON array: {}", e));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let file_name = format!("msgs_{}.json", chunk_index);
|
let file_name = format!("msgs_{}.json", chunk_index);
|
||||||
log_message(format!("Saving message to {}/{}", user_dir, file_name));
|
log_message(format!("Saving message to {}/{}", user_dir, file_name));
|
||||||
save_file(&user_dir, &file_name, &message_chunk.dump());
|
save_file(&user_dir, &file_name, &message_chunk.dump());
|
||||||
}
|
}
|
||||||
pub fn get_messages(&self, loaded_messages: i64, amount: i64) -> JsonValue {
|
pub fn get_messages(&self, loaded_messages: i64, amount: i64) -> JsonValue {
|
||||||
let mut messages = array![];
|
let mut messages = array![];
|
||||||
|
|
||||||
let mut latest_chunk_index: i32 = -1;
|
let mut latest_chunk_index: i32 = -1;
|
||||||
let files = get_children(&format!(
|
let files = get_children(&format!(
|
||||||
"communities/{}/interactables/{}/{}",
|
"communities/{}/interactables/{}/{}",
|
||||||
self.get_community().get_name(),
|
self.get_community().get_name(),
|
||||||
self.get_path(),
|
self.get_path(),
|
||||||
self.get_name()
|
self.get_name()
|
||||||
));
|
));
|
||||||
|
|
||||||
for entry in files {
|
for entry in files {
|
||||||
if let Some(num) = {
|
if let Some(num) = {
|
||||||
entry
|
entry
|
||||||
.strip_prefix("msgs_")
|
.strip_prefix("msgs_")
|
||||||
.and_then(|s| s.strip_suffix(".json"))
|
.and_then(|s| s.strip_suffix(".json"))
|
||||||
} {
|
} {
|
||||||
if let Ok(index) = num.parse::<i32>() {
|
if let Ok(index) = num.parse::<i32>() {
|
||||||
if index > latest_chunk_index {
|
if index > latest_chunk_index {
|
||||||
latest_chunk_index = index;
|
latest_chunk_index = index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if latest_chunk_index == -1 {
|
if latest_chunk_index == -1 {
|
||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut to_skip = loaded_messages;
|
let mut to_skip = loaded_messages;
|
||||||
let mut needed = amount;
|
let mut needed = amount;
|
||||||
|
|
||||||
for chunk_index in (0..=latest_chunk_index).rev() {
|
for chunk_index in (0..=latest_chunk_index).rev() {
|
||||||
if needed == 0 {
|
if needed == 0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let file_name = format!("msgs_{}.json", chunk_index);
|
let file_name = format!("msgs_{}.json", chunk_index);
|
||||||
let file_content = load_file(
|
let file_content = load_file(
|
||||||
&format!(
|
&format!(
|
||||||
"communities/{}/interactables/{}/{}",
|
"communities/{}/interactables/{}/{}",
|
||||||
self.get_community().get_name(),
|
self.get_community().get_name(),
|
||||||
self.get_path(),
|
self.get_path(),
|
||||||
self.get_name()
|
self.get_name()
|
||||||
),
|
),
|
||||||
&file_name,
|
&file_name,
|
||||||
);
|
);
|
||||||
if file_content.is_empty() {
|
if file_content.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Ok(chunk) = json::parse(&file_content) {
|
if let Ok(chunk) = json::parse(&file_content) {
|
||||||
for i in (0..chunk.len()).rev() {
|
for i in (0..chunk.len()).rev() {
|
||||||
if needed == 0 {
|
if needed == 0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if to_skip > 0 {
|
if to_skip > 0 {
|
||||||
to_skip -= 1;
|
to_skip -= 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
messages.push(chunk[i].clone()).unwrap();
|
messages.push(chunk[i].clone()).unwrap();
|
||||||
needed -= 1;
|
needed -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
messages
|
messages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Interactable for TextChat {
|
impl Interactable for TextChat {
|
||||||
fn get_id(&self) -> &Uuid {
|
fn get_id(&self) -> &Uuid {
|
||||||
&self.id
|
&self.id
|
||||||
}
|
}
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
fn get_codec(&self) -> String {
|
fn get_codec(&self) -> String {
|
||||||
"text".to_string()
|
"text".to_string()
|
||||||
}
|
}
|
||||||
fn set_name(&mut self, name: String) {
|
fn set_name(&mut self, name: String) {
|
||||||
self.name = name;
|
self.name = name;
|
||||||
}
|
}
|
||||||
fn set_path(&mut self, path: String) {
|
fn set_path(&mut self, path: String) {
|
||||||
self.path = path;
|
self.path = path;
|
||||||
}
|
}
|
||||||
fn get_community(&self) -> &Arc<Community> {
|
fn get_community(&self) -> &Arc<Community> {
|
||||||
&self.community
|
&self.community
|
||||||
}
|
}
|
||||||
fn set_community(&mut self, community: Arc<Community>) {
|
fn set_community(&mut self, community: Arc<Community>) {
|
||||||
self.community = community;
|
self.community = community;
|
||||||
}
|
}
|
||||||
fn get_name(&self) -> &String {
|
fn get_name(&self) -> &String {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
fn get_path(&self) -> &String {
|
fn get_path(&self) -> &String {
|
||||||
&self.path
|
&self.path
|
||||||
}
|
}
|
||||||
fn get_total_path(&self) -> String {
|
fn get_total_path(&self) -> String {
|
||||||
String::new() + &self.path + "/" + &self.name
|
String::new() + &self.path + "/" + &self.name
|
||||||
}
|
}
|
||||||
fn get_data(&self) -> JsonValue {
|
fn get_data(&self) -> JsonValue {
|
||||||
JsonValue::new_object()
|
JsonValue::new_object()
|
||||||
}
|
}
|
||||||
async fn run_function(&self, cv: CommunicationValue) -> CommunicationValue {
|
async fn run_function(&self, cv: CommunicationValue) -> CommunicationValue {
|
||||||
let payload = cv.get_data(DataTypes::payload).unwrap();
|
let payload = cv.get_data(DataTypes::payload).unwrap();
|
||||||
if cv.get_data(DataTypes::function).unwrap().as_str().unwrap() == "get_messages" {
|
if cv.get_data(DataTypes::function).unwrap().as_str().unwrap() == "get_messages" {
|
||||||
let amount = payload["amount"].as_i64().unwrap();
|
let amount = payload["amount"].as_i64().unwrap();
|
||||||
let loaded_messages = payload["loaded_messages"].as_i64().unwrap();
|
let loaded_messages = payload["loaded_messages"].as_i64().unwrap();
|
||||||
let messages = self.get_messages(loaded_messages, amount).clone();
|
let messages = self.get_messages(loaded_messages, amount).clone();
|
||||||
let mut payload = JsonValue::new_object();
|
let mut payload = JsonValue::new_object();
|
||||||
payload["messages"] = messages;
|
payload["messages"] = messages;
|
||||||
return CommunicationValue::new(CommunicationType::function)
|
return CommunicationValue::new(CommunicationType::function)
|
||||||
.with_id(cv.get_id())
|
.with_id(cv.get_id())
|
||||||
.add_data_str(DataTypes::name, self.name.clone())
|
.add_data_str(DataTypes::name, self.name.clone())
|
||||||
.add_data_str(DataTypes::path, self.path.clone())
|
.add_data_str(DataTypes::path, self.path.clone())
|
||||||
.add_data_str(DataTypes::result, "message_chunk".to_string())
|
.add_data_str(DataTypes::result, "message_chunk".to_string())
|
||||||
.add_data(DataTypes::payload, payload);
|
.add_data(DataTypes::payload, payload);
|
||||||
}
|
}
|
||||||
if cv.get_data(DataTypes::function).unwrap().as_str().unwrap() == "send_message" {
|
if cv.get_data(DataTypes::function).unwrap().as_str().unwrap() == "send_message" {
|
||||||
let message = payload["message"].as_str().unwrap();
|
let message = payload["message"].as_str().unwrap();
|
||||||
let milliseconds_timestamp: u128 = std::time::SystemTime::now()
|
let milliseconds_timestamp: u128 = std::time::SystemTime::now()
|
||||||
.duration_since(std::time::UNIX_EPOCH)
|
.duration_since(std::time::UNIX_EPOCH)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_millis();
|
.as_millis();
|
||||||
self.add_message(milliseconds_timestamp, cv.get_sender(), message);
|
self.add_message(milliseconds_timestamp, cv.get_sender(), message);
|
||||||
|
|
||||||
let mut distribution_payload = JsonValue::new_object();
|
let mut distribution_payload = JsonValue::new_object();
|
||||||
distribution_payload["message"] = JsonValue::String(message.to_string());
|
distribution_payload["message"] = JsonValue::String(message.to_string());
|
||||||
distribution_payload["sender_id"] = JsonValue::String(cv.get_sender().to_string());
|
distribution_payload["sender_id"] = JsonValue::String(cv.get_sender().to_string());
|
||||||
distribution_payload["send_time"] =
|
distribution_payload["send_time"] =
|
||||||
JsonValue::String(milliseconds_timestamp.to_string());
|
JsonValue::String(milliseconds_timestamp.to_string());
|
||||||
let distribution = CommunicationValue::new(CommunicationType::update)
|
let distribution = CommunicationValue::new(CommunicationType::update)
|
||||||
.with_id(cv.get_id())
|
.with_id(cv.get_id())
|
||||||
.add_data_str(DataTypes::name, self.name.clone())
|
.add_data_str(DataTypes::name, self.name.clone())
|
||||||
.add_data_str(DataTypes::path, self.path.clone())
|
.add_data_str(DataTypes::path, self.path.clone())
|
||||||
.add_data_str(DataTypes::result, "message_live".to_string())
|
.add_data_str(DataTypes::result, "message_live".to_string())
|
||||||
.add_data(DataTypes::payload, distribution_payload);
|
.add_data(DataTypes::payload, distribution_payload);
|
||||||
|
|
||||||
let connections: HashMap<i64, Vec<Arc<CommunityConnection>>> =
|
let connections: HashMap<i64, Vec<Arc<CommunityConnection>>> =
|
||||||
self.get_community().get_connections().await.clone();
|
self.get_community().get_connections().await.clone();
|
||||||
|
|
||||||
for con in connections.values() {
|
for con in connections.values() {
|
||||||
for c in con {
|
for c in con {
|
||||||
let cd: &Arc<CommunityConnection> = c;
|
let cd: &Arc<CommunityConnection> = c;
|
||||||
cd.send_message(&distribution).await;
|
cd.send_message(&distribution).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CommunicationValue::new(CommunicationType::function)
|
return CommunicationValue::new(CommunicationType::function)
|
||||||
.with_id(cv.get_id())
|
.with_id(cv.get_id())
|
||||||
.add_data_str(DataTypes::name, self.name.clone())
|
.add_data_str(DataTypes::name, self.name.clone())
|
||||||
.add_data_str(DataTypes::path, self.path.clone())
|
.add_data_str(DataTypes::path, self.path.clone())
|
||||||
.add_data_str(DataTypes::result, "message_received".to_string())
|
.add_data_str(DataTypes::result, "message_received".to_string())
|
||||||
.add_data(DataTypes::payload, JsonValue::new_object());
|
.add_data(DataTypes::payload, JsonValue::new_object());
|
||||||
}
|
}
|
||||||
CommunicationValue::new(CommunicationType::error).with_id(cv.get_id())
|
CommunicationValue::new(CommunicationType::error).with_id(cv.get_id())
|
||||||
}
|
}
|
||||||
fn to_json(&self) -> JsonValue {
|
fn to_json(&self) -> JsonValue {
|
||||||
JsonValue::new_object()
|
JsonValue::new_object()
|
||||||
}
|
}
|
||||||
fn load(
|
fn load(
|
||||||
&mut self,
|
&mut self,
|
||||||
community: Arc<Community>,
|
community: Arc<Community>,
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
path: String,
|
path: String,
|
||||||
name: String,
|
name: String,
|
||||||
_json: &JsonValue,
|
_json: &JsonValue,
|
||||||
) {
|
) {
|
||||||
self.community = community;
|
self.community = community;
|
||||||
self.id = id;
|
self.id = id;
|
||||||
self.name = name;
|
self.name = name;
|
||||||
self.path = path;
|
self.path = path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,190 +1,190 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
communities::{community::Community, interactables::interactable::Interactable},
|
communities::{community::Community, interactables::interactable::Interactable},
|
||||||
data::communication::{CommunicationType, CommunicationValue, DataTypes},
|
data::communication::{CommunicationType, CommunicationValue, DataTypes},
|
||||||
};
|
};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{any::Any, sync::RwLock};
|
use std::{any::Any, sync::RwLock};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
pub enum CallUserState {
|
pub enum CallUserState {
|
||||||
Active,
|
Active,
|
||||||
Muted,
|
Muted,
|
||||||
Deafed,
|
Deafed,
|
||||||
}
|
}
|
||||||
impl CallUserState {
|
impl CallUserState {
|
||||||
pub fn parse(state: &str) -> CallUserState {
|
pub fn parse(state: &str) -> CallUserState {
|
||||||
match state {
|
match state {
|
||||||
"active" => CallUserState::Active,
|
"active" => CallUserState::Active,
|
||||||
"muted" => CallUserState::Muted,
|
"muted" => CallUserState::Muted,
|
||||||
"deafed" => CallUserState::Deafed,
|
"deafed" => CallUserState::Deafed,
|
||||||
_ => CallUserState::Active,
|
_ => CallUserState::Active,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn to_string(&self) -> String {
|
pub fn to_string(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
CallUserState::Active => "active".to_string(),
|
CallUserState::Active => "active".to_string(),
|
||||||
CallUserState::Muted => "muted".to_string(),
|
CallUserState::Muted => "muted".to_string(),
|
||||||
CallUserState::Deafed => "deafed".to_string(),
|
CallUserState::Deafed => "deafed".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CallUser {
|
pub struct CallUser {
|
||||||
pub user_id: Uuid,
|
pub user_id: Uuid,
|
||||||
pub user_state: CallUserState,
|
pub user_state: CallUserState,
|
||||||
pub streaming: bool,
|
pub streaming: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct VoiceChat {
|
pub struct VoiceChat {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
name: String,
|
name: String,
|
||||||
path: String,
|
path: String,
|
||||||
community: Arc<Community>,
|
community: Arc<Community>,
|
||||||
users: RwLock<Vec<CallUser>>,
|
users: RwLock<Vec<CallUser>>,
|
||||||
}
|
}
|
||||||
impl VoiceChat {
|
impl VoiceChat {
|
||||||
pub fn new() -> VoiceChat {
|
pub fn new() -> VoiceChat {
|
||||||
VoiceChat {
|
VoiceChat {
|
||||||
id: Uuid::new_v4(),
|
id: Uuid::new_v4(),
|
||||||
name: String::new(),
|
name: String::new(),
|
||||||
path: String::new(),
|
path: String::new(),
|
||||||
community: Arc::new(Community::new()),
|
community: Arc::new(Community::new()),
|
||||||
users: RwLock::new(Vec::new()),
|
users: RwLock::new(Vec::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn update_user_state(
|
pub fn update_user_state(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
state: CallUserState,
|
state: CallUserState,
|
||||||
streaming: bool,
|
streaming: bool,
|
||||||
) {
|
) {
|
||||||
if let Some(user) = self
|
if let Some(user) = self
|
||||||
.users
|
.users
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|u| u.user_id == user_id)
|
.find(|u| u.user_id == user_id)
|
||||||
{
|
{
|
||||||
user.user_state = state;
|
user.user_state = state;
|
||||||
user.streaming = streaming;
|
user.streaming = streaming;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl Interactable for VoiceChat {
|
impl Interactable for VoiceChat {
|
||||||
fn get_id(&self) -> &Uuid {
|
fn get_id(&self) -> &Uuid {
|
||||||
&self.id
|
&self.id
|
||||||
}
|
}
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
fn get_codec(&self) -> String {
|
fn get_codec(&self) -> String {
|
||||||
"voice".to_string()
|
"voice".to_string()
|
||||||
}
|
}
|
||||||
fn set_name(&mut self, name: String) {
|
fn set_name(&mut self, name: String) {
|
||||||
self.name = name;
|
self.name = name;
|
||||||
}
|
}
|
||||||
fn set_path(&mut self, path: String) {
|
fn set_path(&mut self, path: String) {
|
||||||
self.path = path;
|
self.path = path;
|
||||||
}
|
}
|
||||||
fn get_community(&self) -> &Arc<Community> {
|
fn get_community(&self) -> &Arc<Community> {
|
||||||
&self.community
|
&self.community
|
||||||
}
|
}
|
||||||
fn set_community(&mut self, community: Arc<Community>) {
|
fn set_community(&mut self, community: Arc<Community>) {
|
||||||
self.community = community;
|
self.community = community;
|
||||||
}
|
}
|
||||||
fn get_name(&self) -> &String {
|
fn get_name(&self) -> &String {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
fn get_path(&self) -> &String {
|
fn get_path(&self) -> &String {
|
||||||
&self.path
|
&self.path
|
||||||
}
|
}
|
||||||
fn get_total_path(&self) -> String {
|
fn get_total_path(&self) -> String {
|
||||||
String::new() + &self.path + "/" + &self.name
|
String::new() + &self.path + "/" + &self.name
|
||||||
}
|
}
|
||||||
fn get_data(&self) -> JsonValue {
|
fn get_data(&self) -> JsonValue {
|
||||||
let mut data = JsonValue::new_object();
|
let mut data = JsonValue::new_object();
|
||||||
let mut active_users = JsonValue::new_object();
|
let mut active_users = JsonValue::new_object();
|
||||||
for user in self.users.read().unwrap().iter() {
|
for user in self.users.read().unwrap().iter() {
|
||||||
let mut user_data = JsonValue::new_object();
|
let mut user_data = JsonValue::new_object();
|
||||||
let _ = user_data.insert("state", JsonValue::String(user.user_state.to_string()));
|
let _ = user_data.insert("state", JsonValue::String(user.user_state.to_string()));
|
||||||
let _ = user_data.insert("streaming", JsonValue::Boolean(user.streaming));
|
let _ = user_data.insert("streaming", JsonValue::Boolean(user.streaming));
|
||||||
let _ = active_users.insert(&user.user_id.to_string(), user_data);
|
let _ = active_users.insert(&user.user_id.to_string(), user_data);
|
||||||
}
|
}
|
||||||
let _ = data.insert("active_users", active_users);
|
let _ = data.insert("active_users", active_users);
|
||||||
data
|
data
|
||||||
}
|
}
|
||||||
async fn run_function(&self, cv: CommunicationValue) -> CommunicationValue {
|
async fn run_function(&self, cv: CommunicationValue) -> CommunicationValue {
|
||||||
let payload = cv.get_data(DataTypes::payload).unwrap();
|
let payload = cv.get_data(DataTypes::payload).unwrap();
|
||||||
let function = cv.get_data(DataTypes::function).unwrap().as_str().unwrap();
|
let function = cv.get_data(DataTypes::function).unwrap().as_str().unwrap();
|
||||||
|
|
||||||
if function == "get_call" {
|
if function == "get_call" {
|
||||||
let sender_id = payload["sender_id"].as_str().unwrap();
|
let sender_id = payload["sender_id"].as_str().unwrap();
|
||||||
let message_id = payload["message"].as_str().unwrap();
|
let message_id = payload["message"].as_str().unwrap();
|
||||||
let send_time = payload["send_time"].as_str().unwrap();
|
let send_time = payload["send_time"].as_str().unwrap();
|
||||||
|
|
||||||
let mut response_payload = JsonValue::new_object();
|
let mut response_payload = JsonValue::new_object();
|
||||||
response_payload["sender_id"] = JsonValue::String(sender_id.to_string());
|
response_payload["sender_id"] = JsonValue::String(sender_id.to_string());
|
||||||
response_payload["message"] = JsonValue::String(message_id.to_string());
|
response_payload["message"] = JsonValue::String(message_id.to_string());
|
||||||
response_payload["send_time"] = JsonValue::String(send_time.to_string());
|
response_payload["send_time"] = JsonValue::String(send_time.to_string());
|
||||||
|
|
||||||
return CommunicationValue::new(CommunicationType::function)
|
return CommunicationValue::new(CommunicationType::function)
|
||||||
.with_id(cv.get_id())
|
.with_id(cv.get_id())
|
||||||
.add_data_str(DataTypes::name, self.name.clone())
|
.add_data_str(DataTypes::name, self.name.clone())
|
||||||
.add_data_str(DataTypes::path, self.path.clone())
|
.add_data_str(DataTypes::path, self.path.clone())
|
||||||
.add_data_str(DataTypes::result, "getting_call".to_string())
|
.add_data_str(DataTypes::result, "getting_call".to_string())
|
||||||
.add_data(DataTypes::payload, response_payload);
|
.add_data(DataTypes::payload, response_payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
if function == "update_user_state" {
|
if function == "update_user_state" {
|
||||||
let user_id = payload["user_id"].as_str().unwrap();
|
let user_id = payload["user_id"].as_str().unwrap();
|
||||||
let state = payload["state"].as_str().unwrap();
|
let state = payload["state"].as_str().unwrap();
|
||||||
let streaming = payload["streaming"].as_bool().unwrap();
|
let streaming = payload["streaming"].as_bool().unwrap();
|
||||||
|
|
||||||
if let Some(user) = self
|
if let Some(user) = self
|
||||||
.users
|
.users
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|u| u.user_id == Uuid::parse_str(user_id).unwrap())
|
.find(|u| u.user_id == Uuid::parse_str(user_id).unwrap())
|
||||||
{
|
{
|
||||||
user.user_state = CallUserState::parse(state);
|
user.user_state = CallUserState::parse(state);
|
||||||
user.streaming = streaming;
|
user.streaming = streaming;
|
||||||
}
|
}
|
||||||
let mut response_payload = JsonValue::new_object();
|
let mut response_payload = JsonValue::new_object();
|
||||||
response_payload["user_id"] = JsonValue::String(user_id.to_string());
|
response_payload["user_id"] = JsonValue::String(user_id.to_string());
|
||||||
response_payload["state"] = JsonValue::String(state.to_string());
|
response_payload["state"] = JsonValue::String(state.to_string());
|
||||||
response_payload["streaming"] = JsonValue::Boolean(streaming);
|
response_payload["streaming"] = JsonValue::Boolean(streaming);
|
||||||
|
|
||||||
return CommunicationValue::new(CommunicationType::update)
|
return CommunicationValue::new(CommunicationType::update)
|
||||||
.with_id(cv.get_id())
|
.with_id(cv.get_id())
|
||||||
.add_data_str(DataTypes::name, self.name.clone())
|
.add_data_str(DataTypes::name, self.name.clone())
|
||||||
.add_data_str(DataTypes::path, self.path.clone())
|
.add_data_str(DataTypes::path, self.path.clone())
|
||||||
.add_data_str(DataTypes::result, "user_changed".to_string())
|
.add_data_str(DataTypes::result, "user_changed".to_string())
|
||||||
.add_data(DataTypes::payload, response_payload);
|
.add_data(DataTypes::payload, response_payload);
|
||||||
}
|
}
|
||||||
CommunicationValue::new(CommunicationType::error).with_id(cv.get_id())
|
CommunicationValue::new(CommunicationType::error).with_id(cv.get_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_json(&self) -> JsonValue {
|
fn to_json(&self) -> JsonValue {
|
||||||
let v = JsonValue::new_object();
|
let v = JsonValue::new_object();
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
fn load(
|
fn load(
|
||||||
&mut self,
|
&mut self,
|
||||||
community: Arc<Community>,
|
community: Arc<Community>,
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
path: String,
|
path: String,
|
||||||
name: String,
|
name: String,
|
||||||
_json: &JsonValue,
|
_json: &JsonValue,
|
||||||
) {
|
) {
|
||||||
self.community = community;
|
self.community = community;
|
||||||
self.id = id;
|
self.id = id;
|
||||||
self.name = name;
|
self.name = name;
|
||||||
self.path = path;
|
self.path = path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
pub mod community_manager;
|
pub mod community_manager;
|
||||||
pub mod interactables {
|
pub mod interactables {
|
||||||
pub mod category;
|
pub mod category;
|
||||||
pub mod interactable;
|
pub mod interactable;
|
||||||
pub mod registry;
|
pub mod registry;
|
||||||
pub mod text_chat;
|
pub mod text_chat;
|
||||||
pub mod voice_chat;
|
pub mod voice_chat;
|
||||||
}
|
}
|
||||||
pub mod community;
|
pub mod community;
|
||||||
pub mod community_connection;
|
pub mod community_connection;
|
||||||
pub mod perms {
|
pub mod perms {
|
||||||
pub mod permission;
|
pub mod permission;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,27 @@
|
||||||
use json::JsonValue;
|
use json::JsonValue;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub struct Permission {
|
pub struct Permission {
|
||||||
pub id: Uuid,
|
pub id: Uuid,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
impl Permission {
|
impl Permission {
|
||||||
pub fn new(id: Uuid, name: String) -> Self {
|
pub fn new(id: Uuid, name: String) -> Self {
|
||||||
Permission { id, name }
|
Permission { id, name }
|
||||||
}
|
}
|
||||||
pub fn to_json(&self) -> JsonValue {
|
pub fn to_json(&self) -> JsonValue {
|
||||||
json::object! {
|
json::object! {
|
||||||
"id" => self.id.to_string(),
|
"id" => self.id.to_string(),
|
||||||
"name" => self.name.clone()
|
"name" => self.name.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn from_json(json: JsonValue) -> Self {
|
pub fn from_json(json: JsonValue) -> Self {
|
||||||
Permission {
|
Permission {
|
||||||
id: Uuid::parse_str(json["id"].as_str().unwrap()).unwrap(),
|
id: Uuid::parse_str(json["id"].as_str().unwrap()).unwrap(),
|
||||||
name: json["name"].as_str().unwrap().to_string(),
|
name: json["name"].as_str().unwrap().to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn to_string(&self) -> String {
|
pub fn to_string(&self) -> String {
|
||||||
self.to_json().as_str().unwrap().to_string()
|
self.to_json().as_str().unwrap().to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,7 @@ pub enum CommunicationType {
|
||||||
|
|
||||||
get_user_data,
|
get_user_data,
|
||||||
get_iota_data,
|
get_iota_data,
|
||||||
|
iota_user_data,
|
||||||
|
|
||||||
change_user_data,
|
change_user_data,
|
||||||
change_iota_data,
|
change_iota_data,
|
||||||
|
|
@ -342,6 +343,7 @@ impl CommunicationType {
|
||||||
|
|
||||||
"getuserdata" => CommunicationType::get_user_data,
|
"getuserdata" => CommunicationType::get_user_data,
|
||||||
"getiotadata" => CommunicationType::get_iota_data,
|
"getiotadata" => CommunicationType::get_iota_data,
|
||||||
|
"iotauserdata" => CommunicationType::iota_user_data,
|
||||||
|
|
||||||
"changeuserdata" => CommunicationType::change_user_data,
|
"changeuserdata" => CommunicationType::change_user_data,
|
||||||
"changeiotadata" => CommunicationType::change_iota_data,
|
"changeiotadata" => CommunicationType::change_iota_data,
|
||||||
|
|
@ -362,11 +364,11 @@ impl CommunicationType {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CommunicationValue {
|
pub struct CommunicationValue {
|
||||||
pub id: Uuid,
|
id: Uuid,
|
||||||
pub comm_type: CommunicationType,
|
comm_type: CommunicationType,
|
||||||
pub sender: i64,
|
sender: i64,
|
||||||
pub receiver: i64,
|
receiver: i64,
|
||||||
pub data: HashMap<DataTypes, JsonValue>,
|
data: HashMap<DataTypes, JsonValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
@ -421,7 +423,10 @@ impl CommunicationValue {
|
||||||
self.data.get(&key)
|
self.data.get(&key)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_type(&self, p0: CommunicationType) -> bool {
|
pub fn get_type(&self) -> CommunicationType {
|
||||||
|
self.comm_type.clone()
|
||||||
|
}
|
||||||
|
pub fn is_type(&self, p0: CommunicationType) -> bool {
|
||||||
self.comm_type == p0
|
self.comm_type == p0
|
||||||
}
|
}
|
||||||
pub fn to_json(&self) -> JsonValue {
|
pub fn to_json(&self) -> JsonValue {
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,26 @@
|
||||||
use crate::util::file_util::{load_file, save_file};
|
use crate::util::file_util::{load_file, save_file};
|
||||||
|
|
||||||
pub fn check_eula() -> bool {
|
pub fn check_eula() -> bool {
|
||||||
let eula = "By changing the value to \"true\" you agree to our end user license agreement and our terms of service!\
|
let eula = "By changing the value to \"true\" you agree to our end user license agreement and our terms of service!\
|
||||||
\nYou can find our Terms of service on https://docs.tensamin.net/legal/terms-of-service/.\
|
\nYou can find our Terms of service on https://docs.tensamin.net/legal/terms-of-service/.\
|
||||||
\neula=false";
|
\neula=false";
|
||||||
let file = load_file("", "eula.txt");
|
let file = load_file("", "eula.txt");
|
||||||
if file.is_empty() {
|
if file.is_empty() {
|
||||||
save_file("", "eula.txt", eula);
|
save_file("", "eula.txt", eula);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if file.contains("eula=false") {
|
if file.contains("eula=false") {
|
||||||
false
|
false
|
||||||
} else if file.contains("eula=true") {
|
} else if file.contains("eula=true") {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn accept_eula() {
|
pub fn accept_eula() {
|
||||||
let eula = "By changing the value to \"true\" you agree to our end user license agreement and our terms of service!\
|
let eula = "By changing the value to \"true\" you agree to our end user license agreement and our terms of service!\
|
||||||
\nYou can find our Terms of service on https://docs.tensamin.net/legal/terms-of-service/.\
|
\nYou can find our Terms of service on https://docs.tensamin.net/legal/terms-of-service/.\
|
||||||
\neula=true";
|
\neula=true";
|
||||||
save_file("", "eula.txt", eula);
|
save_file("", "eula.txt", eula);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,108 +1,108 @@
|
||||||
use crate::ACTIVE_TASKS;
|
use crate::ACTIVE_TASKS;
|
||||||
use crate::APP_STATE;
|
use crate::APP_STATE;
|
||||||
use crate::SHUTDOWN;
|
use crate::SHUTDOWN;
|
||||||
use crate::gui::tui::UNIQUE;
|
use crate::gui::tui::UNIQUE;
|
||||||
use crate::langu::language_manager::format;
|
use crate::langu::language_manager::format;
|
||||||
use crate::langu::language_manager::from_key;
|
use crate::langu::language_manager::from_key;
|
||||||
|
|
||||||
use crate::data::communication::{CommunicationType, CommunicationValue, DataTypes};
|
use crate::data::communication::{CommunicationType, CommunicationValue, DataTypes};
|
||||||
|
|
||||||
use std::{thread, time::Duration};
|
use std::{thread, time::Duration};
|
||||||
use sysinfo::{RefreshKind, System};
|
use sysinfo::{RefreshKind, System};
|
||||||
|
|
||||||
pub fn log_cv(cv: &CommunicationValue) {
|
pub fn log_cv(cv: &CommunicationValue) {
|
||||||
if cv.is_type(CommunicationType::identification_response) {
|
if cv.is_type(CommunicationType::identification_response) {
|
||||||
let args = [cv.get_data(DataTypes::accepted).unwrap().as_str().unwrap()];
|
let args = [cv.get_data(DataTypes::accepted).unwrap().as_str().unwrap()];
|
||||||
log_message(format(&"identification_response", &args));
|
log_message(format(&"identification_response", &args));
|
||||||
} else {
|
} else {
|
||||||
log_message_trans(format!("{:?}", &cv.comm_type));
|
log_message_trans(format!("{:?}", &cv.get_type()));
|
||||||
}
|
}
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
*UNIQUE.write().await = true;
|
*UNIQUE.write().await = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
pub fn log_message_trans(key: impl Into<String>) {
|
pub fn log_message_trans(key: impl Into<String>) {
|
||||||
APP_STATE.lock().unwrap().push_log(from_key(&key.into()));
|
APP_STATE.lock().unwrap().push_log(from_key(&key.into()));
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
*UNIQUE.write().await = true;
|
*UNIQUE.write().await = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
pub fn log_message(msg: impl Into<String>) {
|
pub fn log_message(msg: impl Into<String>) {
|
||||||
APP_STATE.lock().unwrap().push_log(msg.into());
|
APP_STATE.lock().unwrap().push_log(msg.into());
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
*UNIQUE.write().await = true;
|
*UNIQUE.write().await = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
pub fn log_message_format(msg: impl Into<String>, args: &[&str]) {
|
pub fn log_message_format(msg: impl Into<String>, args: &[&str]) {
|
||||||
APP_STATE
|
APP_STATE
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.push_log(format(&msg.into(), args));
|
.push_log(format(&msg.into(), args));
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
*UNIQUE.write().await = true;
|
*UNIQUE.write().await = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup() {
|
pub fn setup() {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
{
|
{
|
||||||
ACTIVE_TASKS.lock().unwrap().push("metrics".to_string());
|
ACTIVE_TASKS.lock().unwrap().push("metrics".to_string());
|
||||||
}
|
}
|
||||||
let mut sys = System::new_with_specifics(RefreshKind::new());
|
let mut sys = System::new_with_specifics(RefreshKind::new());
|
||||||
let mut last_total_received = 0u64;
|
let mut last_total_received = 0u64;
|
||||||
let mut last_total_transmitted = 0u64;
|
let mut last_total_transmitted = 0u64;
|
||||||
let mut counter = 0.0;
|
let mut counter = 0.0;
|
||||||
loop {
|
loop {
|
||||||
if *SHUTDOWN.read().await {
|
if *SHUTDOWN.read().await {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sys.refresh_all();
|
sys.refresh_all();
|
||||||
|
|
||||||
let mut tcpu = 0;
|
let mut tcpu = 0;
|
||||||
for cpu in sys.cpus() {
|
for cpu in sys.cpus() {
|
||||||
tcpu += cpu.cpu_usage() as i64;
|
tcpu += cpu.cpu_usage() as i64;
|
||||||
tcpu /= 2;
|
tcpu /= 2;
|
||||||
}
|
}
|
||||||
let ram = (sys.used_memory() as f64 / sys.total_memory() as f64) * 100.0;
|
let ram = (sys.used_memory() as f64 / sys.total_memory() as f64) * 100.0;
|
||||||
|
|
||||||
let total_received = 0u64;
|
let total_received = 0u64;
|
||||||
let total_transmitted = 0u64;
|
let total_transmitted = 0u64;
|
||||||
|
|
||||||
let delta_received = if last_total_received == 0 {
|
let delta_received = if last_total_received == 0 {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
total_received.saturating_sub(last_total_received)
|
total_received.saturating_sub(last_total_received)
|
||||||
};
|
};
|
||||||
let delta_transmitted = if last_total_transmitted == 0 {
|
let delta_transmitted = if last_total_transmitted == 0 {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
total_transmitted.saturating_sub(last_total_transmitted)
|
total_transmitted.saturating_sub(last_total_transmitted)
|
||||||
};
|
};
|
||||||
last_total_received = total_received;
|
last_total_received = total_received;
|
||||||
last_total_transmitted = total_transmitted;
|
last_total_transmitted = total_transmitted;
|
||||||
|
|
||||||
let net_down = delta_received as f64;
|
let net_down = delta_received as f64;
|
||||||
let net_up = delta_transmitted as f64;
|
let net_up = delta_transmitted as f64;
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut st = APP_STATE.lock().unwrap();
|
let mut st = APP_STATE.lock().unwrap();
|
||||||
st.push_cpu((counter, tcpu as f64));
|
st.push_cpu((counter, tcpu as f64));
|
||||||
st.push_ram((counter, ram));
|
st.push_ram((counter, ram));
|
||||||
st.push_net_down((counter, net_down));
|
st.push_net_down((counter, net_down));
|
||||||
st.push_net_up((counter, net_up));
|
st.push_net_up((counter, net_up));
|
||||||
|
|
||||||
st.sys_info = format!("NetDown: {} NetUp: {}", delta_received, delta_transmitted);
|
st.sys_info = format!("NetDown: {} NetUp: {}", delta_received, delta_transmitted);
|
||||||
}
|
}
|
||||||
|
|
||||||
counter += 1.0;
|
counter += 1.0;
|
||||||
*UNIQUE.write().await = true;
|
*UNIQUE.write().await = true;
|
||||||
thread::sleep(Duration::from_millis(1000));
|
thread::sleep(Duration::from_millis(1000));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ACTIVE_TASKS
|
ACTIVE_TASKS
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.retain(|t| !t.eq(&"metrics".to_string()));
|
.retain(|t| !t.eq(&"metrics".to_string()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -348,11 +348,7 @@ impl OmikronConnection {
|
||||||
}
|
}
|
||||||
if cv.is_type(CommunicationType::identification_response) {
|
if cv.is_type(CommunicationType::identification_response) {
|
||||||
if let Some(accepted) = cv.get_data(DataTypes::accepted) {
|
if let Some(accepted) = cv.get_data(DataTypes::accepted) {
|
||||||
if accepted.as_str().unwrap_or("0") != "0" {
|
log_message(format!("Omikron connected: {}", accepted.to_string()));
|
||||||
log_message(format!("Omikron connected: {}", accepted.to_string()));
|
|
||||||
} else {
|
|
||||||
log_message("omikron_connection_failed");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod contact;
|
pub mod contact;
|
||||||
pub mod user_community_util;
|
pub mod user_community_util;
|
||||||
pub mod user_manager;
|
pub mod user_manager;
|
||||||
pub mod user_profile;
|
pub mod user_profile;
|
||||||
|
|
|
||||||
|
|
@ -1,129 +1,129 @@
|
||||||
use aes_gcm::{
|
use aes_gcm::{
|
||||||
Aes256Gcm, Nonce,
|
Aes256Gcm, Nonce,
|
||||||
aead::{Aead, KeyInit, OsRng},
|
aead::{Aead, KeyInit, OsRng},
|
||||||
};
|
};
|
||||||
use base64::{Engine as _, engine::general_purpose::STANDARD};
|
use base64::{Engine as _, engine::general_purpose::STANDARD};
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
use x448::{PublicKey, Secret, SharedSecret};
|
use x448::{PublicKey, Secret, SharedSecret};
|
||||||
|
|
||||||
/// Errors for crypto opertions
|
/// Errors for crypto opertions
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum CryptoError {
|
pub enum CryptoError {
|
||||||
Base64Decode(base64::DecodeError),
|
Base64Decode(base64::DecodeError),
|
||||||
InvalidKey,
|
InvalidKey,
|
||||||
AgreementError,
|
AgreementError,
|
||||||
EncryptionError(aes_gcm::Error),
|
EncryptionError(aes_gcm::Error),
|
||||||
DecryptionError(aes_gcm::Error),
|
DecryptionError(aes_gcm::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<base64::DecodeError> for CryptoError {
|
impl From<base64::DecodeError> for CryptoError {
|
||||||
fn from(err: base64::DecodeError) -> Self {
|
fn from(err: base64::DecodeError) -> Self {
|
||||||
CryptoError::Base64Decode(err)
|
CryptoError::Base64Decode(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct KeyPair {
|
pub struct KeyPair {
|
||||||
pub secret: Secret,
|
pub secret: Secret,
|
||||||
pub public: PublicKey,
|
pub public: PublicKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_keypair() -> KeyPair {
|
pub fn generate_keypair() -> KeyPair {
|
||||||
let mut buf = [0u8; 56];
|
let mut buf = [0u8; 56];
|
||||||
let mut rng = OsRng;
|
let mut rng = OsRng;
|
||||||
rng.fill_bytes(&mut buf);
|
rng.fill_bytes(&mut buf);
|
||||||
let secret = Secret::from_bytes(&buf).unwrap();
|
let secret = Secret::from_bytes(&buf).unwrap();
|
||||||
let public = PublicKey::from(&secret);
|
let public = PublicKey::from(&secret);
|
||||||
KeyPair { secret, public }
|
KeyPair { secret, public }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn public_key_to_base64(pubkey: &PublicKey) -> String {
|
pub fn public_key_to_base64(pubkey: &PublicKey) -> String {
|
||||||
STANDARD.encode(pubkey.as_bytes().as_ref())
|
STANDARD.encode(pubkey.as_bytes().as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn secret_key_to_base64(secret: &Secret) -> String {
|
pub fn secret_key_to_base64(secret: &Secret) -> String {
|
||||||
STANDARD.encode(secret.as_bytes().as_ref())
|
STANDARD.encode(secret.as_bytes().as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_public_key(base64_pub: &str) -> Option<PublicKey> {
|
pub fn load_public_key(base64_pub: &str) -> Option<PublicKey> {
|
||||||
let bytes = STANDARD.decode(base64_pub).unwrap();
|
let bytes = STANDARD.decode(base64_pub).unwrap();
|
||||||
PublicKey::from_bytes(&bytes)
|
PublicKey::from_bytes(&bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_secret_key(base64_secret: &str) -> Option<Secret> {
|
pub fn load_secret_key(base64_secret: &str) -> Option<Secret> {
|
||||||
let bytes = STANDARD.decode(base64_secret).unwrap();
|
let bytes = STANDARD.decode(base64_secret).unwrap();
|
||||||
Secret::from_bytes(&bytes)
|
Secret::from_bytes(&bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn derive_aes_key(shared: &SharedSecret) -> [u8; 32] {
|
fn derive_aes_key(shared: &SharedSecret) -> [u8; 32] {
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
hasher.update(shared.as_bytes());
|
hasher.update(shared.as_bytes());
|
||||||
let result = hasher.finalize();
|
let result = hasher.finalize();
|
||||||
let mut key = [0u8; 32];
|
let mut key = [0u8; 32];
|
||||||
key.copy_from_slice(&result[..32]);
|
key.copy_from_slice(&result[..32]);
|
||||||
key
|
key
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encrypt(
|
pub fn encrypt(
|
||||||
base64_secret: &str,
|
base64_secret: &str,
|
||||||
base64_peer_pub: &str,
|
base64_peer_pub: &str,
|
||||||
plaintext: &str,
|
plaintext: &str,
|
||||||
) -> Result<String, CryptoError> {
|
) -> Result<String, CryptoError> {
|
||||||
let secret = load_secret_key(base64_secret).unwrap();
|
let secret = load_secret_key(base64_secret).unwrap();
|
||||||
let peer_pub = load_public_key(base64_peer_pub).unwrap();
|
let peer_pub = load_public_key(base64_peer_pub).unwrap();
|
||||||
let shared = secret
|
let shared = secret
|
||||||
.to_diffie_hellman(&peer_pub)
|
.to_diffie_hellman(&peer_pub)
|
||||||
.ok_or(CryptoError::AgreementError)?;
|
.ok_or(CryptoError::AgreementError)?;
|
||||||
let key_bytes = derive_aes_key(&shared);
|
let key_bytes = derive_aes_key(&shared);
|
||||||
let cipher = Aes256Gcm::new_from_slice(&key_bytes).expect("Key length should be correct");
|
let cipher = Aes256Gcm::new_from_slice(&key_bytes).expect("Key length should be correct");
|
||||||
let mut nonce_bytes = [0u8; 12];
|
let mut nonce_bytes = [0u8; 12];
|
||||||
OsRng.fill_bytes(&mut nonce_bytes);
|
OsRng.fill_bytes(&mut nonce_bytes);
|
||||||
let nonce = Nonce::from_slice(&nonce_bytes);
|
let nonce = Nonce::from_slice(&nonce_bytes);
|
||||||
let ciphertext = cipher
|
let ciphertext = cipher
|
||||||
.encrypt(nonce, plaintext.as_bytes())
|
.encrypt(nonce, plaintext.as_bytes())
|
||||||
.map_err(CryptoError::EncryptionError)?;
|
.map_err(CryptoError::EncryptionError)?;
|
||||||
// prefix nonce to ciphertext
|
// prefix nonce to ciphertext
|
||||||
let mut out = Vec::with_capacity(nonce_bytes.len() + ciphertext.len());
|
let mut out = Vec::with_capacity(nonce_bytes.len() + ciphertext.len());
|
||||||
out.extend_from_slice(&nonce_bytes);
|
out.extend_from_slice(&nonce_bytes);
|
||||||
out.extend_from_slice(&ciphertext);
|
out.extend_from_slice(&ciphertext);
|
||||||
Ok(STANDARD.encode(&out))
|
Ok(STANDARD.encode(&out))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrypt(
|
pub fn decrypt(
|
||||||
base64_secret: &str,
|
base64_secret: &str,
|
||||||
base64_peer_pub: &str,
|
base64_peer_pub: &str,
|
||||||
encrypted_base64: &str,
|
encrypted_base64: &str,
|
||||||
) -> Result<String, CryptoError> {
|
) -> Result<String, CryptoError> {
|
||||||
let secret = load_secret_key(base64_secret).unwrap();
|
let secret = load_secret_key(base64_secret).unwrap();
|
||||||
let peer_pub = load_public_key(base64_peer_pub).unwrap();
|
let peer_pub = load_public_key(base64_peer_pub).unwrap();
|
||||||
let shared = secret
|
let shared = secret
|
||||||
.to_diffie_hellman(&peer_pub)
|
.to_diffie_hellman(&peer_pub)
|
||||||
.ok_or(CryptoError::AgreementError)?;
|
.ok_or(CryptoError::AgreementError)?;
|
||||||
let key_bytes = derive_aes_key(&shared);
|
let key_bytes = derive_aes_key(&shared);
|
||||||
let cipher = Aes256Gcm::new_from_slice(&key_bytes).expect("Key length should be correct");
|
let cipher = Aes256Gcm::new_from_slice(&key_bytes).expect("Key length should be correct");
|
||||||
|
|
||||||
let encrypted = STANDARD.decode(encrypted_base64)?;
|
let encrypted = STANDARD.decode(encrypted_base64)?;
|
||||||
if encrypted.len() < 12 {
|
if encrypted.len() < 12 {
|
||||||
return Err(CryptoError::DecryptionError(aes_gcm::Error));
|
return Err(CryptoError::DecryptionError(aes_gcm::Error));
|
||||||
}
|
}
|
||||||
let nonce_bytes = &encrypted[..12];
|
let nonce_bytes = &encrypted[..12];
|
||||||
let ciphertext = &encrypted[12..];
|
let ciphertext = &encrypted[12..];
|
||||||
let nonce = Nonce::from_slice(nonce_bytes);
|
let nonce = Nonce::from_slice(nonce_bytes);
|
||||||
let plaintext_bytes = cipher
|
let plaintext_bytes = cipher
|
||||||
.decrypt(nonce, ciphertext)
|
.decrypt(nonce, ciphertext)
|
||||||
.map_err(CryptoError::DecryptionError)?;
|
.map_err(CryptoError::DecryptionError)?;
|
||||||
let plaintext = String::from_utf8(plaintext_bytes)
|
let plaintext = String::from_utf8(plaintext_bytes)
|
||||||
.map_err(|_| CryptoError::DecryptionError(aes_gcm::Error))?;
|
.map_err(|_| CryptoError::DecryptionError(aes_gcm::Error))?;
|
||||||
Ok(plaintext)
|
Ok(plaintext)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash_it(input: &str) -> Vec<u8> {
|
pub fn hash_it(input: &str) -> Vec<u8> {
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
hasher.update(input.as_bytes());
|
hasher.update(input.as_bytes());
|
||||||
hasher.finalize().to_vec()
|
hasher.finalize().to_vec()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hex_hash(input: &str) -> String {
|
pub fn hex_hash(input: &str) -> String {
|
||||||
let digest = hash_it(input);
|
let digest = hash_it(input);
|
||||||
digest.iter().map(|b| format!("{:02x}", b)).collect()
|
digest.iter().map(|b| format!("{:02x}", b)).collect()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1004
src/util/crypto_util.rs
Normal file
1004
src/util/crypto_util.rs
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue