Continuing with the login.

This commit is contained in:
didier amyot committed 2023-02-26 11:01:55 -05:00
1 parent feaab2e843
commit 5cd6d6f424
6 files changed
+241 -36

No files matched your search

Generated
+142 -1
View File
@@ -53,7 +53,7 @@ dependencies = [
"actix-service", "actix-service",
"actix-utils", "actix-utils",
"ahash 0.7.6", "ahash 0.7.6",
"base64", "base64 0.21.0",
"bitflags", "bitflags",
"brotli", "brotli",
"bytes", "bytes",
@@ -268,6 +268,41 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
[[package]]
name = "aead"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c192eb8f11fc081b0fe4259ba5af04217d4e0faddd02417310a927911abd7c8"
dependencies = [
"crypto-common",
"generic-array",
]
[[package]]
name = "aes"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
]
[[package]]
name = "aes-gcm"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82e1366e0c69c9f927b1fa5ce2c7bf9eafc8f9268c0b9800729e8b267612447c"
dependencies = [
"aead",
"aes",
"cipher",
"ctr",
"ghash",
"subtle",
]
[[package]] [[package]]
name = "ahash" name = "ahash"
version = "0.7.6" version = "0.7.6"
@@ -392,6 +427,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5"
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.21.0" version = "0.21.0"
@@ -482,6 +523,16 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cipher"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e"
dependencies = [
"crypto-common",
"inout",
]
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.0.26" version = "4.0.26"
@@ -561,7 +612,14 @@ version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb"
dependencies = [ dependencies = [
"aes-gcm",
"base64 0.20.0",
"hkdf",
"hmac",
"percent-encoding", "percent-encoding",
"rand",
"sha2",
"subtle",
"time", "time",
"version_check", "version_check",
] ]
@@ -600,6 +658,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [ dependencies = [
"generic-array", "generic-array",
"rand_core",
"typenum", "typenum",
] ]
@@ -625,6 +684,15 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "ctr"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
dependencies = [
"cipher",
]
[[package]] [[package]]
name = "derive_more" name = "derive_more"
version = "0.99.17" version = "0.99.17"
@@ -646,6 +714,7 @@ checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
dependencies = [ dependencies = [
"block-buffer", "block-buffer",
"crypto-common", "crypto-common",
"subtle",
] ]
[[package]] [[package]]
@@ -675,6 +744,7 @@ dependencies = [
"async-channel", "async-channel",
"clap", "clap",
"clap-verbosity-flag", "clap-verbosity-flag",
"cookie",
"fraction", "fraction",
"futures", "futures",
"hex", "hex",
@@ -887,6 +957,16 @@ dependencies = [
"wasi", "wasi",
] ]
[[package]]
name = "ghash"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40"
dependencies = [
"opaque-debug",
"polyval",
]
[[package]] [[package]]
name = "h2" name = "h2"
version = "0.3.15" version = "0.3.15"
@@ -960,6 +1040,24 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hkdf"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
dependencies = [
"hmac",
]
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
]
[[package]] [[package]]
name = "home" name = "home"
version = "0.5.4" version = "0.5.4"
@@ -1044,6 +1142,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "inout"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
dependencies = [
"generic-array",
]
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.12" version = "0.1.12"
@@ -1383,6 +1490,12 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
[[package]]
name = "opaque-debug"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]] [[package]]
name = "os_str_bytes" name = "os_str_bytes"
version = "6.4.0" version = "6.4.0"
@@ -1442,6 +1555,18 @@ version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "polyval"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef234e08c11dfcb2e56f79fd70f6f2eb7f025c0ce2333e82f4f0518ecad30c6"
dependencies = [
"cfg-if",
"cpufeatures",
"opaque-debug",
"universal-hash",
]
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.17" version = "0.2.17"
@@ -1801,6 +1926,12 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "subtle"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.103" version = "1.0.103"
@@ -2024,6 +2155,16 @@ dependencies = [
"tinyvec", "tinyvec",
] ]
[[package]]
name = "universal-hash"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5"
dependencies = [
"crypto-common",
"subtle",
]
[[package]] [[package]]
name = "url" name = "url"
version = "2.3.1" version = "2.3.1"
+3
View File
@@ -34,3 +34,6 @@ async-channel = "1.8.0"
[dependencies.apache-avro] [dependencies.apache-avro]
version = "0.14.0" version = "0.14.0"
features = ["zstandard"] features = ["zstandard"]
[dependencies.cookie]
features = ["secure", "percent-encode"]
+5 -1
View File
@@ -10,6 +10,10 @@
</div> </div>
<div id="home-page-main-block"> <div id="home-page-main-block">
{% include "partials/index/form.html" %} {% if is_logged_in %}
{% include "partials/index/success.html" %}
{% else %}
{% include "partials/index/form.html" %}
{% endif %}
</div> </div>
{% endblock %} {% endblock %}
+87
View File
@@ -0,0 +1,87 @@
use std::time::Instant;
use actix_web::{HttpRequest, Responder, web};
use cookie::{CookieJar, Cookie, Key};
use cookie::time::macros::datetime;
use cookie::time::OffsetDateTime;
use minijinja::context;
use crate::webui::MiniJinjaRenderer;
use serde::Deserialize;
use crate::db::external_id::UserId;
struct SessionService {
key: Key,
}
impl SessionService {
fn new() -> SessionService{
let super_secret_not_hardcoded_at_all: [u8; 32] = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1];
SessionService{key: Key::derive_from(&super_secret_not_hardcoded_at_all)}
}
fn create_login_cookie(&self, user_id: &String ) -> Cookie{
let mut jar = CookieJar::new();
jar.private_mut(& self.key).add(Cookie::new("ledger-user-id", user_id.clone()));
jar.get("ledger-user-id").unwrap_or(& Cookie::new("ledger-user-id", "")).clone()
}
fn _decrypt_cookie(&self, cookie: Cookie<'static>) -> Option<Cookie>{
let mut jar = CookieJar::new();
jar.private(& self.key).decrypt(cookie)
}
fn get_login(&self, req: &HttpRequest) -> Option<String> {
req.cookie("ledger-user-id").and_then(|c|self._decrypt_cookie(c)).map(|c| c.value().to_string())
}
fn logout(&self) -> Cookie{
let mut cookie = Cookie::new("ledger-user-id", "");
let epoch = OffsetDateTime::from_unix_timestamp_nanos(0).unwrap();
cookie.set_expires(epoch);
cookie
}
}
#[derive(Deserialize, Debug)]
struct LoginPayload {
username: String,
password: String,
}
#[actix_web::post("/login")]
pub async fn login(
tmpl_env: MiniJinjaRenderer,
web::Json(form): web::Json<LoginPayload>,
) -> actix_web::Result<impl Responder> {
let ctx = context! {
name => form.username,
};
let mut ret = tmpl_env.render("partials/index/success.html", ctx)?.customize();
let s = SessionService::new();
let cookie = s.create_login_cookie(& form.username).to_string();
Ok(ret.insert_header(("Set-Cookie", cookie)))
}
#[actix_web::post("/logout")]
pub async fn logout(tmpl_env: MiniJinjaRenderer) -> actix_web::Result<impl Responder> {
let ctx = context! {};
let s = SessionService::new();
let res = tmpl_env.render("partials/index/form.html", ctx)?;
Ok(res
.customize()
.insert_header(("Set-Cookie", s.logout().to_string())))
}
#[actix_web::get("/")]
pub async fn index(req: HttpRequest,
tmpl_env: MiniJinjaRenderer) -> actix_web::Result<impl Responder> {
let s = SessionService::new();
let userid = & s.get_login(& req);
let username = userid.clone().unwrap_or("".to_string());
let ctx = context!{
is_logged_in => userid.is_some(),
name => username,
};
tmpl_env.render("index.html", ctx)
}
+4 -3
View File
@@ -23,6 +23,7 @@ use crate::webui::worker::{bob, event_processor_loop};
mod views; mod views;
mod worker; mod worker;
mod index_views;
struct MiniJinjaRenderer { struct MiniJinjaRenderer {
@@ -97,9 +98,9 @@ pub async fn web_ui_main(
.service( .service(
actix_files::Files::new("/static", "./resources/static/").use_last_modified(true), actix_files::Files::new("/static", "./resources/static/").use_last_modified(true),
) )
.service(views::index) .service(index_views::index)
.service(views::login) .service(index_views::login)
.service(views::logout) .service(index_views::logout)
.service(views::actions) .service(views::actions)
.service(views::overview) .service(views::overview)
.service(views::overview_submit_button) .service(views::overview_submit_button)
-31
View File
@@ -12,11 +12,6 @@ use crate::services::ServiceFactory;
use crate::util::SQLiteConnectionFactory; use crate::util::SQLiteConnectionFactory;
use crate::webui::MiniJinjaRenderer; use crate::webui::MiniJinjaRenderer;
#[actix_web::get("/")]
pub async fn index(tmpl_env: MiniJinjaRenderer) -> actix_web::Result<impl Responder> {
tmpl_env.render("index.html", ())
}
#[actix_web::get("/actions")] #[actix_web::get("/actions")]
pub async fn actions(tmpl_env: MiniJinjaRenderer) -> actix_web::Result<impl Responder> { pub async fn actions(tmpl_env: MiniJinjaRenderer) -> actix_web::Result<impl Responder> {
tmpl_env.render("actions.html", ()) tmpl_env.render("actions.html", ())
@@ -37,32 +32,6 @@ pub async fn overview(
tmpl_env.render("overview.html", ctx) tmpl_env.render("overview.html", ctx)
} }
#[derive(Deserialize, Debug)]
struct LoginPayload {
username: String,
password: String,
}
#[actix_web::post("/login")]
pub async fn login(
tmpl_env: MiniJinjaRenderer,
web::Json(form): web::Json<LoginPayload>,
) -> actix_web::Result<impl Responder> {
let ctx = context! {
name => form.username,
};
tmpl_env.render("partials/index/success.html", ctx)
}
#[actix_web::post("/logout")]
pub async fn logout(tmpl_env: MiniJinjaRenderer) -> actix_web::Result<impl Responder> {
let ctx = context! {};
let res = tmpl_env.render("partials/index/form.html", ctx)?;
Ok(res
.customize()
.insert_header(("Set-Cookie", "username=nobody")))
}
#[actix_web::get("/partials/overview/submit_button")] #[actix_web::get("/partials/overview/submit_button")]
pub async fn overview_submit_button( pub async fn overview_submit_button(
_req: HttpRequest, _req: HttpRequest,