use sqlx::{sqlite::Sqlite, SqliteConnection, Transaction}; use super::{Id, Invite, Summary}; use crate::{ clock::DateTime, login::{self, Login}, }; pub trait Provider { fn invites(&mut self) -> Invites; } impl<'c> Provider for Transaction<'c, Sqlite> { fn invites(&mut self) -> Invites { Invites(self) } } pub struct Invites<'t>(&'t mut SqliteConnection); impl<'c> Invites<'c> { pub async fn create( &mut self, issuer: &Login, issued_at: &DateTime, ) -> Result { let id = Id::generate(); let invite = sqlx::query_as!( Invite, r#" insert into invite (id, issuer, issued_at) values ($1, $2, $3) returning id as "id: Id", issuer as "issuer: login::Id", issued_at as "issued_at: DateTime" "#, id, issuer.id, issued_at ) .fetch_one(&mut *self.0) .await?; Ok(invite) } pub async fn by_id(&mut self, invite: &Id) -> Result { let invite = sqlx::query_as!( Invite, r#" select id as "id: Id", issuer as "issuer: login::Id", issued_at as "issued_at: DateTime" from invite where id = $1 "#, invite, ) .fetch_one(&mut *self.0) .await?; Ok(invite) } pub async fn summary(&mut self, invite: &Id) -> Result { let invite = sqlx::query!( r#" select issuer.id as "issuer_id: login::Id", issuer.name as "issuer_name", invite.issued_at as "invite_issued_at: DateTime" from invite join login as issuer on (invite.issuer = issuer.id) where invite.id = $1 "#, invite, ) .map(|row| Summary { issuer: Login { id: row.issuer_id, name: row.issuer_name, }, issued_at: row.invite_issued_at, }) .fetch_one(&mut *self.0) .await?; Ok(invite) } pub async fn accept(&mut self, invite: &Invite) -> Result<(), sqlx::Error> { sqlx::query_scalar!( r#" delete from invite where id = $1 returning 1 as "deleted: bool" "#, invite.id, ) .fetch_one(&mut *self.0) .await?; Ok(()) } pub async fn expire(&mut self, expire_at: &DateTime) -> Result<(), sqlx::Error> { sqlx::query!( r#" delete from invite where issued_at < $1 "#, expire_at, ) .execute(&mut *self.0) .await?; Ok(()) } }