1
0
Files
nir/src/database.rs
2024-04-23 12:08:37 +03:00

79 lines
2.0 KiB
Rust

use derive_more::{Display, Error, From};
use sqlx::migrate::Migrator;
use crate::{config, entity};
static MIGRATOR: Migrator = sqlx::migrate!("./migrations");
#[derive(Clone)]
pub struct Database {
pool: sqlx::AnyPool,
}
impl Database {
pub async fn init() -> Result<Self> {
let config = config::config();
let pool = sqlx::any::AnyPoolOptions::new()
.max_connections(config.database.max_connections)
.connect(&config.database.url)
.await
.inspect_err(|e| tracing::error!("Could not connect to database: {e}"))?;
MIGRATOR.run(&pool).await?;
Ok(Self { pool })
}
pub async fn get_user_by_id(&self, id: entity::ShortId) -> Result<entity::User> {
let user = sqlx::query_as("SELECT * FROM users WHERE id = $1")
.bind(id)
.fetch_optional(&self.pool)
.await?
.ok_or(Error::UserDoesNotExists)?;
Ok(user)
}
pub async fn get_user_by_username(&self, username: &str) -> Result<entity::User> {
let user = sqlx::query_as("SELECT * FROM users WHERE username = $1")
.bind(username)
.fetch_optional(&self.pool)
.await?
.ok_or(Error::UserDoesNotExists)?;
Ok(user)
}
pub async fn create_user(&self, username: &str, password: &str) -> Result<entity::User> {
let user = self.get_user_by_username(username).await;
if user.is_ok() {
return Err(Error::UserAlreadyExists);
}
let id = sqlx::query_scalar(
"INSERT INTO users(username, password) VALUES ($1, $2) RETURNING id",
)
.bind(username)
.bind(password)
.fetch_one(&self.pool)
.await?;
let user = self.get_user_by_id(id).await?;
Ok(user)
}
}
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, From, Error, Display)]
pub enum Error {
#[from]
Migrate(sqlx::migrate::MigrateError),
#[from]
Sqlx(sqlx::Error),
UserDoesNotExists,
UserAlreadyExists,
}