Mask details in debug traces.
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
use rust_decimal::Decimal;
|
use rust_decimal::Decimal;
|
||||||
use chrono::NaiveDate;
|
use chrono::NaiveDate;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct BankTransaction {
|
pub struct BankTransaction {
|
||||||
/// Source ID (GoCardless transactionId)
|
/// Source ID (GoCardless transactionId)
|
||||||
pub internal_id: String,
|
pub internal_id: String,
|
||||||
@@ -23,9 +24,83 @@ pub struct BankTransaction {
|
|||||||
pub counterparty_iban: Option<String>,
|
pub counterparty_iban: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
impl fmt::Debug for BankTransaction {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("BankTransaction")
|
||||||
|
.field("internal_id", &self.internal_id)
|
||||||
|
.field("date", &self.date)
|
||||||
|
.field("amount", &"[REDACTED]")
|
||||||
|
.field("currency", &self.currency)
|
||||||
|
.field("foreign_amount", &self.foreign_amount.as_ref().map(|_| "[REDACTED]"))
|
||||||
|
.field("foreign_currency", &self.foreign_currency)
|
||||||
|
.field("description", &"[REDACTED]")
|
||||||
|
.field("counterparty_name", &self.counterparty_name.as_ref().map(|_| "[REDACTED]"))
|
||||||
|
.field("counterparty_iban", &self.counterparty_iban.as_ref().map(|_| "[REDACTED]"))
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct Account {
|
pub struct Account {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub iban: String,
|
pub iban: String,
|
||||||
pub currency: String,
|
pub currency: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Account {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("Account")
|
||||||
|
.field("id", &self.id)
|
||||||
|
.field("iban", &"[REDACTED]")
|
||||||
|
.field("currency", &self.currency)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use rust_decimal::Decimal;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bank_transaction_debug_masks_sensitive_data() {
|
||||||
|
let tx = BankTransaction {
|
||||||
|
internal_id: "test-id".to_string(),
|
||||||
|
date: NaiveDate::from_ymd_opt(2023, 1, 1).unwrap(),
|
||||||
|
amount: Decimal::new(12345, 2), // 123.45
|
||||||
|
currency: "EUR".to_string(),
|
||||||
|
foreign_amount: Some(Decimal::new(67890, 2)), // 678.90
|
||||||
|
foreign_currency: Some("USD".to_string()),
|
||||||
|
description: "Test transaction".to_string(),
|
||||||
|
counterparty_name: Some("Test Counterparty".to_string()),
|
||||||
|
counterparty_iban: Some("DE1234567890".to_string()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let debug_str = format!("{:?}", tx);
|
||||||
|
assert!(debug_str.contains("internal_id"));
|
||||||
|
assert!(debug_str.contains("date"));
|
||||||
|
assert!(debug_str.contains("currency"));
|
||||||
|
assert!(debug_str.contains("foreign_currency"));
|
||||||
|
assert!(debug_str.contains("[REDACTED]"));
|
||||||
|
assert!(!debug_str.contains("123.45"));
|
||||||
|
assert!(!debug_str.contains("678.90"));
|
||||||
|
assert!(!debug_str.contains("Test transaction"));
|
||||||
|
assert!(!debug_str.contains("Test Counterparty"));
|
||||||
|
assert!(!debug_str.contains("DE1234567890"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_account_debug_masks_iban() {
|
||||||
|
let account = Account {
|
||||||
|
id: "123".to_string(),
|
||||||
|
iban: "DE1234567890".to_string(),
|
||||||
|
currency: "EUR".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let debug_str = format!("{:?}", account);
|
||||||
|
assert!(debug_str.contains("id"));
|
||||||
|
assert!(debug_str.contains("currency"));
|
||||||
|
assert!(debug_str.contains("[REDACTED]"));
|
||||||
|
assert!(!debug_str.contains("DE1234567890"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,14 +27,14 @@ where
|
|||||||
let end_date = cli_end_date.unwrap_or_else(|| Local::now().date_naive() - chrono::Duration::days(1));
|
let end_date = cli_end_date.unwrap_or_else(|| Local::now().date_naive() - chrono::Duration::days(1));
|
||||||
|
|
||||||
for account in accounts {
|
for account in accounts {
|
||||||
let span = tracing::info_span!("sync_account", iban = %account.iban);
|
let span = tracing::info_span!("sync_account", account_id = %account.id);
|
||||||
let _enter = span.enter();
|
let _enter = span.enter();
|
||||||
|
|
||||||
info!("Processing account...");
|
info!("Processing account...");
|
||||||
|
|
||||||
let dest_id_opt = destination.resolve_account_id(&account.iban).await?;
|
let dest_id_opt = destination.resolve_account_id(&account.iban).await?;
|
||||||
let Some(dest_id) = dest_id_opt else {
|
let Some(dest_id) = dest_id_opt else {
|
||||||
warn!("Account {} not found in destination. Skipping.", account.iban);
|
warn!("Account {} not found in destination. Skipping.", account.id);
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user