diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..6add084 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +pub mod tables; diff --git a/src/main.rs b/src/main.rs index 5646ba3..305c0d4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,14 +3,14 @@ use rocket::http::Status; use rocket::response::content::{self, RawHtml}; use rocket::{Build, Request, Rocket}; use rocket_db_pools::sqlx::pool::PoolConnection; -use rocket_db_pools::sqlx::{Executor, Postgres, Row}; +use rocket_db_pools::sqlx::Postgres; use rocket_db_pools::Connection; use std::fs; #[macro_use] extern crate rocket; use rocket_db_pools::{ - sqlx::{self, FromRow, PgPool}, + sqlx::{self, Executor}, Database, }; @@ -21,6 +21,8 @@ use rocket::{ tokio::time::{sleep, Duration}, }; +use fossil::tables::{Db, Post, User}; + #[get("/")] fn hello() -> RawHtml { content::RawHtml(fs::read_to_string("/srv/web/index.html").unwrap()) @@ -45,6 +47,22 @@ struct LoginInfo { password: String, } +#[post("/createuser", data = "")] +async fn createuser( + db: Connection, + info: Json, + cookies: &CookieJar<'_>, +) -> &'static str { + let token = cookies.get_private("token"); + match token.is_some() { + true => "You're already logged in. Log out before trying to create a new account.", + false => { + User::create(db, &info.username, &info.password).await; + "Account created." + } + } +} + #[post("/login", data = "")] async fn login(info: Json, cookies: &CookieJar<'_>) -> &'static str { let token = cookies.get_private("token"); @@ -77,56 +95,24 @@ async fn logout(cookies: &CookieJar<'_>) -> &'static str { } } -#[derive(Database)] -#[database("diesel_postgres")] -struct Db(PgPool); - -#[derive(FromRow)] -struct Post { - id: i64, - title: String, - body: String, - published: bool, -} - #[get("/dbtest/")] -async fn dbtest(mut db: Connection, id: i64) -> Option { - let res = db - .fetch_one(sqlx::query_as::<_, Post>( - &format!("SELECT * FROM posts WHERE id = {id};")[..], - )) - .await - .unwrap(); +async fn dbtest(db: Connection, id: i32) -> Option { + let post = Post::get(db, id).await; Some(format!( - "{}\n{}\n{}\n{}", - res.get::("id"), - res.get::("title"), - res.get::("body"), - res.get::("published") + "ID: {}\nTitle: {}\nBody: {}\nPublished: {}", + post.id, post.title, post.body, post.published )) } #[get("/dbcreate//<body>/<published>")] async fn dbcreate( - mut db: Connection<Db>, + db: Connection<Db>, title: String, body: String, published: bool, ) -> &'static str { - db.fetch_all( - sqlx::query( - r#" - INSERT INTO posts (title, body, published) - VALUES ($1, $2, $3); - "#, - ) - .bind(title) - .bind(body) - .bind(published), - ) - .await - .unwrap(); - "created maybe" + Post::create(db, title, body, published).await; + "created!" } #[catch(default)] @@ -142,7 +128,7 @@ async fn migrate(rocket: Rocket<Build>) -> Rocket<Build> { let db = Db::fetch(&rocket).unwrap(); let mut conn: PoolConnection<Postgres> = db.acquire().await.unwrap(); - let row = conn + let _ = conn .fetch_one(sqlx::query_as::<_, Post>( "CREATE TABLE IF NOT EXISTS posts ( id SERIAL PRIMARY KEY, @@ -152,8 +138,18 @@ async fn migrate(rocket: Rocket<Build>) -> Rocket<Build> { )", )) .await; + let _2 = conn + .fetch_one(sqlx::query( + "CREATE TABLE IF NOT EXISTS users ( + id SERIAL PRIMARY KEY, + username VARCHAR NOT NULL, + password TEXT NOT NULL, + token TEXT + )", + )) + .await; - rocket.manage(row) + rocket } #[rocket::main] diff --git a/src/tables.rs b/src/tables.rs new file mode 100644 index 0000000..834ffa4 --- /dev/null +++ b/src/tables.rs @@ -0,0 +1,97 @@ +use rocket_db_pools::sqlx::Executor; +use rocket_db_pools::Connection; +use sqlx::FromRow; + +use rocket_db_pools::{ + sqlx::{self, PgPool, Row}, + Database, +}; + +#[derive(Database)] +#[database("diesel_postgres")] +pub struct Db(PgPool); + +#[derive(FromRow)] +pub struct Post { + pub id: i32, + pub title: String, + pub body: String, + pub published: bool, +} +impl Post { + pub async fn create(mut db: Connection<Db>, title: String, body: String, published: bool) { + match db + .fetch_all( + sqlx::query( + r#" + INSERT INTO posts (title, body, published) + VALUES ($1, $2, $3); + "#, + ) + .bind(title) + .bind(body) + .bind(published), + ) + .await + { + Ok(_) => (), + Err(why) => { + eprintln!("Couldn't create database entry: {why:?}"); + } + } + } + pub async fn get(mut db: Connection<Db>, id: i32) -> Post { + let res = db + .fetch_one(sqlx::query("SELECT * FROM posts WHERE id = $1;").bind(id)) + .await + .unwrap(); + Post { + id: res.get::<i32, _>("id"), + title: res.get::<String, _>("title"), + body: res.get::<String, _>("body"), + published: res.get::<bool, _>("published"), + } + } +} + +#[derive(FromRow)] +pub struct User { + pub id: i32, + pub username: String, + pub password: String, + pub token: Option<String>, +} +impl User { + pub async fn create(mut db: Connection<Db>, username: &String, password: &String) { + match db + .fetch_all( + sqlx::query( + r#" + INSERT INTO users (username, password) + VALUES ($1, $2); + "#, + ) + .bind(username) + .bind(password), + ) + .await + { + Ok(_) => (), + Err(why) => { + eprintln!("Couldn't create database entry: {why:?}"); + } + } + } + pub async fn get(mut db: Connection<Db>, id: i32) -> User { + let res = db + .fetch_one(sqlx::query("SELECT * FROM posts WHERE id = $1;").bind(id)) + .await + .unwrap(); + User { + id: res.get::<i32, _>("id"), + username: res.get::<String, _>("username"), + password: res.get::<String, _>("password"), + token: res.get::<Option<String>, _>("token"), + } + } +}