From fed675f4cb3c4199bff3657b065ab495d16e0de9 Mon Sep 17 00:00:00 2001 From: didier amyot Date: Wed, 1 Mar 2023 14:38:11 -0500 Subject: [PATCH] no fucking idea. was on the plane. project runs, tests pass. --- flake.nix | 4 --- resources/templates/accounts.html | 10 +++++++ resources/templates/base.html | 17 +----------- resources/templates/components/navbar.html | 16 +++++++++++ src/db/_ledger_internal.rs | 2 +- src/db/mod.rs | 4 +++ src/services/_authentication.rs | 21 ++++++++++----- src/services/_securities.rs | 19 +++++++++++++ src/services/mod.rs | 22 ++++++++++----- src/webui/index_views.rs | 11 +++++--- src/webui/mod.rs | 2 ++ src/webui/services.rs | 31 ++++++++++++++++++++++ src/webui/views.rs | 12 ++++++--- tools/run-local | 2 ++ 14 files changed, 133 insertions(+), 40 deletions(-) create mode 100644 resources/templates/accounts.html create mode 100644 src/services/_securities.rs create mode 100644 src/webui/services.rs create mode 100755 tools/run-local diff --git a/flake.nix b/flake.nix index b6b9b11..e98669c 100644 --- a/flake.nix +++ b/flake.nix @@ -43,10 +43,6 @@ cargo-tarpaulin deno]; RUST_SRC_PATH = rustPlatform.rustLibSrc; - shellHook = '' - export PROJECT_ROOT=${PROJECT_ROOT}; - export PATH=$PROJECT_ROOT/tools:$PATH; - ''; }; }); } diff --git a/resources/templates/accounts.html b/resources/templates/accounts.html new file mode 100644 index 0000000..92f2d20 --- /dev/null +++ b/resources/templates/accounts.html @@ -0,0 +1,10 @@ +{% set active_navbar_item = 'accounts' %} + +{% extends "base.html" %} + +{% block body %} + +
bob le chef
+ + +{% endblock %} diff --git a/resources/templates/base.html b/resources/templates/base.html index 16ac26e..410163c 100644 --- a/resources/templates/base.html +++ b/resources/templates/base.html @@ -14,22 +14,7 @@
- - + {% include "components/navbar.html" %}
diff --git a/resources/templates/components/navbar.html b/resources/templates/components/navbar.html index e69de29..97e6c3e 100644 --- a/resources/templates/components/navbar.html +++ b/resources/templates/components/navbar.html @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/src/db/_ledger_internal.rs b/src/db/_ledger_internal.rs index 771dbc8..3957f70 100644 --- a/src/db/_ledger_internal.rs +++ b/src/db/_ledger_internal.rs @@ -2,7 +2,7 @@ use rusqlite::{Connection, params, Row, Transaction, Result}; use crate::util::{CustomResult, Error}; use base64::{Engine as _, engine::general_purpose}; -struct LedgerInternal {} +pub struct LedgerInternal {} impl LedgerInternal { pub fn new() -> LedgerInternal { diff --git a/src/db/mod.rs b/src/db/mod.rs index d36f072..31672e0 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -7,6 +7,10 @@ mod _test_utils; mod _users; mod _ledger_internal; +pub mod ledger_internal{ + pub use super::_ledger_internal::*; +} + pub mod external_id { pub use super::_external_id::*; } diff --git a/src/services/_authentication.rs b/src/services/_authentication.rs index 4b6829c..b95785e 100644 --- a/src/services/_authentication.rs +++ b/src/services/_authentication.rs @@ -1,18 +1,25 @@ use actix_web::HttpRequest; use cookie::{CookieJar, Cookie, Key}; use cookie::time::OffsetDateTime; +use rusqlite::Connection; +use crate::db::ledger_internal::LedgerInternal; +use crate::{CustomResult, Error}; -struct SessionService { +pub 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)} + + pub fn from_conn(conn: &mut Connection) -> CustomResult{ + let tx = conn.transaction().map_err(Error::SqlError)?; + let secret = LedgerInternal::new().get_cookie_secret(& tx)?; + let ret = SessionService{key: Key::derive_from(&secret)}; + Ok(ret) } - fn create_login_cookie(&self, user_id: &String ) -> Cookie{ + pub 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() @@ -26,12 +33,12 @@ impl SessionService { // todo: this service should not be aware of http requests. // basically, it should be easy to migrate of // web framework - fn get_login(&self, req: &HttpRequest) -> Option { + pub fn get_login(&self, req: &HttpRequest) -> Option { req.cookie("ledger-user-id") .and_then(|c|self._decrypt_cookie(c)).map(|c| c.value().to_string()) } - fn logout(&self) -> Cookie{ + pub 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); diff --git a/src/services/_securities.rs b/src/services/_securities.rs new file mode 100644 index 0000000..c7b3a4e --- /dev/null +++ b/src/services/_securities.rs @@ -0,0 +1,19 @@ +use rusqlite::{Connection}; + +pub struct SecurityDTO{ + +} + +pub struct SecurityService<'a> { + conn: &'a Connection, +} + +impl SecurityService<'_> { + pub fn new(conn: &Connection) -> SecurityService { + SecurityService { conn } + } + + pub fn list_securities(self) -> Vec { + vec![] + } +} diff --git a/src/services/mod.rs b/src/services/mod.rs index 5612d62..56c78dd 100644 --- a/src/services/mod.rs +++ b/src/services/mod.rs @@ -1,20 +1,30 @@ use rusqlite::Connection; +use crate::{CustomResult, Error}; -use crate::services::_users::UserService; +pub use crate::services::_users::UserService; +pub use crate::services::_authentication::SessionService; mod _transactions; mod _users; mod _authentication; +mod _securities; -pub struct ServiceFactory<'a> { - conn: &'a Connection, +pub use crate::db::ledger_internal::LedgerInternal; + +pub struct ReadOnlyServiceFactory<'a> { + conn: &'a mut Connection, } -impl ServiceFactory<'_> { - pub fn new(conn: &Connection) -> ServiceFactory { - ServiceFactory { conn } +impl ReadOnlyServiceFactory<'_> { + pub fn new(conn: &mut Connection) -> ReadOnlyServiceFactory { + ReadOnlyServiceFactory { conn } } + pub fn get_user_service(&self) -> UserService { UserService::new(self.conn) } + + pub fn get_authentication_service(&mut self) -> CustomResult { + SessionService::from_conn(self.conn) + } } diff --git a/src/webui/index_views.rs b/src/webui/index_views.rs index 00a9507..2da599c 100644 --- a/src/webui/index_views.rs +++ b/src/webui/index_views.rs @@ -8,6 +8,8 @@ use minijinja::context; use crate::webui::MiniJinjaRenderer; use serde::Deserialize; use crate::db::external_id::UserId; +use crate::services::ReadOnlyServiceFactory; +use crate::SQLiteConnectionFactory; struct SessionService { key: Key, @@ -53,14 +55,17 @@ struct LoginPayload { pub async fn login( tmpl_env: MiniJinjaRenderer, web::Json(form): web::Json, + conn_factory: web::Data, ) -> actix_web::Result { + let mut conn = conn_factory.readonly().unwrap(); // todo; to proper 500 + let mut service_factory = ReadOnlyServiceFactory::new(&mut conn); + let authentication_service = service_factory.get_authentication_service().unwrap(); + let cookie = authentication_service.create_login_cookie(& form.username); 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))) + Ok(ret.insert_header(("Set-Cookie", cookie.to_string()))) } #[actix_web::post("/logout")] diff --git a/src/webui/mod.rs b/src/webui/mod.rs index d448044..5290c0b 100644 --- a/src/webui/mod.rs +++ b/src/webui/mod.rs @@ -24,6 +24,7 @@ use crate::webui::worker::{bob, event_processor_loop}; mod views; mod worker; mod index_views; +mod services; struct MiniJinjaRenderer { @@ -102,6 +103,7 @@ pub async fn web_ui_main( .service(index_views::login) .service(index_views::logout) .service(views::actions) + .service(views::accounts) .service(views::overview) .service(views::overview_submit_button) .service(views::actions_partials) diff --git a/src/webui/services.rs b/src/webui/services.rs new file mode 100644 index 0000000..2e05d37 --- /dev/null +++ b/src/webui/services.rs @@ -0,0 +1,31 @@ +use crate::util::{CustomResult, Error, SQLiteConnectionFactory}; +use crate::services::{SessionService, ReadOnlyServiceFactory, UserService}; + +struct ServicesCache { + session_service: SessionService, +} + +struct Services { + conn_fact: SQLiteConnectionFactory, + cache: ServicesCache, +} + +impl Services { + pub fn new(conn_fact: SQLiteConnectionFactory) -> Services { + let mut tmp_conn = conn_fact.connection().unwrap(); + let session_service = SessionService::from_conn(&mut tmp_conn).unwrap(); + let cache = ServicesCache{session_service}; + Services { conn_fact, cache } + } + + pub fn get_authentication_service(& self) -> &SessionService { + & self.cache.session_service + } + + pub fn get_user_service(&self) -> i32 { + // let mut conn = self.conn_fact.readonly().unwrap(); // todo; to proper 500 + // let service_factory = ReadOnlyServiceFactory::new(&mut conn); + // service_factory.get_user_service() + 88 + } +} \ No newline at end of file diff --git a/src/webui/views.rs b/src/webui/views.rs index 3288c1f..ce0528a 100644 --- a/src/webui/views.rs +++ b/src/webui/views.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use actix_web::{error, web, HttpRequest, Responder}; +use actix_web_lab::__reexports::futures_util::SinkExt; use clap::builder::TypedValueParser; use log::info; use minijinja::context; @@ -8,7 +9,7 @@ use serde::Deserialize; use crate::db::users::list_users; use crate::events::Event; -use crate::services::ServiceFactory; +use crate::services::ReadOnlyServiceFactory; use crate::util::SQLiteConnectionFactory; use crate::webui::MiniJinjaRenderer; @@ -17,13 +18,18 @@ pub async fn actions(tmpl_env: MiniJinjaRenderer) -> actix_web::Result actix_web::Result { + tmpl_env.render("accounts.html", ()) +} + #[actix_web::get("/overview")] pub async fn overview( tmpl_env: MiniJinjaRenderer, conn_factory: web::Data, ) -> actix_web::Result { - let conn = conn_factory.readonly().unwrap(); // todo; to proper 500 - let service_factory = ServiceFactory::new(&conn); + let mut conn = conn_factory.readonly().unwrap(); // todo; to proper 500 + let service_factory = ReadOnlyServiceFactory::new(&mut conn); let user_service = service_factory.get_user_service(); let users = user_service.list_users().unwrap(); let ctx = context! { diff --git a/tools/run-local b/tools/run-local new file mode 100755 index 0000000..e4869ce --- /dev/null +++ b/tools/run-local @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +exec cargo run -- wui run --port 9999 --enable-template-autoreload \ No newline at end of file