Skip to content

paulnyaga1/banking_app

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

35 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Top Summary

Backend Architecture

  1. Technology Stack:

    • FastAPI (Python web framework)
    • PostgreSQL database
    • JWT authentication
    • Python 3.12
  2. Database Schema:

    • users table: Stores user accounts with username, password hash, and balance
    • transactions table: Records all monetary operations (deposits, withdrawals, transfers)
  3. API Endpoints:

    • /api/login: Authentication endpoint
    • /api/balance: Get user's current balance
    • /api/transactions: Get transaction history
    • /api/transfer: Transfer funds between users

Frontend Architecture

The application provides two different frontend implementations:

  1. SPA (Single Page Application):

    • Built with React + Vite + Material UI
    • Served at http://localhost:8000/spa
    • Uses JWT tokens for authentication
    • Client-side routing with React Router
  2. SSR (Server-Side Rendered):

    • Built with Jinja2 templates + HTMX
    • Served at http://localhost:8000/ssr
    • Uses server-side sessions (cookie-based)
    • Better for SEO and works without JavaScript

Deployment & Monitoring

The application includes a complete monitoring stack:

  • Prometheus for metrics
  • Grafana for dashboards
  • OpenTelemetry for tracing
  • Tempo for distributed tracing
  • All orchestrated with Docker Compose

Development Setup

  1. Backend Setup:

    • Create Python virtual environment
    • Set up PostgreSQL database
    • Install dependencies from requirements.txt
    • Run with uvicorn main:app --reload
  2. Frontend Setup:

    • Navigate to frontend directory
    • Install dependencies with npm install
    • Run development server with npm run dev

Testing

  • Automated tests can be run with pytest
  • Code quality tools:
    • Backend: ruff check --fix and ruff format
    • Frontend: ESLint and Prettier

Security Features

  • Password hashing with bcrypt
  • JWT-based authentication for API
  • Session-based authentication for SSR
  • Protected routes and endpoints
  • Input validation with Pydantic

This is a well-structured application that demonstrates modern web development practices, including:

  • Multiple frontend approaches (SPA and SSR)
  • Comprehensive monitoring
  • Security best practices
  • Clean code organization
  • Automated testing
  • Docker-based deployment

Would you like me to elaborate on any particular aspect of the application?

banking_app backend

Setup, manual and automated tests of the backend only (banking_app/backend directory is root):

  1. put .env file to the root directory

  2. python venv creation (python3.12 used): python3 -m venv venv source venv/bin/activate pip install -r requirements.txt pip install --upgrade pip

  3. create the db: psql postgres CREATE USER bankadmin WITH PASSWORD 'password'; CREATE DATABASE bankapp OWNER bankadmin; GRANT ALL PRIVILEGES ON DATABASE bankapp TO bankadmin;

  4. create schema from schema.sql: psql -U bankadmin -d bankapp -f schema.sql

  5. create test user: use utils/get_password_hash.py to generate a password hash for "test_user" with "password_test_user"

psql -U bankadmin -d bankapp

INSERT INTO users (username, password_hash, balance) VALUES ('test_user', '$2b$12$ermJY38l7dGmYBuUcJ3/qutW6NouRvjOR2GmZU5HABh6s6JxPevBm', 1000.00);

  1. run the app from backend dir: uvicorn main:app --reload

  2. test /api/login endpoint through Swagger UI: Request body: { "username": "test_user", "password": "password_test_user" } Response example: { "access_token": "xyz", "token_type": "bearer" }

7-8. go to Authorize and input the token. Then use TryItOut/Execute for /api/balance and /api/transactions endpoints.

  1. test api/transfer endpoint: create test user 2: use utils/get_password_hash.py to generate a password hash for "test_user2" with "password_test_user2"

INSERT INTO users (username, password_hash, balance) VALUES ('test_user2', '$2b$12$ff0HQcrKzv7rxhX.n4gXue7OoSZ15pTAJr5HGIFuGX94bq3TiBFly', 1000.00);

open in 2 browsers and try to transfer money between 2 users

  1. run automated tests through "PYTHONPATH=. pytest tests/"

  2. in case any code modifications are done, use "ruff check --fix" and "ruff format".

πŸ“˜ Schema and API Design Rationale for apis

πŸ—ƒοΈ Database Schema

PostgreSQL schema is designed to reflect a simplified banking system while remaining extensible and normalized:

Tables

  • users

    • Stores registered users.
    • Fields: id, username (unique), password_hash, balance, is_active, created_at
    • balance is stored here for fast access, though all changes are also recorded in transactions.
  • transactions

    • Represents all monetary operations: deposits, withdrawals, transfers.
    • Fields: id, user_id, amount, type (deposit, withdrawal, transfer_in, transfer_out), created_at
    • All transactions are immutable and auditable.
  • Why no separate accounts table?

    • Each user has one account by default for simplicity. Extending to multiple accounts per user would require another table and minor refactoring.

🧩 API Design

Authentication

  • Uses JWT tokens for sessionless, stateless security.
  • Login issues a token with limited expiry.
  • Protected endpoints require an Authorization: Bearer <token> header.

Core Endpoints

  • POST /api/login

    • Accepts username/password, returns JWT.
  • GET /api/balance

    • Returns current user balance from users table.
  • GET /api/transactions?page&limit

    • Returns paginated transaction history from transactions.
  • POST /api/transfer

    • Transfers funds from the authenticated user to another registered user.
    • Performs balance checks and records both transfer_out and transfer_in transactions atomically.

Validation and Error Handling

  • Uses Pydantic schemas to validate requests/responses.
  • Returns appropriate HTTP status codes:
    • 401 Unauthorized for invalid tokens
    • 422 Unprocessable Entity for validation errors
    • 400 Bad Request or 403 Forbidden for business logic errors (e.g. insufficient funds)

βš™οΈ Design Principles

  • Simplicity first: easy to reason about, modify, and extend.
  • Transactional integrity: all operations that mutate data are wrapped in database transactions using SQLAlchemy's session (db.commit()/db.rollback()) to ensure consistency.
  • Security: hashed passwords with bcrypt, JWT auth, limited error leakage.
  • Extensibility: clean separation of models, routes, and schemas allows for adding features like admin views, currency support, or multi-account management.

🌐 SSR vs SPA Differences

This project provides two separate frontends to the same backend API:

  • A Single-Page Application (SPA) built with React + Vite + Material UI
  • A Server-Side Rendered (SSR) frontend built with Jinja2 templates + HTMX

Both versions maintain feature parity across login, dashboard, transaction history, and fund transfer.

πŸ“¦ SPA (React)

  • Served under: http://localhost:8000/spa
  • Built with React Router, BrowserRouter basename="/spa"
  • Authentication via JWT tokens, stored in-memory (React context)
  • Communicates with /api/* endpoints via Axios
  • Token is required in the Authorization header for all protected API calls
  • Built with Material UI

πŸ–₯️ SSR (HTMX + Jinja2)

  • Served under: http://localhost:8000/ssr
  • Uses Jinja2 templates rendered by FastAPI for each page
  • Authentication uses server-side sessions (cookie-based)
  • Uses HTMX for partial updates (e.g., refresh balance, transactions)
  • All routing and rendering are handled on the server
  • Safer for environments where JavaScript may be restricted or disabled

🧠 Key Differences

Feature SPA (React) SSR (HTMX)
Routing Client-side (React Router) Server-side (FastAPI routes)
Auth Storage JWT (in React context) Session cookie
Communication Axios to /api/* HTML forms + HTMX calls to /ssr/*
Performance Fast UX once loaded Faster first page load
SEO-Friendly ❌ (unless prerendered) βœ… Yes
JS Dependency Required Minimal (HTMX only)
State Management React useState / Context Session + database
Best Use Modern apps, dashboards Progressive enhancement, basic devices

πŸ§ͺ SPA and SSR Setup & Manual Test Guide

This project supports both a React-based SPA and an SSR (server-side rendered) HTMX frontend. Both access the same API backend.


βœ… SPA (React + Vite + Material UI)

πŸ”§ Setup

  1. Navigate to the frontend/ directory:

    cd frontend
  2. Install dependencies:

    npm install
  3. Run development server:

    npm run dev

    Then open: http://localhost:5173

  4. Or to build for production:

    npm run build

    The output will be in frontend/dist/


πŸ”¬ Manual Testing (via http://localhost:8000/spa)

  • βœ… /spa/login: Login with test_user / password_test_user
  • βœ… /spa/balance: Check balance
  • βœ… /spa/transactions: See transaction history
  • βœ… /spa/transfer: Transfer funds to another user
  • ❌ Invalid login β†’ shows toast error
  • βœ… Logout β†’ returns to login page
  • πŸ” Refresh /spa/* pages β†’ should not 404
  • πŸ” Token-based authentication in memory

βœ… SSR (HTMX + Jinja2 Templates)

πŸ”§ Setup

  1. No separate build is needed β€” served directly via FastAPI

  2. Start backend:

    cd backend
    uvicorn main:app --reload
  3. Open in browser:
    http://localhost:8000/ssr/login


πŸ”¬ Manual Testing (via /ssr/* routes)

  • βœ… /ssr/login: Login with valid credentials
  • ❌ Invalid login β†’ shows inline error
  • βœ… /ssr/balance: Displays server-rendered balance
  • βœ… /ssr/transactions: Lists recent transactions
  • βœ… /ssr/transfer: Transfer funds with form
  • ❌ Transfer to self or invalid β†’ shows error inline
  • βœ… Session-based auth using cookies
  • βœ… Logout β†’ redirects to /ssr/login

πŸ” Auth Isolation

  • βœ… Logging in via SSR does not affect SPA
  • βœ… SPA uses JWT in headers; SSR uses cookies and sessions

πŸ§ͺ Automated Testing (API Only)

  1. Run backend in dev mode:

    cd backend
    uvicorn main:app --reload
  2. Run test suite from root:

    PYTHONPATH=. pytest tests/

🧹 Code Quality

For frontend (SPA):

cd frontend
npm run lint       # check
npm run format     # check format
npm run format:fix # fix formatting

For backend (SSR + API):

cd backend
ruff check --fix
ruff format

Deployment & Monitoring Setup Guide

Prerequisites

  • Docker & Docker Compose
  • .env files for backend and frontend
  • Node.js (for local frontend development, optional)

Deployment

The stack is orchestrated with docker-compose. It includes:

  • PostgreSQL for database
  • FastAPI backend (/backend)
  • Frontend served with npm run preview
  • Prometheus for metrics scraping
  • Grafana for dashboarding
  • OpenTelemetry Collector for ingest/export
  • Tempo for distributed tracing

Steps

  1. Build and launch all services:

    docker compose up --build
  2. Service Ports:


Monitoring Setup

1. OpenTelemetry Collector

Configured in monitoring/otel-collector-config.yaml:

  • Receives metrics & traces via OTLP (HTTP/gRPC)
  • Exports:
    • Metrics to Prometheus on port 8889
    • Traces to Tempo on port 4317

2. Prometheus

Configuration file: monitoring/prometheus.yml

  • Scrapes:
    • Itself at localhost:9090
    • OpenTelemetry Collector at otel-collector:8889

3. Tempo (Tracing)

Tempo is configured to receive OTLP traces over gRPC and HTTP.

Configuration file: monitoring/tempo.yaml

  • Trace storage is local: /tmp/tempo/traces

4. Grafana

Provisioned with:

  • Data Sources (monitoring/grafana/provisioning/datasources.yml)
    • Prometheus
    • Tempo
  • Dashboards (monitoring/grafana/provisioning/dashbooards.yaml)
    • Includes dashboard from app-metrics-dashboard.json

Default login: admin / admin

5. Metrics in FastAPI

main.py includes:

  • opentelemetry setup with OTLPMetricExporter and OTLPSpanExporter
  • Tracing and metrics collection with FastAPI & requests instrumentation
  • Middleware to count HTTP requests

Metrics collected:

  • HTTP request count
  • Traces with span context

Notes

  • Dashboard is auto-refreshed every 10s (app-metrics-dashboard.json)
  • To reset Grafana or Prometheus, delete volumes: postgres_data, grafana_data
  • Logs and traces are available in Docker logs or Grafana Explore tab

Banking App – Frontend

This is the frontend of a simple banking application built with:


πŸš€ Quick Start

1. Clone the repo and install dependencies

cd frontend
npm install

2. Run the development server

npm run dev

This starts Vite on http://localhost:5173 (default).


πŸ§ͺ Linting and Formatting

Run ESLint (code style check)

npm run lint

Auto-format with Prettier

npm run format

πŸ› οΈ Project Structure (simplified)

frontend/
β”œβ”€β”€ public/                # Static assets
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ pages/             # Page components (Login, Balance, etc.)
β”‚   β”œβ”€β”€ context/           # Auth context (with useAuth hook)
β”‚   β”œβ”€β”€ services/axios.js  # Axios instance
β”‚   β”œβ”€β”€ utils/             # Shared utilities (e.g. handleApiError)
β”‚   └── main.jsx           # App entry point
β”œβ”€β”€ .eslintrc.cjs          # ESLint config
β”œβ”€β”€ .prettierrc            # Prettier config
β”œβ”€β”€ vite.config.js         # Vite config
└── package.json

βœ… Features

  • Secure login with token auth
  • Protected routes
  • Styled with Material UI
  • Toast-based error/success handling
  • Lint + format setup for clean code

πŸ“¦ Build for Production

npm run build

Outputs a static site to the dist/ folder.


🧹 Reset (optional)

To wipe dependencies and rebuild:

rm -rf node_modules dist package-lock.json
npm install

About

No description, website, or topics provided.

Resources

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors