use chrono::{Duration, Utc};
use crate::{
models::{MFATicket, MultiFactorAuthentication, UnvalidatedTicket, ValidatedTicket},
Authifier, Error, Success,
};
use std::ops::Deref;
impl MFATicket {
pub fn new(account_id: String, validated: bool) -> MFATicket {
MFATicket {
id: ulid::Ulid::new().to_string(),
account_id,
token: nanoid!(64),
validated,
authorised: false,
last_totp_code: None,
}
}
pub async fn populate(&mut self, mfa: &MultiFactorAuthentication) {
self.last_totp_code = mfa.totp_token.generate_code().ok();
}
pub async fn save(&self, authifier: &Authifier) -> Success {
authifier.database.save_ticket(self).await
}
pub fn is_expired(&self) -> bool {
let now = Utc::now();
let datetime = ulid::Ulid::from_string(&self.id)
.expect("Valid `ulid`")
.datetime()
.checked_add_signed(Duration::minutes(5))
.expect("checked add signed");
now > datetime
}
pub async fn claim(&self, authifier: &Authifier) -> Success {
if self.is_expired() {
return Err(Error::InvalidToken);
}
authifier.database.delete_ticket(&self.id).await
}
}
impl Deref for ValidatedTicket {
type Target = MFATicket;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Deref for UnvalidatedTicket {
type Target = MFATicket;
fn deref(&self) -> &Self::Target {
&self.0
}
}