changeset 2:93ea889e6009

Add logging and make login check password
author Lewin Bormann <lbo@spheniscida.de>
date Sat, 09 Jul 2022 08:44:23 -0700
parents b587a4c37254
children ca6c273aeb4f
files Cargo.toml Rocket.toml devdata.sql src/main.rs
diffstat 4 files changed, 53 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/Cargo.toml	Fri Jul 08 20:28:28 2022 -0700
+++ b/Cargo.toml	Sat Jul 09 08:44:23 2022 -0700
@@ -6,6 +6,9 @@
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
+env_logger = "0.9.0"
+log = "0.4.17"
 rocket = { version = "0.5.0-rc.2", features = ["secrets"] }
 rocket_db_pools = { version = "0.1.0-rc.2", features = ["sqlx_sqlite"] }
+sha256 = "1.0.3"
 tokio = { version = "1.19.2", features = ["fs"] }
--- a/Rocket.toml	Fri Jul 08 20:28:28 2022 -0700
+++ b/Rocket.toml	Sat Jul 09 08:44:23 2022 -0700
@@ -1,2 +1,6 @@
 [default.databases.sqlite_main]
 url = "/home/lbo/dev/rust/analyrics/dev.sqlite"
+
+[default]
+port = 8000
+secret_key = "edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/devdata.sql	Sat Jul 09 08:44:23 2022 -0700
@@ -0,0 +1,2 @@
+
+INSERT INTO users (id, username, password_hash, name) VALUES (null, "lbo", "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8", "Lewin");
--- a/src/main.rs	Fri Jul 08 20:28:28 2022 -0700
+++ b/src/main.rs	Sat Jul 09 08:44:23 2022 -0700
@@ -1,3 +1,5 @@
+use log::{debug, error, info, Level};
+
 #[macro_use]
 use rocket::{self};
 
@@ -6,8 +8,8 @@
 use rocket::request::{self, FlashMessage};
 use rocket::response::{self, Flash, Redirect, Responder, Response};
 
-use rocket_db_pools::sqlx;
-use rocket_db_pools::{Connection, Database};
+use rocket_db_pools::sqlx::{self, pool::PoolConnection, Executor, Sqlite, SqlitePool};
+use rocket_db_pools::{Connection, Database, Pool};
 
 use std::io;
 use std::path::Path;
@@ -17,7 +19,21 @@
 // TO DO: use other databases?
 #[derive(Database)]
 #[database("sqlite_main")]
-struct ConfigDB(sqlx::SqlitePool);
+struct ConfigDB(SqlitePool);
+
+async fn check_user_password<S: AsRef<str>>(
+    mut conn: PoolConnection<Sqlite>,
+    user: S,
+    password: S,
+) -> Result<bool, sqlx::Error> {
+    // TODO: salt passwords.
+    let pwdhash = sha256::digest(password.as_ref());
+    let q = sqlx::query("SELECT username FROM users WHERE username = ? AND password_hash = ?")
+        .bind(user.as_ref())
+        .bind(pwdhash);
+    let result = conn.fetch_all(q).await?;
+    Ok(result.len() == 1)
+}
 
 const USER_ID_COOKIE_KEY: &str = "user_id";
 
@@ -42,10 +58,14 @@
 
 #[rocket::get("/login")]
 async fn route_login_form<'r>(
+    flash: Option<FlashMessage<'_>>,
     cookies: &CookieJar<'_>,
 ) -> Result<LoginResponse, InternalServerError> {
+    if let Some(flash) = flash {
+        info!("Flash message: {}: {}", flash.kind(), flash.message());
+    }
     if let Some(cookie) = cookies.get_private(USER_ID_COOKIE_KEY) {
-        println!("Logged in as {}", cookie.value());
+        info!("Logged in as {}", cookie.value());
         Ok(LoginResponse::LoggedInAlready {
             redirect: Redirect::to(rocket::uri!("/")),
         })
@@ -71,23 +91,38 @@
 }
 
 #[rocket::post("/login", data = "<login>")]
-async fn route_login_post(cookies: &CookieJar<'_>, login: Form<LoginForm>) -> Flash<Redirect> {
+async fn route_login_post(
+    db: Connection<ConfigDB>,
+    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.")
+    let db = db.into_inner();
+    if let Ok(true) = check_user_password(db, &login.username, &login.password).await {
+        let c = Cookie::new(USER_ID_COOKIE_KEY, login.username.clone());
+        cookies.add_private(c);
+        Flash::success(Redirect::to(rocket::uri!("/")), "Successfully logged in.")
+    } else {
+        Flash::error(
+            Redirect::to(rocket::uri!("/login")),
+            "User/password not found.",
+        )
+    }
 }
 
 #[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());
+        info!("Flash message: {}: {}", flash.kind(), flash.message());
     }
     response::content::RawHtml(asset("index.html").await.unwrap())
 }
 
 #[rocket::launch]
 fn rocketmain() -> _ {
+    env_logger::init();
+
+    info!("{:?}", rocket::Config::figment());
     rocket::build().attach(ConfigDB::init()).mount(
         "/",
         rocket::routes![