[Add] Accepted Document Version
This commit is contained in:
parent
53a057c6e1
commit
0812d85e43
14 changed files with 231 additions and 72 deletions
|
|
@ -1,23 +1,13 @@
|
|||
use std::{
|
||||
io::{Stdout, Write, stdout},
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
};
|
||||
use std::{io::Stdout, sync::Arc, time::Duration};
|
||||
|
||||
use crate::{
|
||||
ACTIVE_TASKS, APP_STATE, SHUTDOWN,
|
||||
APP_STATE, SHUTDOWN,
|
||||
gui::{settings_panel, widgets::betterblock::draw_block_joins},
|
||||
util::config_util::CONFIG,
|
||||
};
|
||||
use crossterm::{
|
||||
cursor::Show,
|
||||
execute,
|
||||
terminal::{EnterAlternateScreen, LeaveAlternateScreen, enable_raw_mode},
|
||||
};
|
||||
use once_cell::sync::Lazy;
|
||||
use ratatui::{
|
||||
Frame, Terminal,
|
||||
crossterm::terminal::disable_raw_mode,
|
||||
layout::{Constraint, Direction, Layout, Rect},
|
||||
prelude::CrosstermBackend,
|
||||
style::Color,
|
||||
|
|
|
|||
|
|
@ -9,20 +9,20 @@ pub struct LanguagePack {
|
|||
language: HashMap<String, String>,
|
||||
}
|
||||
|
||||
// Language packs need to have formatting
|
||||
// Variables need to be provided
|
||||
|
||||
pub static LANGUAGE_PACK: Lazy<Mutex<LanguagePack>> =
|
||||
Lazy::new(|| Mutex::new(LanguagePack::new("en_INT")));
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_language() -> LanguagePack {
|
||||
LANGUAGE_PACK.lock().unwrap().clone()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_languages() -> Vec<String> {
|
||||
file_util::get_children("languages")
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn set_language(language: &str) {
|
||||
LANGUAGE_PACK.lock().unwrap().language.clear();
|
||||
LANGUAGE_PACK.lock().unwrap().load_language(language);
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ async fn main() {
|
|||
break;
|
||||
}
|
||||
let omikron: Arc<OmikronConnection> = Arc::new(OmikronConnection::new());
|
||||
omikron.connect(sb.clone()).await;
|
||||
omikron.connect().await;
|
||||
let mut omikron_connection = OMIKRON_CONNECTION.write().await;
|
||||
*omikron_connection = Some(omikron.clone());
|
||||
log_message_trans("setup_completed");
|
||||
|
|
|
|||
|
|
@ -14,15 +14,14 @@ use crate::{
|
|||
util::{config_util::CONFIG, crypto_helper},
|
||||
};
|
||||
use dashmap::DashMap;
|
||||
use futures::Stream;
|
||||
use futures::stream::{SplitSink, SplitStream};
|
||||
use futures::{FutureExt, Stream};
|
||||
use futures_util::sink::Sink;
|
||||
use futures_util::{SinkExt, StreamExt};
|
||||
use hyper::upgrade::Upgraded;
|
||||
use hyper_util::rt::TokioIo;
|
||||
use json::JsonValue;
|
||||
use json::number::Number;
|
||||
use pkcs8::DecodePrivateKey;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, LazyLock};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
|
@ -31,7 +30,6 @@ use tokio::time::{Duration, Instant, sleep};
|
|||
use tokio_tungstenite::{connect_async, tungstenite::protocol::Message};
|
||||
use tungstenite::Utf8Bytes;
|
||||
use uuid::Uuid;
|
||||
use warp::reply::Json;
|
||||
|
||||
pub static OMIKRON_CONNECTION: LazyLock<Arc<RwLock<Option<Arc<OmikronConnection>>>>> =
|
||||
LazyLock::new(|| Arc::new(RwLock::new(None)));
|
||||
|
|
@ -50,7 +48,6 @@ pub struct OmikronConnection {
|
|||
pub(crate) writer:
|
||||
Arc<Mutex<Option<Box<dyn Sink<Message, Error = tungstenite::Error> + Send + Unpin>>>>,
|
||||
waiting: Arc<DashMap<Uuid, Box<dyn Fn(CommunicationValue) + Send + Sync>>>,
|
||||
pingpong: Arc<Mutex<Option<tokio::task::JoinHandle<()>>>>,
|
||||
pub last_ping: Arc<Mutex<i64>>,
|
||||
pub message_send_times: Arc<Mutex<HashMap<Uuid, Instant>>>,
|
||||
pub is_connected: Arc<Mutex<bool>>,
|
||||
|
|
@ -63,7 +60,6 @@ impl OmikronConnection {
|
|||
user_id: Arc::new(RwLock::new(0)),
|
||||
writer: Arc::new(Mutex::new(None)),
|
||||
waiting: Arc::new(DashMap::new()),
|
||||
pingpong: Arc::new(Mutex::new(None)),
|
||||
last_ping: Arc::new(Mutex::new(-1)),
|
||||
message_send_times: Arc::new(Mutex::new(HashMap::new())),
|
||||
is_connected: Arc::new(Mutex::new(false)),
|
||||
|
|
@ -79,7 +75,6 @@ impl OmikronConnection {
|
|||
writer: Arc::new(Mutex::new(Some(Box::new(writer)
|
||||
as Box<dyn Sink<Message, Error = tungstenite::Error> + Send + Unpin>))),
|
||||
waiting: Arc::new(DashMap::new()),
|
||||
pingpong: Arc::new(Mutex::new(None)),
|
||||
last_ping: Arc::new(Mutex::new(-1)),
|
||||
message_send_times: Arc::new(Mutex::new(HashMap::new())),
|
||||
is_connected: Arc::new(Mutex::new(true)),
|
||||
|
|
@ -94,8 +89,8 @@ impl OmikronConnection {
|
|||
pub async fn is_connected(&self) -> bool {
|
||||
*self.is_connected.lock().await
|
||||
}
|
||||
/// Connect loop with retry
|
||||
pub async fn connect(self: &Arc<Self>, user_ids: String) {
|
||||
|
||||
pub async fn connect(self: &Arc<Self>) {
|
||||
if self.is_connected().await {
|
||||
return;
|
||||
}
|
||||
|
|
@ -104,10 +99,9 @@ impl OmikronConnection {
|
|||
let iota_id = conf.get_iota_id();
|
||||
let public_key = conf.get_public_key();
|
||||
let private_key = conf.get_private_key();
|
||||
drop(conf); // release read lock
|
||||
drop(conf);
|
||||
|
||||
if iota_id == 0 || public_key.is_none() || private_key.is_none() {
|
||||
// Registration flow
|
||||
log_message_trans("iota_register_new");
|
||||
let key_pair = crypto_helper::generate_keypair();
|
||||
let public_key_base64 = crypto_helper::public_key_to_base64(&key_pair.public);
|
||||
|
|
@ -120,7 +114,6 @@ impl OmikronConnection {
|
|||
drop(conf_write);
|
||||
|
||||
if self.connect_internal().await {
|
||||
// a new helper function to just connect
|
||||
match self
|
||||
.clone()
|
||||
.await_response(
|
||||
|
|
@ -148,7 +141,6 @@ impl OmikronConnection {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// Login flow
|
||||
if self.connect_internal().await {
|
||||
self.send_message(
|
||||
&CommunicationValue::new(CommunicationType::identification).add_data(
|
||||
|
|
@ -167,7 +159,6 @@ impl OmikronConnection {
|
|||
}
|
||||
log_message_trans("omikron_connecting");
|
||||
|
||||
// connect to omikron
|
||||
let conf = CONFIG.read().await;
|
||||
let addr = conf
|
||||
.get("omikron_addr")
|
||||
|
|
@ -223,7 +214,6 @@ impl OmikronConnection {
|
|||
*self.user_id.write().await = user_id;
|
||||
}
|
||||
|
||||
/// Listener for all incoming messages
|
||||
async fn spawn_listener(
|
||||
self: &Arc<Self>,
|
||||
mut read_half: Box<dyn Stream<Item = Result<Message, tungstenite::Error>> + Send + Unpin>,
|
||||
|
|
@ -444,7 +434,7 @@ impl OmikronConnection {
|
|||
let sender_id = &cv.get_sender();
|
||||
let receiver_id = &cv.get_receiver();
|
||||
|
||||
chat_files::change_message_state(
|
||||
let _ = chat_files::change_message_state(
|
||||
cv.get_data(DataTypes::send_time)
|
||||
.unwrap_or(&JsonValue::new_object())
|
||||
.as_i64()
|
||||
|
|
@ -520,7 +510,8 @@ impl OmikronConnection {
|
|||
DataTypes::message_state,
|
||||
JsonValue::from(ms.as_str()),
|
||||
),
|
||||
);
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
self.send_message(
|
||||
&CommunicationValue::new(CommunicationType::message_state)
|
||||
|
|
@ -535,7 +526,8 @@ impl OmikronConnection {
|
|||
DataTypes::message_state,
|
||||
JsonValue::from(MessageState::Send.as_str()),
|
||||
),
|
||||
);
|
||||
)
|
||||
.await;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
53
src/terms/doc.rs
Normal file
53
src/terms/doc.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
use json::{JsonValue, object::Object};
|
||||
|
||||
use crate::{terms::terms_getter::Type, util::file_util::load_file};
|
||||
|
||||
#[derive(Clone)]
|
||||
#[allow(unused)]
|
||||
pub struct Doc {
|
||||
version: String,
|
||||
hash: String,
|
||||
doc_type: Type,
|
||||
timestamp: u64,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl Doc {
|
||||
pub fn get_version(&self) -> String {
|
||||
self.version.clone()
|
||||
}
|
||||
pub fn get_hash(&self) -> String {
|
||||
self.hash.clone()
|
||||
}
|
||||
pub fn get_time(&self) -> u64 {
|
||||
self.timestamp.clone()
|
||||
}
|
||||
pub fn get_content(&self) -> String {
|
||||
load_file(
|
||||
format!("docs/{}/", self.doc_type.to_str()).as_str(),
|
||||
format!("{}.md", self.version).as_str(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn to_json(&self) -> JsonValue {
|
||||
let mut json = JsonValue::new_object();
|
||||
|
||||
let _ = json.insert("version", self.version.clone());
|
||||
let _ = json.insert("hash", self.hash.clone());
|
||||
let _ = json.insert("unix", self.timestamp.clone());
|
||||
|
||||
json
|
||||
}
|
||||
pub fn from_json(doc_type: Type, json: Object) -> Option<Self> {
|
||||
let hash = json.get("hash")?.as_str()?.to_string();
|
||||
let version = json.get("version")?.as_str()?.to_string();
|
||||
let timestamp = json.get("unix")?.as_u64()?;
|
||||
|
||||
Some(Doc {
|
||||
version,
|
||||
hash,
|
||||
doc_type,
|
||||
timestamp,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -306,6 +306,14 @@ fn table_to_lines(table: Vec<Vec<String>>) -> Vec<DisplayLine> {
|
|||
}
|
||||
|
||||
let header = &table[0];
|
||||
let mut column_heights = vec![0; table[0].len()];
|
||||
|
||||
for row in table.iter().skip(1) {
|
||||
for (i, cell) in row.iter().enumerate() {
|
||||
let lines = cell.lines().count().max(1);
|
||||
column_heights[i] += lines;
|
||||
}
|
||||
}
|
||||
|
||||
let widths: Vec<usize> = header
|
||||
.iter()
|
||||
|
|
@ -383,22 +391,47 @@ fn wrap_cell(cell: &str, width: usize) -> Vec<String> {
|
|||
return vec![String::new()];
|
||||
}
|
||||
|
||||
let mut out = Vec::new();
|
||||
let mut chars = cell.chars();
|
||||
let mut lines = Vec::new();
|
||||
let mut current = String::new();
|
||||
|
||||
loop {
|
||||
let line: String = chars.by_ref().take(width).collect();
|
||||
if line.is_empty() {
|
||||
break;
|
||||
for word in cell.split_whitespace() {
|
||||
let word_len = word.chars().count();
|
||||
let current_len = current.chars().count();
|
||||
|
||||
if current_len == 0 {
|
||||
if word_len <= width {
|
||||
current.push_str(word);
|
||||
} else {
|
||||
for chunk in word.chars().collect::<Vec<_>>().chunks(width) {
|
||||
lines.push(chunk.iter().collect());
|
||||
}
|
||||
}
|
||||
} else if current_len + 1 + word_len <= width {
|
||||
current.push(' ');
|
||||
current.push_str(word);
|
||||
} else {
|
||||
lines.push(current);
|
||||
current = String::new();
|
||||
|
||||
if word_len <= width {
|
||||
current.push_str(word);
|
||||
} else {
|
||||
for chunk in word.chars().collect::<Vec<_>>().chunks(width) {
|
||||
lines.push(chunk.iter().collect());
|
||||
}
|
||||
}
|
||||
}
|
||||
out.push(line);
|
||||
}
|
||||
|
||||
if out.is_empty() {
|
||||
out.push(String::new());
|
||||
if !current.is_empty() {
|
||||
lines.push(current);
|
||||
}
|
||||
|
||||
out
|
||||
if lines.is_empty() {
|
||||
lines.push(String::new());
|
||||
}
|
||||
|
||||
lines
|
||||
}
|
||||
|
||||
fn flush_span(spans: &mut Vec<Span>, buf: &mut String, style: Style) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
pub mod doc;
|
||||
pub mod md_viewer;
|
||||
pub mod terms_checker;
|
||||
pub mod terms_getter;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
terms::{
|
||||
md_viewer::FileViewer,
|
||||
terms_getter::{Type, get_link, get_terms},
|
||||
terms_getter::{Type, get_current_docs, get_link, get_terms},
|
||||
},
|
||||
util::file_util::{load_file, save_file},
|
||||
};
|
||||
|
|
@ -41,7 +41,9 @@ impl ConsentManager {
|
|||
},
|
||||
};
|
||||
let state = state.sanitize();
|
||||
save_file("", "agreements", &state.to_string());
|
||||
if let Ok(string) = state.to_string().await {
|
||||
save_file("", "agreements", &string);
|
||||
}
|
||||
state
|
||||
};
|
||||
|
||||
|
|
@ -92,24 +94,46 @@ impl ConsentUiState {
|
|||
self
|
||||
}
|
||||
|
||||
fn to_string(self) -> String {
|
||||
async fn to_string(self) -> Result<String, ()> {
|
||||
let current_secs = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs();
|
||||
format!(
|
||||
"\"EULA=true\" indicates that you read and accepted the End User Licence agreement. You can find our EULA at https://legal.tensamin.net/eula/\
|
||||
|
||||
if let Some((eula, tos, pp)) = get_current_docs().await {
|
||||
Ok(format!(
|
||||
"\
|
||||
\"EULA=true\" indicates that you read, understood and accepted the End User Licence agreement. You can find our EULA at https://legal.tensamin.net/eula/\
|
||||
\nEULA={}\
|
||||
\n\"PrivacyPolicy=true\" indicates that you read and accepted the Privacy Policy. You can find our Privacy Policy at https://legal.tensamin.net/privacy-policy/\
|
||||
\nEULA-VERSION={}\
|
||||
\nEULA-HASH={}\
|
||||
\n\"PrivacyPolicy=true\" indicates that you read, understood and accepted the Privacy Policy. You can find our Privacy Policy at https://legal.tensamin.net/privacy-policy/\
|
||||
\nPrivacyPolicy={}\
|
||||
\n\"ToS=true\" indicates that you read and accepted the Terms of Service. You can find our Terms of Service at https://legal.tensamin.net/terms-of-service/\
|
||||
\nPrivacyPolicy-VERSION={}\
|
||||
\nPrivacyPolicy-HASH={}\
|
||||
\n\"ToS=true\" indicates that you read, understood and accepted the Terms of Service. You can find our Terms of Service at https://legal.tensamin.net/terms-of-service/\
|
||||
\nToS={}\
|
||||
\nToS-VERSION={}\
|
||||
\nToS-HASH={}\
|
||||
\nThis file reflects the current consent state used by the application.\
|
||||
\nIt may be regenerated or overwritten by the application.\
|
||||
\nThis file was last edited by Tensamin at:\
|
||||
\nUNIX-SECOND={}",
|
||||
self.eula, self.pp, self.tos, current_secs
|
||||
)
|
||||
\nUNIX-SECOND={}\
|
||||
",
|
||||
self.eula,
|
||||
eula.get_version(),
|
||||
eula.get_hash(),
|
||||
self.tos,
|
||||
tos.get_version(),
|
||||
tos.get_hash(),
|
||||
self.pp,
|
||||
pp.get_version(),
|
||||
pp.get_hash(),
|
||||
current_secs
|
||||
))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
fn from_str(s: &str) -> Self {
|
||||
|
|
@ -195,7 +219,7 @@ async fn run_consent_ui() -> UserChoice {
|
|||
return;
|
||||
}
|
||||
|
||||
let max_width = 132;
|
||||
let max_width = 150;
|
||||
let max_height = 20;
|
||||
|
||||
let content_width = if max_width < size.width { max_width } else { size.width} ;
|
||||
|
|
@ -230,30 +254,43 @@ async fn run_consent_ui() -> UserChoice {
|
|||
};
|
||||
|
||||
let (mut optional_lines, agree_lines): (Vec<i16>, Vec<&str>) =
|
||||
if size.width > 132 {
|
||||
if size.width > 143 {
|
||||
(
|
||||
vec![7, 3, 7, 4],
|
||||
vec![
|
||||
"",
|
||||
"By selecting Continue, you confirm that you have read and agree to the End User License Agreement and applicable Terms of Service.",
|
||||
"By selecting Continue, you confirm that you have read, understood and agree to the End User License Agreement and applicable Terms of Service.",
|
||||
"",
|
||||
"Tensamin services require acceptance of the Terms of Service and Privacy Policy.",
|
||||
"",
|
||||
"While having a document selected press O to view in this UI or press L to open as a link.",
|
||||
]
|
||||
)
|
||||
} else if size.width > 68 {
|
||||
} else if size.width > 92 {
|
||||
(
|
||||
vec![8, 3, 8, 4],
|
||||
vec![
|
||||
"",
|
||||
"By selecting Continue, you confirm that you have read and agree",
|
||||
"to the End User License Agreement and applicable Terms of Service.",
|
||||
"By selecting Continue, you confirm that you have read, understood and agree to the End User",
|
||||
"License Agreement and applicable Terms of Service.",
|
||||
"",
|
||||
"Tensamin services require acceptance of the Terms of Service and Privacy Policy.",
|
||||
"",
|
||||
"While having a document selected press O to view in this UI or press L to open as a link.",
|
||||
]
|
||||
)
|
||||
} else if size.width > 73 {
|
||||
(
|
||||
vec![8, 3, 8, 4],
|
||||
vec![
|
||||
"",
|
||||
"By selecting Continue, you confirm that you have read, understood and",
|
||||
"agree to the End User License Agreement and applicable Terms of Service.",
|
||||
"",
|
||||
"Tensamin services require acceptance of the ToS and Privacy Policy.",
|
||||
"",
|
||||
"While having a document selected press O to view in this UI or",
|
||||
"press L to open as a link.",
|
||||
"While having a document selected press O to view in this UI or press L",
|
||||
"to open as a link.",
|
||||
]
|
||||
)
|
||||
} else {
|
||||
|
|
@ -262,8 +299,8 @@ async fn run_consent_ui() -> UserChoice {
|
|||
vec![
|
||||
"",
|
||||
"By selecting Continue, you confirm that you have",
|
||||
"read and agree to the End User License Agreement",
|
||||
"and applicable Terms of Service.",
|
||||
"read, understood and agree to the End User License",
|
||||
"Agreement and applicable Terms of Service.",
|
||||
"",
|
||||
"Tensamin services require acceptance of the",
|
||||
"Terms of Service and Privacy Policy.",
|
||||
|
|
@ -340,7 +377,7 @@ async fn run_consent_ui() -> UserChoice {
|
|||
}
|
||||
|
||||
let consent_block = Paragraph::new(Text::from(text_lines))
|
||||
.block(Block::default().title(" Tensamin User Consent ").borders(Borders::ALL));
|
||||
.block(Block::default().title(" Tensamin User Consent [Q to Quit] ").borders(Borders::ALL));
|
||||
f.render_widget(consent_block, chunks[0]);
|
||||
|
||||
draw_buttons(f, chunks[1], &state);
|
||||
|
|
@ -358,8 +395,8 @@ async fn run_consent_ui() -> UserChoice {
|
|||
}
|
||||
match key.code {
|
||||
KeyCode::Esc => break UserChoice::Deny,
|
||||
KeyCode::Up => state.prev(),
|
||||
KeyCode::Down | KeyCode::Tab => state.next(),
|
||||
KeyCode::Up | KeyCode::Left => state.prev(),
|
||||
KeyCode::Down | KeyCode::Right | KeyCode::Tab => state.next(),
|
||||
KeyCode::Char('q') | KeyCode::Char('Q') => break UserChoice::Deny,
|
||||
KeyCode::Char('o') | KeyCode::Char('O') => {
|
||||
let terms_type = match state.focus {
|
||||
|
|
@ -516,7 +553,7 @@ fn draw_buttons(f: &mut ratatui::Frame, area: Rect, state: &ConsentUiState) {
|
|||
.fg(Color::Black)
|
||||
.bg(Color::Green)
|
||||
.add_modifier(Modifier::BOLD)
|
||||
} else if state.can_continue() && state.pp {
|
||||
} else if state.can_continue_all() {
|
||||
Style::default().fg(Color::Green)
|
||||
} else {
|
||||
Style::default().fg(Color::DarkGray)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
use json::JsonValue::Object;
|
||||
|
||||
use crate::terms::doc::Doc;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Type {
|
||||
EULA,
|
||||
|
|
@ -10,7 +14,7 @@ impl Type {
|
|||
match self {
|
||||
Self::EULA => "eula",
|
||||
Self::TOS => "tos",
|
||||
Self::PP => "pp",
|
||||
Self::PP => "privacy",
|
||||
}
|
||||
}
|
||||
pub fn to_string(&self) -> String {
|
||||
|
|
@ -21,9 +25,40 @@ impl Type {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_link(terms_type: Type) -> String {
|
||||
format!("https://legal.tensamin.net/{}/", terms_type.to_str())
|
||||
}
|
||||
|
||||
pub async fn get_current_docs() -> Option<(Doc, Doc, Doc)> {
|
||||
let body = reqwest::get("https://legal.tensamin.net/api/current/")
|
||||
.await
|
||||
.ok()?
|
||||
.text()
|
||||
.await
|
||||
.ok()?;
|
||||
|
||||
let json = json::parse(&body).ok()?;
|
||||
|
||||
if let Object(eula) = &json["eula"] {
|
||||
if let Object(tos) = &json["tos"] {
|
||||
if let Object(pp) = &json["pp"] {
|
||||
Some((
|
||||
Doc::from_json(Type::EULA, eula.clone())?,
|
||||
Doc::from_json(Type::TOS, tos.clone())?,
|
||||
Doc::from_json(Type::PP, pp.clone())?,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_terms(terms_type: Type) -> Option<String> {
|
||||
let body = reqwest::get(format!(
|
||||
"https://legal.tensamin.net/api/text/{}/",
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ use x448::{PublicKey, Secret};
|
|||
static USERS: Lazy<Mutex<Vec<UserProfile>>> = Lazy::new(|| Mutex::new(Vec::new()));
|
||||
static UNIQUE: Lazy<Mutex<bool>> = Lazy::new(|| Mutex::new(false));
|
||||
|
||||
// uuid::private_key
|
||||
#[allow(dead_code)]
|
||||
pub async fn load_from_tu(username: &str) -> Result<(), ()> {
|
||||
let file_content = load_file("", &format!("{}.tu", username));
|
||||
let segments = file_content.split("::").collect::<Vec<&str>>();
|
||||
|
|
@ -181,6 +181,7 @@ pub async fn load_users() -> io::Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn set_unique(val: bool) {
|
||||
*UNIQUE.lock().unwrap() = val;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use crate::gui::log_panel::log_message;
|
||||
use crate::users::user_manager;
|
||||
use crate::util::file_util::{has_file, load_file, used_dir_space};
|
||||
use base64::{Engine as _, engine::general_purpose};
|
||||
use json::{JsonValue, object};
|
||||
|
|
@ -84,7 +82,7 @@ impl UserProfile {
|
|||
let created_at = j["created_at"].as_i64()?;
|
||||
let display_name = j["display_name"].as_str().map(|s| s.to_string());
|
||||
|
||||
let mut up = UserProfile {
|
||||
let up = UserProfile {
|
||||
user_id,
|
||||
username,
|
||||
display_name,
|
||||
|
|
@ -110,6 +108,7 @@ impl UserProfile {
|
|||
Some(up)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn randomize_reset_token(&mut self) -> String {
|
||||
let mut bytes = [0u8; 192];
|
||||
OsRng.fill(bytes.as_mut());
|
||||
|
|
@ -118,6 +117,7 @@ impl UserProfile {
|
|||
new_token
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_display_name(&self) -> String {
|
||||
self.display_name
|
||||
.clone()
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use x448::{PublicKey, Secret, SharedSecret};
|
|||
|
||||
/// Errors for crypto opertions
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum CryptoError {
|
||||
Base64Decode(base64::DecodeError),
|
||||
InvalidKey,
|
||||
|
|
@ -55,6 +56,7 @@ pub fn load_secret_key(base64_secret: &str) -> Option<Secret> {
|
|||
Secret::from_bytes(&bytes)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn derive_aes_key(shared: &SharedSecret) -> [u8; 32] {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(shared.as_bytes());
|
||||
|
|
@ -64,6 +66,7 @@ fn derive_aes_key(shared: &SharedSecret) -> [u8; 32] {
|
|||
key
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn encrypt(
|
||||
base64_secret: &str,
|
||||
base64_peer_pub: &str,
|
||||
|
|
@ -89,6 +92,7 @@ pub fn encrypt(
|
|||
Ok(STANDARD.encode(&out))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn decrypt(
|
||||
base64_secret: &str,
|
||||
base64_peer_pub: &str,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use x448::{PublicKey, Secret};
|
|||
|
||||
// --- Custom Errors ---
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum SecurePayloadError {
|
||||
InvalidBase64,
|
||||
InvalidHex,
|
||||
|
|
@ -19,6 +20,7 @@ pub enum SecurePayloadError {
|
|||
|
||||
// --- Data Format Enum ---
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum DataFormat {
|
||||
Raw,
|
||||
Base64,
|
||||
|
|
@ -42,6 +44,7 @@ impl Clone for SecurePayload {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl SecurePayload {
|
||||
/// Clear Constructor: Takes data in any format and the user's private key.
|
||||
pub fn new<S, T: AsRef<[u8]>>(
|
||||
|
|
|
|||
|
|
@ -18,11 +18,13 @@ pub fn delete_file(path: &str, name: &str) -> bool {
|
|||
fs::remove_file(file).is_ok()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn delete_directory(path: &str) -> bool {
|
||||
let dir = Path::new(&get_directory()).join(path);
|
||||
delete_dir_recursive(&dir)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn delete_dir_recursive(directory: &Path) -> bool {
|
||||
if !directory.exists() {
|
||||
return false;
|
||||
|
|
@ -38,6 +40,7 @@ fn delete_dir_recursive(directory: &Path) -> bool {
|
|||
true
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn delete_user_directory(user_id: Uuid) {
|
||||
let user_dir = Path::new(&get_directory())
|
||||
.join("users")
|
||||
|
|
@ -187,6 +190,7 @@ pub fn get_directory() -> String {
|
|||
.to_string()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn used_space() -> u64 {
|
||||
get_directory_size(&PathBuf::from(get_directory()))
|
||||
}
|
||||
|
|
@ -208,6 +212,7 @@ pub fn get_directory_size(directory: &Path) -> u64 {
|
|||
size
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_designed_storage(user_id: Uuid) -> String {
|
||||
let user_dir = Path::new(&get_directory())
|
||||
.join("users")
|
||||
|
|
@ -215,6 +220,7 @@ pub fn get_designed_storage(user_id: Uuid) -> String {
|
|||
design_byte(get_directory_size(&user_dir))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn design_byte(bytes: u64) -> String {
|
||||
let mut hr_size = format!("{:.2}B", bytes as f64);
|
||||
let k = bytes as f64 / 1024.0;
|
||||
|
|
@ -234,6 +240,7 @@ pub fn design_byte(bytes: u64) -> String {
|
|||
hr_size
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn get_used_ram() -> String {
|
||||
let mut sys = System::new_all();
|
||||
sys.refresh_all();
|
||||
|
|
@ -243,6 +250,7 @@ pub fn get_used_ram() -> String {
|
|||
}
|
||||
|
||||
// Helper to download the zip file content to a file on disk
|
||||
#[allow(dead_code)]
|
||||
async fn download_zip(url: &str, as_name: &Path) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let response = reqwest::get(url).await?;
|
||||
|
||||
|
|
@ -258,6 +266,7 @@ async fn download_zip(url: &str, as_name: &Path) -> Result<(), Box<dyn std::erro
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(dead_code, deprecated)]
|
||||
fn extract_zip_contents_to_folder(
|
||||
zip_path: &Path,
|
||||
target_dir: &Path,
|
||||
|
|
@ -334,6 +343,7 @@ fn extract_zip_contents_to_folder(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn download_and_extract_zip(url: &str, as_name: &str) {
|
||||
let base_dir = PathBuf::from(get_directory());
|
||||
let zip_filename = format!("{}.zip", Uuid::new_v4()); // Use a unique name for the downloaded ZIP file
|
||||
|
|
|
|||
Loading…
Reference in a new issue