flabk/src/database/users.rs

96 lines
2.3 KiB
Rust

use std::sync::Arc;
use rand::Rng;
use tokio::sync::Mutex;
use tokio_postgres::{Client, Row};
use super::db;
#[derive(Clone)]
pub struct Users(Arc<Mutex<Client>>);
impl Users {
pub fn new(client: Arc<Mutex<Client>>) -> Self {
Self(client)
}
fn new_id() -> String {
let bytes = rand::thread_rng().gen::<[u8; 16]>();
base_62::encode(&bytes)
}
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) values ($1, $2, $3, $4) returning id",
&[&Self::new_id(), &u.username, &u.host, &u.display_name],
).await?;
Ok(User {
id: row.get("id"),
username: u.username,
host: u.host,
display_name: u.display_name,
})
}
pub async fn user(&self, by: UserSelect) -> Result<Option<User>, anyhow::Error> {
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 from users where {}",
where_clause
)
.as_str(),
&[&where_param],
)
.await?;
if let Some(row) = rows.first() && rows.len() == 1 {
Ok(Some(User::from(row)))
} else {
Ok(None)
}
}
}
pub struct User {
pub id: String,
pub username: String,
pub host: Option<String>,
pub display_name: Option<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"),
}
}
}
pub enum UserSelect {
ID(String),
Username(String),
FullUsername(String),
}