diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..77d9213 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,305 @@ +# Great Lakes Ice Report - API Documentation + +This document provides an overview of the API endpoints. For interactive documentation with examples, visit `/api-docs` when the server is running. + +## Base URL + +- **Development**: `http://localhost:3000` +- **Production**: `https://your-domain.com` + +## Authentication + +Admin endpoints require Bearer token authentication: +``` +Authorization: Bearer YOUR_TOKEN_HERE +``` + +Get a token by authenticating with the admin password at `POST /api/admin/login`. + +## Rate Limiting + +- **General API**: 30 requests per minute per IP +- **Location Submissions**: 10 requests per 15 minutes per IP + +## Public Endpoints + +### Get Configuration +```http +GET /api/config +``` + +Returns MapBox API configuration for frontend geocoding. + +**Response:** +```json +{ + "mapboxAccessToken": "pk.your_token_here", + "hasMapbox": true +} +``` + +### Get Active Locations +```http +GET /api/locations +``` + +Returns all active location reports (less than 48 hours old or marked persistent). + +**Response:** +```json +[ + { + "id": 123, + "address": "Main St & Oak Ave, Grand Rapids, MI", + "latitude": 42.9634, + "longitude": -85.6681, + "description": "Black ice present, multiple vehicles stuck", + "persistent": false, + "created_at": "2025-01-15T10:30:00.000Z" + } +] +``` + +### Submit Location Report +```http +POST /api/locations +``` + +Submit a new ice condition report with automatic profanity filtering. + +**Request Body:** +```json +{ + "address": "Main St & Oak Ave, Grand Rapids, MI", + "latitude": 42.9634, + "longitude": -85.6681, + "description": "Black ice spotted, drive carefully" +} +``` + +**Validation:** +- `address`: Required, max 500 characters +- `latitude`: Optional, valid number +- `longitude`: Optional, valid number +- `description`: Optional, max 1000 characters + +**Response (Success):** +```json +{ + "id": 125, + "address": "Main St & Oak Ave, Grand Rapids, MI", + "latitude": 42.9634, + "longitude": -85.6681, + "description": "Black ice spotted, drive carefully", + "persistent": false, + "created_at": "2025-01-15T12:00:00.000Z" +} +``` + +**Response (Profanity Detected):** +```json +{ + "error": "Submission rejected", + "message": "Your description contains inappropriate language...", + "details": { + "severity": "medium", + "wordCount": 1, + "detectedCategories": ["general"] + } +} +``` + +## Admin Endpoints + +All admin endpoints require authentication via `Authorization: Bearer `. + +### Admin Login +```http +POST /api/admin/login +``` + +Authenticate with admin password to receive access token. + +**Request Body:** +```json +{ + "password": "your_admin_password" +} +``` + +**Response:** +```json +{ + "token": "your_bearer_token_here", + "message": "Login successful" +} +``` + +### Get All Locations +```http +GET /api/admin/locations +``` + +Returns all location reports including expired ones. + +### Update Location +```http +PUT /api/admin/locations/:id +``` + +Update location details. + +**Request Body:** +```json +{ + "address": "Updated Address", + "latitude": 42.9634, + "longitude": -85.6681, + "description": "Updated description" +} +``` + +### Toggle Persistent Status +```http +PATCH /api/admin/locations/:id/persistent +``` + +Mark location as persistent (won't auto-expire) or remove persistent status. + +**Request Body:** +```json +{ + "persistent": true +} +``` + +### Delete Location +```http +DELETE /api/admin/locations/:id +``` + +Permanently delete a location report. + +### Profanity Word Management + +#### Get All Profanity Words +```http +GET /api/admin/profanity-words +``` + +#### Add Profanity Word +```http +POST /api/admin/profanity-words +``` + +**Request Body:** +```json +{ + "word": "badword", + "severity": "medium", + "category": "custom" +} +``` + +#### Update Profanity Word +```http +PUT /api/admin/profanity-words/:id +``` + +#### Delete Profanity Word +```http +DELETE /api/admin/profanity-words/:id +``` + +## Error Responses + +### Rate Limiting +```json +{ + "error": "Too many location reports submitted", + "message": "You can submit up to 10 location reports every 15 minutes. Please wait before submitting more.", + "retryAfter": "15 minutes" +} +``` + +### Validation Errors +```json +{ + "error": "Address must be a string with maximum 500 characters" +} +``` + +### Authentication Errors +```json +{ + "error": "Access denied" +} +``` + +### Not Found +```json +{ + "error": "Location not found" +} +``` + +### Server Errors +```json +{ + "error": "Internal server error" +} +``` + +## Interactive Documentation + +For complete interactive API documentation with live testing capabilities, visit `/api-docs` when running the server. This provides: + +- Complete endpoint specifications +- Request/response schemas +- Interactive testing interface +- Authentication flows +- Example requests and responses + +## Security Features + +- **Rate Limiting**: Prevents abuse and DoS attacks +- **Input Validation**: Strict length and type checking +- **Profanity Filtering**: Automatic content moderation +- **Authentication**: Secure admin access with bearer tokens +- **HTTPS**: SSL/TLS encryption in production +- **Audit Logging**: Suspicious activity detection + +## Client Libraries + +The API follows REST conventions and can be consumed by any HTTP client. Examples: + +### JavaScript/Node.js +```javascript +// Submit location report +const response = await fetch('/api/locations', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + address: 'Main St & Oak Ave', + description: 'Icy conditions' + }) +}); +``` + +### curl +```bash +# Get active locations +curl https://your-domain.com/api/locations + +# Submit location report +curl -X POST https://your-domain.com/api/locations \ + -H "Content-Type: application/json" \ + -d '{"address":"Main St & Oak Ave","description":"Icy conditions"}' + +# Admin login +curl -X POST https://your-domain.com/api/admin/login \ + -H "Content-Type: application/json" \ + -d '{"password":"your_password"}' +``` \ No newline at end of file diff --git a/docs/deployment.md b/docs/deployment.md new file mode 100644 index 0000000..7b25216 --- /dev/null +++ b/docs/deployment.md @@ -0,0 +1,347 @@ +# Great Lakes Ice Report - Deployment Guide + +This guide covers both automated and manual deployment options for the Great Lakes Ice Report application. + +## Prerequisites + +- **Server**: Debian 12 ARM64 (or compatible Linux distribution) +- **Node.js**: Version 18 or higher +- **Domain**: DNS pointing to your server +- **Ports**: 80 and 443 open for web traffic + +## Automated Deployment (Recommended) + +### Quick Start + +1. **Run the deployment script on your server:** + ```bash + curl -sSL https://ice-puremichigan-lol.s3.amazonaws.com/scripts/deploy.sh | bash + ``` + +2. **Clone and setup the application:** + ```bash + git clone git@git.deco.sh:deco/ice.git /opt/ice + cd /opt/ice + npm install # This automatically builds CSS via postinstall + ``` + +3. **Configure environment variables:** + ```bash + cp .env.example .env + nano .env # Add your API keys + ``` + +4. **Start services:** + ```bash + sudo systemctl enable ice + sudo systemctl start ice + sudo systemctl enable caddy + sudo systemctl start caddy + ``` + +### What the Automated Script Does + +The deployment script automatically: + +1. **System Updates**: Updates package repositories and system packages +2. **Node.js Installation**: Installs Node.js 20.x with build tools +3. **Go Installation**: Installs Go (required for building Caddy with plugins) +4. **Custom Caddy Build**: Builds Caddy with rate limiting plugin using xcaddy +5. **Service Configuration**: Creates systemd services for both the app and Caddy +6. **Security Setup**: Configures users, permissions, and security settings + +## Manual Deployment + +### 1. System Preparation + +```bash +# Update system +sudo apt update && sudo apt upgrade -y + +# Install Node.js 20.x +curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - +sudo apt install -y nodejs build-essential + +# Install Git (if not already installed) +sudo apt install -y git +``` + +### 2. Install Go (for Custom Caddy) + +```bash +# Download and install Go +wget -q https://go.dev/dl/go1.21.5.linux-arm64.tar.gz +sudo rm -rf /usr/local/go +sudo tar -C /usr/local -xzf go1.21.5.linux-arm64.tar.gz + +# Add to PATH +export PATH=$PATH:/usr/local/go/bin +echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc +source ~/.bashrc +``` + +### 3. Build Custom Caddy with Rate Limiting + +```bash +# Install xcaddy +go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest +export PATH=$PATH:$(go env GOPATH)/bin + +# Build Caddy with rate limiting plugin +xcaddy build --with github.com/mholt/caddy-ratelimit + +# Install Caddy +sudo mv caddy /usr/local/bin/caddy +sudo chmod +x /usr/local/bin/caddy +``` + +### 4. Create Users and Directories + +```bash +# Create Caddy user +sudo groupadd --system caddy +sudo useradd --system --gid caddy --create-home --home-dir /var/lib/caddy --shell /usr/sbin/nologin caddy + +# Create directories +sudo mkdir -p /etc/caddy /var/log/caddy +sudo chown -R caddy:caddy /var/log/caddy + +# Create app user +sudo groupadd --system great-lakes-ice-report +sudo useradd --system --gid great-lakes-ice-report --create-home --home-dir /opt/great-lakes-ice-report --shell /usr/sbin/nologin great-lakes-ice-report +``` + +### 5. Deploy Application + +```bash +# Clone repository +sudo git clone https://github.com/your-username/ice.git /opt/great-lakes-ice-report +cd /opt/great-lakes-ice-report + +# Install dependencies and build +sudo npm install +sudo npm run build + +# Set ownership +sudo chown -R great-lakes-ice-report:great-lakes-ice-report /opt/great-lakes-ice-report +``` + +### 6. Configure Environment + +```bash +# Copy environment template +sudo cp .env.example .env + +# Edit environment file +sudo nano .env +``` + +**Required environment variables:** +```bash +# MapBox API token (get free token at https://account.mapbox.com/access-tokens/) +MAPBOX_ACCESS_TOKEN=pk.your_mapbox_token_here + +# Admin panel password +ADMIN_PASSWORD=your_secure_password + +# Server port (default: 3000) +PORT=3000 + +# Node environment +NODE_ENV=production +``` + +### 7. Configure Systemd Services + +**Create app service:** +```bash +sudo cp scripts/great-lakes-ice-report.service /etc/systemd/system/ +``` + +**Create Caddy service:** +```bash +sudo tee /etc/systemd/system/caddy.service > /dev/null <