Edwin Eames 6c35393f1f feat(auth): require email confirmation for new accounts
Updates the user registration and new account creation endpoints to require email confirmation.

- Sets the 'confirmed' flag to 'false' by default for all new user accounts.
- Generates a unique confirmation token for each new user.
- Logs the confirmation link to the console for development purposes.

This change ensures that users cannot log in without first verifying their email address, enhancing account security.
2026-01-18 16:28:33 -05:00
2026-01-17 15:21:41 -05:00
2026-01-17 15:41:05 -05:00
2026-01-17 15:41:05 -05:00
2026-01-17 15:41:05 -05:00
2026-01-17 15:41:05 -05:00
2026-01-17 15:21:41 -05:00
2026-01-17 15:21:41 -05:00
2026-01-17 15:21:41 -05:00
2026-01-17 15:21:41 -05:00
2026-01-17 15:21:41 -05:00
2026-01-17 15:21:41 -05:00
2026-01-17 15:41:05 -05:00
2026-01-17 15:21:41 -05:00
2026-01-17 15:21:41 -05:00
2026-01-17 15:21:41 -05:00
2026-01-17 15:21:41 -05:00
2026-01-17 15:21:41 -05:00
2026-01-17 15:21:41 -05:00

Auburn Oil Customer Gateway - API

A modern, high-performance REST API powering the Auburn Oil customer self-service portal. Built with FastAPI and designed for reliability, security, and ease of deployment.

    ___         __                        ____  _ __
   /   | __  __/ /_  __  ___________    / __ \(_) /
  / /| |/ / / / __ \/ / / / ___/ __ \  / / / / / /
 / ___ / /_/ / /_/ / /_/ / /  / / / / / /_/ / / /
/_/  |_\__,_/_.___/\__,_/_/  /_/ /_/  \____/_/_/

         Customer Gateway API

What This Does

This API serves as the backbone for Auburn Oil's customer portal, enabling:

Feature Description
Customer Onboarding Multi-step registration for new customers with tank photo uploads
Order Management Place heating oil delivery orders with real-time pricing
Payment Processing Secure credit card handling via Authorize.net (PCI-compliant)
Account Management Password reset, profile updates, delivery history
Tank Inspections Upload and manage annual tank inspection photos

Tech Stack

  • Framework: FastAPI 0.104 (async Python)
  • Database: PostgreSQL with SQLAlchemy 2.0 (async)
  • Authentication: JWT tokens with bcrypt password hashing
  • Payments: Authorize.net CIM (tokenized card storage)
  • Server: Uvicorn ASGI

Quick Start

Prerequisites

  • Docker & Docker Compose
  • PostgreSQL database (can be remote)
  • Authorize.net merchant account (sandbox for development)

1. Configure Environment

Copy the example environment file and customize:

cp .env.example .env.dev

Edit .env.dev with your settings:

# Database
POSTGRES_SERVER=your-db-host
POSTGRES_PORT=5432
POSTGRES_DBNAME=auburnoil
POSTGRES_USERNAME=postgres
POSTGRES_PASSWORD=your-secure-password

# Security (generate a strong key!)
JWT_SECRET_KEY=your-256-bit-secret-key
JWT_ALGORITHM=HS256
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=1440

# Payments (use sandbox credentials for dev)
AUTH_NET_API_LOGIN_ID=your-login-id
AUTH_NET_TRANSACTION_KEY=your-transaction-key

# Email (for password resets)
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_FROM_EMAIL=noreply@yourdomain.com

# Frontend URL (for password reset links)
FRONTEND_URL=http://localhost:3000

2. Deploy with Docker

Development (with hot-reload):

cd deploy
docker compose -f docker-compose.dev.yml up --build

Local Network Testing:

cd deploy
docker compose -f docker-compose.local.yml up --build

Production:

cd deploy
docker compose -f docker-compose.prod.yml up -d --build

3. Access the API

Environment API URL Docs
Development http://localhost:8000 http://localhost:8000/docs
Production https://api.portal.auburnoil.com https://api.portal.auburnoil.com/docs

API Endpoints

Authentication (/auth)

Method Endpoint Description
POST /auth/login Login with email/password, returns JWT
POST /auth/register Register existing customer (requires account #)
POST /auth/new New customer single-step registration
POST /auth/step1 New customer wizard - Step 1 (info)
POST /auth/step2 New customer wizard - Step 2 (credentials)
POST /auth/step3 New customer wizard - Step 3 (tank photos)
GET /auth/me Get current user profile
POST /auth/forgot-password Request password reset email
POST /auth/reset-password Complete password reset
POST /auth/change-password Change password (authenticated)
POST /auth/upload-tank-images Upload tank inspection photos
GET /auth/tank-images/{account} Get tank image history

Orders (/order)

Method Endpoint Description
POST /order/ Place new delivery order (min 100 gallons)

Customer Info (/info)

Method Endpoint Description
GET /info/deliveries Get delivery history (last 20)
GET /info/pricing/current Get current oil price per gallon

Payments (/payment)

Method Endpoint Description
POST /payment/process Process payment (saved or new card)
GET /payment/cards List saved payment methods
POST /payment/cards Save new card (tokenize)
PUT /payment/cards/{id} Update card details
DELETE /payment/cards/{id} Remove saved card
POST /payment/cards/{id}/set-default Set default payment method
POST /payment/sync-billing-info Sync billing to Authorize.net

Database Setup

Run Migrations

Apply database migrations in order:

# Connect to your PostgreSQL database
psql -h your-host -U postgres -d auburnoil

# Run migrations
\i migrations/20240108_create_portal_user_table.sql
\i migrations/20240108_add_tank_image_upload_dates.sql

Key Tables

Table Purpose
customer_customer Customer profiles and addresses
portal_user Portal login credentials
delivery_delivery Delivery orders and history
card_card Saved payment methods (tokenized)
transactions Payment transaction records
customer_tank Tank inspection metadata
pricing_oil_oil Daily oil pricing

Project Structure

api/
├── main.py              # FastAPI app entry point
├── config.py            # Environment configuration
├── database.py          # Database connection (async)
├── models.py            # SQLAlchemy ORM models
├── schemas.py           # Pydantic request/response schemas
├── routers/
│   ├── auth.py          # Authentication endpoints
│   ├── info.py          # Customer info endpoints
│   ├── order.py         # Order management
│   └── payment.py       # Payment processing
├── services/
│   └── authorizenet.py  # Authorize.net integration
├── .env.example         # Environment template
├── .env.dev             # Development config
├── .env.local           # Local network config
├── .env.prod            # Production config
├── Dockerfile.dev       # Development container
├── Dockerfile.local     # Local network container
├── Dockerfile.prod      # Production container
└── requirements.txt     # Python dependencies

Security Features

  • JWT Authentication: Stateless token-based auth with configurable expiration
  • Password Hashing: bcrypt with automatic truncation for compatibility
  • PCI Compliance: Card data never stored locally (Authorize.net tokenization)
  • Image Sanitization: Uploaded images resized, metadata stripped
  • CORS Protection: Environment-specific allowed origins
  • Input Validation: Pydantic schemas validate all inputs

Environment Variables Reference

Variable Required Description
MODE Yes DEVELOPMENT, LOCAL, or PRODUCTION
POSTGRES_SERVER Yes Database host
POSTGRES_PORT Yes Database port (usually 5432)
POSTGRES_DBNAME Yes Database name
POSTGRES_USERNAME Yes Database user
POSTGRES_PASSWORD Yes Database password
JWT_SECRET_KEY Yes Secret for signing tokens (use 256+ bits)
JWT_ALGORITHM Yes Algorithm (HS256 recommended)
JWT_ACCESS_TOKEN_EXPIRE_MINUTES Yes Token lifetime in minutes
AUTH_NET_API_LOGIN_ID Yes Authorize.net API Login ID
AUTH_NET_TRANSACTION_KEY Yes Authorize.net Transaction Key
SMTP_SERVER Yes SMTP server for emails
SMTP_PORT Yes SMTP port (587 for TLS)
SMTP_USERNAME Yes SMTP username
SMTP_PASSWORD Yes SMTP password/app password
SMTP_FROM_EMAIL Yes From address for emails
FRONTEND_URL Yes Frontend URL for reset links

Troubleshooting

Common Issues

Database connection failed

Check POSTGRES_* environment variables
Ensure database is accessible from Docker network
Verify firewall allows connections on port 5432

JWT token invalid

Ensure JWT_SECRET_KEY is the same across restarts
Check token hasn't expired
Verify JWT_ALGORITHM matches what was used to sign

Authorize.net errors

Sandbox vs Production: Use correct credentials for each
Test cards: Use Authorize.net test card numbers in sandbox
Check API Login ID and Transaction Key are correct

Image upload fails

Max file size: 20MB per image
Supported formats: JPEG, PNG
Check /images volume is mounted correctly

Development

Running Locally (without Docker)

# Create virtual environment
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

# Set environment variables
export MODE=DEVELOPMENT
# ... set other variables

# Run with hot-reload
uvicorn main:app --reload --host 0.0.0.0 --port 8000

API Documentation

FastAPI auto-generates interactive documentation:


Auburn Oil Customer Gateway - Built with reliability in mind for New Hampshire and Massachusetts heating oil customers.

Description
No description provided
Readme 80 KiB
Languages
Python 100%