Continuing with the login.
This commit is contained in:
1 parent
feaab2e843
commit
5cd6d6f424
6 files changed
+241
-36
No files matched your search
@@ -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
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in new issue
Block a user