Added a bunch of things
This commit is contained in:
1 parent
c365289914
commit
ce92916942
15 files changed
+131
-55
No files matched your search
Generated
+1
@@ -2216,6 +2216,7 @@ version = "1.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
|
checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -33,7 +33,10 @@ async-channel = "1.8.0"
|
|||||||
base64 = "0.21.0"
|
base64 = "0.21.0"
|
||||||
r2d2_sqlite = "0.21.0"
|
r2d2_sqlite = "0.21.0"
|
||||||
r2d2 = "0.8.10"
|
r2d2 = "0.8.10"
|
||||||
uuid = "1.3.0"
|
|
||||||
|
[dependencies.uuid]
|
||||||
|
version = "1.3.0"
|
||||||
|
features = ["v4"]
|
||||||
|
|
||||||
[dependencies.apache-avro]
|
[dependencies.apache-avro]
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
|
|||||||
@@ -13,13 +13,13 @@
|
|||||||
<select name="event_type"
|
<select name="event_type"
|
||||||
class="uk-select"
|
class="uk-select"
|
||||||
aria-label="Select"
|
aria-label="Select"
|
||||||
class="uk-button uk-button-default"
|
|
||||||
hx-get="/partials/actions/action-form"
|
hx-get="/partials/actions/action-form"
|
||||||
hx-trigger="change,load"
|
hx-trigger="change,load"
|
||||||
hx-target="#action-form"
|
hx-target="#action-form"
|
||||||
hx-swap="innerHTML">>
|
hx-swap="innerHTML">>
|
||||||
<option value="create_user">Create User</option>
|
<option value="create_user">Create User</option>
|
||||||
<option value="create_security">Create Security</option>
|
<option value="create_security">Create Security</option>
|
||||||
|
<option value="create_account">Create Account</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" name="initiator" value="bob le chef">
|
<input type="hidden" name="initiator" value="bob le chef">
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
<div class="uk-margin">
|
||||||
|
<label class="uk-form-label"> Security
|
||||||
|
<select class="uk-select">
|
||||||
|
{% for sec in securities %}
|
||||||
|
<option value="{{ sec.id }}">{{ sec.name }} ({{ sec.symbol }}) </option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{%include "partials/actions/submit_button.html"%}
|
||||||
+4
-2
@@ -108,7 +108,8 @@ pub fn list_accounts<'a>(conn: &Connection) -> CustomResult<Vec<Account>> {
|
|||||||
|
|
||||||
sec.id AS sec_id,
|
sec.id AS sec_id,
|
||||||
sec.symbol AS sec_symbol,
|
sec.symbol AS sec_symbol,
|
||||||
sec.security_type AS sec_security_type
|
sec.security_type AS sec_security_type,
|
||||||
|
sec.name AS sec_name
|
||||||
FROM accounts acc
|
FROM accounts acc
|
||||||
JOIN securities sec ON acc.security = sec.id
|
JOIN securities sec ON acc.security = sec.id
|
||||||
ORDER BY acc.id ASC";
|
ORDER BY acc.id ASC";
|
||||||
@@ -130,7 +131,8 @@ pub fn get_account_by_id(tx: &Connection, id: &AccountId) -> CustomResult<Accoun
|
|||||||
|
|
||||||
sec.id AS sec_id,
|
sec.id AS sec_id,
|
||||||
sec.symbol AS sec_symbol,
|
sec.symbol AS sec_symbol,
|
||||||
sec.security_type AS sec_security_type
|
sec.security_type AS sec_security_type,
|
||||||
|
sec.name AS sec_name
|
||||||
FROM accounts acc
|
FROM accounts acc
|
||||||
JOIN securities sec ON acc.security = sec.id
|
JOIN securities sec ON acc.security = sec.id
|
||||||
WHERE acc.id = ?1";
|
WHERE acc.id = ?1";
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use regex::{Captures, Regex};
|
use regex::{Captures, Regex};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Clone)]
|
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
|
||||||
struct SafeId {
|
struct SafeId {
|
||||||
encrypted_id: [u8; 8],
|
encrypted_id: [u8; 8],
|
||||||
signature: [u8; 8],
|
signature: [u8; 8],
|
||||||
@@ -103,13 +104,13 @@ macro_rules! impl_ids {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Clone)]
|
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct AccountId(SafeId);
|
pub struct AccountId(SafeId);
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Clone)]
|
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct UserId(SafeId);
|
pub struct UserId(SafeId);
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Clone)]
|
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct SecurityId(SafeId);
|
pub struct SecurityId(SafeId);
|
||||||
|
|
||||||
impl_ids!(AccountId, "a");
|
impl_ids!(AccountId, "a");
|
||||||
|
|||||||
+34
-3
@@ -4,12 +4,21 @@ use serde::Serialize;
|
|||||||
use crate::db::_external_id::{Id, SecurityId};
|
use crate::db::_external_id::{Id, SecurityId};
|
||||||
use crate::util::{CustomResult, Error};
|
use crate::util::{CustomResult, Error};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, PartialEq)]
|
#[derive(Debug, Clone, Serialize, PartialEq)]
|
||||||
pub enum SecurityType {
|
pub enum SecurityType {
|
||||||
Currency,
|
Currency,
|
||||||
Bond,
|
Bond,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToString for SecurityType {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
match self {
|
||||||
|
SecurityType::Currency => "currency".to_string(),
|
||||||
|
SecurityType::Bond => "bond".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SecurityType {
|
impl SecurityType {
|
||||||
fn from_string_unsafe(s: String) -> SecurityType {
|
fn from_string_unsafe(s: String) -> SecurityType {
|
||||||
if s == "currency".to_string() {
|
if s == "currency".to_string() {
|
||||||
@@ -46,12 +55,25 @@ pub struct Security {
|
|||||||
id: i64,
|
id: i64,
|
||||||
security_type: SecurityType,
|
security_type: SecurityType,
|
||||||
symbol: String,
|
symbol: String,
|
||||||
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Security {
|
impl Security {
|
||||||
pub fn id(&self) -> SecurityId {
|
pub fn id(&self) -> SecurityId {
|
||||||
SecurityId::from_id(self.id)
|
SecurityId::from_id(self.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> String {
|
||||||
|
self.name.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn symbol(&self) -> String {
|
||||||
|
self.symbol.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn security_type(&self) -> SecurityType {
|
||||||
|
self.security_type.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Security {
|
impl Security {
|
||||||
@@ -60,6 +82,7 @@ impl Security {
|
|||||||
id: row.get("sec_id")?,
|
id: row.get("sec_id")?,
|
||||||
security_type: SecurityType::from_string_unsafe(row.get("sec_security_type")?),
|
security_type: SecurityType::from_string_unsafe(row.get("sec_security_type")?),
|
||||||
symbol: row.get("sec_symbol")?,
|
symbol: row.get("sec_symbol")?,
|
||||||
|
name: row.get("sec_name")?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +105,10 @@ pub fn create_security(tx: &Transaction, sec: &NewSecurity) -> CustomResult<Secu
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_security_by_id(tx: &Transaction, id: i32) -> CustomResult<Security> {
|
pub fn get_security_by_id(tx: &Transaction, id: i32) -> CustomResult<Security> {
|
||||||
let q = "SELECT id AS sec_id, security_type AS sec_security_type, symbol AS sec_symbol
|
let q = "SELECT id AS sec_id,
|
||||||
|
security_type AS sec_security_type,
|
||||||
|
symbol AS sec_symbol,
|
||||||
|
name AS sec_name
|
||||||
FROM securities
|
FROM securities
|
||||||
WHERE id = ?1";
|
WHERE id = ?1";
|
||||||
tx.query_row(q, params![id], Security::from_row)
|
tx.query_row(q, params![id], Security::from_row)
|
||||||
@@ -90,7 +116,10 @@ pub fn get_security_by_id(tx: &Transaction, id: i32) -> CustomResult<Security> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_securities(conn: &Connection) -> CustomResult<Vec<Security>> {
|
pub fn list_securities(conn: &Connection) -> CustomResult<Vec<Security>> {
|
||||||
let q = "SELECT id AS sec_id, security_type AS sec_security_type, symbol AS sec_symbol
|
let q = "SELECT id AS sec_id,
|
||||||
|
security_type AS sec_security_type,
|
||||||
|
symbol AS sec_symbol,
|
||||||
|
name AS sec_name
|
||||||
FROM securities
|
FROM securities
|
||||||
ORDER BY id ASC";
|
ORDER BY id ASC";
|
||||||
let mut stmt = conn.prepare(q).map_err(Error::SqlError)?;
|
let mut stmt = conn.prepare(q).map_err(Error::SqlError)?;
|
||||||
@@ -166,6 +195,7 @@ mod test_securities {
|
|||||||
id: 1,
|
id: 1,
|
||||||
security_type: SecurityType::Currency,
|
security_type: SecurityType::Currency,
|
||||||
symbol: "P".to_string(),
|
symbol: "P".to_string(),
|
||||||
|
name: "piastre".to_string(),
|
||||||
};
|
};
|
||||||
assert_eq!(1, ret.len());
|
assert_eq!(1, ret.len());
|
||||||
assert_eq!(&expt, ret.get(0).unwrap());
|
assert_eq!(&expt, ret.get(0).unwrap());
|
||||||
@@ -175,6 +205,7 @@ mod test_securities {
|
|||||||
id: 2,
|
id: 2,
|
||||||
security_type: SecurityType::Bond,
|
security_type: SecurityType::Bond,
|
||||||
symbol: "B".to_string(),
|
symbol: "B".to_string(),
|
||||||
|
name: "bong".to_string(),
|
||||||
};
|
};
|
||||||
let tx = conn.transaction().unwrap();
|
let tx = conn.transaction().unwrap();
|
||||||
create_security(&tx, &sec)?;
|
create_security(&tx, &sec)?;
|
||||||
|
|||||||
@@ -1,6 +1,26 @@
|
|||||||
|
use crate::db::external_id::SecurityId;
|
||||||
|
use crate::db::securities::{list_securities, Security};
|
||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub struct SecurityDTO {}
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct SecurityDTO {
|
||||||
|
id: SecurityId,
|
||||||
|
symbol: String,
|
||||||
|
name: String,
|
||||||
|
security_type: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SecurityDTO {
|
||||||
|
fn from_entity(sec: &Security) -> SecurityDTO {
|
||||||
|
SecurityDTO {
|
||||||
|
id: sec.id(),
|
||||||
|
symbol: sec.symbol(),
|
||||||
|
name: sec.name().to_string(),
|
||||||
|
security_type: sec.security_type().to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct SecurityService<'a> {
|
pub struct SecurityService<'a> {
|
||||||
conn: &'a Connection,
|
conn: &'a Connection,
|
||||||
@@ -12,6 +32,10 @@ impl SecurityService<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_securities(self) -> Vec<SecurityDTO> {
|
pub fn list_securities(self) -> Vec<SecurityDTO> {
|
||||||
vec![]
|
list_securities(self.conn)
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(SecurityDTO::from_entity)
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-16
@@ -1,6 +1,5 @@
|
|||||||
use rusqlite::Connection;
|
|
||||||
|
|
||||||
pub use crate::services::_authentication::SessionService;
|
pub use crate::services::_authentication::SessionService;
|
||||||
|
pub use crate::services::_securities::SecurityService;
|
||||||
pub use crate::services::_users::UserService;
|
pub use crate::services::_users::UserService;
|
||||||
|
|
||||||
mod _authentication;
|
mod _authentication;
|
||||||
@@ -9,17 +8,3 @@ mod _transactions;
|
|||||||
mod _users;
|
mod _users;
|
||||||
|
|
||||||
pub use crate::db::ledger_internal::LedgerInternal;
|
pub use crate::db::ledger_internal::LedgerInternal;
|
||||||
|
|
||||||
pub struct ReadOnlyServiceFactory<'a> {
|
|
||||||
conn: &'a mut Connection,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ReadOnlyServiceFactory<'_> {
|
|
||||||
pub fn new(conn: &mut Connection) -> ReadOnlyServiceFactory {
|
|
||||||
ReadOnlyServiceFactory { conn }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_user_service(&self) -> UserService {
|
|
||||||
UserService::new(self.conn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::webui::services::Services;
|
use crate::webui::services::ServicesFactory;
|
||||||
use crate::webui::templates::MiniJinjaRenderer;
|
use crate::webui::templates::MiniJinjaRenderer;
|
||||||
|
|
||||||
use actix_web::{web, HttpRequest, Responder};
|
use actix_web::{web, HttpRequest, Responder};
|
||||||
@@ -15,7 +15,7 @@ pub struct LoginPayload {
|
|||||||
pub async fn login(
|
pub async fn login(
|
||||||
tmpl_env: MiniJinjaRenderer,
|
tmpl_env: MiniJinjaRenderer,
|
||||||
web::Json(form): web::Json<LoginPayload>,
|
web::Json(form): web::Json<LoginPayload>,
|
||||||
service_factory: web::Data<Services>,
|
service_factory: web::Data<ServicesFactory>,
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
let authentication_service = service_factory.get_authentication_service()?;
|
let authentication_service = service_factory.get_authentication_service()?;
|
||||||
let cookie = authentication_service.create_login_cookie(&form.username);
|
let cookie = authentication_service.create_login_cookie(&form.username);
|
||||||
@@ -30,7 +30,7 @@ pub async fn login(
|
|||||||
|
|
||||||
#[actix_web::post("/logout")]
|
#[actix_web::post("/logout")]
|
||||||
pub async fn logout(
|
pub async fn logout(
|
||||||
service_factory: web::Data<Services>,
|
service_factory: web::Data<ServicesFactory>,
|
||||||
tmpl_env: MiniJinjaRenderer,
|
tmpl_env: MiniJinjaRenderer,
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
let authentication_service = service_factory.get_authentication_service()?;
|
let authentication_service = service_factory.get_authentication_service()?;
|
||||||
@@ -43,7 +43,7 @@ pub async fn logout(
|
|||||||
#[actix_web::get("/")]
|
#[actix_web::get("/")]
|
||||||
pub async fn index(
|
pub async fn index(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
service_factory: web::Data<Services>,
|
service_factory: web::Data<ServicesFactory>,
|
||||||
tmpl_env: MiniJinjaRenderer,
|
tmpl_env: MiniJinjaRenderer,
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
let authentication_service = service_factory.get_authentication_service()?;
|
let authentication_service = service_factory.get_authentication_service()?;
|
||||||
|
|||||||
+3
-3
@@ -18,7 +18,7 @@ use uuid::Uuid;
|
|||||||
|
|
||||||
use crate::events::Event;
|
use crate::events::Event;
|
||||||
use crate::util::{CustomResult, Error, SQLiteConnectionFactory};
|
use crate::util::{CustomResult, Error, SQLiteConnectionFactory};
|
||||||
use crate::webui::services::{creat_db_pool, Services};
|
use crate::webui::services::{creat_db_pool, ServicesFactory};
|
||||||
use crate::webui::templates::MiniJinjaRenderer;
|
use crate::webui::templates::MiniJinjaRenderer;
|
||||||
use crate::webui::worker::{event_processor_loop, EventProcessor};
|
use crate::webui::worker::{event_processor_loop, EventProcessor};
|
||||||
|
|
||||||
@@ -80,11 +80,12 @@ pub async fn web_ui_main(
|
|||||||
) -> CustomResult<()> {
|
) -> CustomResult<()> {
|
||||||
let (event_sender, event_receiver) = async_channel::unbounded::<(Uuid, Event)>();
|
let (event_sender, event_receiver) = async_channel::unbounded::<(Uuid, Event)>();
|
||||||
let pool = creat_db_pool(&conn_fact.path().unwrap());
|
let pool = creat_db_pool(&conn_fact.path().unwrap());
|
||||||
let services = Services::new(pool);
|
let services = ServicesFactory::new(pool);
|
||||||
|
|
||||||
let server = HttpServer::new(move || {
|
let server = HttpServer::new(move || {
|
||||||
let template_reloader = create_auto_reloader(enable_template_autoreload);
|
let template_reloader = create_auto_reloader(enable_template_autoreload);
|
||||||
App::new()
|
App::new()
|
||||||
|
.wrap(Logger::default())
|
||||||
.app_data(web::Data::new(services.clone()))
|
.app_data(web::Data::new(services.clone()))
|
||||||
.app_data(web::Data::new(template_reloader))
|
.app_data(web::Data::new(template_reloader))
|
||||||
.app_data(web::Data::new(event_sender.clone()))
|
.app_data(web::Data::new(event_sender.clone()))
|
||||||
@@ -92,7 +93,6 @@ pub async fn web_ui_main(
|
|||||||
.service(create_api_scope())
|
.service(create_api_scope())
|
||||||
.service(create_views_scope())
|
.service(create_views_scope())
|
||||||
.wrap(ErrorHandlers::new().handler(StatusCode::NOT_FOUND, not_found))
|
.wrap(ErrorHandlers::new().handler(StatusCode::NOT_FOUND, not_found))
|
||||||
.wrap(Logger::default())
|
|
||||||
})
|
})
|
||||||
.workers(2)
|
.workers(2)
|
||||||
.bind(("0.0.0.0", port))
|
.bind(("0.0.0.0", port))
|
||||||
|
|||||||
+12
-5
@@ -1,4 +1,4 @@
|
|||||||
use crate::services::{SessionService, UserService};
|
use crate::services::{SecurityService, SessionService, UserService};
|
||||||
|
|
||||||
use actix_web::{error, Result};
|
use actix_web::{error, Result};
|
||||||
use r2d2::PooledConnection;
|
use r2d2::PooledConnection;
|
||||||
@@ -19,17 +19,17 @@ struct ServicesCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Services {
|
pub struct ServicesFactory {
|
||||||
pool: DbPool,
|
pool: DbPool,
|
||||||
cache: ServicesCache,
|
cache: ServicesCache,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Services {
|
impl ServicesFactory {
|
||||||
pub fn new(pool: DbPool) -> Services {
|
pub fn new(pool: DbPool) -> ServicesFactory {
|
||||||
let mut conn = pool.get().unwrap();
|
let mut conn = pool.get().unwrap();
|
||||||
let session_service = SessionService::from_conn(&mut conn).unwrap();
|
let session_service = SessionService::from_conn(&mut conn).unwrap();
|
||||||
let cache = ServicesCache { session_service };
|
let cache = ServicesCache { session_service };
|
||||||
Services { pool, cache }
|
ServicesFactory { pool, cache }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_connection(&self) -> Result<PooledConnection<SqliteConnectionManager>> {
|
pub fn get_connection(&self) -> Result<PooledConnection<SqliteConnectionManager>> {
|
||||||
@@ -48,4 +48,11 @@ impl Services {
|
|||||||
) -> Result<UserService> {
|
) -> Result<UserService> {
|
||||||
Ok(UserService::new(conn))
|
Ok(UserService::new(conn))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_security_service<'a>(
|
||||||
|
&'a self,
|
||||||
|
conn: &'a PooledConnection<SqliteConnectionManager>,
|
||||||
|
) -> Result<SecurityService> {
|
||||||
|
Ok(SecurityService::new(conn))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+17
-8
@@ -1,14 +1,16 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use actix_web::{error, web, HttpRequest, Responder};
|
use actix_web::{error, web, HttpRequest, Responder};
|
||||||
|
use actix_web_lab::respond::Html;
|
||||||
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use minijinja::context;
|
use minijinja::context;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::events::Event;
|
use crate::events::Event;
|
||||||
|
|
||||||
use crate::webui::services::Services;
|
use crate::webui::services::ServicesFactory;
|
||||||
use crate::webui::templates::MiniJinjaRenderer;
|
use crate::webui::templates::MiniJinjaRenderer;
|
||||||
|
|
||||||
#[actix_web::get("/actions")]
|
#[actix_web::get("/actions")]
|
||||||
@@ -24,7 +26,7 @@ pub async fn accounts(tmpl_env: MiniJinjaRenderer) -> actix_web::Result<impl Res
|
|||||||
#[actix_web::get("/overview")]
|
#[actix_web::get("/overview")]
|
||||||
pub async fn overview(
|
pub async fn overview(
|
||||||
tmpl_env: MiniJinjaRenderer,
|
tmpl_env: MiniJinjaRenderer,
|
||||||
service_factory: web::Data<Services>,
|
service_factory: web::Data<ServicesFactory>,
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<impl Responder> {
|
||||||
let conn = service_factory.get_connection()?;
|
let conn = service_factory.get_connection()?;
|
||||||
let user_service = service_factory.get_user_service(&conn)?;
|
let user_service = service_factory.get_user_service(&conn)?;
|
||||||
@@ -40,7 +42,7 @@ pub async fn overview(
|
|||||||
pub async fn overview_submit_button(
|
pub async fn overview_submit_button(
|
||||||
tmpl_env: MiniJinjaRenderer,
|
tmpl_env: MiniJinjaRenderer,
|
||||||
query: web::Query<HashMap<String, String>>,
|
query: web::Query<HashMap<String, String>>,
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<Html> {
|
||||||
let ctx = context! {
|
let ctx = context! {
|
||||||
event_type => query.get("event_type").unwrap_or(&"".to_string()),
|
event_type => query.get("event_type").unwrap_or(&"".to_string()),
|
||||||
};
|
};
|
||||||
@@ -51,12 +53,18 @@ pub async fn overview_submit_button(
|
|||||||
pub async fn actions_partials(
|
pub async fn actions_partials(
|
||||||
tmpl_env: MiniJinjaRenderer,
|
tmpl_env: MiniJinjaRenderer,
|
||||||
query: web::Query<HashMap<String, String>>,
|
query: web::Query<HashMap<String, String>>,
|
||||||
) -> actix_web::Result<impl Responder> {
|
service_factory: web::Data<ServicesFactory>,
|
||||||
|
) -> actix_web::Result<Html> {
|
||||||
let event_type = query
|
let event_type = query
|
||||||
.get("event_type")
|
.get("event_type")
|
||||||
.unwrap_or(&"404".to_string())
|
.unwrap_or(&"404".to_string())
|
||||||
.to_string();
|
.to_string();
|
||||||
let ctx = context! {event_type => event_type};
|
let conn = service_factory.get_connection()?;
|
||||||
|
let security_service = service_factory.get_security_service(&conn)?;
|
||||||
|
let ctx = context! {
|
||||||
|
event_type => event_type,
|
||||||
|
securities => security_service.list_securities(),
|
||||||
|
};
|
||||||
let template_location = format!("partials/actions/{:}.html", event_type);
|
let template_location = format!("partials/actions/{:}.html", event_type);
|
||||||
info!("Getting template at: {:?}", template_location);
|
info!("Getting template at: {:?}", template_location);
|
||||||
tmpl_env.render(template_location.as_str(), ctx)
|
tmpl_env.render(template_location.as_str(), ctx)
|
||||||
@@ -66,15 +74,16 @@ pub async fn actions_partials(
|
|||||||
pub struct CreateEventPayload {
|
pub struct CreateEventPayload {
|
||||||
event: Event,
|
event: Event,
|
||||||
event_type: String,
|
event_type: String,
|
||||||
|
initiator: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_web::post("/events/{event_type}")]
|
#[actix_web::post("/events/{event_type}")]
|
||||||
pub async fn push_event(
|
pub async fn push_event(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
tmpl_env: MiniJinjaRenderer,
|
tmpl_env: MiniJinjaRenderer,
|
||||||
event_channel: web::Data<async_channel::Sender<Event>>,
|
event_channel: web::Data<async_channel::Sender<(Uuid, Event)>>,
|
||||||
web::Json(form): web::Json<CreateEventPayload>,
|
web::Json(form): web::Json<CreateEventPayload>,
|
||||||
) -> actix_web::Result<impl Responder> {
|
) -> actix_web::Result<Html> {
|
||||||
let path_event_type = req.match_info().get("event_type").unwrap();
|
let path_event_type = req.match_info().get("event_type").unwrap();
|
||||||
if path_event_type.to_string() != form.event_type {
|
if path_event_type.to_string() != form.event_type {
|
||||||
return Err(error::ErrorBadRequest("Inconsistent event type."));
|
return Err(error::ErrorBadRequest("Inconsistent event type."));
|
||||||
@@ -83,7 +92,7 @@ pub async fn push_event(
|
|||||||
if validation.is_err() {
|
if validation.is_err() {
|
||||||
return Err(error::ErrorBadRequest(validation.err().unwrap()));
|
return Err(error::ErrorBadRequest(validation.err().unwrap()));
|
||||||
}
|
}
|
||||||
let _ = event_channel.send(form.event).await;
|
let _ = event_channel.send((Uuid::new_v4(), form.event)).await;
|
||||||
let ctx = context! {
|
let ctx = context! {
|
||||||
event_type => "event received.",
|
event_type => "event received.",
|
||||||
};
|
};
|
||||||
|
|||||||
+5
-5
@@ -109,7 +109,7 @@ pub mod test_worker {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::events::CreateNewUser;
|
use crate::events::CreateNewUser;
|
||||||
use crate::migration;
|
use crate::migration;
|
||||||
use futures::{future, TryFutureExt};
|
use futures::future;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
struct StatefulEventProcessor {
|
struct StatefulEventProcessor {
|
||||||
@@ -122,13 +122,13 @@ pub mod test_worker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn call_count(&self) -> i32 {
|
fn call_count(&self) -> i32 {
|
||||||
let mut m = self.m.lock().unwrap();
|
let m = self.m.lock().unwrap();
|
||||||
m.clone()
|
m.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventProcessor for StatefulEventProcessor {
|
impl EventProcessor for StatefulEventProcessor {
|
||||||
fn process_event(&self, conn: &mut Connection, event: Event) -> CustomResult<()> {
|
fn process_event(&self, _conn: &mut Connection, event: Event) -> CustomResult<()> {
|
||||||
let mut m = self.m.lock().unwrap();
|
let mut m = self.m.lock().unwrap();
|
||||||
*m += 1;
|
*m += 1;
|
||||||
get_event_processing_result(&event)
|
get_event_processing_result(&event)
|
||||||
@@ -186,7 +186,7 @@ pub mod test_worker {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_on_close_channel() {
|
async fn test_on_close_channel() {
|
||||||
let mut ep = StatefulEventProcessor::new();
|
let ep = StatefulEventProcessor::new();
|
||||||
let (event_sender, event_receiver) = async_channel::unbounded::<(Uuid, Event)>();
|
let (event_sender, event_receiver) = async_channel::unbounded::<(Uuid, Event)>();
|
||||||
event_sender.close();
|
event_sender.close();
|
||||||
let r = event_processor_loop(&mut get_connection(), &ep, event_receiver).await;
|
let r = event_processor_loop(&mut get_connection(), &ep, event_receiver).await;
|
||||||
@@ -196,7 +196,7 @@ pub mod test_worker {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_basic() -> CustomResult<()> {
|
async fn test_basic() -> CustomResult<()> {
|
||||||
let mut ep = StatefulEventProcessor::new();
|
let ep = StatefulEventProcessor::new();
|
||||||
let mut conn = get_connection();
|
let mut conn = get_connection();
|
||||||
let (event_sender, event_receiver) = async_channel::unbounded::<(Uuid, Event)>();
|
let (event_sender, event_receiver) = async_channel::unbounded::<(Uuid, Event)>();
|
||||||
let f1 = send_events(event_sender, get_events());
|
let f1 = send_events(event_sender, get_events());
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
exec cargo run -- wui run --port 9999 --enable-template-autoreload
|
exec cargo run -- -vvv wui run --port 9999 --enable-template-autoreload
|
||||||
Reference in new issue
Block a user