2024-02-10 12:25:46 +01:00
|
|
|
use secrecy::SecretString;
|
|
|
|
use sqlx::{query, query_as, Connection, SqliteConnection};
|
2024-02-10 12:06:53 +01:00
|
|
|
|
|
|
|
use crate::auth::UserToken;
|
|
|
|
|
|
|
|
// TODO: allow configuring this via envar
|
|
|
|
const DB_URI_DEFAULT: &str = "sqlite://sqlite.db";
|
|
|
|
|
|
|
|
pub trait Database {
|
2024-02-10 12:25:46 +01:00
|
|
|
async fn get_token(&mut self, username: &str) -> Result<UserToken, sqlx::Error>;
|
2024-02-10 12:06:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct SqliteDatabase {
|
|
|
|
conn: SqliteConnection,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SqliteDatabase {
|
|
|
|
pub async fn open() -> Self {
|
|
|
|
let mut db = Self {
|
|
|
|
conn: SqliteConnection::connect(DB_URI_DEFAULT)
|
|
|
|
.await
|
|
|
|
.expect("Failed to open SQLite database"),
|
|
|
|
};
|
|
|
|
|
|
|
|
db.init().await;
|
|
|
|
|
|
|
|
db
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn init(&mut self) {
|
|
|
|
query(
|
|
|
|
"CREATE TABLE IF NOT EXISTS user_tokens (
|
|
|
|
id INTEGER PRIMARY KEY NOT NULL,
|
|
|
|
username VARCHAR(255),
|
|
|
|
token NCHAR(30),
|
|
|
|
created DATETIME,
|
|
|
|
valid BOOLEAN,
|
|
|
|
);",
|
|
|
|
)
|
|
|
|
.execute(&mut self.conn)
|
|
|
|
.await
|
|
|
|
.expect("Failed to initialize table user_tokens");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Database for SqliteDatabase {
|
2024-02-10 12:25:46 +01:00
|
|
|
async fn get_token(&mut self, username: &str) -> Result<UserToken, sqlx::Error> {
|
|
|
|
let row: (String,) = query_as(
|
|
|
|
"SELECT token
|
|
|
|
FROM user_tokens
|
|
|
|
WHERE
|
|
|
|
username = {username}
|
|
|
|
AND valid = TRUE
|
|
|
|
ORDER BY
|
|
|
|
created DESC",
|
|
|
|
)
|
|
|
|
.bind(username)
|
|
|
|
.fetch_one(&mut self.conn)
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
Ok(UserToken(SecretString::new(row.0)))
|
2024-02-10 12:06:53 +01:00
|
|
|
}
|
|
|
|
}
|