158 lines
5.0 KiB
Rust
158 lines
5.0 KiB
Rust
use crate::models::characters::{Character, NewCharacter, StrippedCharacter};
|
|
use crate::models::users::{NewUser, User};
|
|
use sqlx::sqlite::{SqliteConnectOptions, SqlitePool, SqlitePoolOptions};
|
|
use sqlx::ConnectOptions;
|
|
use std::str::FromStr;
|
|
|
|
/// Type alias for the Rocket-managed singleton database connection.
|
|
pub type TenebrousDbConn<'a> = rocket::State<'a, SqlitePool>;
|
|
|
|
/// Create a connection pool to the database.
|
|
pub(crate) async fn create_pool(db_path: &str) -> Result<SqlitePool, crate::errors::Error> {
|
|
//Create database if missing.
|
|
let conn = SqliteConnectOptions::from_str(&format!("sqlite://{}", db_path))?
|
|
.create_if_missing(true)
|
|
.connect()
|
|
.await?;
|
|
|
|
drop(conn);
|
|
|
|
//Return actual conncetion pool.
|
|
SqlitePoolOptions::new()
|
|
.max_connections(5)
|
|
.connect(db_path)
|
|
.await
|
|
.map_err(|e| e.into())
|
|
}
|
|
|
|
#[rocket::async_trait]
|
|
pub(crate) trait Dao {
|
|
async fn load_user_by_id(&self, id: i32) -> sqlx::Result<Option<User>>;
|
|
|
|
async fn load_user(&self, for_username: &str) -> sqlx::Result<Option<User>>;
|
|
|
|
async fn insert_user(&self, new_user: NewUser<'_>) -> sqlx::Result<User>;
|
|
|
|
async fn load_character_list(&self, for_user_id: i32) -> sqlx::Result<Vec<StrippedCharacter>>;
|
|
|
|
async fn load_character(&self, character_id: i32) -> sqlx::Result<Option<Character>>;
|
|
|
|
async fn insert_character(&self, new_character: NewCharacter<'_>) -> sqlx::Result<()>;
|
|
|
|
async fn update_character<'a>(&self, character: &'a Character) -> sqlx::Result<()>;
|
|
|
|
async fn update_character_sheet<'a>(&self, character: &'a Character) -> sqlx::Result<()>;
|
|
}
|
|
|
|
#[rocket::async_trait]
|
|
impl Dao for SqlitePool {
|
|
async fn load_user_by_id(&self, user_id: i32) -> sqlx::Result<Option<User>> {
|
|
sqlx::query_as!(
|
|
User,
|
|
r#"SELECT id as "id: _", username, password FROM users WHERE id = ?"#,
|
|
user_id
|
|
)
|
|
.fetch_optional(self)
|
|
.await
|
|
}
|
|
|
|
async fn load_user(&self, for_username: &str) -> sqlx::Result<Option<User>> {
|
|
sqlx::query_as!(
|
|
User,
|
|
r#"SELECT id as "id: _", username, password FROM users WHERE username = ?"#,
|
|
for_username
|
|
)
|
|
.fetch_optional(self)
|
|
.await
|
|
}
|
|
|
|
async fn insert_user(&self, new_user: NewUser<'_>) -> sqlx::Result<User> {
|
|
sqlx::query("INSERT INTO users (username, password) values (?, ?)")
|
|
.bind(new_user.username)
|
|
.bind(new_user.password)
|
|
.execute(self)
|
|
.await?;
|
|
|
|
self.load_user(new_user.username)
|
|
.await
|
|
.and_then(|user| user.ok_or(sqlx::Error::RowNotFound))
|
|
}
|
|
|
|
async fn load_character_list(&self, for_user_id: i32) -> sqlx::Result<Vec<StrippedCharacter>> {
|
|
sqlx::query_as!(
|
|
StrippedCharacter,
|
|
r#"SELECT id as "id: _",
|
|
user_id as "user_id: _",
|
|
data_type as "data_type: _",
|
|
data_version as "data_version: _",
|
|
viewable, character_name
|
|
FROM characters WHERE user_id = ?"#,
|
|
for_user_id
|
|
)
|
|
.fetch_all(self)
|
|
.await
|
|
}
|
|
|
|
async fn load_character(&self, character_id: i32) -> sqlx::Result<Option<Character>> {
|
|
sqlx::query_as!(
|
|
Character,
|
|
r#"SELECT id as "id: _",
|
|
user_id as "user_id: _",
|
|
viewable, character_name, data,
|
|
data_type as "data_type: _",
|
|
data_version as "data_version: _"
|
|
FROM characters WHERE id = ?"#,
|
|
character_id
|
|
)
|
|
.fetch_optional(self)
|
|
.await
|
|
}
|
|
|
|
async fn insert_character(&self, new_character: NewCharacter<'_>) -> sqlx::Result<()> {
|
|
sqlx::query(
|
|
"INSERT INTO characters
|
|
(user_id, viewable, character_name, data_type, data_version, data)
|
|
values (?, ?, ?, ?, ?, ?)",
|
|
)
|
|
.bind(new_character.user_id)
|
|
.bind(new_character.viewable)
|
|
.bind(new_character.character_name)
|
|
.bind(new_character.data_type)
|
|
.bind(new_character.data_version)
|
|
.bind(new_character.data)
|
|
.execute(self)
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn update_character<'a>(&self, character: &'a Character) -> sqlx::Result<()> {
|
|
sqlx::query(
|
|
"UPDATE characters
|
|
set user_id = ?, viewable = ?, character_name = ?,
|
|
data_type = ?, data_version = ?, data = ? where id = ?",
|
|
)
|
|
.bind(character.user_id)
|
|
.bind(character.viewable)
|
|
.bind(&character.character_name)
|
|
.bind(character.data_type)
|
|
.bind(character.data_version)
|
|
.bind(&character.data)
|
|
.bind(character.id)
|
|
.execute(self)
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn update_character_sheet<'a>(&self, character: &'a Character) -> sqlx::Result<()> {
|
|
sqlx::query("UPDATE characters set data = ? where id = ?")
|
|
.bind(&character.data)
|
|
.bind(character.id)
|
|
.execute(self)
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
}
|