You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

169 lines
5.3 KiB
Rust

use serde::Serialize;
use sqlx::{Pool, Postgres};
use uuid::Uuid;
#[derive(Clone)]
pub struct DB {
connection_pool: Pool::<Postgres>
}
#[derive(Serialize)]
pub struct Site {
uuid: Uuid,
title: String,
base_url: String,
theme: String,
boards: Vec<Board>
}
#[derive(Serialize, Clone)]
pub struct Board {
uuid: Uuid,
title: String,
description: String,
threads: Vec<Thread>
}
impl Board {
fn clone(&self) -> Board {
todo!()
}
}
#[derive(Serialize, Clone)]
pub struct Thread {
uuid: Uuid,
title: String,
posts: Vec<Post>
}
#[derive(Serialize, Clone)]
pub struct Post {
uuid: Uuid,
contents: String,
author: User
}
#[derive(Serialize, Clone)]
pub struct User {
uuid: Uuid,
email: String,
username: String,
password_hash: String,
is_admin: bool
}
impl DB {
pub async fn init() -> Self {
let db_url = std::env::var("DATABASE_URL").expect("Please provide DATABASE_URL in environment");
let pool = Pool::<Postgres>::connect(db_url.as_str()).await.expect("Could not connect to database");
sqlx::migrate!()
.run(&pool)
.await
.expect("Could not run database migrations");
DB {
connection_pool: pool
}
}
pub async fn get_site_data(&self) -> Result<Site, String> {
let rows = sqlx::query!(r#"
select
site_uuid,
site_title,
site_base_url,
site_theme,
board_uuid,
board_title,
board_description,
thread_uuid,
thread_title,
post_uuid as "post_uuid?",
post_contents as "post_contents?",
user_uuid,
user_email,
user_username,
user_password_hash,
user_is_admin
from forum.site
left join forum.board on board_site = site_uuid
left join forum.thread on thread_board = board_uuid
left join forum.post on post_thread = thread_uuid
left join forum.user on post_author = user_uuid
"#).fetch_all(&self.connection_pool).await.expect("Could not connect to database");
let mut site : Option<Site> = None;
let mut last_board : Option<Board> = None;
let mut last_thread : Option<Thread> = None;
let mut last_post : Option<Post> = None;
for row in rows {
if site.is_none() || row.site_uuid.is_some() && row.site_uuid.unwrap() != site.as_ref().unwrap().uuid {
site = Some(Site {
uuid: row.site_uuid.unwrap(),
title: row.site_title.unwrap_or(String::new()),
base_url: row.site_base_url.unwrap_or(String::new()),
theme: row.site_theme.unwrap_or(String::new()),
boards: Vec::new()
})
}
if last_board.is_none() || row.board_uuid.is_some() && row.board_uuid.unwrap() != last_board.as_ref().unwrap().uuid {
if let Some(ref board) = last_board {
site.as_mut().unwrap().boards.push(board.clone())
}
if row.board_uuid.is_some() {
last_board = Some(Board {
uuid: row.board_uuid.unwrap(),
title: row.board_title.unwrap_or(String::new()),
description: row.board_description.unwrap_or(String::new()),
threads: Vec::new()
})
}
}
if last_thread.is_none() || row.thread_uuid.is_some() && row.thread_uuid.unwrap() != last_thread.as_mut().unwrap().uuid {
if let Some(ref thread) = last_thread {
last_board.as_mut().unwrap().threads.push(thread.clone())
}
if row.thread_uuid.is_some() {
last_thread = Some(Thread {
uuid: row.thread_uuid.unwrap(),
title: row.thread_title.unwrap_or(String::new()),
posts: Vec::new()
})
}
}
// if last_post.is_none() || row.post_uuid != last_post.as_ref().unwrap().uuid {
// if let Some(post) = last_post {
// last_thread.as_mut().unwrap().posts.push(post)
// }
//
// if row.post_uuid.is_some() {
// last_post = Some(Post {
// uuid: row.post_uuid,
// contents: row.post_contents,
// author: User {
// uuid: row.user_uuid.unwrap(),
// email: row.user_email.unwrap_or(String::new()),
// username: row.user_username.unwrap_or(String::new()),
// password_hash: row.user_password_hash.unwrap_or(String::new()),
// is_admin: row.user_is_admin.unwrap_or(false)
// }
// })
// }
// }
}
if let Some(site) = site {
Ok(site)
} else {
Err("Could not find site in DB".to_string())
}
}
}