nom-nom-nix-gc/src/models/mod.rs
Félix Baylac Jacqué afef067479
Some checks failed
Build nomnom / Build-NomNom (push) Failing after 3m59s
WIP - postgres
2023-10-06 15:47:15 +02:00

132 lines
4.2 KiB
Rust

use serde::{Deserialize, Serialize};
use url::Url;
use std::ops::DerefMut;
use std::sync::Arc;
use std::collections::HashMap;
use anyhow::Result;
use deadpool_postgres::{Manager, ManagerConfig, Pool, RecyclingMethod};
use handlebars::Handlebars;
use tokio::sync::RwLock;
use tokio_postgres::NoTls;
use webauthn_rs::prelude::{Uuid, PasskeyRegistration, Passkey};
use webauthn_rs::{Webauthn, WebauthnBuilder};
#[derive(Deserialize, Debug)]
pub struct Configuration {
pub url: String,
pub db_host: Option<String>,
pub db_port: Option<u16>,
pub db_name: String
}
pub type DbField<T> = Arc<RwLock<T>>;
#[derive(Clone)]
pub struct Db {
pub user_keys: DbField<HashMap<Uuid, Passkey>>,
pub user_uuid_object: DbField<HashMap<Uuid, User>>,
}
#[derive(Clone)]
pub struct TempSession {
pub user_registrations: Arc<RwLock<HashMap<Uuid,PendingRegistration>>>
}
#[derive(Clone)]
pub struct PendingRegistration {
pub user: User,
pub registration: PasskeyRegistration
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
pub struct User {
pub user_name: String,
pub display_name: String,
}
#[derive(Clone)]
pub struct AppState<'a>{
pub webauthn: Arc<Webauthn>,
pub db: Pool,
pub hbs: Arc<Handlebars<'a>>,
pub session: TempSession
}
mod embedded {
use refinery::embed_migrations;
embed_migrations!("src/sql/01-init.sql");
}
impl AppState<'_> {
pub fn new(args: Configuration) -> Self {
let rp = "localhost";
let rp_origin = Url::parse("http://localhost:8000").expect("Invalid URL");
let builder = WebauthnBuilder::new(rp, &rp_origin).expect("Invalid configuration");
let builder = builder.rp_name("LocalHost");
let webauthn = Arc::new(builder.build().expect("Invalid configuration"));
let db: Db = Db {
user_keys: Arc::new(RwLock::new(HashMap::new())),
user_uuid_object: Arc::new(RwLock::new(HashMap::new()))
};
let hbs = Arc::new(crate::templates::new().unwrap());
let session: TempSession = TempSession {
user_registrations: Arc::new(RwLock::new(HashMap::new()))
};
let mut pg_config = tokio_postgres::Config::new();
pg_config.host_path("/run/postgresql");
pg_config.host_path("/tmp");
pg_config.user("deadpool");
pg_config.dbname("deadpool");
let mgr_config = ManagerConfig {
recycling_method: RecyclingMethod::Fast
};
let mgr = Manager::from_config(pg_config, NoTls, mgr_config);
let db = Pool::builder(mgr).max_size(16).build().unwrap();
AppState {
webauthn,
db,
hbs,
session
}
}
pub async fn run_migrations(&mut self) -> Result<()> {
let mut conn = self.db.get().await?;
let client = conn.deref_mut().deref_mut();
embedded::migrations::runner().run_async(client).await?;
Ok(())
}
pub async fn save_user(&self, user: &User) -> Result<()> {
let mut conn = self.db.get().await?;
let client = conn.deref_mut();
let stmt = client.prepare_cached("INSERT INTO Users (user_name, display_name) VALUES ($1, $2, $3)").await?;
client.query(&stmt, &[&user.user_name, &user.display_name]);
Ok(())
}
pub async fn save_user_key(&self, uuid: &Uuid, passkey: &Passkey) -> Result<()> {
let passkey_json: String = serde_json::to_string(&passkey)?;
let mut conn = self.db.get().await?;
let client = conn.deref_mut();
let stmt = client.prepare_cached("INSERT INTO Keys (key_dump, user_id) VALUES ($1,$2)").await?;
client.query(&stmt, &[&passkey_json, &uuid.to_string()]).await?;
Ok(())
}
pub async fn get_user_keys(&self, user_uuid: &Uuid) -> Result<Vec<Result<Passkey, serde_json::Error>>> {
let mut conn = self.db.get().await?;
let client = conn.deref_mut();
let stmt = client.prepare_cached("SELECT key_dump FROM Keys WHERE user_id = $1").await?;
let res = client.query(&stmt, &[&user_uuid.to_string()]).await?;
let res2 = res.iter().map(|row| {
serde_json::from_str(row.get(0))
}).collect();
Ok(res2)
}
}