brass/web/src/models/password_reset.rs

67 lines
1.6 KiB
Rust

use chrono::TimeDelta;
use sqlx::{query_as, PgPool};
use super::Result;
use crate::utils::token_generation::generate_token_and_expiration;
pub trait Token {
async fn delete(&self, pool: &PgPool) -> Result<()>;
}
pub struct NoneToken {}
impl Token for NoneToken {
async fn delete(&self, _pool: &PgPool) -> Result<()> {
unimplemented!()
}
}
#[derive(Debug)]
pub struct PasswordReset {
pub token: String,
pub userid: i32,
}
impl PasswordReset {
pub async fn insert_new_for_user(pool: &PgPool, user_id: i32) -> Result<PasswordReset> {
let (token, expires) = generate_token_and_expiration(64, TimeDelta::hours(24));
let inserted = query_as!(
PasswordReset,
"INSERT INTO passwordReset (token, userId, expires) VALUES ($1, $2, $3) RETURNING token, userid;",
token,
user_id,
expires
)
.fetch_one(pool)
.await?;
Ok(inserted)
}
pub async fn does_token_exist(pool: &PgPool, token: &str) -> Result<Option<PasswordReset>> {
let result = query_as!(
PasswordReset,
"SELECT token, userId FROM passwordReset WHERE token = $1 AND expires > NOW();",
token
)
.fetch_optional(pool)
.await?;
Ok(result)
}
pub async fn delete(pool: &PgPool, token: &str) -> Result<()> {
sqlx::query!("DELETE FROM passwordReset WHERE token = $1;", token)
.execute(pool)
.await?;
Ok(())
}
}
impl Token for PasswordReset {
async fn delete(&self, pool: &PgPool) -> Result<()> {
PasswordReset::delete(pool, &self.token).await
}
}