register logic (bricked) user management !! omikron con wait for

response method !!
This commit is contained in:
Alex Emmet 2026-01-13 22:58:54 +01:00
commit 0d51dc9ac7
16 changed files with 361 additions and 260 deletions

View file

@ -1,158 +0,0 @@
use crate::CONFIG;
use crate::data::communication::{CommunicationType, CommunicationValue, DataTypes};
use crate::users::user_profile::UserProfile;
use json::JsonValue;
use json::number::Number;
use reqwest::header::CONTENT_TYPE;
use reqwest::{Client, Response};
use std::time::Duration;
#[derive(Debug, Clone)]
pub struct AuthUser {
pub created_at: i64,
pub username: String,
pub display: String,
pub avatar: String,
pub about: String,
pub status: String,
pub public_key: String,
pub sub_level: i32,
pub sub_end: i32,
}
fn client() -> Client {
Client::builder()
.connect_timeout(Duration::from_secs(100))
.timeout(Duration::from_secs(150))
.build()
.unwrap()
}
pub async fn unregister_user(user_id: i64, reset_token: &str) -> Option<bool> {
let url = format!("https:/auth.tensamin.net/api/delete/{}", user_id);
let client = client();
let mut payload = JsonValue::new_object();
payload["reset_token"] = reset_token.into();
let res = client
.post(&url)
.header(CONTENT_TYPE, "application/json")
.body(payload.dump())
.send()
.await
.ok()?;
let json = res.text().await.ok()?;
let cv = CommunicationValue::from_json(&json);
Option::from(cv.is_type(CommunicationType::success))
}
pub async fn get_user(user_id: i64) -> Option<AuthUser> {
let url = format!("https://auth.tensamin.net/api/get/{}", user_id);
let client = client();
let res = client.get(&url).send().await.ok()?;
let json = res.text().await.ok()?;
let cv = CommunicationValue::from_json(&json);
if cv.comm_type != CommunicationType::success {
return None;
}
Some(AuthUser {
created_at: cv
.get_data(DataTypes::created_at)
.unwrap()
.to_string()
.parse::<i64>()
.unwrap_or(-1),
username: cv.get_data(DataTypes::username).unwrap().to_string(),
display: cv.get_data(DataTypes::display).unwrap().to_string(),
avatar: cv.get_data(DataTypes::avatar).unwrap().to_string(),
about: cv.get_data(DataTypes::about).unwrap().to_string(),
status: cv.get_data(DataTypes::status).unwrap().to_string(),
public_key: cv.get_data(DataTypes::public_key).unwrap().to_string(),
sub_level: cv
.get_data(DataTypes::sub_level)
.unwrap()
.to_string()
.parse::<i32>()
.unwrap_or(-1),
sub_end: cv
.get_data(DataTypes::sub_end)
.unwrap()
.to_string()
.parse::<i32>()
.unwrap_or(-1),
})
}
pub async fn get_register() -> Option<i64> {
let url = "https://auth.tensamin.net/api/register/init".to_string();
let client = client();
let res = client.get(&url).send().await.ok()?;
let json = res.text().await.ok()?;
let cv = CommunicationValue::from_json(&json);
cv.get_data(DataTypes::user_id)
.unwrap_or(&json::JsonValue::Number(Number::from(0)))
.as_i64()
}
pub async fn complete_register(user_profile: &UserProfile, iota_id: &str) -> bool {
let url = "https://auth.tensamin.net/api/register/complete";
let client = client();
let mut payload = JsonValue::new_object();
payload["id"] = user_profile.user_id.into();
payload["public_key"] = user_profile.public_key.clone().into();
payload["private_key_hash"] = user_profile.private_key_hash.clone().into();
payload["username"] = user_profile.username.clone().into();
payload["iota_id"] = iota_id.into();
payload["reset_token"] = user_profile.reset_token.clone().into();
let res = client
.post(url)
.header(CONTENT_TYPE, "application/json")
.body(payload.to_string())
.send()
.await
.unwrap();
let body = res.text().await.unwrap();
CommunicationValue::from_json(&body).is_type(CommunicationType::success)
}
pub async fn migrate_user(user_profile: &mut UserProfile) -> bool {
let url = format!(
"https://auth.tensamin.net/api/change/iota-id/{}",
user_profile.user_id
);
let client = client();
let mut payload = JsonValue::new_object();
payload["iota_id"] = JsonValue::String(CONFIG.read().await.get_iota_id().to_string());
payload["reset_token"] = user_profile.reset_token.clone().into();
payload["new_token"] = user_profile.randomize_reset_token().into();
let res = client
.post(url)
.header(CONTENT_TYPE, "application/json")
.body(payload.dump())
.send()
.await;
match res {
Ok(resp) => handle_response(resp).await,
Err(_) => false,
}
}
async fn handle_response(resp: Response) -> bool {
match resp.text().await {
Ok(text) => {
let cv = CommunicationValue::from_json(&text.to_string());
cv.comm_type == CommunicationType::success
}
Err(_) => false,
}
}

18
src/auth/auth_user.rs Normal file
View file

@ -0,0 +1,18 @@
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct AuthUser {
pub id: i64,
pub username: String,
pub password_hash: String,
pub public_key: String,
}
impl AuthUser {
pub fn new(id: i64, username: String, password_hash: String, public_key: String) -> Self {
AuthUser {
id,
username,
password_hash,
public_key,
}
}
}

View file

@ -1,129 +0,0 @@
use aes_gcm::{
Aes256Gcm, Nonce,
aead::{Aead, KeyInit, OsRng},
};
use base64::{Engine as _, engine::general_purpose::STANDARD};
use rand_core::RngCore;
use sha2::{Digest, Sha256};
use x448::{PublicKey, Secret, SharedSecret};
/// Errors for crypto operations
#[derive(Debug)]
pub enum CryptoError {
Base64Decode(base64::DecodeError),
InvalidKey,
AgreementError,
EncryptionError(aes_gcm::Error),
DecryptionError(aes_gcm::Error),
}
impl From<base64::DecodeError> for CryptoError {
fn from(err: base64::DecodeError) -> Self {
CryptoError::Base64Decode(err)
}
}
pub struct KeyPair {
pub secret: Secret,
pub public: PublicKey,
}
pub fn generate_keypair() -> KeyPair {
let mut buf = [0u8; 56];
let mut rng = OsRng;
rng.fill_bytes(&mut buf);
let secret = Secret::from_bytes(&buf).unwrap();
let public = PublicKey::from(&secret);
KeyPair { secret, public }
}
pub fn public_key_to_base64(pubkey: &PublicKey) -> String {
STANDARD.encode(pubkey.as_bytes().as_ref())
}
pub fn secret_key_to_base64(secret: &Secret) -> String {
STANDARD.encode(secret.as_bytes().as_ref())
}
pub fn load_public_key(base64_pub: &str) -> Option<PublicKey> {
let bytes = STANDARD.decode(base64_pub).unwrap();
PublicKey::from_bytes(&bytes)
}
pub fn load_secret_key(base64_secret: &str) -> Option<Secret> {
let bytes = STANDARD.decode(base64_secret).unwrap();
Secret::from_bytes(&bytes)
}
fn derive_aes_key(shared: &SharedSecret) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(shared.as_bytes());
let result = hasher.finalize();
let mut key = [0u8; 32];
key.copy_from_slice(&result[..32]);
key
}
pub fn encrypt(
base64_secret: &str,
base64_peer_pub: &str,
plaintext: &str,
) -> Result<String, CryptoError> {
let secret = load_secret_key(base64_secret).unwrap();
let peer_pub = load_public_key(base64_peer_pub).unwrap();
let shared = secret
.to_diffie_hellman(&peer_pub)
.ok_or(CryptoError::AgreementError)?;
let key_bytes = derive_aes_key(&shared);
let cipher = Aes256Gcm::new_from_slice(&key_bytes).expect("Key length should be correct");
let mut nonce_bytes = [0u8; 12];
OsRng.fill_bytes(&mut nonce_bytes);
let nonce = Nonce::from_slice(&nonce_bytes);
let ciphertext = cipher
.encrypt(nonce, plaintext.as_bytes())
.map_err(CryptoError::EncryptionError)?;
// prefix nonce to ciphertext
let mut out = Vec::with_capacity(nonce_bytes.len() + ciphertext.len());
out.extend_from_slice(&nonce_bytes);
out.extend_from_slice(&ciphertext);
Ok(STANDARD.encode(&out))
}
pub fn decrypt(
base64_secret: &str,
base64_peer_pub: &str,
encrypted_base64: &str,
) -> Result<String, CryptoError> {
let secret = load_secret_key(base64_secret).unwrap();
let peer_pub = load_public_key(base64_peer_pub).unwrap();
let shared = secret
.to_diffie_hellman(&peer_pub)
.ok_or(CryptoError::AgreementError)?;
let key_bytes = derive_aes_key(&shared);
let cipher = Aes256Gcm::new_from_slice(&key_bytes).expect("Key length should be correct");
let encrypted = STANDARD.decode(encrypted_base64)?;
if encrypted.len() < 12 {
return Err(CryptoError::DecryptionError(aes_gcm::Error));
}
let nonce_bytes = &encrypted[..12];
let ciphertext = &encrypted[12..];
let nonce = Nonce::from_slice(nonce_bytes);
let plaintext_bytes = cipher
.decrypt(nonce, ciphertext)
.map_err(CryptoError::DecryptionError)?;
let plaintext = String::from_utf8(plaintext_bytes)
.map_err(|_| CryptoError::DecryptionError(aes_gcm::Error))?;
Ok(plaintext)
}
pub fn hash_it(input: &str) -> Vec<u8> {
let mut hasher = Sha256::new();
hasher.update(input.as_bytes());
hasher.finalize().to_vec()
}
pub fn hex_hash(input: &str) -> String {
let digest = hash_it(input);
digest.iter().map(|b| format!("{:02x}", b)).collect()
}

View file

@ -1,7 +1,7 @@
use json::JsonValue;
use crate::util::file_util::load_file;
// NOT USED AT MOMENT
pub fn is_private_key_valid(user_id: &i64, key_hash: &str) -> bool {
let file_contents = load_file("", "users.json");

View file

@ -1,3 +1,2 @@
pub mod auth_connector;
pub mod crypto_helper;
pub mod auth_user;
pub mod local_auth;