diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 4088abc..0e6d627 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -344,8 +344,10 @@ checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", + "js-sys", "num-traits", "serde", + "wasm-bindgen", "windows-targets 0.52.5", ] @@ -3212,6 +3214,7 @@ dependencies = [ "aes", "block-modes", "block-padding 0.3.3", + "chrono", "hex", "magic-crypt", "rand 0.8.5", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 5b45152..318fa50 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -22,6 +22,7 @@ hex = "0.4" aes = "0.7.5" block-modes = "0.8.1" block-padding = "0.3.3" +chrono = "0.4.38" [features] # This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!! diff --git a/src-tauri/src/api/aes_enc_dec.rs b/src-tauri/src/api/aes_enc_dec.rs index a80f7fe..b6588ce 100644 --- a/src-tauri/src/api/aes_enc_dec.rs +++ b/src-tauri/src/api/aes_enc_dec.rs @@ -22,7 +22,7 @@ pub fn decrypt(key: &[u8], encrypted_data: &[u8]) -> String { String::from_utf8(decrypted_ciphertext).unwrap() // Вывод результата в виде строки } -/// Примеры +// Примеры //println!("TEST ENC: {:?}", crate::aes_enc_dec::encrypt(&hex::decode(crate::multi_tcp_listener::get_token()).unwrap(), "{\"command\": \"status1\"}")); //println!("TEST DEC: {:?}\n", crate::aes_enc_dec::decrypt(&hex::decode(crate::multi_tcp_listener::get_token()).unwrap(), &crate::aes_enc_dec::encrypt(&hex::decode(crate::multi_tcp_listener::get_token()).unwrap(), "{\"command\": \"status1\"}"))); diff --git a/src-tauri/src/api/config_tcp.rs b/src-tauri/src/api/config_tcp.rs index cfba92c..5aadc1d 100644 --- a/src-tauri/src/api/config_tcp.rs +++ b/src-tauri/src/api/config_tcp.rs @@ -46,7 +46,7 @@ pub fn check_or_create_config_file(app_handle: tauri::AppHandle) { let data = String::from(format!("{}\ \"port\": 49494,\ - \"autostart\": true,\ + \"autostart\": false,\ \"token\": \"{}\"\ {}", "{", token, "}")); println!("{}", data); diff --git a/src-tauri/src/api/handler_commands.rs b/src-tauri/src/api/handler_commands.rs new file mode 100644 index 0000000..e46292c --- /dev/null +++ b/src-tauri/src/api/handler_commands.rs @@ -0,0 +1,75 @@ +use serde_json::Value; +use chrono::{DateTime, Local}; + +use crate::aes_enc_dec::encrypt; +use crate::tasks; + +pub fn get_tasks_tcp(token: String) -> Vec{ + encrypt(&hex::decode(token).unwrap(), tasks::get_tasks().to_string().as_str()) +} + +pub fn get_task_by_id_tcp(token: String, json: Value) -> Vec { + let tasks: Value = tasks::get_tasks(); + let res; + if !json.get("id").is_none(){ + res = encrypt(&hex::decode(token).unwrap(), tasks[json["id"].as_str().unwrap_or("")].to_string().as_str()); + } else{ + res = encrypt(&hex::decode(token).unwrap(), "400"); + } + res +} + +pub fn create_task_tcp(token: String, json: Value) -> Vec { + if json["task"].is_object(){ + if json["task"]["name"].is_string(){ + let current_datetime: DateTime = Local::now(); + let date: String = current_datetime.format("%Y.%m.%d").to_string(); + let time: String = current_datetime.format("%H:%M").to_string(); + + let name = json["task"]["name"].as_str().unwrap().to_string(); + let description = json["task"]["description"].as_str().unwrap_or("").to_string(); + let priority = json["task"]["priority"].as_str().unwrap_or("0").to_string(); + + encrypt(&hex::decode(token).unwrap(), tasks::add_task(date, time, name, description, priority).as_str()) + } else{ + encrypt(&hex::decode(token).unwrap(), "400") + } + } else{ + encrypt(&hex::decode(token).unwrap(), "400") + } +} + +pub fn edit_task_tcp(token: String, json: Value) -> Vec { + if json["task"].is_object(){ + if json["task"]["id"].is_number(){ + let id_task = json["task"]["id"].as_number().unwrap().to_string(); + let name = json["task"]["name"].as_str().unwrap().to_string(); + let description = json["task"]["description"].as_str().unwrap_or("").to_string(); + let priority = json["task"]["priority"].as_str().unwrap_or("0").to_string(); + + if tasks::edit_task(id_task, name, description, priority) { + encrypt(&hex::decode(token).unwrap(), "200") + } else{ + encrypt(&hex::decode(token).unwrap(), "400") + } + } else{ + encrypt(&hex::decode(token).unwrap(), "400") + } + } else{ + encrypt(&hex::decode(token).unwrap(), "400") + } +} + +pub fn delete_task_tcp(token: String, json: Value) -> Vec { + let res; + if !json.get("id").is_none(){ + if tasks::delete_task(json["id"].to_string()){ + res = encrypt(&hex::decode(token).unwrap(), "200"); + } else{ + res = encrypt(&hex::decode(token).unwrap(), "400"); + } + } else{ + res = encrypt(&hex::decode(token).unwrap(), "400"); + } + res +} \ No newline at end of file diff --git a/src-tauri/src/api/multithread_tcp_listener.rs b/src-tauri/src/api/multithread_tcp_listener.rs index d07e272..700a04c 100644 --- a/src-tauri/src/api/multithread_tcp_listener.rs +++ b/src-tauri/src/api/multithread_tcp_listener.rs @@ -6,7 +6,7 @@ use std::string::String; use serde_json::Value; use tauri::{AppHandle, Manager}; -use crate::config_tcp; +use crate::{config_tcp, handler_commands}; use crate::enc_dec_file::decrypt_file; use crate::aes_enc_dec::{encrypt, decrypt}; @@ -31,7 +31,7 @@ fn enc_hex_to_data(data: &str) -> String{ } // Расшифровка обёрнутых в HEX данных до строки -pub fn create_tcp_listener(app_handle: AppHandle) -> TcpListener{ +fn create_tcp_listener(app_handle: AppHandle) -> TcpListener{ let path: PathBuf = [ app_handle.path_resolver().app_local_data_dir().unwrap(), "ToDo".into(), @@ -88,19 +88,44 @@ fn handle_connection(mut stream: TcpStream) { let res = enc_hex_to_data(req.trim()); // Дешифрование let json: Value = serde_json::from_str(res.as_str()).unwrap_or(serde_json::json!("")); // Попытка преобразования запроса в JSON if json != serde_json::json!(""){ + println!("JSON: {:?}", json); println!("JSON command: {:?}", json["command"]); match json["command"].as_str().unwrap() { // Сравнивание команд "stop" => { unsafe { TCP_COMMAND = "stop"; } + let res = encrypt(&hex::decode(get_token()).unwrap(), "200"); + stream.write(hex::encode(res).as_bytes()).unwrap(); }, "status" => { let res = encrypt(&hex::decode(get_token()).unwrap(), "200"); stream.write(hex::encode(res).as_bytes()).unwrap(); }, + "get_tasks" => { + let res = handler_commands::get_tasks_tcp(get_token()); + stream.write(hex::encode(res).as_bytes()).unwrap(); + }, + "get_task_by_id" => { + let res = handler_commands::get_task_by_id_tcp(get_token(), json); + stream.write(hex::encode(res).as_bytes()).unwrap(); + }, + "create_task" => { + let res = handler_commands::create_task_tcp(get_token(), json); + stream.write(hex::encode(res).as_bytes()).unwrap(); + }, + "edit_task" => { + let res = handler_commands::edit_task_tcp(get_token(), json); + stream.write(hex::encode(res).as_bytes()).unwrap(); + }, + "delete_task" => { + let res = handler_commands::delete_task_tcp(get_token(), json); + stream.write(hex::encode(res).as_bytes()).unwrap(); + }, _ => {} } + } else{ + stream.write(hex::encode(encrypt(&hex::decode(get_token()).unwrap(), "400")).as_bytes()).unwrap(); } } }, diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index caa288b..8aacefe 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -5,6 +5,7 @@ use std::thread; // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command #[path="api/multithread_tcp_listener.rs"] mod multi_tcp_listener; +#[path= "api/handler_commands.rs"] mod handler_commands; #[path= "api/config_tcp.rs"] mod config_tcp; #[path= "api/aes_enc_dec.rs"] mod aes_enc_dec; @@ -24,22 +25,21 @@ fn open_api_window(app_handle: tauri::AppHandle){ .decorations(false) .build() { Ok(_) => {} - Err(err) => { - println!("{err}"); + Err(_) => { + //println!("{err}"); } } }); } fn main() { + std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1"); tauri::Builder::default() .setup(|app| { let app_handle = app.handle(); if config_tcp::get_autostart(app_handle.clone()) { - thread::spawn(move || { - multi_tcp_listener::create_tcp_listener(app_handle); - }); + multi_tcp_listener::start_tcp_server(app_handle); } Ok(()) diff --git a/src-tauri/src/tasks_functions.rs b/src-tauri/src/tasks_functions.rs index 4ac374d..e282d0f 100644 --- a/src-tauri/src/tasks_functions.rs +++ b/src-tauri/src/tasks_functions.rs @@ -1,189 +1,184 @@ use std::fs::{read_to_string}; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::fs::File; use serde_json::{Value, json}; use rust_fuzzy_search::fuzzy_search_best_n; use crate::enc_dec_file::{encrypt_n_save_file, decrypt_file}; +static mut PATH_CONFIG: Option<&'static str> = None; + #[tauri::command] pub fn check_or_create_tasks_file(app_handle: tauri::AppHandle) { - let mut path = app_handle.path_resolver().app_local_data_dir().unwrap(); - path.push("ToDo"); - path.push("tasks"); + let path: PathBuf = [ + app_handle.path_resolver().app_local_data_dir().unwrap(), + "ToDo".into(), + "tasks.enc".into(), + ].iter().collect(); // Путь к конфиг файлу - path.set_extension("enc"); + let path_str = Box::leak(Box::new(path.to_string_lossy().into_owned())); - let exist: bool = Path::new(&path).exists(); - if exist{ - let content = read_to_string(path); - return match content { - Ok(_) => {}, - Err(_) => { - println!("Не удалось открыть конфигурационный файл!"); + unsafe { + PATH_CONFIG = Some(path_str); + } + + unsafe { + let exist: bool = Path::new(PATH_CONFIG.unwrap()).exists(); + if exist{ + let content = read_to_string(path); + return match content { + Ok(_) => {}, + Err(_) => { + println!("Не удалось открыть конфигурационный файл!"); + } + } + } else{ + let path = Path::new(&path); + let prefix = path.parent().unwrap(); + let file = std::fs::create_dir_all(prefix); + match file{ + Ok(_) => {}, + Err(err) => println!("Не удалось создать директории! \n{}", err) + } + let file = File::create(path); + match file{ + Ok(_) => { + let data = String::from("{\ + \"id\": 0,\ + \"tasks\": {}\ + }"); + encrypt_n_save_file(path.into(), data); + }, + Err(err) => println!("Не удалось создать файл! \n{}", err) } } - } else{ - let path = Path::new(&path); - let prefix = path.parent().unwrap(); - let file = std::fs::create_dir_all(prefix); - match file{ - Ok(_) => {}, - Err(err) => println!("Не удалось создать директории! \n{}", err) - } - let file = File::create(path); - match file{ - Ok(_) => { - let data = String::from("{\ - \"id\": 0,\ - \"tasks\": {}\ - }"); - encrypt_n_save_file(path.into(), data); - }, - Err(err) => println!("Не удалось создать файл! \n{}", err) - } } } #[tauri::command] -pub fn get_tasks(app_handle: tauri::AppHandle) -> Value { - let mut path = app_handle.path_resolver().app_local_data_dir().unwrap(); - path.push("ToDo"); - path.push("tasks"); +pub fn get_tasks() -> Value { + unsafe { + let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap())); + let data: Value = serde_json::from_str(content.as_str()).unwrap(); - path.set_extension("enc"); + let res = &data["tasks"]; - let content = decrypt_file(path); - let data: Value = serde_json::from_str(content.as_str()).unwrap(); - - let res = &data["tasks"]; - - return res.clone(); + return res.clone(); + } } #[tauri::command] -pub fn search_tasks(app_handle: tauri::AppHandle, value: String) -> Value { - let mut path = app_handle.path_resolver().app_local_data_dir().unwrap(); - path.push("ToDo"); - path.push("tasks"); +pub fn search_tasks(value: String) -> Value { + unsafe { + let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap())); + let data: Value = serde_json::from_str(content.as_str()).unwrap(); - path.set_extension("enc"); + let mut tasks = vec![]; - let content = decrypt_file(path); - let data: Value = serde_json::from_str(content.as_str()).unwrap(); + let binding = data.clone(); + for (_key, value) in binding["tasks"].as_object().unwrap() { + tasks.push(value["name"].as_str().unwrap().to_lowercase()); + } - let mut tasks = vec![]; + let tasks_str: Vec<&str> = tasks.iter().map(|s| &**s).collect(); - let binding = data.clone(); - for (_key, value) in binding["tasks"].as_object().unwrap() { - tasks.push(value["name"].as_str().unwrap().to_lowercase()); - } + let n: usize = 5; + let binding = value.to_lowercase(); + let res: Vec<(&str, f32)> = fuzzy_search_best_n(&binding, &tasks_str, n); - let tasks_str: Vec<&str> = tasks.iter().map(|s| &**s).collect(); + let mut result = json!({}); - let n : usize = 5; - let binding = value.to_lowercase(); - let res : Vec<(&str, f32)> = fuzzy_search_best_n(&binding, &tasks_str, n); - - let mut result = json!({}); - - let res1 = res.clone(); - let binding1 = data.clone(); - for (name, score) in res1 { - if score > 0.6 { - for (key, value) in binding1["tasks"].as_object().unwrap() { - if value.get("name").unwrap().as_str().unwrap().to_lowercase().as_str() == name { - result[key] = binding1["tasks"].get(key).unwrap().clone(); - break; + let res1 = res.clone(); + let binding1 = data.clone(); + for (name, score) in res1 { + if score > 0.6 { + for (key, value) in binding1["tasks"].as_object().unwrap() { + if value.get("name").unwrap().as_str().unwrap().to_lowercase().as_str() == name { + result[key] = binding1["tasks"].get(key).unwrap().clone(); + break; + } } } } + + return result; } - - return result; } #[tauri::command] -pub fn add_task(app_handle: tauri::AppHandle, date: String, time: String, name: String, description: String, priority: String) { - let mut path = app_handle.path_resolver().app_local_data_dir().unwrap(); - path.push("ToDo"); - path.push("tasks"); +pub fn add_task(date: String, time: String, name: String, description: String, priority: String) -> String { + unsafe { + let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap())); + let mut data: Value = serde_json::from_str(content.as_str()).unwrap(); - path.set_extension("enc"); + let pending = data.clone(); + let id = &pending["id"]; - let content = decrypt_file(path.clone()); - let mut data: Value = serde_json::from_str(content.as_str()).unwrap(); + let task = json!({ + "id": id.to_string(), + "date": date, + "time": time, + "name": name, + "description": description, + "priority": priority, + "completed": false + }); - let pending = data.clone(); - let id = &pending["id"]; + data["id"] = (id.as_i64().unwrap() + 1).into(); - let task = json!({ - "id": id.to_string(), - "date": date, - "time": time, - "name": name, - "description": description, - "priority": priority, - "completed": false - }); + data["tasks"][id.to_string()] = task; + encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data.to_string()); - data["id"] = (id.as_i64().unwrap() + 1).into(); - - data["tasks"][id.to_string()] = task; - encrypt_n_save_file(path.into(), data.to_string()); + return id.to_string(); + } } #[tauri::command] -pub fn edit_task(app_handle: tauri::AppHandle, id_task: String, name: String, description: String, priority: String) { - let mut path = app_handle.path_resolver().app_local_data_dir().unwrap(); - path.push("ToDo"); - path.push("tasks"); +pub fn edit_task(id_task: String, name: String, description: String, priority: String) -> bool{ + unsafe { + let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap())); + let mut data: Value = serde_json::from_str(content.as_str()).unwrap(); - path.set_extension("enc"); + return if !data["tasks"][id_task.clone()].get("id").is_none(){ + data["tasks"][id_task.clone()]["name"] = json!(name); + data["tasks"][id_task.clone()]["description"] = json!(description); + data["tasks"][id_task]["priority"] = json!(priority); - let content = decrypt_file(path.clone()); - let mut data: Value = serde_json::from_str(content.as_str()).unwrap(); - data["tasks"][id_task.clone()]["name"] = json!(name); - data["tasks"][id_task.clone()]["description"] = json!(description); - data["tasks"][id_task]["priority"] = json!(priority); - - encrypt_n_save_file(path.into(), data.to_string()); -} - -#[tauri::command] -pub fn delete_task(app_handle: tauri::AppHandle, id_task: String) { - let mut path = app_handle.path_resolver().app_local_data_dir().unwrap(); - path.push("ToDo"); - path.push("tasks"); - - path.set_extension("enc"); - - let content = decrypt_file(path.clone()); - let mut data: Value = serde_json::from_str(content.as_str()).unwrap(); - - let tasks = data["tasks"].as_object_mut().unwrap(); - let binding = tasks.clone(); - for (key, value) in binding{ - if id_task == value["id"] { - tasks.remove(&key); - break; + encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data.to_string()); + true + } else{ + false } } - data["tasks"] = json!(tasks); - encrypt_n_save_file(path.into(), data.to_string()); } #[tauri::command] -pub fn set_task_field(app_handle: tauri::AppHandle, id_task: String, field: String, value: String) { - let mut path = app_handle.path_resolver().app_local_data_dir().unwrap(); - path.push("ToDo"); - path.push("tasks"); +pub fn delete_task(id_task: String) -> bool{ + unsafe { + let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap())); + let mut data: Value = serde_json::from_str(content.as_str()).unwrap(); - path.set_extension("enc"); + let tasks = data["tasks"].as_object_mut().unwrap(); + let binding = tasks.clone(); + for (key, value) in binding { + if id_task == value["id"] { + tasks.remove(&key); + data["tasks"] = json!(tasks); + encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data.to_string()); + return true + } + } + false + } +} - let content = decrypt_file(path.clone()); - let mut data: Value = serde_json::from_str(content.as_str()).unwrap(); - data["tasks"][id_task][field] = json!(value); +#[tauri::command] +pub fn set_task_field(id_task: String, field: String, value: String) { + unsafe { + let content = decrypt_file(PathBuf::from(PATH_CONFIG.unwrap())); + let mut data: Value = serde_json::from_str(content.as_str()).unwrap(); + data["tasks"][id_task][field] = json!(value); - encrypt_n_save_file(path.into(), data.to_string()); + encrypt_n_save_file(PathBuf::from(PATH_CONFIG.unwrap()), data.to_string()); + } } \ No newline at end of file diff --git a/src/ApiApp.vue b/src/ApiApp.vue index 8e72a9d..f512dac 100644 --- a/src/ApiApp.vue +++ b/src/ApiApp.vue @@ -8,10 +8,13 @@ import {invoke} from "@tauri-apps/api"; import ConfirmModal from "./api_components/ConfirmModal.vue"; import {listen} from "@tauri-apps/api/event"; import SettingsModal from "./api_components/SettingsModal.vue"; +import PageHandler from "./api_wiki/PageHandler.vue"; const isDark = useDark(); const toggleDark = useToggle(isDark); +let wiki_open = ref(false); + let pending = ref(true); let api_status = ref(false); @@ -106,7 +109,11 @@ function select_input(event){ @@ -178,7 +196,7 @@ function select_input(event){ line-height: 24px; font-weight: 400; - background-color: rgb(246 247 248); + background-color: rgb(244 245 246); font-synthesis: none; text-rendering: optimizeLegibility; @@ -188,6 +206,6 @@ function select_input(event){ } :root.dark { - background-color: rgb(30, 30, 30); + background-color: rgb(35, 35, 35); } \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index 129262b..33a97c0 100644 --- a/src/App.vue +++ b/src/App.vue @@ -147,7 +147,8 @@ async function open_api(){