use serde::{Deserialize, Serialize};
use zeroize::{Zeroize, ZeroizeOnDrop};
use crate::{field_access, impl_display, Error, Result};
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct Email {
email: String,
}
impl Email {
pub fn new<I: Into<String>>(email: I) -> Self {
Self {
email: email.into(),
}
}
}
field_access! {
Email {
email: as_ref { &str, String },
}
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize, Zeroize, ZeroizeOnDrop)]
pub struct Password {
password: String,
}
impl Password {
pub fn new<I: Into<String>>(password: I) -> Self {
Self {
password: password.into(),
}
}
}
field_access! {
Password {
password: as_ref { &str, String },
}
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize, Zeroize)]
pub struct Request {
username: String,
password: String,
token: String,
}
impl Request {
pub fn create(
algo: jwt::Algorithm,
key: &jwt::EncodingKey,
email: &Email,
password: &Password,
) -> Result<Self> {
jwt::encode(&jwt::Header::new(algo), email, key)
.map_err(|err| Error::io_other(format!("fetch_api_key: error signing request: {err}")))
.map(|token| Self {
username: email.email().into(),
password: password.password().into(),
token,
})
}
}
field_access! {
Request {
username: as_ref { &str, String },
password: as_ref { &str, String },
token: as_ref { &str, String },
}
}
impl_display!(Request);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_request() {
let algo = jwt::Algorithm::HS256;
let key = jwt::EncodingKey::from_base64_secret("MWFlMTgyZjg3NzM1MzMyYmUxNDEwYWMyM2RlMDRkNzRlOWIwNmI4Mjc2YjQwMmZmYWMzNjllNTA5ZThiN2I0Mg==").unwrap();
let email = Email::new("user@example.dev");
let email_str = email.email();
let password = Password::new("super_secret_password");
let password_str = password.password();
let req = Request::create(algo, &key, &email, &password).unwrap();
let token = req.token();
let email_json = format!(r#"{{"email":"{email_str}"}}"#);
let req_json = format!(
r#"{{"username":"{email_str}","password":"{password_str}","token":"{token}"}}"#
);
assert_eq!(serde_json::to_string(&email).unwrap(), email_json);
assert_eq!(serde_json::from_str::<Email>(&email_json).unwrap(), email);
assert_eq!(serde_json::to_string(&req).unwrap(), req_json);
assert_eq!(serde_json::from_str::<Request>(&req_json).unwrap(), req);
assert_eq!(req.token(), token);
}
}