use sqlx::{sqlite::Sqlite, SqliteConnection, Transaction}; use uuid::Uuid; use super::logins::Id as LoginId; use crate::error::BoxedError; type DateTime = chrono::DateTime; pub trait Provider { fn tokens(&mut self) -> Tokens; } impl<'c> Provider for Transaction<'c, Sqlite> { fn tokens(&mut self) -> Tokens { Tokens(self) } } pub struct Tokens<'t>(&'t mut SqliteConnection); impl<'c> Tokens<'c> { /// Issue a new token for an existing login. The issued_at timestamp will /// be used to control expiry. pub async fn issue( &mut self, login: &LoginId, issued_at: DateTime, ) -> Result { let secret = Uuid::new_v4().to_string(); let secret = sqlx::query_scalar!( r#" insert into token (secret, login, issued_at) values ($1, $2, $3) returning secret as "secret!" "#, secret, login, issued_at, ) .fetch_one(&mut *self.0) .await?; Ok(secret) } }