Skip to content
 
 

Repository files navigation

GlobeTrotter – Travel Assistant

GlobeTrotter is a monolithic Flask application that serves as the starting point for a semester-long capstone project.
Students build the monolith first, then refactor it into microservices, and finally deploy it to the cloud with resilience patterns using Docker, Kubernetes, and cloud-native tooling.


Project Structure

.
├── app/
│   ├── __init__.py         # Flask app factory
│   ├── models.py           # Data models and JSON file I/O
│   ├── auth.py             # Registration, login, JWT handling
│   ├── destinations.py     # Destination search endpoint
│   ├── recommendations.py  # Personalised recommendations endpoint
│   ├── itineraries.py      # Create / list itineraries
│   └── main.py             # App entry point
├── data/
│   ├── destinations.json   # Static destination catalogue (seed data)
│   ├── users.json          # Created at runtime
│   └── itineraries.json    # Created at runtime
├── tests/                  # Placeholder for future tests
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
└── README.md

REST API

Method Endpoint Auth required Description
POST /register No Register a new user
POST /login No Authenticate and receive a JWT token
GET /destinations No Search the destination catalogue
GET /recommendations Yes (JWT) Get personalised recommendations
POST /itineraries Yes (JWT) Create a new itinerary
GET /itineraries Yes (JWT) List all itineraries for the logged-in user

Protected routes expect the header:
Authorization: Bearer <your-token>

Example requests

# Register
curl -X POST http://localhost:5000/register \
  -H "Content-Type: application/json" \
  -d '{"username": "alice", "password": "s3cr3t", "preferences": ["beach", "food"]}'

# Login
curl -X POST http://localhost:5000/login \
  -H "Content-Type: application/json" \
  -d '{"username": "alice", "password": "s3cr3t"}'
# Save the returned token: TOKEN=<value from .token field>

# Search destinations
curl "http://localhost:5000/destinations?tag=beach&max_cost=100"

# Personalised recommendations
curl http://localhost:5000/recommendations \
  -H "Authorization: Bearer $TOKEN"

# Create an itinerary
curl -X POST http://localhost:5000/itineraries \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"title": "Beach Escape", "destinations": ["Bali"], "start_date": "2025-07-01", "end_date": "2025-07-14"}'

# List itineraries
curl http://localhost:5000/itineraries \
  -H "Authorization: Bearer $TOKEN"

Running Locally

Prerequisites

  • Python 3.13+
  • pip
# 1. Install dependencies
pip install -r requirements.txt

# 2. Start the server
python app/main.py

The API will be available at http://localhost:5000.


Testing

Run the test suite

# Install pytest if not already installed
pip install pytest

# Run all tests
pytest -q

Currently, the test suite covers:

  • JWT token creation and decoding (tests/test_auth.py)
  • JSON file I/O helpers (tests/test_models_io.py)
  • Recommendation scoring and sorting (tests/test_recommendations.py)

Writing tests

Place test files in the tests/ directory following the naming convention test_*.py. The CI pipeline runs pytest on every push.


Code Quality

Linting and Formatting

The project uses ruff, black, and isort for code quality:

# Install tools
pip install ruff black isort

# Auto-format code
black .
isort .

# Check for linting issues
ruff check .

Configuration is in pyproject.toml and .flake8.

Pre-commit hooks

Set up automatic linting before commit:

pip install pre-commit
pre-commit install

CI/CD Pipeline

A GitHub Actions workflow (.github/workflows/ci.yml) runs automatically on push and pull requests:

  • Tests: Runs pytest across Python 3.11, 3.12, and 3.13
  • Linting: Checks with ruff
  • Import sorting: Validates with isort
  • Formatting: Checks conformance with black

View workflow status

Go to the Actions tab on GitHub.


Security

Dependency scanning

The project includes vulnerability scanning via pip-audit:

pip install pip-audit
pip-audit --format=json

Known vulnerabilities (as of Jul 28, 2026):

  • PyJWT (2.8.0 → 2.13.0): Critical header parameter validation flaws
  • Flask (2.3.3 → 3.1.3): Cache-header bypass in session handling
  • Werkzeug (2.3.7 → 3.1.6): Multipart parser DoS and safe_join bypasses
  • python-dotenv (1.0.0 → 1.2.2): Symlink following in setkey()
  • pip (25.2 → 26.1.2): Console script path traversal and tar extraction issues

Recommendation: Upgrade dependencies in requirements.txt:

pip install --upgrade PyJWT Flask Werkzeug python-dotenv
pip freeze > requirements.txt

Environment Configuration

Create a .env file (copy from .env.example) to override defaults:

# Environment variables
SECRET_KEY=your-random-secret-key-here
FLASK_DEBUG=0
FLASK_ENV=production
PORT=5000

Important: Never commit .env to version control. Use .env.example as a template.


Running with Docker

Quick start

# Build and start the container
docker-compose up --build

# Stop containers
docker-compose down

# View logs
docker-compose logs -f globetrotter

The application will be available at http://localhost:5000 and includes a health check that verifies container readiness.

Docker improvements

The Dockerfile now features:

  • Multi-stage build: Separates dependencies layer from application layer (smaller production images)
  • Non-root user: Runs as appuser (enhanced security)
  • Health check: Built-in container health monitoring
  • Python 3.13: Latest stable release
  • Optimized caching: Virtual environment re-used across stages

The docker-compose.yml includes:

  • Automatic restart on failure (up to 3 retries)
  • Health check with monitoring endpoints
  • Isolated network (globetrotter-net)
  • Logging configuration with size limits (10 MB, 3 files)
  • Volume mounts for development (live code changes)

Build for production

To build a production-ready image:

docker build -t globetrotter:latest --target production .

Configuration

Environment Variable Default Description
SECRET_KEY globetrotter-secret-change-in-prod JWT signing key – must be overridden in production
FLASK_DEBUG 0 Set to 1 to enable Flask debug mode (development only)
PORT 5000 Port the app listens on
PYTHONUNBUFFERED 1 Unbuffered Python output (for container logging)

Important: Always set SECRET_KEY to a long, random value in production (e.g. python -c "import secrets; print(secrets.token_hex(32))").


Data Storage

All data is persisted in plain JSON files inside the data/ directory:

File Purpose
data/destinations.json Static catalogue of travel destinations (seed data)
data/users.json Registered users (created at runtime)
data/itineraries.json User itineraries (created at runtime)

Note: data/*.json (except destinations.json) are excluded from version control via .gitignore.

About

GlobeTrotter Travel Assistant – A distributed travel recommendation system built as a semester-long capstone project. Students starts by building a monolith, then refactor to microservices, and finally deploy to the cloud. They add resilience patterns using Docker, Kubernetes, and cloud-native tools.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages