(fix) user_id now retrieving from JWT not from URL
This commit is contained in:
parent
80ed37647b
commit
4d0ad0226f
3 changed files with 86 additions and 78 deletions
27
src/route.rs
27
src/route.rs
|
|
@ -1,10 +1,16 @@
|
||||||
// src/route.rs
|
// src/route.rs
|
||||||
|
// CORRECT VERSION - keeps your protected_routes pattern
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
middleware,
|
||||||
|
routing::{get, post},
|
||||||
|
Router,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{auth, state::AppState};
|
||||||
|
|
||||||
pub mod handlers;
|
pub mod handlers;
|
||||||
|
|
||||||
use axum::{middleware, routing::{get, post}, Router};
|
|
||||||
use crate::{state::AppState, auth};
|
|
||||||
|
|
||||||
pub fn router(app_state: AppState) -> Router {
|
pub fn router(app_state: AppState) -> Router {
|
||||||
// Public routes (no auth required)
|
// Public routes (no auth required)
|
||||||
let public_routes = Router::new()
|
let public_routes = Router::new()
|
||||||
|
|
@ -12,31 +18,30 @@ pub fn router(app_state: AppState) -> Router {
|
||||||
.route("/api/auth/register", post(auth::handlers::register_handler))
|
.route("/api/auth/register", post(auth::handlers::register_handler))
|
||||||
.route("/api/auth/login", post(auth::handlers::login_handler));
|
.route("/api/auth/login", post(auth::handlers::login_handler));
|
||||||
|
|
||||||
// Protected routes (auth required)
|
// Protected routes (auth required) - user_id extracted from JWT in handlers
|
||||||
let protected_routes = Router::new()
|
let protected_routes = Router::new()
|
||||||
.route("/api/auth/me", get(auth::handlers::me_handler))
|
.route("/api/auth/me", get(auth::handlers::me_handler))
|
||||||
.route("/api/consent/{bank}/{user_id}",
|
.route("/api/consent/{bank}", // ← Removed {user_id} - get from JWT!
|
||||||
post(handlers::create_consent_handler)
|
post(handlers::create_consent_handler)
|
||||||
.get(handlers::get_consent_handler)
|
.get(handlers::get_consent_handler)
|
||||||
.delete(handlers::delete_consent_handler)
|
.delete(handlers::delete_consent_handler)
|
||||||
)
|
)
|
||||||
.route("/api/accounts/{bank}/{user_id}",
|
.route("/api/accounts/{bank}", // ← Removed {user_id} - get from JWT!
|
||||||
get(handlers::get_accounts_handler)
|
get(handlers::get_accounts_handler)
|
||||||
)
|
)
|
||||||
.route("/api/transactions/{bank}/{user_id}/{account_id}",
|
.route("/api/transactions/{bank}/{account_id}", // ← Removed {user_id}
|
||||||
get(handlers::get_transactions_handler)
|
get(handlers::get_transactions_handler)
|
||||||
)
|
)
|
||||||
.route("/api/transactions/{bank_user_id}",
|
.route("/api/transactions", // ← Get all transactions (user from JWT)
|
||||||
get(handlers::get_all_transactions_handler) // ← Новый эндпоинт
|
get(handlers::get_all_transactions_handler)
|
||||||
)
|
)
|
||||||
.route("/api/balances/{bank}/{account_id}",
|
.route("/api/balances/{bank}/{account_id}",
|
||||||
get(handlers::get_balances_handler)
|
get(handlers::get_balances_handler)
|
||||||
)
|
)
|
||||||
.layer(middleware::from_fn(auth::auth_middleware));
|
.layer(middleware::from_fn(auth::auth_middleware)); // ← Your existing middleware
|
||||||
|
|
||||||
// Merge both
|
// Merge both
|
||||||
public_routes
|
public_routes
|
||||||
.merge(protected_routes)
|
.merge(protected_routes)
|
||||||
.with_state(app_state)
|
.with_state(app_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,9 @@ use crate::{
|
||||||
db,
|
db,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::auth::jwt::Claims;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
use axum::Extension;
|
||||||
|
|
||||||
// --- Health Check ---
|
// --- Health Check ---
|
||||||
|
|
||||||
|
|
@ -48,29 +50,33 @@ struct ConsentCreatedResponse {
|
||||||
|
|
||||||
pub async fn create_consent_handler(
|
pub async fn create_consent_handler(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
Path((bank_code, user_id)): Path<(String, String)>,
|
Path(bank_code): Path<String>, // ← Only bank_code now
|
||||||
|
Extension(claims): Extension<Claims>, // ← Get user_id from JWT!
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
|
let user_id = &claims.bank_user_id; // ← Extract from JWT
|
||||||
|
|
||||||
let bank = bank_code.parse::<Bank>()
|
let bank = bank_code.parse::<Bank>()
|
||||||
.map_err(|_| (StatusCode::BAD_REQUEST, Json(json!({
|
.map_err(|_| (StatusCode::BAD_REQUEST, Json(json!({
|
||||||
"error": "Invalid bank code. Use: vbank, abank, or sbank"
|
"error": "Invalid bank code. Use: vbank, abank, or sbank"
|
||||||
}))))?;
|
}))))?;
|
||||||
|
|
||||||
|
// Rest stays the same - just use `user_id` variable
|
||||||
let client = state.banking_clients.get_client(bank);
|
let client = state.banking_clients.get_client(bank);
|
||||||
|
|
||||||
let consent_response = client
|
let consent_response = client
|
||||||
.request_consent(&user_id)
|
.request_consent(user_id) // ← Use extracted user_id
|
||||||
.await
|
.await
|
||||||
.map_err(map_banking_error)?;
|
.map_err(map_banking_error)?;
|
||||||
|
|
||||||
let expires_at = chrono::DateTime::parse_from_rfc3339(&consent_response.created_at)
|
let expires_at = chrono::DateTime::parse_from_rfc3339(&consent_response.created_at)
|
||||||
.ok()
|
.ok()
|
||||||
.map(|dt| dt.with_timezone(&chrono::Utc))
|
.map(|dt| dt.with_timezone(&chrono::Utc))
|
||||||
.unwrap_or_else(|| chrono::Utc::now()) // fallback to now if parse fails
|
.unwrap_or_else(|| chrono::Utc::now())
|
||||||
+ chrono::Duration::days(365);
|
+ chrono::Duration::days(365);
|
||||||
|
|
||||||
db::consents::store_consent(
|
db::consents::store_consent(
|
||||||
&state.db_pool,
|
&state.db_pool,
|
||||||
&user_id,
|
user_id, // ← Use extracted user_id
|
||||||
bank.code(),
|
bank.code(),
|
||||||
&consent_response.consent_id,
|
&consent_response.consent_id,
|
||||||
expires_at,
|
expires_at,
|
||||||
|
|
@ -94,14 +100,17 @@ pub async fn create_consent_handler(
|
||||||
|
|
||||||
pub async fn get_consent_handler(
|
pub async fn get_consent_handler(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
Path((bank_code, user_id)): Path<(String, String)>,
|
Path(bank_code): Path<String>, // ← Only bank_code now
|
||||||
|
Extension(claims): Extension<Claims>, // ← Get user_id from JWT!
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
|
let user_id = &claims.bank_user_id; // ← Extract from JWT
|
||||||
|
|
||||||
let bank = bank_code.parse::<Bank>()
|
let bank = bank_code.parse::<Bank>()
|
||||||
.map_err(|_| (StatusCode::BAD_REQUEST, Json(json!({
|
.map_err(|_| (StatusCode::BAD_REQUEST, Json(json!({
|
||||||
"error": "Invalid bank code"
|
"error": "Invalid bank code"
|
||||||
}))))?;
|
}))))?;
|
||||||
|
|
||||||
db::consents::get_valid_consent(&state.db_pool, &user_id, bank.code())
|
db::consents::get_valid_consent(&state.db_pool, user_id, bank.code())
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (
|
.map_err(|e| (
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
|
@ -121,12 +130,15 @@ pub async fn get_consent_handler(
|
||||||
|
|
||||||
pub async fn get_accounts_handler(
|
pub async fn get_accounts_handler(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
Path((bank_code, user_id)): Path<(String, String)>,
|
Path(bank_code): Path<String>, // ← Only bank_code now
|
||||||
|
Extension(claims): Extension<Claims>, // ← Get user_id from JWT!
|
||||||
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
|
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
|
||||||
|
let user_id = &claims.bank_user_id; // ← Extract from JWT
|
||||||
|
|
||||||
let bank = bank_code.parse::<Bank>()
|
let bank = bank_code.parse::<Bank>()
|
||||||
.map_err(|_| (StatusCode::BAD_REQUEST, Json(json!({ "error": "Invalid bank code" }))))?;
|
.map_err(|_| (StatusCode::BAD_REQUEST, Json(json!({ "error": "Invalid bank code" }))))?;
|
||||||
|
|
||||||
let consent_id = db::consents::get_valid_consent(&state.db_pool, &user_id, bank.code())
|
let consent_id = db::consents::get_valid_consent(&state.db_pool, user_id, bank.code())
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({ "error": e.to_string() }))))?
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({ "error": e.to_string() }))))?
|
||||||
.ok_or_else(|| (
|
.ok_or_else(|| (
|
||||||
|
|
@ -136,16 +148,16 @@ pub async fn get_accounts_handler(
|
||||||
|
|
||||||
let client = state.banking_clients.get_client(bank);
|
let client = state.banking_clients.get_client(bank);
|
||||||
|
|
||||||
let accounts_response = client.get_accounts(&user_id, &consent_id)
|
let accounts_response = client.get_accounts(user_id, &consent_id)
|
||||||
.await
|
.await
|
||||||
.map_err(map_banking_error)?;
|
.map_err(map_banking_error)?;
|
||||||
|
|
||||||
// ✨ NEW: Save accounts to database
|
// ✨ Save accounts to database
|
||||||
for account in &accounts_response.data.account {
|
for account in &accounts_response.data.account {
|
||||||
let _ = db::accounts::store_account(
|
let _ = db::accounts::store_account(
|
||||||
&state.db_pool,
|
&state.db_pool,
|
||||||
&account.account_id,
|
&account.account_id,
|
||||||
&user_id,
|
user_id, // ← Use extracted user_id
|
||||||
bank.code(),
|
bank.code(),
|
||||||
account.status.as_deref().unwrap_or("unknown"),
|
account.status.as_deref().unwrap_or("unknown"),
|
||||||
&account.currency,
|
&account.currency,
|
||||||
|
|
@ -171,13 +183,16 @@ pub struct TransactionQuery {
|
||||||
|
|
||||||
pub async fn get_transactions_handler(
|
pub async fn get_transactions_handler(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
Path((bank_code, user_id, account_id)): Path<(String, String, String)>,
|
Path((bank_code, account_id)): Path<(String, String)>, // ← Changed: no user_id
|
||||||
Query(params): Query<TransactionQuery>,
|
Query(params): Query<TransactionQuery>,
|
||||||
|
Extension(claims): Extension<Claims>, // ← Get user_id from JWT!
|
||||||
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
|
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
|
||||||
|
let user_id = &claims.bank_user_id; // ← Extract from JWT
|
||||||
|
|
||||||
let bank = bank_code.parse::<Bank>()
|
let bank = bank_code.parse::<Bank>()
|
||||||
.map_err(|_| (StatusCode::BAD_REQUEST, Json(json!({ "error": "Invalid bank code" }))))?;
|
.map_err(|_| (StatusCode::BAD_REQUEST, Json(json!({ "error": "Invalid bank code" }))))?;
|
||||||
|
|
||||||
let consent_id = db::consents::get_valid_consent(&state.db_pool, &user_id, bank.code())
|
let consent_id = db::consents::get_valid_consent(&state.db_pool, user_id, bank.code())
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({ "error": e.to_string() }))))?
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({ "error": e.to_string() }))))?
|
||||||
.ok_or_else(|| (
|
.ok_or_else(|| (
|
||||||
|
|
@ -191,7 +206,7 @@ pub async fn get_transactions_handler(
|
||||||
.await
|
.await
|
||||||
.map_err(map_banking_error)?;
|
.map_err(map_banking_error)?;
|
||||||
|
|
||||||
// ✨ NEW: Save all transactions to cache
|
// ✨ Save all transactions to cache
|
||||||
for tx in &transactions_response.data.transaction {
|
for tx in &transactions_response.data.transaction {
|
||||||
let _ = db::transactions::store_transaction(
|
let _ = db::transactions::store_transaction(
|
||||||
&state.db_pool,
|
&state.db_pool,
|
||||||
|
|
@ -202,8 +217,8 @@ pub async fn get_transactions_handler(
|
||||||
&tx.amount.currency,
|
&tx.amount.currency,
|
||||||
&tx.credit_debit_indicator,
|
&tx.credit_debit_indicator,
|
||||||
&tx.status,
|
&tx.status,
|
||||||
tx.booking_date_time, // Already DateTime<Utc>
|
tx.booking_date_time,
|
||||||
tx.value_date_time, // Already Option<DateTime<Utc>>
|
tx.value_date_time,
|
||||||
&tx.transaction_information,
|
&tx.transaction_information,
|
||||||
tx.bank_transaction_code.as_ref().map(|b| b.code.as_str()),
|
tx.bank_transaction_code.as_ref().map(|b| b.code.as_str()),
|
||||||
).await;
|
).await;
|
||||||
|
|
@ -214,9 +229,10 @@ pub async fn get_transactions_handler(
|
||||||
|
|
||||||
pub async fn get_all_transactions_handler(
|
pub async fn get_all_transactions_handler(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
Path(bank_user_id): Path<String>,
|
Query(params): Query<TransactionQuery>,
|
||||||
Query(params): Query<TransactionQuery>, // ← Добавили query params
|
Extension(claims): Extension<Claims>, // ← Add this
|
||||||
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
|
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
|
||||||
|
let bank_user_id = &claims.bank_user_id;
|
||||||
let page = params.page.unwrap_or(1);
|
let page = params.page.unwrap_or(1);
|
||||||
let limit = params.limit.unwrap_or(20); // Default: 20 на странице для ленты
|
let limit = params.limit.unwrap_or(20); // Default: 20 на странице для ленты
|
||||||
|
|
||||||
|
|
@ -300,12 +316,15 @@ pub async fn get_all_transactions_handler(
|
||||||
|
|
||||||
pub async fn delete_consent_handler(
|
pub async fn delete_consent_handler(
|
||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
Path((bank_code, user_id)): Path<(String, String)>,
|
Path(bank_code): Path<String>, // ← Only bank_code now
|
||||||
|
Extension(claims): Extension<Claims>, // ← Get user_id from JWT!
|
||||||
) -> impl IntoResponse {
|
) -> impl IntoResponse {
|
||||||
|
let user_id = &claims.bank_user_id; // ← Extract from JWT
|
||||||
|
|
||||||
let bank = bank_code.parse::<Bank>()
|
let bank = bank_code.parse::<Bank>()
|
||||||
.map_err(|_| (StatusCode::BAD_REQUEST, Json(json!({ "error": "Invalid bank code" }))))?;
|
.map_err(|_| (StatusCode::BAD_REQUEST, Json(json!({ "error": "Invalid bank code" }))))?;
|
||||||
|
|
||||||
let consent_id = db::consents::get_valid_consent(&state.db_pool, &user_id, bank.code())
|
let consent_id = db::consents::get_valid_consent(&state.db_pool, user_id, bank.code())
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({ "error": e.to_string() }))))?
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({ "error": e.to_string() }))))?
|
||||||
.ok_or_else(|| (StatusCode::NOT_FOUND, Json(json!({ "error": "Consent not found" }))))?;
|
.ok_or_else(|| (StatusCode::NOT_FOUND, Json(json!({ "error": "Consent not found" }))))?;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Save as test_multiberry.sh
|
# Save as test_multiberry_secure.sh
|
||||||
# Extended comprehensive test with DB verification
|
# Tests secure API - user_id extracted from JWT token automatically
|
||||||
|
|
||||||
BASE_URL="http://localhost:3000/api"
|
BASE_URL="http://localhost:3000/api"
|
||||||
|
|
||||||
|
|
@ -9,7 +9,7 @@ echo "1️⃣ REGISTER USER"
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
REGISTER=$(curl -s -X POST $BASE_URL/auth/register \
|
REGISTER=$(curl -s -X POST $BASE_URL/auth/register \
|
||||||
-H 'Content-Type: application/json' \
|
-H 'Content-Type: application/json' \
|
||||||
-d '{"bank_user_number": 1, "password": "testpass123"}')
|
-d '{"bank_user_number": 2, "password": "testpass123"}')
|
||||||
|
|
||||||
echo "$REGISTER" | jq .
|
echo "$REGISTER" | jq .
|
||||||
TOKEN=$(echo "$REGISTER" | jq -r '.token')
|
TOKEN=$(echo "$REGISTER" | jq -r '.token')
|
||||||
|
|
@ -30,14 +30,14 @@ echo ""
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo "3️⃣ GET ME (verify auth middleware)"
|
echo "3️⃣ GET ME (verify auth middleware)"
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
curl -s http://localhost:3000/api/auth/me \
|
curl -s $BASE_URL/auth/me \
|
||||||
-H "Authorization: Bearer $TOKEN" | jq .
|
-H "Authorization: Bearer $TOKEN" | jq .
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo "4️⃣ REQUEST CONSENT from VBank"
|
echo "4️⃣ REQUEST CONSENT from VBank (user from JWT)"
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
CONSENT=$(curl -s -X POST $BASE_URL/consent/vbank/$BANK_USER_ID \
|
CONSENT=$(curl -s -X POST $BASE_URL/consent/vbank \
|
||||||
-H "Authorization: Bearer $TOKEN")
|
-H "Authorization: Bearer $TOKEN")
|
||||||
|
|
||||||
echo "$CONSENT" | jq .
|
echo "$CONSENT" | jq .
|
||||||
|
|
@ -46,9 +46,9 @@ echo "✅ Consent ID: $CONSENT_ID"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo "5️⃣ GET ACCOUNTS (auto-saved to DB)"
|
echo "5️⃣ GET ACCOUNTS (user from JWT, auto-saved to DB)"
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
ACCOUNTS=$(curl -s $BASE_URL/accounts/vbank/$BANK_USER_ID \
|
ACCOUNTS=$(curl -s $BASE_URL/accounts/vbank \
|
||||||
-H "Authorization: Bearer $TOKEN")
|
-H "Authorization: Bearer $TOKEN")
|
||||||
|
|
||||||
echo "$ACCOUNTS" | jq .
|
echo "$ACCOUNTS" | jq .
|
||||||
|
|
@ -68,9 +68,9 @@ echo "✅ Current Balance: $BALANCE_AMOUNT RUB"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo "7️⃣ GET TRANSACTIONS (page 1, limit 6 - auto-saved)"
|
echo "7️⃣ GET TRANSACTIONS (user from JWT, page 1, limit 6)"
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
TRANS_PAGE1=$(curl -s "$BASE_URL/transactions/vbank/$BANK_USER_ID/$ACCOUNT_ID?page=1&limit=6" \
|
TRANS_PAGE1=$(curl -s "$BASE_URL/transactions/vbank/$ACCOUNT_ID?page=1&limit=6" \
|
||||||
-H "Authorization: Bearer $TOKEN")
|
-H "Authorization: Bearer $TOKEN")
|
||||||
|
|
||||||
echo "$TRANS_PAGE1" | jq .
|
echo "$TRANS_PAGE1" | jq .
|
||||||
|
|
@ -81,54 +81,38 @@ echo ""
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo "8️⃣ GET TRANSACTIONS (page 2, limit 6)"
|
echo "8️⃣ GET TRANSACTIONS (page 2, limit 6)"
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
curl -s "$BASE_URL/transactions/vbank/$BANK_USER_ID/$ACCOUNT_ID?page=2&limit=6" \
|
curl -s "$BASE_URL/transactions/vbank/$ACCOUNT_ID?page=2&limit=6" \
|
||||||
-H "Authorization: Bearer $TOKEN" | jq .
|
-H "Authorization: Bearer $TOKEN" | jq .
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo "9️⃣ DELETE CONSENT"
|
echo "9️⃣ GET ALL TRANSACTIONS (unified view from all banks)"
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
curl -s -X DELETE $BASE_URL/consent/vbank/$BANK_USER_ID \
|
curl -s "$BASE_URL/transactions?page=1&limit=10" \
|
||||||
-H "Authorization: Bearer $TOKEN" | jq .
|
-H "Authorization: Bearer $TOKEN" | jq .
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo "🔟 VERIFY DATABASE CACHE"
|
echo "🔟 DELETE CONSENT (user from JWT)"
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo ""
|
curl -s -X DELETE $BASE_URL/consent/vbank \
|
||||||
echo "Run in another terminal:"
|
-H "Authorization: Bearer $TOKEN" | jq .
|
||||||
echo "just psql-exec"
|
|
||||||
echo ""
|
|
||||||
echo "Then execute these queries:"
|
|
||||||
echo ""
|
|
||||||
echo "-- Check users registered:"
|
|
||||||
echo "SELECT bank_user_id, created_at FROM users ORDER BY created_at DESC LIMIT 5;"
|
|
||||||
echo ""
|
|
||||||
echo "-- Check consents granted:"
|
|
||||||
echo "SELECT user_id, bank_code, consent_id, status, expires_at FROM user_consents;"
|
|
||||||
echo ""
|
|
||||||
echo "-- Check accounts cached:"
|
|
||||||
echo "SELECT account_id, user_id, bank_code, nickname, currency FROM accounts;"
|
|
||||||
echo ""
|
|
||||||
echo "-- Check balances cached:"
|
|
||||||
echo "SELECT account_id, balance_type, amount, currency, date_time FROM balances;"
|
|
||||||
echo ""
|
|
||||||
echo "-- Check transactions cached (show count by account):"
|
|
||||||
echo "SELECT account_id, COUNT(*) as tx_count, MIN(booking_date_time) as oldest, MAX(booking_date_time) as newest FROM transactions GROUP BY account_id;"
|
|
||||||
echo ""
|
|
||||||
echo "-- Show recent transactions:"
|
|
||||||
echo "SELECT transaction_id, account_id, amount, currency, credit_debit_indicator, transaction_information, booking_date_time FROM transactions ORDER BY booking_date_time DESC LIMIT 10;"
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo "✅ FULL TEST COMPLETE!"
|
echo "✅ FULL SECURE TEST COMPLETE!"
|
||||||
echo "=========================================="
|
echo "=========================================="
|
||||||
echo ""
|
echo ""
|
||||||
echo "Summary:"
|
echo "🔒 Security Benefits:"
|
||||||
echo "✅ Authentication (register/login/auth middleware)"
|
echo " ✅ User cannot manipulate user_id in URL"
|
||||||
echo "✅ Consent Management (request consent)"
|
echo " ✅ All user identification comes from JWT"
|
||||||
echo "✅ Account Aggregation (fetch & cache accounts)"
|
echo " ✅ Frontend only needs to send token"
|
||||||
echo "✅ Balance Retrieval (fetch & cache balances)"
|
echo " ✅ Backend automatically knows WHO is making request"
|
||||||
echo "✅ Transaction History (fetch & cache transactions)"
|
|
||||||
echo "✅ Data Persistence (all cached in PostgreSQL)"
|
|
||||||
echo ""
|
echo ""
|
||||||
|
echo "📊 Data Aggregation:"
|
||||||
|
echo " ✅ Accounts cached from bank"
|
||||||
|
echo " ✅ Balances cached"
|
||||||
|
echo " ✅ Transactions cached"
|
||||||
|
echo " ✅ Multi-bank support ready"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue