Linted code.
This commit is contained in:
1 parent
894f969d0f
commit
174d7e855a
16 files changed
+276
-178
No files matched your search
@@ -45,6 +45,7 @@
|
||||
RUST_SRC_PATH = rustPlatform.rustLibSrc;
|
||||
shellHook = ''
|
||||
export PROJECT_ROOT=${PROJECT_ROOT};
|
||||
export PATH=$PROJECT_ROOT/tools:$PATH;
|
||||
'';
|
||||
};
|
||||
});
|
||||
|
||||
+47
-18
@@ -1,5 +1,5 @@
|
||||
use rusqlite::{Connection, OptionalExtension, params, Result, Row, Transaction};
|
||||
use fraction::{Fraction};
|
||||
use fraction::Fraction;
|
||||
use rusqlite::{params, Connection, OptionalExtension, Result, Row, Transaction};
|
||||
|
||||
use crate::db::_external_id::{AccountId, Id, UserId};
|
||||
use crate::db::_securities::Security;
|
||||
@@ -100,7 +100,6 @@ impl AccountHistory {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn list_accounts<'a>(conn: &Connection) -> CustomResult<Vec<Account>> {
|
||||
let q = "SELECT acc.id AS acc_id,
|
||||
acc.amount AS acc_amount,
|
||||
@@ -135,17 +134,25 @@ pub fn get_account_by_id(tx: &Connection, id: &AccountId) -> CustomResult<Accoun
|
||||
FROM accounts acc
|
||||
JOIN securities sec ON acc.security = sec.id
|
||||
WHERE acc.id = ?1";
|
||||
return tx.query_row(q, params![id], Account::from_row).map_err(Error::SqlError);
|
||||
return tx
|
||||
.query_row(q, params![id], Account::from_row)
|
||||
.map_err(Error::SqlError);
|
||||
}
|
||||
|
||||
fn create_account(tx: &Connection, sec: &SecurityId, user: &UserId, account_type: AccountType) -> CustomResult<Account> {
|
||||
fn create_account(
|
||||
tx: &Connection,
|
||||
sec: &SecurityId,
|
||||
user: &UserId,
|
||||
account_type: AccountType,
|
||||
) -> CustomResult<Account> {
|
||||
let q = "INSERT INTO accounts(security, version, amount, timestamp, account_type)
|
||||
VALUES (?1, 0, 0, CURRENT_TIMESTAMP, ?2)";
|
||||
let account_type = match account_type {
|
||||
AccountType::Checking => "checking",
|
||||
AccountType::SecurityEmitter => "security_emitter",
|
||||
};
|
||||
tx.execute(q, (sec, account_type)).map_err(Error::SqlError)?;
|
||||
tx.execute(q, (sec, account_type))
|
||||
.map_err(Error::SqlError)?;
|
||||
let id = AccountId::from_id(tx.last_insert_rowid() as i64);
|
||||
|
||||
let q = "INSERT INTO account_user_permissions(user_id, account_id)
|
||||
@@ -165,7 +172,8 @@ fn get_account_history(tx: &Connection, id: &AccountId) -> CustomResult<AccountH
|
||||
WHERE account_id = ?1
|
||||
ORDER BY account_version DESC";
|
||||
let mut stmt = tx.prepare(q).map_err(Error::SqlError)?;
|
||||
let snapshots: Vec<AccountSnapshot> = stmt.query_map(params![id], AccountSnapshot::from_row)
|
||||
let snapshots: Vec<AccountSnapshot> = stmt
|
||||
.query_map(params![id], AccountSnapshot::from_row)
|
||||
.map_err(Error::SqlError)?
|
||||
.filter(Result::is_ok)
|
||||
.map(Result::unwrap)
|
||||
@@ -174,11 +182,19 @@ fn get_account_history(tx: &Connection, id: &AccountId) -> CustomResult<AccountH
|
||||
return AccountHistory::new(get_account_by_id(tx, id)?, snapshots);
|
||||
}
|
||||
|
||||
pub fn create_checking_account(tx: &Connection, sec: &SecurityId, user: &UserId) -> CustomResult<Account> {
|
||||
pub fn create_checking_account(
|
||||
tx: &Connection,
|
||||
sec: &SecurityId,
|
||||
user: &UserId,
|
||||
) -> CustomResult<Account> {
|
||||
create_account(tx, sec, user, AccountType::Checking)
|
||||
}
|
||||
|
||||
pub fn create_security_emitter_account(tx: &Connection, sec: &SecurityId, user: &UserId) -> CustomResult<Account> {
|
||||
pub fn create_security_emitter_account(
|
||||
tx: &Connection,
|
||||
sec: &SecurityId,
|
||||
user: &UserId,
|
||||
) -> CustomResult<Account> {
|
||||
create_account(tx, sec, user, AccountType::SecurityEmitter)
|
||||
}
|
||||
|
||||
@@ -186,7 +202,10 @@ pub fn is_owner(tx: &Connection, account_id: &AccountId, user_id: &UserId) -> Cu
|
||||
let q = "SELECT id FROM account_user_permissions WHERE account_id = ?1 AND user_id = ?2";
|
||||
let params = params![account_id, user_id];
|
||||
let ite = |row: &Row| row.get::<usize, i64>(0);
|
||||
let option = tx.query_row(q, params, ite).optional().map_err(Error::SqlError)?;
|
||||
let option = tx
|
||||
.query_row(q, params, ite)
|
||||
.optional()
|
||||
.map_err(Error::SqlError)?;
|
||||
Ok(option.is_some())
|
||||
}
|
||||
|
||||
@@ -218,13 +237,16 @@ fn update_account_history(tx: &Connection, account_id: &AccountId) -> CustomResu
|
||||
FROM accounts
|
||||
WHERE id = ?1
|
||||
";
|
||||
tx.execute(q, params![account_id]).map_err(Error::SqlError)?;
|
||||
tx.execute(q, params![account_id])
|
||||
.map_err(Error::SqlError)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_to_account(tx: &Connection,
|
||||
pub fn add_to_account(
|
||||
tx: &Connection,
|
||||
account_id: &AccountId,
|
||||
amount: i64) -> CustomResult<AccountChangeReceipt> {
|
||||
amount: i64,
|
||||
) -> CustomResult<AccountChangeReceipt> {
|
||||
let q = "
|
||||
UPDATE accounts SET amount = CASE account_type
|
||||
WHEN 'security_emitter'
|
||||
@@ -236,7 +258,9 @@ pub fn add_to_account(tx: &Connection,
|
||||
RETURNING id, version, amount, UNIXEPOCH(CURRENT_TIMESTAMP) as timestamp
|
||||
";
|
||||
let params = params![amount, account_id];
|
||||
let ret = tx.query_row(q, params, AccountChangeReceipt::from_row).map_err(Error::SqlError);
|
||||
let ret = tx
|
||||
.query_row(q, params, AccountChangeReceipt::from_row)
|
||||
.map_err(Error::SqlError);
|
||||
update_account_history(tx, account_id)?;
|
||||
return ret;
|
||||
}
|
||||
@@ -261,7 +285,11 @@ mod test_accounts {
|
||||
return (conn, users, securities);
|
||||
}
|
||||
|
||||
fn create_all_accounts(tx: &Transaction, users: &Vec<User>, secs: &Vec<Security>) -> CustomResult<Vec<Account>> {
|
||||
fn create_all_accounts(
|
||||
tx: &Transaction,
|
||||
users: &Vec<User>,
|
||||
secs: &Vec<Security>,
|
||||
) -> CustomResult<Vec<Account>> {
|
||||
let mut ret: Vec<Account> = Vec::new();
|
||||
for sec in secs.iter() {
|
||||
for user in users.iter() {
|
||||
@@ -361,8 +389,10 @@ mod test_accounts {
|
||||
let acc = get_account_by_id(&tx2, &acc.id()).unwrap();
|
||||
assert_eq!(acc.timestamp, receipt.timestamp);
|
||||
assert_eq!(acc.amount, 33);
|
||||
assert_eq!(get_account_history(&tx2, &acc.id())?.average_amount(),
|
||||
Fraction::from(0 + 33) / Fraction::from(2));
|
||||
assert_eq!(
|
||||
get_account_history(&tx2, &acc.id())?.average_amount(),
|
||||
Fraction::from(0 + 33) / Fraction::from(2)
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -390,4 +420,3 @@ mod test_accounts {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
+1
-4
@@ -14,10 +14,7 @@ pub struct Cheque {
|
||||
}
|
||||
|
||||
impl Cheque {
|
||||
pub fn new(drawer: Drawer,
|
||||
payee: Payee,
|
||||
amount: i64,
|
||||
cheque_number: i64) -> Cheque {
|
||||
pub fn new(drawer: Drawer, payee: Payee, amount: i64, cheque_number: i64) -> Cheque {
|
||||
Cheque {
|
||||
drawer_user_id: drawer.0,
|
||||
drawer_account_id: drawer.1,
|
||||
|
||||
+53
-28
@@ -8,7 +8,6 @@ struct SafeId {
|
||||
signature: [u8; 8],
|
||||
}
|
||||
|
||||
|
||||
pub trait Id {
|
||||
type Output;
|
||||
fn from_regex_captures(caps: &Captures) -> Option<Self::Output>;
|
||||
@@ -19,7 +18,12 @@ pub trait Id {
|
||||
|
||||
impl fmt::Display for SafeId {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}-{}", hex::encode(self.encrypted_id), hex::encode(self.signature))
|
||||
write!(
|
||||
f,
|
||||
"{}-{}",
|
||||
hex::encode(self.encrypted_id),
|
||||
hex::encode(self.signature)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,11 +59,8 @@ impl Id for SafeId {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
macro_rules! impl_ids {
|
||||
($T:ident, $prefix:literal) => {
|
||||
|
||||
impl fmt::Display for $T {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}-{}", $prefix, self.0)
|
||||
@@ -78,16 +79,17 @@ macro_rules! impl_ids {
|
||||
|
||||
fn from_regex_captures(caps: &Captures) -> Option<$T> {
|
||||
let type_ = caps.name("type")?;
|
||||
if(type_.as_str() != $prefix){
|
||||
if (type_.as_str() != $prefix) {
|
||||
return None;
|
||||
}
|
||||
SafeId::from_regex_captures(caps).map(|x| $T(x))
|
||||
}
|
||||
|
||||
fn from_string(s: &String) -> Option<$T> {
|
||||
let external_id_pattern = Regex::new(r"^(?P<type>\w)-(?P<id>\w+)-(?P<sign>\w+)$").unwrap();
|
||||
let external_id_pattern =
|
||||
Regex::new(r"^(?P<type>\w)-(?P<id>\w+)-(?P<sign>\w+)$").unwrap();
|
||||
let caps = external_id_pattern.captures(&s)?;
|
||||
Self::from_regex_captures(& caps)
|
||||
Self::from_regex_captures(&caps)
|
||||
}
|
||||
|
||||
fn from_id(id: i64) -> $T {
|
||||
@@ -98,7 +100,7 @@ macro_rules! impl_ids {
|
||||
self.0.get_id()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
@@ -121,17 +123,15 @@ pub enum ExternalId {
|
||||
SecurityId(SecurityId),
|
||||
}
|
||||
|
||||
|
||||
fn deserialize_str(s: &str) -> Option<[u8; 8]> {
|
||||
let mut encrypted_id_bytes = [0u8; 8];
|
||||
let r = hex::decode_to_slice(s, &mut encrypted_id_bytes as &mut [u8]);
|
||||
return match r {
|
||||
Ok(_) => Some(encrypted_id_bytes),
|
||||
Err(_) => None
|
||||
Err(_) => None,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
impl ToString for ExternalId {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
@@ -142,17 +142,20 @@ impl ToString for ExternalId {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl ExternalId {
|
||||
pub fn from_string(s: &String) -> Option<ExternalId> {
|
||||
let pattern = Regex::new(r"^(?P<type>\w)-(?P<id>\w+)-(?P<sign>\w+)$").unwrap();
|
||||
let caps = pattern.captures(&s)?;
|
||||
|
||||
match caps.name("type")?.as_str() {
|
||||
"a" => Some(ExternalId::AccountId(AccountId::from_regex_captures(&caps)?)),
|
||||
"a" => Some(ExternalId::AccountId(AccountId::from_regex_captures(
|
||||
&caps,
|
||||
)?)),
|
||||
"u" => Some(ExternalId::UserId(UserId::from_regex_captures(&caps)?)),
|
||||
"s" => Some(ExternalId::SecurityId(SecurityId::from_regex_captures(&caps)?)),
|
||||
_ => None
|
||||
"s" => Some(ExternalId::SecurityId(SecurityId::from_regex_captures(
|
||||
&caps,
|
||||
)?)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,16 +175,31 @@ pub mod test_external_ids {
|
||||
#[test]
|
||||
fn test_id_macro() {
|
||||
let id = SecurityId::from_id(33);
|
||||
assert_eq!(id.to_string(), "s-0000000000000021-0000000000000021".to_string());
|
||||
assert!(SecurityId::from_string(&"s-0000000000000021-0000000000000021".to_string()).is_some());
|
||||
assert!(SecurityId::from_string(&"u-0000000000000021-0000000000000021".to_string()).is_none());
|
||||
assert!(SecurityId::from_string(&"0000000000000021-0000000000000021".to_string()).is_none());
|
||||
assert_eq!(
|
||||
id.to_string(),
|
||||
"s-0000000000000021-0000000000000021".to_string()
|
||||
);
|
||||
assert!(
|
||||
SecurityId::from_string(&"s-0000000000000021-0000000000000021".to_string()).is_some()
|
||||
);
|
||||
assert!(
|
||||
SecurityId::from_string(&"u-0000000000000021-0000000000000021".to_string()).is_none()
|
||||
);
|
||||
assert!(
|
||||
SecurityId::from_string(&"0000000000000021-0000000000000021".to_string()).is_none()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn safe_id_happy_path_1() {
|
||||
let sid = SafeId { encrypted_id: [1, 2, 3, 4, 5, 6, 7, 8], signature: [8, 7, 6, 5, 4, 3, 2, 1] };
|
||||
assert_eq!("0102030405060708-0807060504030201".to_string(), sid.to_string());
|
||||
let sid = SafeId {
|
||||
encrypted_id: [1, 2, 3, 4, 5, 6, 7, 8],
|
||||
signature: [8, 7, 6, 5, 4, 3, 2, 1],
|
||||
};
|
||||
assert_eq!(
|
||||
"0102030405060708-0807060504030201".to_string(),
|
||||
sid.to_string()
|
||||
);
|
||||
let deserialized_eid = SafeId::from_string(&sid.to_string()).unwrap();
|
||||
assert_eq!(sid, deserialized_eid);
|
||||
}
|
||||
@@ -189,7 +207,10 @@ pub mod test_external_ids {
|
||||
#[test]
|
||||
fn safe_id_happy_path_2() {
|
||||
let sid = SafeId::from_id(56);
|
||||
assert_eq!("0000000000000038-0000000000000038".to_string(), sid.to_string());
|
||||
assert_eq!(
|
||||
"0000000000000038-0000000000000038".to_string(),
|
||||
sid.to_string()
|
||||
);
|
||||
let deserialized_eid = SafeId::from_string(&sid.to_string()).unwrap();
|
||||
assert_eq!(sid, deserialized_eid);
|
||||
assert_eq!(56, deserialized_eid.get_id());
|
||||
@@ -200,31 +221,35 @@ pub mod test_external_ids {
|
||||
let bad_strings = vec!["a", "a-b", "01020304-0708090É"];
|
||||
for bad_string in bad_strings.iter() {
|
||||
let ret = SafeId::from_string(&bad_string.to_string());
|
||||
assert!(ret.is_none(), "This should not be a valid safe id: {}", bad_string);
|
||||
assert!(
|
||||
ret.is_none(),
|
||||
"This should not be a valid safe id: {}",
|
||||
bad_string
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn external_id_simple_test() {
|
||||
let base = "0000000000000038-0000000000000038";
|
||||
let eid = ExternalId::from_string(& format!("u-{:}", base)).unwrap();
|
||||
let eid = ExternalId::from_string(&format!("u-{:}", base)).unwrap();
|
||||
assert!(match eid {
|
||||
ExternalId::UserId(_) => true,
|
||||
_ => false
|
||||
_ => false,
|
||||
});
|
||||
assert_eq!(eid.to_string(), format!("u-{:}", base));
|
||||
|
||||
let eid = ExternalId::from_string(&format!("a-{:}", base)).unwrap();
|
||||
assert!(match eid {
|
||||
ExternalId::AccountId(_) => true,
|
||||
_ => false
|
||||
_ => false,
|
||||
});
|
||||
assert_eq!(eid.to_string(), format!("a-{:}", base));
|
||||
|
||||
let eid = ExternalId::from_string(&format!("s-{:}", base)).unwrap();
|
||||
assert!(match eid {
|
||||
ExternalId::SecurityId(_) => true,
|
||||
_ => false
|
||||
_ => false,
|
||||
});
|
||||
assert_eq!(eid.to_string(), format!("s-{:}", base));
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use rusqlite::{Connection, params, Result, Row, ToSql, Transaction};
|
||||
use rusqlite::{params, Connection, Result, Row, ToSql, Transaction};
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::db::_external_id::{Id, SecurityId};
|
||||
@@ -61,8 +61,7 @@ pub struct NewSecurity {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
pub fn create_security(tx: &Transaction,
|
||||
sec: &NewSecurity) -> Result<Security> {
|
||||
pub fn create_security(tx: &Transaction, sec: &NewSecurity) -> Result<Security> {
|
||||
let q = "INSERT INTO
|
||||
securities(name, symbol, security_type)
|
||||
VALUES(?1, ?2, ?3)";
|
||||
@@ -73,7 +72,6 @@ pub fn create_security(tx: &Transaction,
|
||||
return get_security_by_id(tx, new_sec_id);
|
||||
}
|
||||
|
||||
|
||||
pub fn get_security_by_id(tx: &Transaction, id: i32) -> Result<Security> {
|
||||
let q = "SELECT id AS sec_id, security_type AS sec_security_type, symbol AS sec_symbol
|
||||
FROM securities
|
||||
@@ -95,10 +93,9 @@ pub fn list_securities(conn: &Connection) -> Result<Vec<Security>> {
|
||||
return Ok(ret);
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_securities {
|
||||
use rusqlite::{Connection, params};
|
||||
use rusqlite::{params, Connection};
|
||||
|
||||
use crate::db::_test_utils::*;
|
||||
use crate::migration;
|
||||
@@ -160,7 +157,6 @@ mod test_securities {
|
||||
assert_eq!(1, ret.len());
|
||||
assert_eq!(&expt, ret.get(0).unwrap());
|
||||
|
||||
|
||||
let sec = mock_currency_2();
|
||||
let expt = Security {
|
||||
id: 2,
|
||||
|
||||
+12
-6
@@ -1,11 +1,11 @@
|
||||
use rusqlite::{Result, Transaction};
|
||||
|
||||
use crate::db::{_securities, _users};
|
||||
use crate::db::_accounts::create_checking_account;
|
||||
use crate::db::_external_id::UserId;
|
||||
use crate::db::_securities::{NewSecurity, Security, SecurityType};
|
||||
use crate::db::_users::User;
|
||||
use crate::db::accounts::Account;
|
||||
use crate::db::{_securities, _users};
|
||||
use crate::util::CustomResult;
|
||||
|
||||
pub fn mock_currency_1() -> NewSecurity {
|
||||
@@ -42,14 +42,20 @@ pub fn setup_users_and_securities(tx: &Transaction) -> Result<(Vec<User>, Vec<Se
|
||||
Ok((users, securities))
|
||||
}
|
||||
|
||||
pub fn setup_basic_environment(tx: &Transaction) -> CustomResult<(Vec<User>, Vec<Security>, Vec<Account>)> {
|
||||
pub fn setup_basic_environment(
|
||||
tx: &Transaction,
|
||||
) -> CustomResult<(Vec<User>, Vec<Security>, Vec<Account>)> {
|
||||
let (users, securities) = setup_users_and_securities(tx).unwrap();
|
||||
|
||||
let acc1 = create_checking_account(tx,
|
||||
let acc1 = create_checking_account(
|
||||
tx,
|
||||
&securities.get(0).unwrap().id(),
|
||||
&users.get(0).unwrap().id())?;
|
||||
let acc2 = create_checking_account(tx,
|
||||
&users.get(0).unwrap().id(),
|
||||
)?;
|
||||
let acc2 = create_checking_account(
|
||||
tx,
|
||||
&securities.get(1).unwrap().id(),
|
||||
&users.get(1).unwrap().id())?;
|
||||
&users.get(1).unwrap().id(),
|
||||
)?;
|
||||
Ok((users, securities, vec![acc1, acc2]))
|
||||
}
|
||||
+9
-7
@@ -1,7 +1,6 @@
|
||||
use rusqlite::{Connection, params, Result, Transaction, Row};
|
||||
use serde::{Serialize};
|
||||
use crate::db::_external_id::{UserId, Id};
|
||||
|
||||
use crate::db::_external_id::{Id, UserId};
|
||||
use rusqlite::{params, Connection, Result, Row, Transaction};
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct User {
|
||||
@@ -17,8 +16,10 @@ impl User {
|
||||
}
|
||||
|
||||
pub fn create_user(tx: &Transaction, name: &String, public_key: &String) -> Result<User> {
|
||||
tx.execute("INSERT INTO users (name, public_key) VALUES (?1, ?2)",
|
||||
(name, public_key))?;
|
||||
tx.execute(
|
||||
"INSERT INTO users (name, public_key) VALUES (?1, ?2)",
|
||||
(name, public_key),
|
||||
)?;
|
||||
return get_user_by_id(tx, tx.last_insert_rowid() as i32);
|
||||
}
|
||||
|
||||
@@ -39,7 +40,8 @@ fn get_user_by_id(tx: &Transaction, id: i32) -> Result<User> {
|
||||
|
||||
pub fn list_users(conn: &Connection) -> Result<Vec<User>> {
|
||||
let mut stmt = conn.prepare("SELECT id, name, public_key FROM users")?;
|
||||
let ret: Vec<User> = stmt.query_map([], _user_from_row)?
|
||||
let ret: Vec<User> = stmt
|
||||
.query_map([], _user_from_row)?
|
||||
.filter(Result::is_ok)
|
||||
.map(Result::unwrap)
|
||||
.collect();
|
||||
|
||||
+8
-14
@@ -1,10 +1,10 @@
|
||||
mod _users;
|
||||
mod _securities;
|
||||
mod _accounts;
|
||||
mod _cheques;
|
||||
mod _external_id;
|
||||
mod _test_utils;
|
||||
mod _interests;
|
||||
mod _securities;
|
||||
mod _test_utils;
|
||||
mod _users;
|
||||
|
||||
pub mod external_id {
|
||||
pub use super::_external_id::*;
|
||||
@@ -19,14 +19,10 @@ pub mod users {
|
||||
}
|
||||
|
||||
pub mod accounts {
|
||||
pub use super::_accounts::{Account,
|
||||
AccountChangeReceipt,
|
||||
create_checking_account,
|
||||
create_security_emitter_account,
|
||||
is_owner,
|
||||
get_account_by_id,
|
||||
list_accounts,
|
||||
add_to_account};
|
||||
pub use super::_accounts::{
|
||||
add_to_account, create_checking_account, create_security_emitter_account,
|
||||
get_account_by_id, is_owner, list_accounts, Account, AccountChangeReceipt,
|
||||
};
|
||||
}
|
||||
|
||||
pub mod cheques {
|
||||
@@ -34,7 +30,5 @@ pub mod cheques {
|
||||
}
|
||||
|
||||
pub mod test_utils {
|
||||
pub use super::_test_utils::{mock_currency_1,
|
||||
mock_currency_2,
|
||||
setup_basic_environment};
|
||||
pub use super::_test_utils::{mock_currency_1, mock_currency_2, setup_basic_environment};
|
||||
}
|
||||
@@ -5,6 +5,7 @@ use std::fs::File;
|
||||
use std::io::{BufReader, Read, Write};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::util::{CustomResult, Error};
|
||||
use apache_avro::types::Value;
|
||||
use apache_avro::Schema::Union;
|
||||
use apache_avro::{
|
||||
@@ -13,8 +14,6 @@ use apache_avro::{
|
||||
use resource::resource_str;
|
||||
use rusqlite::Connection;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::util::{CustomResult, Error};
|
||||
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, PartialEq)]
|
||||
struct CacheChequeEvent {
|
||||
@@ -50,7 +49,6 @@ mod test {
|
||||
|
||||
use super::*;
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_basic() -> CustomResult<()> {
|
||||
let file = tempfile().unwrap();
|
||||
|
||||
+16
-12
@@ -1,7 +1,7 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::{Arg, ArgAction, ArgMatches, Command, value_parser};
|
||||
use clap::parser::ValuesRef;
|
||||
use clap::{value_parser, Arg, ArgAction, ArgMatches, Command};
|
||||
use log::{debug, error, info};
|
||||
use rusqlite::Connection;
|
||||
use serde::Serialize;
|
||||
@@ -99,18 +99,14 @@ fn new_user_command_line_parser() -> Command {
|
||||
}
|
||||
|
||||
fn ls_user_command_line_parser() -> Command {
|
||||
return Command::new("ls")
|
||||
.long_flag("ls")
|
||||
.about("List all users.");
|
||||
return Command::new("ls").long_flag("ls").about("List all users.");
|
||||
}
|
||||
|
||||
|
||||
fn process_events_command_line_parser() -> Command {
|
||||
Command::new("process")
|
||||
.about("Process events one after the other. In the order received")
|
||||
.arg_required_else_help(true)
|
||||
.arg(clap::arg!(<PATH> ... "Stuff to add")
|
||||
.value_parser(value_parser!(PathBuf)))
|
||||
.arg(clap::arg!(<PATH> ... "Stuff to add").value_parser(value_parser!(PathBuf)))
|
||||
}
|
||||
|
||||
fn user_command_line_parser() -> Command {
|
||||
@@ -136,16 +132,19 @@ fn ls_securities_command_line_parser() -> Command {
|
||||
|
||||
fn run_web_ui_command_line_parser() -> Command {
|
||||
return Command::new("run")
|
||||
.arg(Arg::new("port")
|
||||
.arg(
|
||||
Arg::new("port")
|
||||
.long("port")
|
||||
.value_parser(clap::value_parser!(u16).range(3000..))
|
||||
.action(ArgAction::Set)
|
||||
.default_value("3200"))
|
||||
.arg(Arg::new("enable-template-autoreload")
|
||||
.default_value("3200"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("enable-template-autoreload")
|
||||
.long("enable-template-autoreload")
|
||||
.required(false)
|
||||
.num_args(0)
|
||||
.help("Reload underlying template (for development)")
|
||||
.help("Reload underlying template (for development)"),
|
||||
)
|
||||
.about("Run web user interface.");
|
||||
}
|
||||
@@ -356,7 +355,12 @@ mod cli_test {
|
||||
self.process_events_count += 1;
|
||||
}
|
||||
|
||||
fn run_webui(&mut self, conn: &mut Connection, port: u16, enable_template_autoreload: bool) {
|
||||
fn run_webui(
|
||||
&mut self,
|
||||
conn: &mut Connection,
|
||||
port: u16,
|
||||
enable_template_autoreload: bool,
|
||||
) {
|
||||
self.run_webui_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
+14
-9
@@ -1,7 +1,7 @@
|
||||
use std::time::Instant;
|
||||
use resource::resource_str;
|
||||
use rusqlite::{Connection, Transaction};
|
||||
use sha2::{Digest, Sha256};
|
||||
use resource::{resource_str};
|
||||
use std::time::Instant;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum IntegrityError {
|
||||
@@ -33,10 +33,10 @@ fn get_id_of_new_migration(tx: &Transaction) -> Result<usize, rusqlite::Error> {
|
||||
return tx.query_row(q, (), |row| row.get::<usize, usize>(0));
|
||||
}
|
||||
|
||||
|
||||
pub fn migrate(conn: &mut Connection, migrations: &Vec<String>) -> Result<(), Error> {
|
||||
let tx = conn.transaction().map_err(|e| Error::Sql(e))?;
|
||||
tx.execute(INITIAL_MIGRATION, ()).map_err(|e| Error::Sql(e))?;
|
||||
tx.execute(INITIAL_MIGRATION, ())
|
||||
.map_err(|e| Error::Sql(e))?;
|
||||
let id = get_id_of_new_migration(&tx).map_err(|e| Error::Sql(e))?;
|
||||
|
||||
for (i, migration) in migrations.iter().enumerate() {
|
||||
@@ -56,13 +56,13 @@ fn apply_migration(tx: &Transaction, id: usize, migration: &String) -> Result<()
|
||||
let q = "INSERT INTO shitty_migrations(id, sha256) VALUES (?1, ?2)";
|
||||
tx.execute(q, (&id, &hash)).map_err(|e| Error::Sql(e))?;
|
||||
|
||||
|
||||
let now = Instant::now();
|
||||
tx.execute_batch(migration).map_err(|e| Error::Sql(e))?;
|
||||
let elapsed_time = now.elapsed();
|
||||
|
||||
let q = "UPDATE shitty_migrations SET duration = ?1 WHERE id = ?2";
|
||||
tx.execute(q, (elapsed_time.as_secs_f32(), &id)).map_err(|e| Error::Sql(e))?;
|
||||
tx.execute(q, (elapsed_time.as_secs_f32(), &id))
|
||||
.map_err(|e| Error::Sql(e))?;
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
@@ -76,7 +76,9 @@ fn compute_migration_sha256(migration: &String) -> String {
|
||||
|
||||
fn check_migration(tx: &Transaction, id: usize, migration: &String) -> Result<(), Error> {
|
||||
let q = "SELECT sha256 FROM shitty_migrations WHERE id = ?1";
|
||||
let res = tx.query_row(q, (&id, ), |row| row.get::<usize, String>(0)).map_err(|e| Error::Sql(e))?;
|
||||
let res = tx
|
||||
.query_row(q, (&id,), |row| row.get::<usize, String>(0))
|
||||
.map_err(|e| Error::Sql(e))?;
|
||||
let expected = compute_migration_sha256(migration);
|
||||
if !res.eq(&expected) {
|
||||
return Err(Error::Integrity(IntegrityError::MigrationCheckFailed {
|
||||
@@ -91,11 +93,14 @@ fn check_migration(tx: &Transaction, id: usize, migration: &String) -> Result<()
|
||||
|
||||
fn get_migrations() -> Vec<String> {
|
||||
let mut ret = Vec::new();
|
||||
ret.push(resource_str!("migrations/sql/create_tables_001.sql").as_ref().to_string());
|
||||
ret.push(
|
||||
resource_str!("migrations/sql/create_tables_001.sql")
|
||||
.as_ref()
|
||||
.to_string(),
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
pub fn apply_migrations(conn: &mut Connection) -> Result<(), Error> {
|
||||
let migrations = get_migrations();
|
||||
return migrate(conn, &migrations);
|
||||
|
||||
+104
-64
@@ -1,4 +1,4 @@
|
||||
use rusqlite::{Connection, ffi, params, Savepoint, Transaction};
|
||||
use rusqlite::{ffi, params, Connection, Savepoint, Transaction};
|
||||
|
||||
use crate::db::accounts;
|
||||
use crate::db::accounts::get_account_by_id;
|
||||
@@ -6,22 +6,32 @@ use crate::db::cheques::Cheque;
|
||||
use crate::db::external_id::AccountId;
|
||||
use crate::util::*;
|
||||
|
||||
fn _move_securities(tx: &Savepoint,
|
||||
fn _move_securities(
|
||||
tx: &Savepoint,
|
||||
cheque: &Cheque,
|
||||
account_id: &AccountId) -> CustomResult<(accounts::AccountChangeReceipt, accounts::AccountChangeReceipt)> {
|
||||
account_id: &AccountId,
|
||||
) -> CustomResult<(
|
||||
accounts::AccountChangeReceipt,
|
||||
accounts::AccountChangeReceipt,
|
||||
)> {
|
||||
let drawer_receipt = accounts::add_to_account(tx, &cheque.drawer_account_id, -cheque.amount)?;
|
||||
let payee_receipt = accounts::add_to_account(tx, account_id, cheque.amount)?;
|
||||
if drawer_receipt.amount < 0 {
|
||||
let m = format!("Drawer of {:?} does not have sufficient amount in account.", cheque);
|
||||
let m = format!(
|
||||
"Drawer of {:?} does not have sufficient amount in account.",
|
||||
cheque
|
||||
);
|
||||
return Err(Error::InvalidAmount(m));
|
||||
}
|
||||
Ok((drawer_receipt, payee_receipt))
|
||||
}
|
||||
|
||||
fn _add_cheque_to_cashed_cheques_log(tx: &Connection,
|
||||
fn _add_cheque_to_cashed_cheques_log(
|
||||
tx: &Connection,
|
||||
cheque: &Cheque,
|
||||
drawer_receipt: &accounts::AccountChangeReceipt,
|
||||
payee_receipt: &accounts::AccountChangeReceipt) -> Result<(), Error> {
|
||||
payee_receipt: &accounts::AccountChangeReceipt,
|
||||
) -> Result<(), Error> {
|
||||
let q = "
|
||||
INSERT INTO cashed_cheques(
|
||||
drawer_user_id,
|
||||
@@ -36,7 +46,8 @@ fn _add_cheque_to_cashed_cheques_log(tx: &Connection,
|
||||
)
|
||||
VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)
|
||||
";
|
||||
let params = params![cheque.drawer_user_id,
|
||||
let params = params![
|
||||
cheque.drawer_user_id,
|
||||
cheque.drawer_account_id,
|
||||
drawer_receipt.version,
|
||||
cheque.payee_user_id,
|
||||
@@ -44,41 +55,60 @@ fn _add_cheque_to_cashed_cheques_log(tx: &Connection,
|
||||
payee_receipt.version,
|
||||
cheque.cheque_number,
|
||||
cheque.amount,
|
||||
cheque.security_id];
|
||||
cheque.security_id
|
||||
];
|
||||
let ret = tx.execute(q, params).map_err(Error::SqlError);
|
||||
match ret {
|
||||
Ok(_) => Ok(()),
|
||||
Err(Error::SqlError(rusqlite::Error::SqliteFailure(ffi::Error { code: _, extended_code: 2067 }, _))) =>
|
||||
Err(Error::DoubleSpendingError(format!("Cheque number {} from user {} has already been cached.", cheque.cheque_number, cheque.drawer_user_id))),
|
||||
Err(a) => Err(a)
|
||||
Err(Error::SqlError(rusqlite::Error::SqliteFailure(
|
||||
ffi::Error {
|
||||
code: _,
|
||||
extended_code: 2067,
|
||||
},
|
||||
_,
|
||||
))) => Err(Error::DoubleSpendingError(format!(
|
||||
"Cheque number {} from user {} has already been cached.",
|
||||
cheque.cheque_number, cheque.drawer_user_id
|
||||
))),
|
||||
Err(a) => Err(a),
|
||||
}
|
||||
}
|
||||
|
||||
fn cash_cheque_unsafe(savepoint: &Savepoint,
|
||||
fn cash_cheque_unsafe(
|
||||
savepoint: &Savepoint,
|
||||
cheque: &Cheque,
|
||||
account_id: &AccountId) -> CustomResult<()> {
|
||||
account_id: &AccountId,
|
||||
) -> CustomResult<()> {
|
||||
if cheque.amount < 0 {
|
||||
return Err(Error::InvalidAmount(format!("The cheque {:?} has a negative amount.", cheque)));
|
||||
return Err(Error::InvalidAmount(format!(
|
||||
"The cheque {:?} has a negative amount.",
|
||||
cheque
|
||||
)));
|
||||
}
|
||||
if !accounts::is_owner(&savepoint, &cheque.drawer_account_id, &cheque.drawer_user_id)? {
|
||||
return Err(Error::InvalidDrawer(format!("The drawer is the security owner: {:?}", cheque)));
|
||||
if !accounts::is_owner(
|
||||
&savepoint,
|
||||
&cheque.drawer_account_id,
|
||||
&cheque.drawer_user_id,
|
||||
)? {
|
||||
return Err(Error::InvalidDrawer(format!(
|
||||
"The drawer is the security owner: {:?}",
|
||||
cheque
|
||||
)));
|
||||
}
|
||||
|
||||
if !accounts::is_owner(&savepoint, account_id, &cheque.payee_user_id)? {
|
||||
return Err(Error::InvalidPayee(format!("Trying to cash the cheque {:?} in \
|
||||
an account {:?} that is not owned by the payee.", cheque, account_id)));
|
||||
return Err(Error::InvalidPayee(format!(
|
||||
"Trying to cash the cheque {:?} in \
|
||||
an account {:?} that is not owned by the payee.",
|
||||
cheque, account_id
|
||||
)));
|
||||
}
|
||||
let (drawer_receipt, payee_receipt) = _move_securities(&savepoint, cheque, account_id)?;
|
||||
_add_cheque_to_cashed_cheques_log(&savepoint,
|
||||
cheque,
|
||||
&drawer_receipt,
|
||||
&payee_receipt)?;
|
||||
_add_cheque_to_cashed_cheques_log(&savepoint, cheque, &drawer_receipt, &payee_receipt)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cash_cheque(tx: &mut Transaction,
|
||||
cheque: &Cheque,
|
||||
account_id: &AccountId) -> CustomResult<()> {
|
||||
fn cash_cheque(tx: &mut Transaction, cheque: &Cheque, account_id: &AccountId) -> CustomResult<()> {
|
||||
let mut savepoint = tx.savepoint().map_err(Error::SqlError)?;
|
||||
let ret = cash_cheque_unsafe(&savepoint, cheque, account_id);
|
||||
match ret {
|
||||
@@ -86,13 +116,10 @@ fn cash_cheque(tx: &mut Transaction,
|
||||
savepoint.rollback().map_err(Error::SqlError)?;
|
||||
ret
|
||||
}
|
||||
Ok(_) => {
|
||||
savepoint.commit().map_err(Error::SqlError)
|
||||
}
|
||||
Ok(_) => savepoint.commit().map_err(Error::SqlError),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_caching_cheques {
|
||||
use rusqlite::Connection;
|
||||
@@ -118,7 +145,8 @@ mod test_caching_cheques {
|
||||
let sec = securities.get(0).unwrap();
|
||||
let drawer = users.get(0).unwrap();
|
||||
let payee = users.get(1).unwrap();
|
||||
let security_emitter_account = create_security_emitter_account(&tx, &sec.id(), &drawer.id()).unwrap();
|
||||
let security_emitter_account =
|
||||
create_security_emitter_account(&tx, &sec.id(), &drawer.id()).unwrap();
|
||||
let payee_account = create_checking_account(&tx, &sec.id(), &payee.id()).unwrap();
|
||||
|
||||
tx.commit().unwrap();
|
||||
@@ -127,9 +155,13 @@ mod test_caching_cheques {
|
||||
(conn, security_emitter, payee, payee_account.id())
|
||||
}
|
||||
|
||||
fn _create_100_secs_in_payee_account(tx: &mut Transaction, security_emitter: &Drawer, payee: &Payee, payee_account: &AccountId) {
|
||||
let cheque = Cheque::new(
|
||||
security_emitter.clone(), payee.clone(), 100, 99);
|
||||
fn _create_100_secs_in_payee_account(
|
||||
tx: &mut Transaction,
|
||||
security_emitter: &Drawer,
|
||||
payee: &Payee,
|
||||
payee_account: &AccountId,
|
||||
) {
|
||||
let cheque = Cheque::new(security_emitter.clone(), payee.clone(), 100, 99);
|
||||
|
||||
cash_cheque(tx, &cheque, &payee_account).unwrap();
|
||||
}
|
||||
@@ -144,7 +176,8 @@ mod test_caching_cheques {
|
||||
let mut tx = conn.transaction().unwrap();
|
||||
|
||||
_create_100_secs_in_payee_account(&mut tx, &security_emitter, &payee, &payee_account);
|
||||
let reg_account = create_checking_account(&tx, &security_emitter.2, &security_emitter.0).unwrap();
|
||||
let reg_account =
|
||||
create_checking_account(&tx, &security_emitter.2, &security_emitter.0).unwrap();
|
||||
|
||||
tx.commit().unwrap();
|
||||
|
||||
@@ -154,14 +187,12 @@ mod test_caching_cheques {
|
||||
return (conn, drawer, new_payee, reg_account.id());
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_happy_path_currency_emitter() -> CustomResult<()> {
|
||||
let (mut conn, security_emitter, payee, payee_account) = setup_security_emitter();
|
||||
let mut tx = conn.transaction().unwrap();
|
||||
|
||||
let cheque = Cheque::new(
|
||||
security_emitter, payee, 1000, 99);
|
||||
let cheque = Cheque::new(security_emitter, payee, 1000, 99);
|
||||
|
||||
cash_cheque(&mut tx, &cheque, &payee_account)?;
|
||||
tx.commit().unwrap();
|
||||
@@ -178,8 +209,7 @@ mod test_caching_cheques {
|
||||
let (mut conn, drawer, payee, payee_account) = setup_basic();
|
||||
let mut tx = conn.transaction().unwrap();
|
||||
|
||||
let cheque = Cheque::new(
|
||||
drawer.clone(), payee, 25, 10001);
|
||||
let cheque = Cheque::new(drawer.clone(), payee, 25, 10001);
|
||||
|
||||
cash_cheque(&mut tx, &cheque, &payee_account)?;
|
||||
|
||||
@@ -192,16 +222,22 @@ mod test_caching_cheques {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_negative_cheque(conn: &mut Connection, drawer: Drawer, payee: Payee, payee_account: AccountId) -> CustomResult<()> {
|
||||
fn test_negative_cheque(
|
||||
conn: &mut Connection,
|
||||
drawer: Drawer,
|
||||
payee: Payee,
|
||||
payee_account: AccountId,
|
||||
) -> CustomResult<()> {
|
||||
let mut tx = conn.transaction().unwrap();
|
||||
|
||||
let cheque = Cheque::new(
|
||||
drawer, payee, -1, 99);
|
||||
let cheque = Cheque::new(drawer, payee, -1, 99);
|
||||
|
||||
let ret = cash_cheque(&mut tx, &cheque, &payee_account);
|
||||
match ret {
|
||||
Err(Error::InvalidAmount(_)) => Ok(()),
|
||||
_ => Err(Error::Testing("Expected invalid amount error here.".to_string()))
|
||||
_ => Err(Error::Testing(
|
||||
"Expected invalid amount error here.".to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,15 +253,15 @@ mod test_caching_cheques {
|
||||
test_negative_cheque(&mut conn, drawer, payee, payee_account)
|
||||
}
|
||||
|
||||
fn test_double_spend(conn: &mut Connection, drawer: Drawer, payee: Payee, payee_account: AccountId) -> CustomResult<()> {
|
||||
fn test_double_spend(
|
||||
conn: &mut Connection,
|
||||
drawer: Drawer,
|
||||
payee: Payee,
|
||||
payee_account: AccountId,
|
||||
) -> CustomResult<()> {
|
||||
let mut tx = conn.transaction().unwrap();
|
||||
|
||||
let cheque = Cheque::new(
|
||||
drawer,
|
||||
payee,
|
||||
10,
|
||||
99,
|
||||
);
|
||||
let cheque = Cheque::new(drawer, payee, 10, 99);
|
||||
|
||||
cash_cheque(&mut tx, &cheque, &payee_account)?;
|
||||
tx.commit().unwrap();
|
||||
@@ -234,7 +270,9 @@ mod test_caching_cheques {
|
||||
let ret = cash_cheque(&mut tx, &cheque, &payee_account);
|
||||
match ret {
|
||||
Err(Error::DoubleSpendingError(_)) => Ok(()),
|
||||
_ => Err(Error::Testing("Expected double spending error here.".to_string()))
|
||||
_ => Err(Error::Testing(
|
||||
"Expected double spending error here.".to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,21 +288,21 @@ mod test_caching_cheques {
|
||||
test_double_spend(&mut conn, drawer, payee, payee_account)
|
||||
}
|
||||
|
||||
fn test_invalid_drawer(conn: &mut Connection, drawer: Drawer, payee: Payee, payee_account: AccountId) -> CustomResult<()> {
|
||||
fn test_invalid_drawer(
|
||||
conn: &mut Connection,
|
||||
drawer: Drawer,
|
||||
payee: Payee,
|
||||
payee_account: AccountId,
|
||||
) -> CustomResult<()> {
|
||||
let mut tx = conn.transaction().unwrap();
|
||||
let not_currency_owner_user_id = UserId::from_id(drawer.0.get_id() + 72623);
|
||||
let not_currency_owner: Drawer = (not_currency_owner_user_id, drawer.1, drawer.2);
|
||||
let cheque = Cheque::new(
|
||||
not_currency_owner,
|
||||
payee,
|
||||
100,
|
||||
99,
|
||||
);
|
||||
let cheque = Cheque::new(not_currency_owner, payee, 100, 99);
|
||||
|
||||
let ret = cash_cheque(&mut tx, &cheque, &payee_account);
|
||||
match ret {
|
||||
Err(Error::InvalidDrawer(_)) => Ok(()),
|
||||
_ => Err(Error::Testing("Expected invalid drawer here.".to_string()))
|
||||
_ => Err(Error::Testing("Expected invalid drawer here.".to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,22 +318,24 @@ mod test_caching_cheques {
|
||||
test_invalid_drawer(&mut conn, drawer, payee, payee_account)
|
||||
}
|
||||
|
||||
fn test_invalid_payee(conn: &mut Connection, security_emitter: Drawer, payee: Payee) -> CustomResult<()> {
|
||||
fn test_invalid_payee(
|
||||
conn: &mut Connection,
|
||||
security_emitter: Drawer,
|
||||
payee: Payee,
|
||||
) -> CustomResult<()> {
|
||||
let (mut conn, security_emitter, payee, payee_account) = setup_security_emitter();
|
||||
let mut tx = conn.transaction().unwrap();
|
||||
let wrong_payee_account = &security_emitter.1;
|
||||
|
||||
let cheque = Cheque::new(
|
||||
security_emitter.clone(), payee.clone(), 1000, 99);
|
||||
let cheque = Cheque::new(security_emitter.clone(), payee.clone(), 1000, 99);
|
||||
|
||||
let ret = cash_cheque(&mut tx, &cheque, wrong_payee_account);
|
||||
match ret {
|
||||
Err(Error::InvalidPayee(_)) => Ok(()),
|
||||
_ => Err(Error::Testing("Expected invalid payee here.".to_string()))
|
||||
_ => Err(Error::Testing("Expected invalid payee here.".to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_invalid_payee_security_emitter_cheque() -> CustomResult<()> {
|
||||
let (mut conn, security_emitter, payee, payee_account) = setup_security_emitter();
|
||||
|
||||
+2
-3
@@ -3,12 +3,12 @@ mod views;
|
||||
use actix_utils::future::{ready, Ready};
|
||||
use minijinja;
|
||||
use minijinja_autoreload::AutoReloader;
|
||||
use std::{collections::HashMap, env, fs, io, path::PathBuf};
|
||||
use std::io::{Error, ErrorKind};
|
||||
use std::path::Path;
|
||||
use std::{collections::HashMap, env, fs, io, path::PathBuf};
|
||||
|
||||
use actix_web::{
|
||||
dev::{ServiceResponse},
|
||||
dev::ServiceResponse,
|
||||
error,
|
||||
http::{header::ContentType, StatusCode},
|
||||
middleware::{ErrorHandlerResponse, ErrorHandlers, Logger},
|
||||
@@ -54,7 +54,6 @@ impl FromRequest for MiniJinjaRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn web_ui_main(port: u16, enable_template_autoreload: bool) -> std::io::Result<()> {
|
||||
// The closure is invoked every time the environment is outdated to recreate it.
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
use actix_web::{Responder, web};
|
||||
use crate::webui::MiniJinjaRenderer;
|
||||
use actix_web::{web, Responder};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[actix_web::get("/")]
|
||||
pub async fn index(
|
||||
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
find ${PROJECT_ROOT}/src -name '*.rs' | xargs rustfmt --edition 2021
|
||||
Reference in new issue
Block a user