From 131ff952ca2ef903ba005d99d64524c13c86714c Mon Sep 17 00:00:00 2001 From: Rorik Star Platinum Date: Fri, 7 Nov 2025 16:59:05 +0300 Subject: [PATCH] (feat) added loggind(tracing) --- Cargo.lock | 4 +-- src/api.rs | 2 +- src/api/consents.rs | 63 ++++++++++++++++++++++++++++++------------ src/api/models.rs | 2 +- src/auth.rs | 1 - src/auth/middleware.rs | 2 +- src/db/accounts.rs | 2 +- src/main.rs | 15 ++++++---- src/route.rs | 25 ++++++++++------- src/route/handlers.rs | 6 ++-- 10 files changed, 79 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5f7c72b..50ad8ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1111,9 +1111,9 @@ dependencies = [ [[package]] name = "jsonwebtoken" -version = "10.1.0" +version = "10.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d119c6924272d16f0ab9ce41f7aa0bfef9340c00b0bb7ca3dd3b263d4a9150b" +checksum = "c76e1c7d7df3e34443b3621b459b066a7b79644f059fc8b2db7070c825fd417e" dependencies = [ "aws-lc-rs", "base64", diff --git a/src/api.rs b/src/api.rs index 93f0903..9ba9b17 100644 --- a/src/api.rs +++ b/src/api.rs @@ -6,5 +6,5 @@ pub mod consents; pub mod accounts; pub mod transactions; -pub use client::{Bank, BankClient, BankingClients, BankingError}; +pub use client::{BankClient, BankingError, BankingClients}; pub use models::{ApiResponse, AccountData, TransactionData, ConsentResponse}; diff --git a/src/api/consents.rs b/src/api/consents.rs index d9539f3..1d692f8 100644 --- a/src/api/consents.rs +++ b/src/api/consents.rs @@ -1,13 +1,38 @@ // src/api/consents.rs -// Consent request and retrieval logic +// Consent request and retrieval logic - Functional style use super::{client::{BankClient, BankingError}, models::{ConsentRequestBody, ConsentResponse}}; +use tracing::{info, debug, error}; impl BankClient { pub async fn request_consent(&self, client_id: &str) -> Result { + info!("🔐 Requesting consent for client_id: {}", client_id); + + let body = self.build_consent_request(client_id); let token = self.get_token().await?; - let body = ConsentRequestBody { + debug!("✅ Got bank token"); + debug!("📤 Sending consent request to bank"); + + let response = self.http_client + .post(self.base_url.join("/account-consents/request")?) + .bearer_auth(token) + .header("x-requesting-bank", self.client_id.as_str()) + .json(&body) + .send() + .await?; + + debug!("📥 Bank response status: {}", response.status()); + + response + .text() + .await + .map_err(Into::into) + .and_then(|text| self.parse_consent_response(&text)) + } + + fn build_consent_request(&self, client_id: &str) -> ConsentRequestBody { + ConsentRequestBody { client_id: client_id.to_string(), permissions: vec![ "ReadAccountsDetail".to_string(), @@ -17,22 +42,24 @@ impl BankClient { reason: "Account aggregation for Multiberry app".to_string(), requesting_bank: self.client_id.clone(), requesting_bank_name: "Multiberry Backend".to_string(), - }; - - let response = self.http_client - .post(self.base_url.join("/account-consents/request")?) - .bearer_auth(token) - .header("x-requesting-bank", self.client_id.as_str()) - .json(&body) - .send() - .await?; - - match response.status().is_success() { - true => response.json().await.map_err(Into::into), - false => Err(BankingError::ApiError { - status: response.status().as_u16(), - body: response.text().await.unwrap_or_default(), - }), } } + + fn parse_consent_response(&self, text: &str) -> Result { + info!("✅ Bank consent response: {}", text); + + serde_json::from_str::(text) + .map_err(|e| { + error!("❌ Failed to deserialize ConsentResponse: {}", e); + error!("Raw response was: {}", text); + BankingError::ApiError { + status: 500, + body: format!("Deserialization error: {}", e), + } + }) + .map(|consent| { + info!("✅ Successfully parsed consent: {}", consent.consent_id); + consent + }) + } } diff --git a/src/api/models.rs b/src/api/models.rs index cc140cb..74acf0f 100644 --- a/src/api/models.rs +++ b/src/api/models.rs @@ -33,7 +33,7 @@ pub struct Meta { // --- Consent Models --- #[derive(Debug, Serialize, Clone)] -#[serde(rename_all = "camelCase")] +#[serde(rename_all = "snake_case")] pub struct ConsentRequestBody { pub client_id: String, pub permissions: Vec, diff --git a/src/auth.rs b/src/auth.rs index 98540cc..03d9729 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -5,5 +5,4 @@ pub mod jwt; pub mod middleware; pub mod password; -pub use jwt::Claims; pub use middleware::auth_middleware; diff --git a/src/auth/middleware.rs b/src/auth/middleware.rs index 3cb5dea..e87dfc8 100644 --- a/src/auth/middleware.rs +++ b/src/auth/middleware.rs @@ -11,7 +11,7 @@ use axum::{ }; use serde_json::json; -use super::jwt::{validate_token, Claims}; +use super::jwt::validate_token; pub async fn auth_middleware( headers: HeaderMap, diff --git a/src/db/accounts.rs b/src/db/accounts.rs index 6c2aef1..5891856 100644 --- a/src/db/accounts.rs +++ b/src/db/accounts.rs @@ -1,7 +1,7 @@ // src/db/accounts.rs use sqlx::PgPool; -use chrono::{DateTime, Utc, NaiveDate}; +use chrono::NaiveDate; pub async fn store_account( pool: &PgPool, diff --git a/src/main.rs b/src/main.rs index 178883e..d0832a7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,19 +14,22 @@ use crate::state::AppState; #[tokio::main] async fn main() { - // 1. Загружаем переменные окружения из .env или secrets (через sops) dotenvy::dotenv().ok(); - // 3. Создаём общее состояние приложения - let app_state = AppState::new().await; + // Initialize tracing + tracing_subscriber::fmt() + .with_max_level(tracing::Level::DEBUG) + .init(); - // 4. Конфигурируем роуты (все роуты централизованы в route::router()) + tracing::info!("🚀 Starting Multiberry Backend Server"); + + let app_state = AppState::new().await; let app = route::router(app_state); - // 5. Запускаем сервер - let addr = SocketAddr::from(([0, 0, 0, 0], 3000)); + let addr = std::net::SocketAddr::from(([0, 0, 0, 0], 3000)); println!("🚀 Server listening on {}", addr); let listener = tokio::net::TcpListener::bind(&addr).await.unwrap(); axum::serve(listener, app).await.unwrap(); } + diff --git a/src/route.rs b/src/route.rs index d9b07b8..9335863 100644 --- a/src/route.rs +++ b/src/route.rs @@ -6,25 +6,30 @@ use axum::{middleware, routing::{get, post}, Router}; use crate::{state::AppState, auth}; pub fn router(app_state: AppState) -> Router { - Router::new() - // Public routes (no auth required) + // Public routes (no auth required) + let public_routes = Router::new() .route("/api/health", get(handlers::health_handler)) .route("/api/auth/register", post(auth::handlers::register_handler)) - .route("/api/auth/login", post(auth::handlers::login_handler)) - - // Protected routes (auth required) + .route("/api/auth/login", post(auth::handlers::login_handler)); + + // Protected routes (auth required) + let protected_routes = Router::new() .route("/api/auth/me", get(auth::handlers::me_handler)) - .route("/api/consent/:bank/:user_id", + .route("/api/consent/{bank}/{user_id}", post(handlers::create_consent_handler) .get(handlers::get_consent_handler) ) - .route("/api/accounts/:bank/:user_id", + .route("/api/accounts/{bank}/{user_id}", get(handlers::get_accounts_handler) ) - .route("/api/transactions/:bank/:user_id/:account_id", + .route("/api/transactions/{bank}/{user_id}/{account_id}", get(handlers::get_transactions_handler) ) - .layer(middleware::from_fn(auth::auth_middleware)) - + .layer(middleware::from_fn(auth::auth_middleware)); + + // Merge both + public_routes + .merge(protected_routes) .with_state(app_state) } + diff --git a/src/route/handlers.rs b/src/route/handlers.rs index a509358..90634b3 100644 --- a/src/route/handlers.rs +++ b/src/route/handlers.rs @@ -55,8 +55,10 @@ pub async fn create_consent_handler( let client = state.banking_clients.get_client(bank); - let consent_response = client.request_consent(&user_id).await - .map_err(|e| map_banking_error(e))?; + let consent_response = client + .request_consent(&user_id) + .await + .map_err(map_banking_error)?; db::consents::store_consent( &state.db_pool,