// src/api/consents.rs // 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?; 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(), "ReadBalances".to_string(), "ReadTransactionsDetail".to_string(), ], reason: "Account aggregation for Multiberry app".to_string(), requesting_bank: self.client_id.clone(), requesting_bank_name: "Multiberry Backend".to_string(), } } 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 }) } pub async fn delete_consent(&self, consent_id: &str) -> Result<(), BankingError> { info!("🗑️ Deleting consent: {}", consent_id); let token = self.get_token().await?; let response = self.http_client .delete(self.base_url.join(&format!("/account-consents/{}", consent_id))?) .bearer_auth(token) .header("x-fapi-interaction-id", format!("team275-{}", chrono::Utc::now().timestamp())) .send() .await?; match response.status().as_u16() { 204 => { info!("✅ Consent deleted successfully"); Ok(()) }, status => { error!("❌ Failed to delete consent: {}", status); Err(BankingError::ApiError { status, body: response.text().await.unwrap_or_default(), }) } } } }