Skip to content

Repository files navigation

πŸ“ Notes REST API

Tests

REST API for a notes application built with Express.js, MongoDB, and Redis.

The project focuses on authentication, API design, validation, testing, and common backend security practices.

✨ Features

  • πŸ” JWT Authentication β€” Access and refresh tokens via HTTP-only cookies
  • πŸ›‘οΈ CSRF Protection β€” XSRF-TOKEN validation for state-changing requests
  • πŸ“ Full CRUD β€” Create, read, update, and delete notes
  • πŸ” Search & Filter β€” Full-text search + tag-based filtering
  • πŸ“„ Pagination β€” Efficient pagination for large collections
  • πŸ“š OpenAPI/Swagger β€” Interactive API documentation
  • πŸš€ Production Practices β€” Rate limiting, logging, error handling, security headers
  • πŸ§ͺ Testing β€” Comprehensive test suite with Jest + Supertest

πŸ› οΈ Tech Stack

Category Technology
Runtime Node.js
Framework Express.js
Database MongoDB (Mongoose)
Cache Redis
Containerization Docker, Docker Compose
Auth JWT, bcrypt
Validation express-validator
Docs Swagger UI, OpenAPI 3.0
Logging Winston + Morgan
Testing Jest + Supertest
Linting ESLint + Prettier

πŸš€ Quick Start

Prerequisites

  • Docker & Docker Compose (recommended)
  • Node.js >= 18 (for local development)

With Docker (Recommended)

# Clone repository
git clone https://github.com/n1kFord/notes-rest-api.git
cd notes-rest-api

# Start all services (MongoDB, Redis, and API)
docker compose up -d

# Check logs
docker compose logs -f

# Access API
curl http://localhost:8080/health

# Open Swagger documentation
http://localhost:8080/api/docs

# Stop services
docker compose down

# Stop and remove volumes (clears database)
docker compose down -v

Local Development

# Install dependencies
npm install

# Setup environment
cp .env.example .env
# Edit .env with your configuration

# Start MongoDB and Redis (using Docker)
docker compose up -d mongo redis

# Start development server
npm run dev # or npm start

# Production mode
npm start

Environment Variables

# Server
PORT=8080
NODE_ENV=development

# MongoDB
MONGODB_URI=mongodb://localhost:27017/notes_app

# Redis
REDIS_URL=redis://localhost:6379

# JWT Secrets (generate strong secrets β€” at least 32 chars!)
JWT_SECRET=your_super_secret_jwt_key_min_32_chars
JWT_REFRESH_SECRET=your_super_secret_refresh_key_min_32_chars

# Token Expiry (optional)
ACCESS_TOKEN_EXPIRY=15m
REFRESH_TOKEN_EXPIRY=7d

πŸ“š API Documentation

Interactive Swagger UI is available at /api/docs when the server is running.

Auth Routes (/api/auth)

Method Endpoint Description Auth
POST /register Register new user ❌
POST /login Login user ❌
POST /refresh Refresh access token βœ…
POST /logout Logout user βœ…
GET /me Get current user info βœ…

Notes Routes (/api/notes)

Method Endpoint Description Auth
GET / Get all user notes βœ…
GET /:id Get specific note βœ…
POST / Create new note βœ…
PUT /:id Update note βœ…
DELETE /:id Delete note βœ…
GET /search?q=query Search notes βœ…
GET /tags/:tag Get notes by tag βœ…

πŸ“¦ API Examples

Register

POST /api/auth/register
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "Password123",
  "confirmPassword": "Password123"
}

Response: 201 Created

{ "success": true }

Login

POST /api/auth/login
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "Password123"
}

Response: 200 OK

{ "success": true }

Cookies set:

Cookie Description
token JWT access token (HttpOnly)
refreshToken JWT refresh token (HttpOnly)
XSRF-TOKEN CSRF protection token

Create Note

POST /api/notes
Cookie: token=<access_token>; XSRF-TOKEN=<csrf_token>
x-xsrf-token: <csrf_token>

{
  "title": "My First Note",
  "content": "This is the content of my first note",
  "tags": ["work", "important"]
}

Response: 201 Created

{
    "_id": "507f1f77bcf86cd799439011",
    "title": "My First Note",
    "content": "This is the content of my first note",
    "userId": "507f1f77bcf86cd799439001",
    "tags": ["work", "important"],
    "createdAt": "2026-01-15T10:30:00.000Z",
    "updatedAt": "2026-01-15T10:30:00.000Z"
}

Get All Notes

GET /api/notes?page=1&limit=10
Cookie: token=<access_token>

Response: 200 OK

{
  "notes": [...],
  "total": 25,
  "page": 1,
  "totalPages": 3
}

Search Notes

GET /api/notes/search?q=project&page=1&limit=10
Cookie: token=<access_token>

πŸ—„οΈ Database Schema

User

{
  _id: ObjectId,
  email: String (unique, indexed),
  password: String (bcrypt hashed),
  createdAt: Date,
  updatedAt: Date
}

Note

{
  _id: ObjectId,
  title: String (required, max 200),
  content: String (required),
  userId: ObjectId (ref: User, indexed),
  tags: [String] (indexed),
  createdAt: Date,
  updatedAt: Date
}

Indexes:

  • { userId: 1, createdAt: -1 } β€” efficient pagination
  • { userId: 1, tags: 1 } β€” tag filtering
  • { title: "text", content: "text" } β€” full-text search

Security

  • JWT authentication using HTTP-only cookies
  • Refresh token rotation
  • CSRF protection
  • Request validation
  • Rate limiting
  • Password hashing with bcrypt
  • Centralized error handling
  • Request logging

πŸ§ͺ Testing

# Run all tests
npm test

# Run with coverage
npm test -- --coverage

# CI mode
npm run test:ci

πŸ“ Project Structure

src/
β”œβ”€β”€ config/          # Database, Redis, and app configuration
β”œβ”€β”€ middlewares/     # Authentication, CSRF, validation, error handling
β”œβ”€β”€ models/          # MongoDB schemas
β”œβ”€β”€ routers/         # API route handlers
β”œβ”€β”€ store/           # Redis data storage
β”œβ”€β”€ utils/           # Shared helpers and utilities
β”œβ”€β”€ validations/     # Request validation rules
β”œβ”€β”€ tests/           # API and integration tests
β”œβ”€β”€ index.js         # Application entry point
└── swagger.js       # OpenAPI configuration

docker-compose.yml   # Docker services configuration
Dockerfile           # API container image

🚦 Status Codes

Code Description
200 OK
201 Created
204 No Content
400 Bad Request
401 Unauthorized
403 Forbidden (CSRF)
404 Not Found
409 Conflict
429 Too Many Requests
500 Internal Server Error

πŸ“ Scripts

Command Description
npm start Production start
npm run dev Development with nodemon
npm test Run tests
npm run test:ci CI tests with coverage
npm run lint ESLint check
npm run lint:fix ESLint auto-fix
npm run format Prettier format
npm run format:check Prettier check
npm run validate Lint + format + test

πŸ“„ License

This project is licensed under the MIT License.
Feel free to use, modify, and distribute with attribution.

πŸ’‘ Created with care by @n1kFord


Built with ❀️ for learning modern Node.js backend development

Releases

Packages

Contributors

Languages