use query! and query_as!

This commit is contained in:
deneb 2024-02-10 14:31:07 +01:00
parent d8b79ae852
commit dfa8cada5b
2 changed files with 45 additions and 24 deletions

1
.env Normal file
View file

@ -0,0 +1 @@
DATABASE_URL=sqlite://sqlite.db

View file

@ -9,11 +9,20 @@ use crate::secrets::UserToken;
// TODO: allow configuring this via envar // TODO: allow configuring this via envar
const DB_URI_DEFAULT: &str = "sqlite://sqlite.db"; const DB_URI_DEFAULT: &str = "sqlite://sqlite.db";
const TABLE_USER_TOKENS: &str = "user_tokens"; // TODO: check again if it's possible to pass this as a parameter to query!
// const TABLE_USER_TOKENS: &str = "user_tokens";
pub enum UserTokenEntry { pub enum UserTokenEntry {
Valid(UserToken, time::Time, time::Time), Valid(
Invalid(UserToken, time::Time, time::Time), UserToken,
time::OffsetDateTime,
Option<time::OffsetDateTime>,
),
Invalid(
UserToken,
time::OffsetDateTime,
Option<time::OffsetDateTime>,
),
} }
pub trait Database { pub trait Database {
@ -47,8 +56,8 @@ impl SqliteDatabase {
#[instrument] #[instrument]
pub async fn init(&mut self) { pub async fn init(&mut self) {
query(&format!( query!(
"CREATE TABLE IF NOT EXISTS {TABLE_USER_TOKENS} ( "CREATE TABLE IF NOT EXISTS user_tokens (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
username VARCHAR(255) NOT NULL, username VARCHAR(255) NOT NULL,
token NCHAR(30) NOT NULL, token NCHAR(30) NOT NULL,
@ -56,7 +65,7 @@ impl SqliteDatabase {
created DATETIME NOT NULL, created DATETIME NOT NULL,
last_used DATETIME last_used DATETIME
)" )"
)) )
.execute(&mut self.conn) .execute(&mut self.conn)
.await .await
.expect("Failed to initialize table user_tokens"); .expect("Failed to initialize table user_tokens");
@ -66,38 +75,49 @@ impl SqliteDatabase {
impl Database for SqliteDatabase { impl Database for SqliteDatabase {
#[instrument] #[instrument]
async fn get_token(&mut self, username: &str) -> Result<Option<UserTokenEntry>, sqlx::Error> { async fn get_token(&mut self, username: &str) -> Result<Option<UserTokenEntry>, sqlx::Error> {
let row: Option<(String, bool, time::Time, time::Time)> = query_as( struct TokenRow {
token: String,
valid: bool,
created: time::OffsetDateTime,
last_used: Option<time::OffsetDateTime>,
}
let row = query_as!(
TokenRow,
"SELECT token, valid, created, last_used "SELECT token, valid, created, last_used
FROM user_tokens FROM user_tokens
WHERE username = ? WHERE username = $1
ORDER BY created DESC", ORDER BY created DESC",
username
) )
.bind(username) // .bind(username)
.fetch_optional(&mut self.conn) .fetch_optional(&mut self.conn)
.await?; .await?;
Ok(row.map(|row| match row { Ok(row.map(
(token_str, true, created, last_used) => { |TokenRow {
UserTokenEntry::Valid(UserToken::from(token_str), created, last_used) token,
} valid,
created,
(token_str, false, created, last_used) => { last_used,
UserTokenEntry::Invalid(UserToken::from(token_str), created, last_used) }| match valid {
} true => UserTokenEntry::Valid(UserToken::from(token), created, last_used),
})) false => UserTokenEntry::Invalid(UserToken::from(token), created, last_used),
},
))
} }
#[instrument] #[instrument]
async fn save_token(&mut self, username: &str, token: &UserToken) -> Result<(), sqlx::Error> { async fn save_token(&mut self, username: &str, token: &UserToken) -> Result<(), sqlx::Error> {
query(&format!( let token_inner = token.0.expose_secret();
"INSERT INTO {TABLE_USER_TOKENS} query!(
"INSERT INTO user_tokens
(username, token, created, valid) (username, token, created, valid)
VALUES VALUES
(?, ?, DATETIME('NOW'), TRUE) ($1, $2, DATETIME('NOW'), TRUE)
", ",
)) username,
.bind(username) token_inner
.bind(token.0.expose_secret()) )
.execute(&mut self.conn) .execute(&mut self.conn)
.await?; .await?;