Fixes Patches Creation & More
Working with files / Paths fixed Websocket PingPongs (There is no data behind this just PingPong) Storing User Profiles correctly Added necessary dependencies and initial code support for: - X.509 certificate handling via x509/pkcs8 crates - Key generation and crypto operations via x448/sha2 - Structured hex encoding and base64 encoding
This commit is contained in:
parent
bba3f548ab
commit
0d07ddf851
23 changed files with 887 additions and 266 deletions
|
|
@ -14,11 +14,11 @@ pub struct Contact {
|
|||
#[derive(Debug, Clone)]
|
||||
pub enum UserStatus {
|
||||
Online,
|
||||
DoNotDisturb,
|
||||
Do_Not_Disturb,
|
||||
WC,
|
||||
Away,
|
||||
UserOffline,
|
||||
IotaOffline,
|
||||
User_Offline,
|
||||
Iota_Offline,
|
||||
}
|
||||
|
||||
impl Default for Contact {
|
||||
|
|
@ -31,7 +31,7 @@ impl Default for Contact {
|
|||
user_id: None,
|
||||
user_name: None,
|
||||
last_message_at: Some(now),
|
||||
user_status: UserStatus::UserOffline,
|
||||
user_status: UserStatus::User_Offline,
|
||||
about: None,
|
||||
}
|
||||
}
|
||||
|
|
@ -43,7 +43,7 @@ impl Contact {
|
|||
user_id: Some(user_id),
|
||||
user_name: None,
|
||||
last_message_at: Some(last_message_at),
|
||||
user_status: UserStatus::UserOffline,
|
||||
user_status: UserStatus::User_Offline,
|
||||
about: None,
|
||||
}
|
||||
}
|
||||
|
|
@ -53,7 +53,7 @@ impl Contact {
|
|||
user_id: Some(user_id),
|
||||
user_name: None,
|
||||
last_message_at: None,
|
||||
user_status: UserStatus::UserOffline,
|
||||
user_status: UserStatus::User_Offline,
|
||||
about: None,
|
||||
}
|
||||
}
|
||||
|
|
@ -64,13 +64,13 @@ impl Contact {
|
|||
pub fn to_json(&self) -> JsonValue {
|
||||
let mut obj = JsonValue::new_object();
|
||||
if let Some(id) = &self.user_id {
|
||||
obj["userID"] = JsonValue::from(id.to_string());
|
||||
obj["user_id"] = JsonValue::from(id.to_string());
|
||||
}
|
||||
if let Some(name) = &self.user_name {
|
||||
obj["userName"] = JsonValue::from(name.as_str());
|
||||
obj["user_name"] = JsonValue::from(name.as_str());
|
||||
}
|
||||
if let Some(ts) = &self.last_message_at {
|
||||
obj["lastMessageAt"] = JsonValue::from(ts.to_string());
|
||||
obj["last_message_at"] = JsonValue::from(ts.to_string());
|
||||
}
|
||||
obj
|
||||
}
|
||||
|
|
@ -81,29 +81,27 @@ impl Contact {
|
|||
}
|
||||
|
||||
pub fn from_json(o: &JsonValue) -> Contact {
|
||||
let user_id = o["userID"]
|
||||
.as_str()
|
||||
.and_then(|s| Uuid::parse_str(s).ok());
|
||||
let user_id = o["user_id"].as_str().and_then(|s| Uuid::parse_str(s).ok());
|
||||
|
||||
let user_name = o["userName"].as_str().map(|s| s.to_string());
|
||||
let user_name = o["user_name"].as_str().map(|s| s.to_string());
|
||||
|
||||
let last_message_at = o["lastMessageAt"].as_i64();
|
||||
let last_message_at = o["last_message_at"].as_i64();
|
||||
|
||||
Contact {
|
||||
user_id,
|
||||
user_name,
|
||||
last_message_at,
|
||||
user_status: UserStatus::UserOffline, // default
|
||||
user_status: UserStatus::User_Offline, // default
|
||||
about: None,
|
||||
}
|
||||
}
|
||||
pub fn info(&self) -> JsonValue {
|
||||
let mut obj = self.to_json();
|
||||
if let Some(id) = &self.user_id {
|
||||
obj["userID"] = JsonValue::from(id.to_string());
|
||||
obj["user_id"] = JsonValue::from(id.to_string());
|
||||
}
|
||||
if let Some(name) = &self.user_name {
|
||||
obj["userName"] = JsonValue::from(name.as_str());
|
||||
obj["user_name"] = JsonValue::from(name.as_str());
|
||||
}
|
||||
obj
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
pub mod contact;
|
||||
pub mod user_community_util;
|
||||
pub mod user_manager;
|
||||
pub mod user_profile_full;
|
||||
pub mod user_profile;
|
||||
pub mod user_community_util;
|
||||
pub mod user_profile_full;
|
||||
|
|
|
|||
|
|
@ -6,12 +6,7 @@ use uuid::Uuid;
|
|||
pub struct UserCommunityUtil;
|
||||
|
||||
impl UserCommunityUtil {
|
||||
pub fn add_community(
|
||||
storage_owner: Uuid,
|
||||
address: String,
|
||||
title: String,
|
||||
position: String,
|
||||
) {
|
||||
pub fn add_community(storage_owner: Uuid, address: String, title: String, position: String) {
|
||||
let path = format!("users/{}/communities.json", storage_owner);
|
||||
let mut communities: JsonValue = Self::load_array(&path);
|
||||
|
||||
|
|
@ -58,7 +53,7 @@ impl UserCommunityUtil {
|
|||
if let Some(parent) = Path::new(path).parent() {
|
||||
let _ = fs::create_dir_all(parent);
|
||||
}
|
||||
|
||||
|
||||
let _ = fs::write(path, arr.pretty(3));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,26 @@
|
|||
use std::fs;
|
||||
use std::sync::Mutex;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use uuid::Uuid;
|
||||
use rand::Rng;
|
||||
use rand::rngs::OsRng;
|
||||
use base64::{engine::general_purpose, Engine as _};
|
||||
use json::{JsonValue};
|
||||
use once_cell::sync::Lazy;
|
||||
use crate::auth::auth_connector::AuthConnector;
|
||||
use crate::users::user_profile::UserProfile;
|
||||
use crate::users::user_profile_full::UserProfileFull;
|
||||
use crate::util::config_util::CONFIG;
|
||||
use crate::util::file_util::{load_file, save_file};
|
||||
use base64::{Engine as _, engine::general_purpose};
|
||||
use der::DerOrd;
|
||||
use hex;
|
||||
use json::JsonValue;
|
||||
use once_cell::sync::Lazy;
|
||||
use pkcs8::EncodePublicKey;
|
||||
use pkcs8::spki::SubjectPublicKeyInfoOwned;
|
||||
use pkcs8::{ObjectIdentifier, PrivateKeyInfo, SubjectPublicKeyInfo, der::Encode};
|
||||
use rand::Rng;
|
||||
use rand_core::OsRng;
|
||||
use rand_core::RngCore;
|
||||
use rustls::pki_types::SubjectPublicKeyInfoDer;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::io;
|
||||
use std::sync::Mutex;
|
||||
use uuid::Uuid;
|
||||
use x448::{PublicKey, Secret};
|
||||
use x509::AlgorithmIdentifier;
|
||||
|
||||
pub struct UserManager;
|
||||
|
||||
|
|
@ -18,14 +28,22 @@ static USERS: Lazy<Mutex<Vec<UserProfile>>> = Lazy::new(|| Mutex::new(Vec::new()
|
|||
static UNIQUE: Lazy<Mutex<bool>> = Lazy::new(|| Mutex::new(false));
|
||||
|
||||
impl UserManager {
|
||||
pub fn create_user(username: &str) -> Option<UserProfileFull> {
|
||||
// Stub: normally AuthConnector.getRegister() returns a UUID
|
||||
let user_id = Uuid::new_v4();
|
||||
pub async fn create_user(username: &str) -> Option<UserProfileFull> {
|
||||
let user_id = AuthConnector::get_register().await.unwrap();
|
||||
let mut buf = [0u8; 56];
|
||||
let mut rng = OsRng;
|
||||
rng.fill_bytes(&mut buf);
|
||||
let private_key = Secret::from_bytes(&buf).unwrap();
|
||||
let public_key = PublicKey::from(&private_key);
|
||||
|
||||
// Stubbed: CryptoHelper.generateKeyPair()
|
||||
let public_key = general_purpose::STANDARD.encode(b"dummy-public");
|
||||
let private_key = general_purpose::STANDARD.encode(b"dummy-private");
|
||||
let private_key_hash = format!("hash-{}", &private_key);
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(
|
||||
&general_purpose::STANDARD
|
||||
.encode(&private_key.as_bytes())
|
||||
.as_bytes(),
|
||||
);
|
||||
let result = hasher.finalize();
|
||||
let private_key_hash = hex::encode(result);
|
||||
|
||||
let mut bytes = [0u8; 192];
|
||||
OsRng.fill(bytes.as_mut());
|
||||
|
|
@ -35,12 +53,27 @@ impl UserManager {
|
|||
user_id,
|
||||
username.to_string(),
|
||||
None,
|
||||
public_key,
|
||||
general_purpose::STANDARD.encode(&public_key.as_bytes()),
|
||||
private_key_hash,
|
||||
reset_token,
|
||||
);
|
||||
|
||||
let up_full = UserProfileFull { user_profile: up.clone(), private_key };
|
||||
let up_full = UserProfileFull {
|
||||
user_profile: up.clone(),
|
||||
private_key: general_purpose::STANDARD.encode(&private_key.as_bytes()),
|
||||
};
|
||||
|
||||
AuthConnector::complete_register(&up, &CONFIG.lock().unwrap().get_iota_id().to_string())
|
||||
.await;
|
||||
save_file(
|
||||
"",
|
||||
&format!("{}.tu", username),
|
||||
&format!(
|
||||
"{}::{}",
|
||||
user_id,
|
||||
general_purpose::STANDARD.encode(&private_key.as_bytes())
|
||||
),
|
||||
);
|
||||
|
||||
USERS.lock().unwrap().push(up);
|
||||
Self::save_users().ok();
|
||||
|
|
@ -48,7 +81,12 @@ impl UserManager {
|
|||
}
|
||||
|
||||
pub fn get_user(user_id: Uuid) -> Option<UserProfile> {
|
||||
USERS.lock().unwrap().iter().cloned().find(|u| u.user_id == user_id)
|
||||
USERS
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.cloned()
|
||||
.find(|u| u.user_id == user_id)
|
||||
}
|
||||
|
||||
pub fn get_users() -> Vec<UserProfile> {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
use std::fs;
|
||||
use std::sync::Mutex;
|
||||
use std::collections::HashMap;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use uuid::Uuid;
|
||||
use crate::auth::auth_connector::AuthConnector;
|
||||
use crate::users::user_manager::UserManager;
|
||||
use base64::{Engine as _, engine::general_purpose};
|
||||
use json::{JsonValue, object, stringify};
|
||||
use rand::Rng;
|
||||
use rand::rngs::OsRng;
|
||||
use base64::{engine::general_purpose, Engine as _};
|
||||
use json::{JsonValue, object, stringify};
|
||||
use crate::users::user_manager::UserManager;
|
||||
use crate::auth::auth_connector::AuthConnector;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use std::sync::Mutex;
|
||||
use uuid::Uuid;
|
||||
|
||||
// --- UserProfile ---
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -43,34 +43,42 @@ impl UserProfile {
|
|||
|
||||
pub fn to_json(&self) -> JsonValue {
|
||||
let mut obj = object! {
|
||||
"UUID" => self.user_id.to_string(),
|
||||
"uuid" => self.user_id.to_string(),
|
||||
"username" => self.username.clone(),
|
||||
"publicKey" => self.public_key.clone(),
|
||||
"privateKeyHash" => self.private_key_hash.clone(),
|
||||
"resetToken" => self.reset_token.clone()
|
||||
"public_key" => self.public_key.clone(),
|
||||
"private_key_hash" => self.private_key_hash.clone(),
|
||||
"reset_token" => self.reset_token.clone()
|
||||
};
|
||||
if let Some(d) = &self.display_name {
|
||||
obj["displayName"] = d.clone().into();
|
||||
obj["display_name"] = d.clone().into();
|
||||
}
|
||||
obj
|
||||
}
|
||||
|
||||
pub async fn from_json(j: &JsonValue) -> Option<Self> {
|
||||
let uuid = Uuid::parse_str(j["UUID"].as_str()?).ok()?;
|
||||
let uuid = Uuid::parse_str(j["uuid"].as_str()?).ok()?;
|
||||
let username = j["username"].as_str()?.to_string();
|
||||
let public_key = j["publicKey"].as_str()?.to_string();
|
||||
let private_key_hash = j["privateKeyHash"].as_str()?.to_string();
|
||||
let reset_token = j["resetToken"].as_str()?.to_string();
|
||||
let display_name = j["displayName"].as_str().map(|s| s.to_string());
|
||||
let public_key = j["public_key"].as_str()?.to_string();
|
||||
let private_key_hash = j["private_key_hash"].as_str()?.to_string();
|
||||
let reset_token = j["reset_token"].as_str()?.to_string();
|
||||
let display_name = j["display_name"].as_str().map(|s| s.to_string());
|
||||
|
||||
let mut up = UserProfile::new(uuid, username, display_name, public_key, private_key_hash, reset_token);
|
||||
let mut up = UserProfile::new(
|
||||
uuid,
|
||||
username,
|
||||
display_name,
|
||||
public_key,
|
||||
private_key_hash,
|
||||
reset_token,
|
||||
);
|
||||
|
||||
// Migration hook (stubbed, since AuthConnector isn’t implemented here)
|
||||
if j.has_key("migrate")
|
||||
|| j.has_key("migrating")
|
||||
|| j.has_key("changing")
|
||||
|| j.has_key("move")
|
||||
|| j.has_key("moving") {
|
||||
if j.has_key("migrate")
|
||||
|| j.has_key("migrating")
|
||||
|| j.has_key("changing")
|
||||
|| j.has_key("move")
|
||||
|| j.has_key("moving")
|
||||
{
|
||||
if AuthConnector::migrate_user(&mut up, stringify!("{}", Uuid::new_v4())).await {
|
||||
println!("[INFO] Migration triggered for {}", up.username);
|
||||
UserManager::set_unique(true);
|
||||
|
|
@ -90,6 +98,8 @@ impl UserProfile {
|
|||
}
|
||||
|
||||
pub fn get_display_name(&self) -> String {
|
||||
self.display_name.clone().unwrap_or_else(|| self.username.clone())
|
||||
self.display_name
|
||||
.clone()
|
||||
.unwrap_or_else(|| self.username.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@ use crate::users::user_profile::UserProfile;
|
|||
pub struct UserProfileFull {
|
||||
pub user_profile: UserProfile,
|
||||
pub private_key: String,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue