use std::collections::HashMap; use actix_web::{error, web, HttpRequest, Responder}; use actix_web_lab::respond::Html; use log::info; use minijinja::context; use rusqlite::params; use serde::Deserialize; use uuid::Uuid; use crate::db::external_id::{Id, SecurityId}; use crate::events::Event; use crate::webui::services::ServicesFactory; use crate::webui::templates::MiniJinjaRenderer; #[actix_web::get("/actions")] pub async fn actions(tmpl_env: MiniJinjaRenderer) -> actix_web::Result { tmpl_env.render("actions.html", ()) } #[actix_web::get("/accounts")] pub async fn accounts(tmpl_env: MiniJinjaRenderer, req: HttpRequest, service_factory: web::Data) -> actix_web::Result { let conn = service_factory.get_connection()?; let auth_service = service_factory.get_authentication_service(&conn)?; let user = auth_service.get_login(&req); let account_service = service_factory.get_account_service(& conn)?; let accounts = account_service.get_user_accounts(&user.unwrap()) .map_err(error::ErrorInternalServerError)?; tmpl_env.render("accounts.html", context!{accounts => accounts}) } #[actix_web::get("/accounts/{account_id}")] pub async fn account(tmpl_env: MiniJinjaRenderer, req: HttpRequest, service_factory: web::Data) -> actix_web::Result { tmpl_env.render("account.html", context!{}) } #[actix_web::get("/securities")] pub async fn securities(tmpl_env: MiniJinjaRenderer, service_factory: web::Data) -> actix_web::Result { let conn = service_factory.get_connection()?; let account_service = service_factory.get_security_service(& conn)?; let ctx = context!{ securities => account_service.list_securities() }; tmpl_env.render("securities.html", ctx) } #[actix_web::get("/securities/{sec_id}")] pub async fn security(tmpl_env: MiniJinjaRenderer, service_factory: web::Data) -> actix_web::Result { let ctx = context!{}; tmpl_env.render("security.html", ctx) } #[actix_web::get("/users")] pub async fn users( tmpl_env: MiniJinjaRenderer, service_factory: web::Data, ) -> actix_web::Result { let conn = service_factory.get_connection()?; let user_service = service_factory.get_user_service(&conn)?; let users = user_service.list_users().unwrap(); let ctx = context! { users => users, }; tmpl_env.render("users.html", ctx) } #[actix_web::get("/partials/overview/submit_button")] pub async fn overview_submit_button( tmpl_env: MiniJinjaRenderer, query: web::Query>, ) -> actix_web::Result { let ctx = context! { event_type => query.get("event_type").unwrap_or(&"".to_string()), }; tmpl_env.render("partials/overview/submit_button.html", ctx) } #[actix_web::get("/partials/actions/accounts-by-security-selectors")] pub async fn get_accounts_by_security_selectors( req: HttpRequest, tmpl_env: MiniJinjaRenderer, query: web::Query>, service_factory: web::Data, ) -> actix_web::Result { let sec_id = query .get("sec-id") .and_then(SecurityId::from_string) .ok_or(error::ErrorBadRequest("Invalid sec-id parameters"))?; let conn = service_factory.get_connection()?; let account_service = service_factory.get_account_service(&conn)?; let authentication_service = service_factory.get_authentication_service(&conn)?; let maybe_user = authentication_service.get_login(&req); if maybe_user.is_none() { return Err(error::ErrorForbidden("")) } let user_id = maybe_user.unwrap(); let ctx = context! { sec_id => &sec_id, user_id => &user_id, accounts => account_service.get_checking_accounts_for_security(&sec_id).map_err(error::ErrorInternalServerError)?, }; tmpl_env.render("partials/actions/accounts-by-security-selectors.html", ctx) } #[actix_web::get("/partials/actions/action-form")] pub async fn actions_partials( req: HttpRequest, tmpl_env: MiniJinjaRenderer, query: web::Query>, service_factory: web::Data, ) -> actix_web::Result { let event_type = query .get("event_type") .unwrap_or(&"404".to_string()) .to_string(); let conn = service_factory.get_connection()?; let security_service = service_factory.get_security_service(&conn)?; let account_service = service_factory.get_account_service(&conn)?; let authentication_service = service_factory.get_authentication_service(&conn)?; let maybeUser = authentication_service.get_login(&req); if maybeUser.is_none() { return Err(actix_web::error::ErrorForbidden("")) } let user = maybeUser.unwrap(); let ctx = context! { event_type => event_type, securities => security_service.list_securities(), emitter_accounts => account_service.get_user_emitter_accounts(&user).map_err(error::ErrorInternalServerError)?, accounts => account_service.get_user_emitter_accounts(&user).map_err(error::ErrorInternalServerError)?, user => authentication_service.get_logged_in_user(&req).map_err(error::ErrorInternalServerError)?, }; let template_location = format!("partials/actions/{:}.html", event_type); info!("Getting template at: {:?}", template_location); tmpl_env.render(template_location.as_str(), ctx) } #[derive(Deserialize, Debug)] pub struct CreateEventPayload { event: Event, event_type: String, initiator: String, } #[actix_web::post("/events/{event_type}")] pub async fn push_event( req: HttpRequest, tmpl_env: MiniJinjaRenderer, event_channel: web::Data>, web::Json(form): web::Json, ) -> actix_web::Result { let path_event_type = req.match_info().get("event_type").unwrap(); if path_event_type.to_string() != form.event_type { return Err(error::ErrorBadRequest("Inconsistent event type.")); } let validation = form.event.validate_event(); if validation.is_err() { return Err(error::ErrorBadRequest(validation.err().unwrap())); } let _ = event_channel.send((Uuid::new_v4(), form.event)).await; let ctx = context! { event_type => "event received.", }; tmpl_env.render("partials/v1/event_processed.html", ctx) }