From 779e4aa2ea376c52b5e4b8baf0136d280a54308c Mon Sep 17 00:00:00 2001 From: emilis Date: Tue, 13 Sep 2022 15:56:10 +0100 Subject: [PATCH] finished move from warp to axum, added nav --- Cargo.lock | 329 +++--------------------------- Cargo.toml | 2 +- flabk_icon_placeholder.svg | 148 ++++++++++++++ src/database/users.rs | 2 +- src/helpers.rs | 20 -- src/main.rs | 1 - src/model.rs | 1 - src/servek/html.rs | 194 +++++++++++------- src/servek/mod.rs | 63 +++++- src/servek/servek.rs | 47 +++-- src/svc/auth.rs | 26 ++- src/svc/profiles.rs | 3 - static/style/main.css | 49 ++++- templates/html/404.html | 2 + templates/html/html-redirect.html | 18 ++ templates/html/index.html | 6 +- templates/html/login.html | 4 +- templates/html/nav-loggedin.html | 13 ++ templates/html/nav-loggedout.html | 13 ++ templates/html/post-signin.html | 15 -- templates/html/profile.html | 4 +- templates/html/signup.html | 23 +-- 22 files changed, 524 insertions(+), 459 deletions(-) create mode 100644 flabk_icon_placeholder.svg delete mode 100644 src/helpers.rs delete mode 100644 src/model.rs create mode 100644 templates/html/html-redirect.html create mode 100644 templates/html/nav-loggedin.html create mode 100644 templates/html/nav-loggedout.html delete mode 100644 templates/html/post-signin.html diff --git a/Cargo.lock b/Cargo.lock index 73847a3..990d3b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -170,16 +170,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "buf_redux" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f" -dependencies = [ - "memchr", - "safemem", -] - [[package]] name = "bumpalo" version = "3.11.0" @@ -210,6 +200,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cookie" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + [[package]] name = "cpufeatures" version = "0.2.5" @@ -277,15 +278,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" -[[package]] -name = "fastrand" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" -dependencies = [ - "instant", -] - [[package]] name = "flabk" version = "0.0.1" @@ -304,7 +296,7 @@ dependencies = [ "serde_json", "tokio", "tokio-postgres", - "warp", + "tower-cookies", ] [[package]] @@ -403,25 +395,6 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" -[[package]] -name = "h2" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util 0.7.4", - "tracing", -] - [[package]] name = "handlebars" version = "4.3.3" @@ -436,37 +409,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "headers" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" -dependencies = [ - "base64", - "bitflags", - "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http", -] - [[package]] name = "hermit-abi" version = "0.1.19" @@ -535,7 +477,6 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", "http", "http-body", "httparse", @@ -549,35 +490,6 @@ dependencies = [ "want", ] -[[package]] -name = "idna" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - [[package]] name = "itoa" version = "1.0.3" @@ -690,24 +602,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "multipart" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00dec633863867f29cb39df64a397cdf4a6354708ddd7759f70c7fb51c5f9182" -dependencies = [ - "buf_redux", - "httparse", - "log", - "mime", - "mime_guess", - "quick-error", - "rand", - "safemem", - "tempfile", - "twoway", -] - [[package]] name = "num-bigint" version = "0.2.6" @@ -879,7 +773,7 @@ checksum = "1538eb784f07615c6d9a8ab061089c6c54a344c5b4301db51990ca1c241e8c04" dependencies = [ "once_cell", "pest", - "sha-1 0.10.0", + "sha-1", ] [[package]] @@ -978,12 +872,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - [[package]] name = "quote" version = "1.0.21" @@ -1032,15 +920,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - [[package]] name = "ring" version = "0.16.20" @@ -1102,12 +981,6 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" -[[package]] -name = "safemem" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" - [[package]] name = "same-file" version = "1.0.6" @@ -1117,12 +990,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scoped-tls" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" - [[package]] name = "scopeguard" version = "1.1.0" @@ -1172,19 +1039,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sha-1" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "sha-1" version = "0.10.0" @@ -1196,17 +1050,6 @@ dependencies = [ "digest 0.10.3", ] -[[package]] -name = "sha1" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006769ba83e921b3085caa8334186b00cf92b4cb1a6cf4632fbccc8eff5c7549" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.3", -] - [[package]] name = "sha2" version = "0.9.9" @@ -1334,20 +1177,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "tempfile" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" -dependencies = [ - "cfg-if", - "fastrand", - "libc", - "redox_syscall", - "remove_dir_all", - "winapi", -] - [[package]] name = "thiserror" version = "1.0.34" @@ -1454,45 +1283,7 @@ dependencies = [ "postgres-types", "socket2", "tokio", - "tokio-util 0.7.4", -] - -[[package]] -name = "tokio-stream" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511de3f85caf1c98983545490c3d09685fa8eb634e57eec22bb4db271f46cbd8" -dependencies = [ - "futures-util", - "log", - "pin-project", - "tokio", - "tungstenite", -] - -[[package]] -name = "tokio-util" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "log", - "pin-project-lite", - "tokio", + "tokio-util", ] [[package]] @@ -1525,6 +1316,23 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-cookies" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19833e336396f3953e5ab1513d72b5e5ea51d5ad39b78d306766a05740b48b97" +dependencies = [ + "async-trait", + "axum-core", + "cookie", + "futures-util", + "http", + "parking_lot", + "pin-project-lite", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-http" version = "0.3.4" @@ -1583,34 +1391,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" -[[package]] -name = "tungstenite" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0b2d8558abd2e276b0a8df5c05a2ec762609344191e5fd23e292c910e9165b5" -dependencies = [ - "base64", - "byteorder", - "bytes", - "http", - "httparse", - "log", - "rand", - "sha-1 0.9.8", - "thiserror", - "url", - "utf-8", -] - -[[package]] -name = "twoway" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" -dependencies = [ - "memchr", -] - [[package]] name = "typenum" version = "1.15.0" @@ -1665,23 +1445,6 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" -[[package]] -name = "url" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - [[package]] name = "version_check" version = "0.9.4" @@ -1709,36 +1472,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "warp" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cef4e1e9114a4b7f1ac799f16ce71c14de5778500c5450ec6b7b920c55b587e" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "headers", - "http", - "hyper", - "log", - "mime", - "mime_guess", - "multipart", - "percent-encoding", - "pin-project", - "scoped-tls", - "serde", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-stream", - "tokio-tungstenite", - "tokio-util 0.6.10", - "tower-service", - "tracing", -] - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 0db7b9d..90e0cfb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,4 +20,4 @@ serde = { version = "1.0.144", features = ["derive", "std", "serde_derive"]} serde_json = "1.0.85" tokio = { version = "1", features = ["full"] } tokio-postgres = { version = "0.7.7", features = ["with-serde_json-1"] } -warp = { version = "0.3.2" } +tower-cookies = "0.7.0" diff --git a/flabk_icon_placeholder.svg b/flabk_icon_placeholder.svg new file mode 100644 index 0000000..3a521d9 --- /dev/null +++ b/flabk_icon_placeholder.svg @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + fK + fK + + + diff --git a/src/database/users.rs b/src/database/users.rs index f7588da..163c2e8 100644 --- a/src/database/users.rs +++ b/src/database/users.rs @@ -52,7 +52,7 @@ impl Users { .await .query( format!( - "select id, username, host, display_name, password_hash from users where {}", + "select id, username, host, display_name, password_hash, email from users where {}", where_clause ) .as_str(), diff --git a/src/helpers.rs b/src/helpers.rs deleted file mode 100644 index d964050..0000000 --- a/src/helpers.rs +++ /dev/null @@ -1,20 +0,0 @@ -use warp::hyper::StatusCode; - -pub(crate) fn html_with_status(body: String, status: StatusCode) -> warp::http::Response { - warp::http::Response::builder() - .header("Content-Type", "text/html; charset=utf-8") - .status(status) - .body(body) - .expect("failed marshalling html response") -} - -pub(crate) fn html(body: String) -> warp::http::Response { - html_with_status(body, StatusCode::OK) -} - -// pub(crate) fn html(body: String) -> Result, warp::http::Error> { -// warp::http::Response::builder() -// .header("Content-Type", "text/html; charset=utf-8") -// .status(StatusCode::OK) -// .body(body) -// } diff --git a/src/main.rs b/src/main.rs index ebe578f..dc5f79c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,4 @@ mod database; -mod model; mod sec; mod servek; mod svc; diff --git a/src/model.rs b/src/model.rs deleted file mode 100644 index 8b13789..0000000 --- a/src/model.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/servek/html.rs b/src/servek/html.rs index 7a934b8..c741f69 100644 --- a/src/servek/html.rs +++ b/src/servek/html.rs @@ -4,52 +4,114 @@ use axum::{ body::Full, extract::Path, handler::Handler, - http::{header, StatusCode}, - response::{self, Html, IntoResponse, Redirect, Response}, + http::{header, HeaderValue, StatusCode}, + response::{self, Html, IntoResponse, Response}, routing, Extension, Form, Json, Router, }; -use warp::{http::HeaderValue, hyper::Uri, path::Tail, Filter, Rejection, Reply}; +use mime_guess::mime; +use tower_cookies::{Cookie, Cookies}; -use crate::svc::auth::AuthError; +use crate::svc::{ + auth::{AuthError, Claims}, + profiles, +}; use super::{ servek::{Server, ServerError}, - CreateProfileRequest, LoginRequest, Notification, + CreateProfileRequest, LoginRequest, NavType, Notification, Redirect, WithNav, }; use rust_embed::RustEmbed; +const AUTH_COOKIE_NAME: &str = "flabk_token"; + #[derive(RustEmbed)] #[folder = "static"] struct StaticData; impl Server { - async fn index() -> impl IntoResponse { - ( - StatusCode::OK, - response::Html(include_str!("../../templates/html/index.html")), - ) - } - pub(super) fn register_html(&self, router: &Router) -> Router { router .clone() + .route("/favicon.svg", routing::get(Self::favicon)) .route("/", routing::get(Self::index)) - .route("/login", routing::get(Self::login_page)) + .route("/login", routing::get(Self::login_page).post(Self::login)) + .route("/logout", routing::get(Self::logout)) .route( "/signup", routing::get(Self::signup_page).post(Self::create_user), ) + .route("/@/:username", routing::get(Self::profile)) .route("/static/*file", routing::get(Self::static_handler)) .fallback(routing::get(Self::handler_404)) } - async fn handler_404() -> impl IntoResponse { + fn from_cookie(&self, cookie: Option) -> Result>, ServerError> { + if let Some(cookie) = cookie { + let claims = self.auth.get_claims(cookie.value().to_owned())?; + Ok(WithNav::new(Some(claims.clone()), claims.into())) + } else { + Ok(WithNav { + nav_type: NavType::LoggedOut, + obj: None, + }) + } + } + + async fn index( + Extension(srv): Extension, + cookies: Cookies, + ) -> Result { + let user = srv.from_cookie(cookies.get(AUTH_COOKIE_NAME))?; + Ok(( + StatusCode::OK, + response::Html(srv.hb.render("index", &user)?), + )) + } + + async fn favicon() -> impl IntoResponse { ( StatusCode::OK, - response::Html(include_str!("../../templates/html/404.html")), + ( + [( + header::CONTENT_TYPE, + HeaderValue::from_static(mime::IMAGE_SVG.as_ref()), + )], + axum::body::boxed(Full::from( + include_bytes!("../../flabk_icon_placeholder.svg").as_ref(), + )), + ), ) } + async fn handler_404( + Extension(srv): Extension, + cookies: Cookies, + ) -> Result { + Ok(( + StatusCode::OK, + response::Html( + srv.hb + .render("404", &srv.from_cookie(cookies.get(AUTH_COOKIE_NAME))?)?, + ), + )) + } + + async fn logout( + Extension(srv): Extension, + cookies: Cookies, + ) -> Result { + cookies.remove(Cookie::new(AUTH_COOKIE_NAME, "")); + Ok(( + StatusCode::OK, + response::Html(srv.hb.render( + "redirect", + &Redirect { + location: "/".to_owned(), + }, + )?), + )) + } + fn login_page_with( &self, tag_name: String, @@ -73,68 +135,54 @@ impl Server { )) } - // async fn login( - // Extension(srv): Extension, - // Form(login): Form, - // ) -> Result { - // if login.username == "" || login.password == "" { - // return srv.login_page_with( - // "error-partial".to_owned(), - // "credentials required".to_owned(), - // ); - // } - // let token = srv.auth.login(login.username, login.password).await?; - // } + async fn login( + cookies: Cookies, + Extension(srv): Extension, + Form(login): Form, + ) -> Result { + if login.username == "" || login.password == "" { + return Ok(( + StatusCode::BAD_REQUEST, + srv.login_page_with( + "error-partial".to_owned(), + "credentials required".to_owned(), + )?, + )); + } + let token = srv.auth.login(login.username, login.password).await?; - // async fn login( - // srv: Server, - // Form(body): Form>, - // ) -> Result, ServerError> { - // let user = body - // .get("username") - // .ok_or(ServerError::BadRequest("no username provided".to_owned()))?; - // let pass = body - // .get("password") - // .ok_or(ServerError::BadRequest("no password provided".to_owned()))?; + if cookies.get(AUTH_COOKIE_NAME).is_some() { + cookies.remove(Cookie::new(AUTH_COOKIE_NAME, "")); + } + cookies.add(Cookie::new(AUTH_COOKIE_NAME, token)); - // let token = srv - // .auth - // .login(user.clone(), pass.clone()) - // .await - // .map(|html| response::Html(html)); - // if let Err(e) = &token { - // if let AuthError::InvalidCredentials = e { - // return srv.login_with_error("invalid credentials".to_owned()); - // } - // } - // Ok(token?) - // } - - fn with_server( - srv: Server, - ) -> impl Filter + Clone { - warp::any().map(move || srv.clone()) + Ok(( + StatusCode::OK, + response::Html(srv.hb.render( + "redirect", + &Redirect { + location: "/".to_owned(), + }, + )?), + )) } - // fn profile(&self) -> impl Filter + Clone { - // warp::get().and( - // warp::path!("@" / String) - // .and(Self::with_server(self.clone())) - // .and_then(|username: String, srv: Server| async move { - // srv.hb - // .render( - // "profile", - // &serde_json::json!(srv - // .profiler - // .profile(username) - // .await - // .map_err(|e| ServerError::from(e))?), - // ) - // .map(|html| warp::reply::html(html)) - // .map_err(|e| ServerError::from(e).rejection()) - // }), - // ) - // } + async fn profile( + cookies: Cookies, + Extension(srv): Extension, + Path(username): Path, + ) -> Result { + Ok(( + StatusCode::OK, + response::Html(srv.hb.render( + "profile", + &WithNav::new( + srv.profiler.profile(username).await?, + srv.from_cookie(cookies.get(AUTH_COOKIE_NAME))?.nav_type, + ), + )?), + )) + } async fn create_user( Extension(srv): Extension, diff --git a/src/servek/mod.rs b/src/servek/mod.rs index b2126ab..e005d5a 100644 --- a/src/servek/mod.rs +++ b/src/servek/mod.rs @@ -1,4 +1,11 @@ +use axum::response::{Html, IntoResponse}; use serde::{Deserialize, Serialize}; +use tower_cookies::{Cookie, Cookies}; + +use crate::svc::{ + auth::{Auth, AuthError, Claims}, + profiles::User, +}; mod html; pub mod servek; @@ -22,7 +29,59 @@ pub struct CreateProfileRequest { pub email: String, } +// pub enum HtmlOrRedirect { +// Html(Html), +// Redirect(()), +// } + #[derive(Debug, Clone, Serialize)] -pub struct Login { - pub token: String, +pub struct Redirect { + pub location: String, +} + +#[derive(Debug, Clone, Serialize)] +pub enum NavType { + LoggedIn, + LoggedOut, +} + +impl From> for NavType { + fn from(claims: Result) -> Self { + if claims.map(|c| c.expired()).unwrap_or(true) { + NavType::LoggedOut + } else { + NavType::LoggedIn + } + } +} + +impl From for NavType { + fn from(c: Claims) -> Self { + if c.expired() { + NavType::LoggedOut + } else { + NavType::LoggedIn + } + } +} + +#[derive(Debug, Clone, Serialize)] +pub struct WithNav { + pub nav_type: NavType, + pub obj: T, +} + +impl WithNav { + pub fn new(obj: T, nav_type: NavType) -> WithNav { + WithNav { nav_type, obj } + } +} + +impl Into for WithNav +where + T: Serialize, +{ + fn into(self) -> serde_json::Value { + serde_json::json!(self) + } } diff --git a/src/servek/servek.rs b/src/servek/servek.rs index 0ce24b9..5121349 100644 --- a/src/servek/servek.rs +++ b/src/servek/servek.rs @@ -2,23 +2,16 @@ use core::panic; use std::{convert::Infallible, fmt::Display, net::SocketAddr}; use axum::{ - http::uri::InvalidUri, + http::{uri::InvalidUri, StatusCode}, response::{self, IntoResponse, Response}, routing, Extension, Router, }; use handlebars::{Handlebars, RenderError}; -use warp::{ - hyper::StatusCode, - reject::{MethodNotAllowed, Reject}, - Filter, Rejection, Reply, -}; +use tower_cookies::CookieManagerLayer; -use crate::{ - model, - svc::{ - auth::{Auth, AuthError}, - profiles::{Profiler, UserError}, - }, +use crate::svc::{ + auth::{Auth, AuthError}, + profiles::{Profiler, UserError}, }; #[derive(Clone)] @@ -37,10 +30,29 @@ impl Server { .expect("login template"); hb.register_template_string("signup", include_str!("../../templates/html/signup.html")) .expect("login template"); + hb.register_template_string( + "redirect", + include_str!("../../templates/html/html-redirect.html"), + ) + .expect("redirect template"); hb.register_template_string("error-partial", r#"

{{message}}

"#) .expect("error-partial"); hb.register_template_string("success-partial", r#"

{{message}}

"#) .expect("success-partial"); + hb.register_template_string("index", include_str!("../../templates/html/index.html")) + .expect("index"); + hb.register_template_string("404", include_str!("../../templates/html/404.html")) + .expect("404"); + hb.register_partial( + "LoggedOut", + include_str!("../../templates/html/nav-loggedout.html"), + ) + .expect("LoggedOut"); + hb.register_partial( + "LoggedIn", + include_str!("../../templates/html/nav-loggedin.html"), + ) + .expect("LoggedIn"); Self { hb, profiler, auth } } @@ -48,7 +60,8 @@ impl Server { let router = Router::new(); let router = self .register_html(&router) - .layer(Extension::(self.clone())); + .layer(Extension::(self.clone())) + .layer(CookieManagerLayer::new()); let addr = SocketAddr::from(([127, 0, 0, 1], port)); println!("listening on {}", addr); @@ -69,8 +82,6 @@ pub(super) enum ServerError { BadRequest(String), } -impl Reject for ServerError {} - impl From for ServerError { fn from(r: RenderError) -> Self { Self::Internal(r.to_string()) @@ -108,7 +119,11 @@ impl IntoResponse for ServerError { fn into_response(self) -> axum::response::Response { match self { ServerError::Internal(err) => (StatusCode::INTERNAL_SERVER_ERROR, err).into_response(), - ServerError::NotFound => (StatusCode::NOT_FOUND, "").into_response(), + ServerError::NotFound => ( + StatusCode::NOT_FOUND, + response::Html(include_str!("../../templates/html/404.html")), + ) + .into_response(), ServerError::BadRequest(err) => (StatusCode::BAD_REQUEST, err).into_response(), } } diff --git a/src/svc/auth.rs b/src/svc/auth.rs index f89a2b5..bdf420e 100644 --- a/src/svc/auth.rs +++ b/src/svc/auth.rs @@ -1,7 +1,8 @@ use std::time::SystemTime; -use jsonwebtoken::{EncodingKey, Header}; +use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, TokenData, Validation}; use serde::{Deserialize, Serialize}; +use tower_cookies::Cookie; use crate::{ database::{ @@ -47,18 +48,38 @@ impl Auth { Ok(jsonwebtoken::encode( &Header::default(), &Claims::from(user), - &EncodingKey::from_secret("secret".as_ref()), + &EncodingKey::from_secret(self.secret.as_ref()), )?) } + + pub fn get_claims(&self, token: String) -> Result { + Ok(jsonwebtoken::decode::( + token.as_str(), + &DecodingKey::from_secret(self.secret.as_ref()), + &Validation::new(Algorithm::HS256), + )? + .claims) + } } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Claims { pub sub: String, + pub username: String, pub exp: u64, pub iat: u64, } +impl Claims { + pub fn expired(&self) -> bool { + SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap() + .as_secs() + >= self.exp + } +} + impl From for Claims { fn from(u: users::User) -> Self { let now = SystemTime::now() @@ -67,6 +88,7 @@ impl From for Claims { .as_secs(); Claims { sub: u.id, + username: u.username, exp: now + SECS_JWT_EXPIRE, iat: now, } diff --git a/src/svc/profiles.rs b/src/svc/profiles.rs index 36b542e..3db222d 100644 --- a/src/svc/profiles.rs +++ b/src/svc/profiles.rs @@ -1,5 +1,4 @@ use serde::Serialize; -use warp::{reject::Reject, Rejection}; use crate::{ database::{ @@ -95,5 +94,3 @@ impl ToString for UserError { } } } - -impl Reject for UserError {} diff --git a/static/style/main.css b/static/style/main.css index 556858f..506b2b3 100644 --- a/static/style/main.css +++ b/static/style/main.css @@ -3,10 +3,26 @@ body { color: rebeccapurple; } +p, +h1, +h2, +label { + font-size: 160%; +} + h1 { text-align: center; } +/* .big { + font-size: 200%; +} */ + +.big>input { + font-size: 180%; + margin: 5%; +} + input { background-color: black; @@ -14,10 +30,6 @@ input { border-color: rebeccapurple; } -form>div { - width: 80%; -} - .error { color: rgba(255, 0, 0, 0.7); font-weight: bold; @@ -33,7 +45,7 @@ form>div { } #central { - width: 30%; + width: 40%; border: 5px solid rebeccapurple; height: 30vw; padding: 10px; @@ -43,10 +55,35 @@ form>div { justify-content: center; align-items: center; background-color: rgba(13, 6, 19, 0.4); - font-size: large; font-weight: bold; } a { color: rebeccapurple; } + + +nav { + /* background-color: #333; */ + margin: 0; + overflow: hidden; +} + +nav ul { + margin: 0; + padding: 0; +} + +nav ul li { + display: inline-block; + list-style-type: none; +} + +nav>ul>li>a { + /* color: #aaa; */ + /* background-color:#FF0; */ + display: block; + line-height: 2em; + padding: 0.5em 0.5em; + text-decoration: none; +} diff --git a/templates/html/404.html b/templates/html/404.html index ce91864..547872a 100644 --- a/templates/html/404.html +++ b/templates/html/404.html @@ -4,9 +4,11 @@ flabk - not found + + {{> (lookup this "nav_type") }}

404 not found


return

diff --git a/templates/html/html-redirect.html b/templates/html/html-redirect.html new file mode 100644 index 0000000..d982ed0 --- /dev/null +++ b/templates/html/html-redirect.html @@ -0,0 +1,18 @@ + + + + + redirecting + + + + + + + + diff --git a/templates/html/index.html b/templates/html/index.html index 092f0dc..0b59626 100644 --- a/templates/html/index.html +++ b/templates/html/index.html @@ -4,12 +4,12 @@ flabk + -

hi

-

login

-

sign up

+ {{> (lookup this "nav_type") }} +

hi {{obj.username}}

diff --git a/templates/html/login.html b/templates/html/login.html index c78b7f6..bb46918 100644 --- a/templates/html/login.html +++ b/templates/html/login.html @@ -4,14 +4,16 @@ flabk - login + + {{> LoggedOut }}

login

login form

{{> (lookup this "tag_name")}} -
+ diff --git a/templates/html/nav-loggedin.html b/templates/html/nav-loggedin.html new file mode 100644 index 0000000..b5e2416 --- /dev/null +++ b/templates/html/nav-loggedin.html @@ -0,0 +1,13 @@ + diff --git a/templates/html/nav-loggedout.html b/templates/html/nav-loggedout.html new file mode 100644 index 0000000..f1728fc --- /dev/null +++ b/templates/html/nav-loggedout.html @@ -0,0 +1,13 @@ + diff --git a/templates/html/post-signin.html b/templates/html/post-signin.html deleted file mode 100644 index 2d3f0db..0000000 --- a/templates/html/post-signin.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - logging in - - - - - - - diff --git a/templates/html/profile.html b/templates/html/profile.html index 86730a3..2b52928 100644 --- a/templates/html/profile.html +++ b/templates/html/profile.html @@ -4,10 +4,12 @@ @{{username}} + -

hi {{username}}, your id is {{id}}

+ {{> (lookup this "nav_type") }} +

hi {{obj.username}}, your id is {{obj.id}}

diff --git a/templates/html/signup.html b/templates/html/signup.html index 4ec7cc3..6988d42 100644 --- a/templates/html/signup.html +++ b/templates/html/signup.html @@ -4,28 +4,21 @@ flabk - signup + + {{> LoggedOut }}

signup

signup form

{{> (lookup this "tag_name")}} - -
- - -
-
-
- - -
-
-
- - -
+ + +
+ +
+