use chrono::{DateTime, NaiveDateTime, TimeZone, Utc};
use serde::{Deserialize, Deserializer, Serialize};
#[derive(Debug, Deserialize)]
pub struct Token {
pub access: String,
pub refresh: String
}
#[derive(Debug, Serialize)]
pub struct Auth {
pub email: String,
pub password: String
}
#[derive(Debug, Serialize)]
pub struct Refresh {
pub refresh: String
}
#[derive(Debug, Deserialize)]
pub struct User {
#[serde(deserialize_with = "id_deserializer")]
pub id: String,
pub email: String
}
#[derive(Debug, Serialize)]
pub struct UserPassword {
pub current_password: String
}
#[derive(Debug, Serialize)]
pub struct UserChangePassword {
pub current_password: String,
pub new_password: String
}
#[derive(Debug, Deserialize, Serialize)]
pub struct NewPassword {
pub site: String,
pub login: String,
pub lowercase: bool,
pub uppercase: bool,
pub symbols: bool,
pub digits: bool,
pub length: u8,
pub counter: u32,
pub version: u8
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Passwords {
pub count: u32,
pub results: Vec<Password>
}
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Password {
pub id: String,
pub site: String,
pub login: String,
pub lowercase: bool,
pub uppercase: bool,
pub symbols: bool,
pub digits: bool,
pub length: u8,
pub counter: u32,
pub version: u8,
pub created: DateTime<Utc>,
pub modified: DateTime<Utc>
}
impl<'de> Deserialize<'de> for Password {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>, {
#[derive(Deserialize)]
struct RawPassword {
#[serde(deserialize_with = "id_deserializer")]
id: String,
site: String,
login: String,
lowercase: bool,
uppercase: bool,
symbols: bool,
digits: Option<bool>,
numbers: Option<bool>,
length: u8,
counter: u32,
version: u8,
#[serde(deserialize_with = "date_deserializer")]
created: DateTime<Utc>,
#[serde(deserialize_with = "date_deserializer")]
modified: DateTime<Utc>
}
let RawPassword {id, site, login, lowercase, uppercase, symbols, digits, numbers, length, counter, version, created, modified} = RawPassword::deserialize(deserializer)?;
let digits = digits.or(numbers).ok_or(serde::de::Error::missing_field("digits or numbers"))?;
Ok(Password {id, site, login, lowercase, uppercase, symbols, digits, length, counter, version, created, modified})
}
}
fn id_deserializer<'de, D>(deserializer: D) -> Result<String, D::Error> where D: Deserializer<'de>, {
#[derive(Deserialize)]
#[serde(untagged)]
enum StringOrInteger {
String(String),
Integer(u64)
}
match StringOrInteger::deserialize(deserializer)? {
StringOrInteger::String(string) => Ok(string),
StringOrInteger::Integer(integer) => Ok(integer.to_string())
}
}
fn date_deserializer<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error> where D: Deserializer<'de>, {
let s = String::deserialize(deserializer)?;
match s.parse::<NaiveDateTime>() {
Ok(date) => Ok(Utc.from_utc_datetime(&date)),
Err(_) => s.parse::<DateTime<Utc>>().map_err(serde::de::Error::custom)
}
}
impl From<NewPassword> for Password {
fn from(new_password: NewPassword) -> Self {
Password {
id: String::new(),
site: new_password.site,
login: new_password.login,
lowercase: new_password.lowercase,
uppercase: new_password.uppercase,
symbols: new_password.symbols,
digits: new_password.digits,
length: new_password.length,
counter: new_password.counter,
version: new_password.version,
created: Utc::now(),
modified: Utc::now()
}
}
}