73 lines
1.9 KiB
Rust
73 lines
1.9 KiB
Rust
use crate::Error;
|
|
use chrono::{DateTime, Duration, Utc};
|
|
use database::sqlx::SqliteExecutor;
|
|
use database::TotpLoginRequests as DatabaseTotpLoginRequests;
|
|
use id::UserID;
|
|
|
|
pub const TOTP_REQUEST_COOKIE_NAME: &str = "totp_request";
|
|
pub const TOTP_REQUEST_LEN: usize = 25;
|
|
|
|
pub struct TotpLoginRequest {
|
|
// Info
|
|
token: String,
|
|
user: UserID,
|
|
|
|
// Timings
|
|
created_at: DateTime<Utc>,
|
|
expires_at: DateTime<Utc>,
|
|
used_at: Option<DateTime<Utc>>,
|
|
}
|
|
|
|
impl TotpLoginRequest {
|
|
pub fn token(&self) -> &str {
|
|
&self.token
|
|
}
|
|
pub fn user(&self) -> &UserID {
|
|
&self.user
|
|
}
|
|
pub fn has_expired(&self) -> bool {
|
|
self.expires_at < Utc::now()
|
|
}
|
|
pub fn used_at(&self) -> Option<DateTime<Utc>> {
|
|
self.used_at
|
|
}
|
|
}
|
|
|
|
impl From<DatabaseTotpLoginRequests> for TotpLoginRequest {
|
|
fn from(db: DatabaseTotpLoginRequests) -> Self {
|
|
Self {
|
|
token: db.token,
|
|
user: UserID(db.user),
|
|
created_at: db.created_at,
|
|
expires_at: db.expires_at,
|
|
used_at: db.used_at,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TotpLoginRequest {
|
|
pub async fn insert(
|
|
conn: impl SqliteExecutor<'_>,
|
|
token: &str,
|
|
user: &UserID,
|
|
validity_minutes: i64,
|
|
) -> Result<Option<()>, Error> {
|
|
let expires_at = Utc::now() + Duration::minutes(validity_minutes);
|
|
|
|
Ok(DatabaseTotpLoginRequests::insert(conn, token, &user.0, expires_at.timestamp()).await?)
|
|
}
|
|
|
|
pub async fn get_one(
|
|
conn: impl SqliteExecutor<'_>,
|
|
token: &str,
|
|
) -> Result<Option<Self>, Error> {
|
|
Ok(DatabaseTotpLoginRequests::get_one(conn, token)
|
|
.await?
|
|
.map(Self::from))
|
|
}
|
|
|
|
/// Consume and mark as used
|
|
pub async fn use_code(self, conn: impl SqliteExecutor<'_>) -> Result<Option<()>, Error> {
|
|
Ok(DatabaseTotpLoginRequests::use_token(conn, &self.token).await?)
|
|
}
|
|
}
|