Skip to content

ambakhtiar/BloodHelp-Backend

Repository files navigation

🩸 BloodHelp — API Server

An enterprise-grade, multi-role REST API powering Bangladesh's premier blood donation & medical crowdfunding ecosystem.

Node.js Express TypeScript Prisma PostgreSQL Zod Build License

OverviewArchitectureFeaturesDatabaseSecurityAPI DocsSetup


📖 Project Overview

BloodHelp Backend is the high-performance, secure API server powering the full BloodHelp ecosystem. It bridges blood donors, hospitals, charitable organisations, and individuals urgently seeking medical funds — all within a single, unified platform.

The system is built on strict Role-Based Access Control (RBAC), a hybrid JWT authentication strategy, and a modular domain-driven architecture designed for production scalability.

Live API Base URL: https://bloodhelp-backend.vercel.app/api/v1

Frontend: https://bloodhelp.vercel.app · Frontend Repo: BloodHelp-Frontend


🏗 System Architecture

The application strictly adheres to the Controller → Service → Repository pattern, ensuring complete decoupling of business logic from routing and data access layers.

graph TD
    Client[Client Apps / Frontend] -->|HTTPS Requests| Router[API Gateway & Router Layer]

    subgraph Core Infrastructure
        Router -->|Validated by Zod| Controllers[Controllers Layer]
        Controllers -->|Business Rules| Services[Services Layer]
        Services -->|Data Access| Prisma[Prisma ORM]
    end

    subgraph Security Layer
        AuthM[Hybrid Auth Middleware]
        RBACM[Role Guard Middleware]
        GlobalErr[Global Error Handler]
    end

    Router -.-> AuthM
    Router -.-> RBACM
    Controllers -.-> GlobalErr

    Prisma --> DB[(PostgreSQL Database)]
    Services --> Cloudinary[(Cloudinary CDN)]
    Services --> SSLCommerz[(SSLCommerz Gateway)]
    Services --> Email[(Nodemailer / SMTP)]
Loading

📂 Directory Structure

src/
├── app/
│   ├── config/              # Centralised, type-safe environment config
│   ├── db/                  # Super Admin seed script
│   ├── errors/              # Custom AppError class hierarchy
│   ├── builder/             # QueryBuilder: pagination, filtering, sorting
│   ├── middlewares/         # Auth, RBAC Guard, Global Error, Not Found
│   ├── routes/              # Unified v1 route assembler
│   └── modules/             # Domain-driven feature modules
│       ├── auth/            # Login, Register, Token Rotation, OTP
│       ├── user/            # Profiles, Donor search with geo-filter
│       ├── post/            # Blood Finding, Donation, Crowdfunding
│       ├── post.engagement/ # Likes, Comments, Nested Replies
│       ├── hospital/        # Verified donation ledgers & requests
│       ├── organisation/    # Volunteer management & history tracking
│       ├── admin/           # Platform analytics & account moderation
│       ├── manage-admins/   # Super Admin: admin lifecycle management
│       ├── notification/    # Action-triggered in-app alerts
│       ├── payment/         # SSLCommerz IPN, webhooks, ledger
│       └── upload/          # Cloudinary signed upload & destroy
└── server.ts                # Entry point: Express app bootstrap

Each module follows a strict 5-file pattern:

modules/[name]/
├── [name].controller.ts    # Thin: calls service, formats response
├── [name].service.ts       # All business logic + domain rules
├── [name].route.ts         # Route definitions + middleware chain
├── [name].validation.ts    # Zod schemas for all request inputs
└── [name].interface.ts     # TypeScript types for the module

🚀 Core Features

  • 🛡️ Enterprise Security — Hybrid JWT pattern immune to both CSRF and XSS attack vectors
  • 🩸 Intelligent Donor Matchmaking — Geo-filtered search by Division → District → Upazila with blood group, availability, and eligibility rule enforcement (Male: 2-month interval, Female: 3-month interval)
  • 📝 3-Type Post SystemBLOOD_FINDING (urgent requests), BLOOD_DONATION (donor/camp announcements), HELPING (medical crowdfunding with SSLCommerz)
  • 🏥 Verified Hospital Ledger — Hospitals officially record physical donations against user profiles, auto-updating donor availability — replacing unreliable self-reporting
  • 🏢 NGO Volunteer Network — Consent-based invitations, scoped donation history visibility, external volunteer management
  • 💸 Automated Crowdfunding — Full SSLCommerz integration with IPN-verified raisedAmount tracking against targetAmount
  • 🔔 Action-Triggered Notifications — Alerts for donation requests, consent invitations, post approvals, and payment confirmations
  • ☁️ Signed Cloud Uploads — Cloudinary signed upload signatures; no media stored on application servers

🗄 Database & ERD

Prisma v7's Multi-File Schema Architecture keeps database definitions atomic and maintainable. All entities use a global soft-delete pattern (isDeleted: Boolean @default(false)) — no data is permanently destroyed.

erDiagram
    USER ||--o| DONOR_PROFILE : has
    USER ||--o| HOSPITAL : is
    USER ||--o| ORGANISATION : is
    USER ||--o{ SESSION : tracks
    USER ||--o{ POST : creates
    USER ||--o{ NOTIFICATION : receives
    USER ||--o{ PAYMENT : makes

    BLOOD_DONOR }o--o| USER : linked_to
    BLOOD_DONOR ||--o{ DONATION_HISTORY : records
    BLOOD_DONOR ||--o{ HOSPITAL_DONATION_RECORD : in
    BLOOD_DONOR ||--o{ ORGANISATION_VOLUNTEER : part_of

    POST ||--o{ LIKE : has
    POST ||--o{ COMMENT : has
    POST ||--o{ PAYMENT : funds
    POST ||--o| POST_DONATION_CONSENT : pending
    COMMENT ||--o{ COMMENT : replies_to
Loading

Key Design Decisions:

  • BloodDonor is decoupled from User — supports both platform-registered users and externally-added volunteers (by hospitals/organisations) without requiring account creation
  • PostDonationConsent tracks the 7-day consent window when User A posts a donation on behalf of User B
  • Session stores hashed refresh tokens with device + IP metadata, enabling logout from all devices

🔒 Security Design

Hybrid Token Strategy

Access Token Refresh Token
Lifetime 15 minutes 30 days
Transport JSON response body HttpOnly + Secure + SameSite=None cookie
Client Storage Memory / React state Browser cookie store
CSRF Risk ✅ None — not auto-sent ✅ Mitigated via Origin validation
XSS Risk ✅ None — not in localStorage ✅ None — inaccessible to JavaScript

Token Rotation Flow

Access Token expires (15 min)
        │
        ▼
Client calls POST /auth/refresh-token  ←── no body required
        │
        ▼
Server reads HttpOnly cookie, validates against Session table
        │
        ▼
New Access Token issued → queued requests resume
User never sees a logout or interruption

Additional Protections

  • Passwords hashed with bcrypt (12 salt rounds)
  • All inputs validated through Zod before reaching controller logic
  • Session table enables revocation of individual or all device sessions
  • RBAC enforced at middleware level — not just the controller level

🔌 API Reference

Base URL: https://bloodhelp-backend.vercel.app/api/v1 Auth Header: Authorization: Bearer <access_token>

🔑 Auth Module — 7 endpoints
Method Endpoint Description Auth
POST /auth/register Register User / Hospital / Organisation
POST /auth/login Authenticate, receive access + refresh tokens
POST /auth/logout Invalidate current session 🔐
POST /auth/refresh-token Rotate access token via HttpOnly cookie
POST /auth/change-password Update password (requires current password) 🔐
POST /auth/forgot-password Request OTP to registered email
POST /auth/reset-password Reset password using OTP
👤 User & Donor Module — 4 endpoints
Method Endpoint Description Auth
GET /users/me Fetch current authenticated user's full profile 🔐
PUT /users/me Update profile (name, location, health data) 🔐
GET /users/donation-history Personal blood donation history 🔐 USER
GET /users/donors Search donors — filter by bloodGroup, division, district, upazila 🔐
📝 Post Module — 9 endpoints
Method Endpoint Description Auth
POST /posts Create post (BLOOD_FINDING / BLOOD_DONATION / HELPING) 🔐
GET /posts Public feed with filters (type, bloodGroup, location)
GET /posts/:id Single post with full details
GET /posts/user/:userId All posts by a specific user 🔐
PATCH /posts/:id Update post content 🔐 Author/Admin
DELETE /posts/:id Soft-delete a post 🔐 Author/Admin
PATCH /posts/:id/resolve Mark blood-finding post as resolved 🔐 Author
PATCH /posts/:id/approve Approve a HELPING post for public display 🔐 ADMIN
PATCH /posts/:id/verify Apply verification badge 🔐 ADMIN
💬 Engagement Module — 6 endpoints
Method Endpoint Description Auth
POST /posts/engagement/like Toggle like / unlike 🔐
POST /posts/engagement/comment Add comment (supports parentId for nested replies) 🔐
GET /posts/engagement/:postId/comments Fetch all comments + nested replies
PATCH /posts/engagement/comments/:commentId Edit own comment 🔐 Author
DELETE /posts/engagement/comments/:commentId Delete comment 🔐 Author/Admin
DELETE /posts/engagement/comments/:postId/delete-all Purge all comments on a post 🔐 ADMIN
🏥 Hospital Module — 3 endpoints
Method Endpoint Description Auth
POST /hospitals/record-donation Officially record a physical blood donation 🔐 HOSPITAL
GET /hospitals/donation-records All records managed by this hospital 🔐 HOSPITAL
PATCH /hospitals/requests/:requestId Accept or reject a donor request 🔐 USER
🏢 Organisation Module — 7 endpoints
Method Endpoint Description Auth
POST /organisations/volunteers Add a volunteer (platform user or external) 🔐 ORG
PATCH /organisations/volunteers/consent/:volunteerId Accept/reject an organisation invite 🔐 USER
GET /organisations/volunteers List all organisation volunteers 🔐 ORG
GET /organisations/volunteers/history Donation history of volunteers in this org 🔐 ORG
PATCH /organisations/volunteers/:id/donation-date Manually update volunteer donation date 🔐 ORG
PATCH /organisations/volunteers/:id Update volunteer details 🔐 ORG
DELETE /organisations/volunteers/:id Remove a volunteer 🔐 ORG
🛡️ Admin Module — 7 endpoints
Method Endpoint Description Auth
GET /admin/analytics Platform-wide statistics dashboard 🔐 ADMIN
GET /admin/users List all users (filter: role, status) 🔐 ADMIN
PATCH /admin/users/:id/status Approve / Block / Reject a user account 🔐 ADMIN
GET /admin/hospitals List all registered hospitals 🔐 ADMIN
PATCH /admin/hospitals/:id/status Update hospital registration status 🔐 ADMIN
GET /admin/organisations List all registered organisations 🔐 ADMIN
PATCH /admin/organisations/:id/status Update organisation registration status 🔐 ADMIN
👑 Manage Admins — 6 endpoints (Super Admin only)
Method Endpoint Description Auth
POST /manage-admins Create a new Admin account 🔐 SUPER_ADMIN
GET /manage-admins List all Admin accounts 🔐 SUPER_ADMIN
GET /manage-admins/:id Fetch a specific Admin's details 🔐 SUPER_ADMIN
PATCH /manage-admins/:id Update Admin profile 🔐 SUPER_ADMIN
PATCH /manage-admins/:id/access Toggle Admin's access rights 🔐 SUPER_ADMIN
DELETE /manage-admins/:id Delete an Admin account 🔐 SUPER_ADMIN
🔔 Notification Module — 3 endpoints
Method Endpoint Description Auth
GET /notifications Fetch all notifications for current user 🔐
PATCH /notifications/mark-all-read Mark all notifications as read 🔐
PATCH /notifications/:id Mark a single notification as read 🔐
💳 Payment Module — 5 endpoints
Method Endpoint Description Auth
POST /payments/initiate Create transaction, get SSLCommerz gateway URL 🔐 USER
POST /payments/success Payment success callback (IPN) Gateway
POST /payments/fail Payment failure callback Gateway
POST /payments/cancel Payment cancellation callback Gateway
POST /payments/ipn Instant Payment Notification handler Gateway
☁️ Upload Module — 2 endpoints
Method Endpoint Description Auth
POST /upload/signature Generate Cloudinary signed upload signature 🔐
DELETE /upload/destroy Delete an uploaded image from Cloudinary 🔐

Total: 52 endpoints across 11 modules


⚙️ Getting Started

Prerequisites

1. Clone & Install

git clone https://github.com/ambakhtiar/BloodHelp-Backend.git
cd BloodHelp-Backend
npm install

2. Configure Environment

cp .env.example .env

Fill in all required values — see Environment Variables below.

3. Database Setup

# Generate the Prisma client
npx prisma generate

# Push schema to your PostgreSQL instance
npx prisma db push

# (Optional) Seed the initial Super Admin account
npm run seed:superAdmin

4. Start Dev Server

npm run dev
# Server starts at http://localhost:5000 with hot-reload via tsx watch

🔧 Environment Variables

Create a .env file at the project root:

# ── Application ──────────────────────────────────────
NODE_ENV=development
PORT=5000

# ── Database ─────────────────────────────────────────
DATABASE_URL="postgresql://postgres:password@localhost:5432/BloodHelp?schema=public"

# ── JWT Authentication ────────────────────────────────
JWT_SECRET="your_access_token_secret_min_32_chars"
JWT_EXPIRES_IN="15m"
JWT_REFRESH_SECRET="your_refresh_token_secret_min_32_chars"
JWT_REFRESH_EXPIRES_IN="30d"
BCRYPT_SALT_ROUNDS=12

# ── URLs ──────────────────────────────────────────────
BACKEND_URL="http://localhost:5000"
FRONTEND_URL="http://localhost:3000"
CLIENT_URL="http://localhost:3000"

# ── SSLCommerz Payment Gateway ────────────────────────
SSL_COMMERZ_STORE_ID="your_store_id"
SSL_COMMERZ_STORE_PASSWORD="your_store_password"
SSL_COMMERZ_IS_LIVE=false

# ── Cloudinary ────────────────────────────────────────
CLOUDINARY_CLOUD_NAME="your_cloud_name"
CLOUDINARY_API_KEY="your_api_key"
CLOUDINARY_API_SECRET="your_api_secret"

# ── Email (Nodemailer) ────────────────────────────────
SMTP_HOST="smtp.gmail.com"
SMTP_PORT=587
SMTP_USER="your_email@gmail.com"
SMTP_PASS="your_app_password"

⚠️ Never commit .env to version control. Ensure it is listed in .gitignore.


📜 NPM Scripts

Script Command Description
dev tsx watch src/server.ts Development server with hot-reload
build prisma generate && tsup Compile TypeScript to ESM output
start node dist/server.js Serve the production build
seed:superAdmin tsx src/app/db/index.ts Seed initial Super Admin account
lint eslint . ./src/**/* Run ESLint across the codebase

🚀 Deployment

Vercel (Recommended)

  1. Connect your GitHub repository to Vercel
  2. Set all required environment variables in the Vercel project dashboard
  3. Set Build Command to npm run build
  4. Ensure vercel.json is present at the root:
{
  "version": 2,
  "builds": [{ "src": "dist/server.js", "use": "@vercel/node" }],
  "routes": [{ "src": "/(.*)", "dest": "dist/server.js" }]
}
  1. Click Deploy — subsequent pushes to main deploy automatically.

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/your-feature-name
  3. Commit using conventional commits: git commit -m "feat: add X"
  4. Push and open a Pull Request against main
  5. Ensure npm run lint passes before requesting review

📄 License

Distributed under the MIT License. See LICENSE for details.


Designed & developed by AM Bakhtiar

Backend · Frontend · Live Demo

About

Multi-role blood donation & medical crowdfunding REST API — 6 RBAC roles, hybrid JWT, geo-filtered donor search, SSLCommerz payments, hospital ledger. Built with Node.js, Express, Prisma & TypeScript.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors