use query! and query_as!
This commit is contained in:
parent
d8b79ae852
commit
dfa8cada5b
2 changed files with 45 additions and 24 deletions
1
.env
Normal file
1
.env
Normal file
|
@ -0,0 +1 @@
|
||||||
|
DATABASE_URL=sqlite://sqlite.db
|
68
src/db.rs
68
src/db.rs
|
@ -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?;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue