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

+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 worker;
mod index_views;
struct MiniJinjaRenderer {
@@ -97,9 +98,9 @@ pub async fn web_ui_main(
.service(
actix_files::Files::new("/static", "./resources/static/").use_last_modified(true),
)
.service(views::index)
.service(views::login)
.service(views::logout)
.service(index_views::index)
.service(index_views::login)
.service(index_views::logout)
.service(views::actions)
.service(views::overview)
.service(views::overview_submit_button)
-31
View File
@@ -12,11 +12,6 @@ use crate::services::ServiceFactory;
use crate::util::SQLiteConnectionFactory;
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")]
pub async fn actions(tmpl_env: MiniJinjaRenderer) -> actix_web::Result<impl Responder> {
tmpl_env.render("actions.html", ())
@@ -37,32 +32,6 @@ pub async fn overview(
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")]
pub async fn overview_submit_button(
_req: HttpRequest,