changeset 0:3f4f2ba2da92

Initial commit
author Lewin Bormann <lbo@spheniscida.de>
date Fri, 08 Jul 2022 20:19:14 -0700
parents
children b587a4c37254
files .hgignore Cargo.toml Rocket.toml index.html login.html schema_sqlite.sql src/main.rs
diffstat 7 files changed, 127 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Fri Jul 08 20:19:14 2022 -0700
@@ -0,0 +1,4 @@
+^target/
+Cargo.lock
+^\w+.sqlite.*
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Cargo.toml	Fri Jul 08 20:19:14 2022 -0700
@@ -0,0 +1,11 @@
+[package]
+name = "analyrics"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+rocket = { version = "0.5.0-rc.2", features = ["secrets"] }
+rocket_db_pools = { version = "0.1.0-rc.2", features = ["sqlx_sqlite"] }
+tokio = { version = "1.19.2", features = ["fs"] }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Rocket.toml	Fri Jul 08 20:19:14 2022 -0700
@@ -0,0 +1,2 @@
+[default.databases.sqlite_main]
+url = "/home/lbo/dev/rust/analyrics/dev.sqlite"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/index.html	Fri Jul 08 20:19:14 2022 -0700
@@ -0,0 +1,8 @@
+<html>
+    <head>
+        <title>Analyrics Login</title>
+    </head>
+    <body>
+        Welcome to anaLyrics.
+    </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/login.html	Fri Jul 08 20:19:14 2022 -0700
@@ -0,0 +1,8 @@
+<html>
+    <head>
+        <title>Analyrics Login</title>
+    </head>
+    <body>
+
+    </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/schema_sqlite.sql	Fri Jul 08 20:19:14 2022 -0700
@@ -0,0 +1,8 @@
+
+DROP TABLE IF EXISTS users;
+CREATE TABLE users (
+    id INTEGER PRIMARY KEY,
+    username VARCHAR(64),
+    name VARCHAR(64),
+    password_hash VARCHAR(128)
+);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main.rs	Fri Jul 08 20:19:14 2022 -0700
@@ -0,0 +1,86 @@
+#[macro_use]
+use rocket::{self};
+
+use rocket::form::{Form};
+use rocket::http::{Cookie, CookieJar, Header, Status};
+use rocket::response::{self, Flash, Redirect, Responder, Response};
+use rocket::request::{self, FlashMessage};
+
+use rocket_db_pools::sqlx;
+use rocket_db_pools::{Connection, Database};
+
+use std::io;
+use std::path::Path;
+
+use tokio::fs::{self, File};
+
+// TO DO: use other databases?
+#[derive(Database)]
+#[database("sqlite_main")]
+struct ConfigDB(sqlx::SqlitePool);
+
+const USER_ID_COOKIE_KEY: &str = "user_id";
+
+async fn asset<P: AsRef<Path>>(p: P) -> io::Result<File> {
+    fs::OpenOptions::new().read(true).open(p).await
+}
+
+#[derive(Responder)]
+enum LoginResponse {
+    // use templates later.
+    #[response(status = 200, content_type = "html")]
+    Ok { body: File },
+    #[response(status = 302, content_type = "html")]
+    LoggedInAlready { redirect: Redirect },
+}
+
+#[derive(Responder)]
+#[response(content_type = "text", status = 500)]
+struct InternalServerError {
+    body: String,
+}
+
+#[rocket::get("/login")]
+async fn route_login_form<'r>(
+    cookies: &CookieJar<'_>,
+) -> Result<LoginResponse, InternalServerError> {
+    if let Some(cookie) = cookies.get_private(USER_ID_COOKIE_KEY) {
+        println!("Logged in as {}", cookie.value());
+        Ok(LoginResponse::LoggedInAlready {
+            redirect: Redirect::to(rocket::uri!("/")),
+        })
+    } else {
+        Ok(LoginResponse::Ok {
+            body: asset("login.html").await.unwrap(),
+        })
+    }
+}
+
+#[derive(rocket::FromForm)]
+struct LoginForm {
+    username: String,
+    password: String,
+}
+
+#[rocket::post("/login", data = "<login>")]
+async fn route_login_post(cookies: &CookieJar<'_>, login: Form<LoginForm>) -> Flash<Redirect> {
+    // TO DO: look up user in database.
+    let c = Cookie::new(USER_ID_COOKIE_KEY, login.username.clone());
+    cookies.add_private(c);
+    Flash::success(Redirect::to(rocket::uri!("/")), "Successfully logged in.")
+}
+
+#[rocket::get("/")]
+async fn route_index(flash: Option<FlashMessage<'_>>) -> response::content::RawHtml<File> {
+    if let Some(flash) = flash {
+        println!("Flash message: {}: {}", flash.kind(), flash.message());
+    }
+    response::content::RawHtml(asset("index.html").await.unwrap())
+}
+
+#[rocket::launch]
+fn rocketmain() -> _ {
+    rocket::build()
+        .attach(ConfigDB::init())
+        .mount("/", rocket::routes![route_index, route_login_form, route_login_post])
+}