use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] pub struct User { pub id: String, pub name: Option, pub email: String, #[serde(with = "bool_from_int")] pub email_verified: bool, pub master_password_hash: String, pub master_password_hint: Option, pub password_salt: Option, // Salt for server-side PBKDF2 (NULL for legacy users) pub key: String, pub private_key: String, pub public_key: String, pub kdf_type: i32, pub kdf_iterations: i32, pub security_stamp: String, pub created_at: String, pub updated_at: String, } mod bool_from_int { use serde::{self, Deserialize, Deserializer, Serializer}; pub fn deserialize<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { let value = i64::deserialize(deserializer)?; match value { 0 => Ok(false), 1 => Ok(true), _ => Err(serde::de::Error::custom("expected integer 0 or 1")), } } pub fn serialize(value: &bool, serializer: S) -> Result where S: Serializer, { if *value { serializer.serialize_i64(1) } else { serializer.serialize_i64(0) } } } // For /accounts/prelogin response #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct PreloginResponse { pub kdf: i32, pub kdf_iterations: i32, } // For /accounts/register request #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RegisterRequest { pub name: Option, pub email: String, pub master_password_hash: String, pub master_password_hint: Option, pub user_symmetric_key: String, pub user_asymmetric_keys: KeyData, pub kdf: i32, pub kdf_iterations: i32, } #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct KeyData { pub public_key: String, pub encrypted_private_key: String, } // For DELETE /accounts request #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct DeleteAccountRequest { #[serde(alias = "MasterPasswordHash")] pub master_password_hash: Option, pub otp: Option, }