start implementing accounts

This commit is contained in:
SadlyNotSappho 2024-01-30 09:07:27 -08:00
parent 16c1fd028a
commit 147d7a251f
3 changed files with 137 additions and 43 deletions

1
src/lib.rs Normal file
View File

@ -0,0 +1 @@
pub mod tables;

View File

@ -3,14 +3,14 @@ use rocket::http::Status;
use rocket::response::content::{self, RawHtml}; use rocket::response::content::{self, RawHtml};
use rocket::{Build, Request, Rocket}; use rocket::{Build, Request, Rocket};
use rocket_db_pools::sqlx::pool::PoolConnection; 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 rocket_db_pools::Connection;
use std::fs; use std::fs;
#[macro_use] #[macro_use]
extern crate rocket; extern crate rocket;
use rocket_db_pools::{ use rocket_db_pools::{
sqlx::{self, FromRow, PgPool}, sqlx::{self, Executor},
Database, Database,
}; };
@ -21,6 +21,8 @@ use rocket::{
tokio::time::{sleep, Duration}, tokio::time::{sleep, Duration},
}; };
use fossil::tables::{Db, Post, User};
#[get("/")] #[get("/")]
fn hello() -> RawHtml<String> { fn hello() -> RawHtml<String> {
content::RawHtml(fs::read_to_string("/srv/web/index.html").unwrap()) content::RawHtml(fs::read_to_string("/srv/web/index.html").unwrap())
@ -45,6 +47,22 @@ struct LoginInfo {
password: String, password: String,
} }
#[post("/createuser", data = "<info>")]
async fn createuser(
db: Connection<Db>,
info: Json<LoginInfo>,
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 = "<info>")] #[post("/login", data = "<info>")]
async fn login(info: Json<LoginInfo>, cookies: &CookieJar<'_>) -> &'static str { async fn login(info: Json<LoginInfo>, cookies: &CookieJar<'_>) -> &'static str {
let token = cookies.get_private("token"); 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/<id>")] #[get("/dbtest/<id>")]
async fn dbtest(mut db: Connection<Db>, id: i64) -> Option<String> { async fn dbtest(db: Connection<Db>, id: i32) -> Option<String> {
let res = db let post = Post::get(db, id).await;
.fetch_one(sqlx::query_as::<_, Post>(
&format!("SELECT * FROM posts WHERE id = {id};")[..],
))
.await
.unwrap();
Some(format!( Some(format!(
"{}\n{}\n{}\n{}", "ID: {}\nTitle: {}\nBody: {}\nPublished: {}",
res.get::<i32, _>("id"), post.id, post.title, post.body, post.published
res.get::<String, _>("title"),
res.get::<String, _>("body"),
res.get::<bool, _>("published")
)) ))
} }
#[get("/dbcreate/<title>/<body>/<published>")] #[get("/dbcreate/<title>/<body>/<published>")]
async fn dbcreate( async fn dbcreate(
mut db: Connection<Db>, db: Connection<Db>,
title: String, title: String,
body: String, body: String,
published: bool, published: bool,
) -> &'static str { ) -> &'static str {
db.fetch_all( Post::create(db, title, body, published).await;
sqlx::query( "created!"
r#"
INSERT INTO posts (title, body, published)
VALUES ($1, $2, $3);
"#,
)
.bind(title)
.bind(body)
.bind(published),
)
.await
.unwrap();
"created maybe"
} }
#[catch(default)] #[catch(default)]
@ -142,7 +128,7 @@ async fn migrate(rocket: Rocket<Build>) -> Rocket<Build> {
let db = Db::fetch(&rocket).unwrap(); let db = Db::fetch(&rocket).unwrap();
let mut conn: PoolConnection<Postgres> = db.acquire().await.unwrap(); let mut conn: PoolConnection<Postgres> = db.acquire().await.unwrap();
let row = conn let _ = conn
.fetch_one(sqlx::query_as::<_, Post>( .fetch_one(sqlx::query_as::<_, Post>(
"CREATE TABLE IF NOT EXISTS posts ( "CREATE TABLE IF NOT EXISTS posts (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
@ -152,8 +138,18 @@ async fn migrate(rocket: Rocket<Build>) -> Rocket<Build> {
)", )",
)) ))
.await; .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] #[rocket::main]

97
src/tables.rs Normal file
View File

@ -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"),
}
}
}