flabk/src/database/users.rs

95 lines
2.4 KiB
Rust

use std::sync::Arc;
use tokio::sync::Mutex;
use tokio_postgres::{Client, Row};
use crate::sec;
use super::db;
#[derive(Clone)]
pub struct Users(Arc<Mutex<Client>>);
impl Users {
pub fn new(client: Arc<Mutex<Client>>) -> Self {
Self(client)
}
pub async fn create_user(&self, u: User) -> Result<User, db::DBError> {
let row = self.0.lock().await.query_one(
"insert into users (id, username, host, display_name, password_hash) values ($1, $2, $3, $4, $5) returning id",
&[&sec::new_id(), &u.username, &u.host, &u.display_name, &u.password_hash],
).await?;
Ok(User {
id: row.get("id"),
username: u.username,
host: u.host,
display_name: u.display_name,
password_hash: u.password_hash,
})
}
pub async fn user(&self, by: UserSelect) -> Result<User, db::DBError> {
let where_param: String;
let where_clause = match by {
UserSelect::ID(id) => {
where_param = id;
"id = $1"
}
UserSelect::Username(username) => {
where_param = username;
"username = $1"
}
UserSelect::FullUsername(full) => {
where_param = full;
"(username || '@' || host) = $1"
}
};
let rows = self
.0
.lock()
.await
.query(
format!(
"select id, username, host, display_name, password_hash from users where {}",
where_clause
)
.as_str(),
&[&where_param],
)
.await?;
if let Some(row) = rows.first() && rows.len() == 1 {
Ok(User::from(row))
} else {
Err(db::DBError::NotFound)
}
}
}
pub struct User {
pub id: String,
pub username: String,
pub host: Option<String>,
pub display_name: Option<String>,
pub password_hash: String,
}
impl From<&Row> for User {
fn from(row: &Row) -> Self {
Self {
id: row.get("id"),
username: row.get("username"),
host: row.get("host"),
display_name: row.get("display_name"),
password_hash: row.get("password_hash"),
}
}
}
pub enum UserSelect {
ID(String),
Username(String),
FullUsername(String),
}