# Server API Scripts (Optional Feature) This directory contains optional server-side PHP scripts that enable shared tournament hosting. ## Features When deployed to a PHP-enabled web server, these scripts enable: 1. **Shared Tournament Viewing**: Browse and load tournaments uploaded to the server 2. **Tournament Upload**: Share completed tournaments by uploading them to the server 3. **Graceful Degradation**: Features appear only when server is configured; local-only usage remains fully functional ## Requirements - PHP 7.0 or higher (PHP 8.2+ recommended) - Write permissions to `/tournaments` directory - Web server (Apache, Nginx, etc.) ## Quick Start with Docker (Recommended) The easiest way to get the API running is with the official Docker image: ```bash docker run -d \ --name newton-tournament \ -p 2020:2020 \ -v ./tournaments:/var/www/html/tournaments \ ghcr.io/skrodahl/newton:latest ``` **Benefits:** - ✅ All API endpoints pre-configured and working - ✅ nginx + PHP 8.2-FPM included - ✅ No manual setup required - ✅ Persistent tournament storage via volume mount **Test endpoints:** - List: `http://localhost:2020/api/list-tournaments.php` - Upload: POST to `http://localhost:2020/api/upload-tournament.php` See [DOCKER-QUICKSTART.md](../DOCKER-QUICKSTART.md) for complete Docker deployment guide. ## Manual Setup (Traditional Deployment) If you prefer to deploy without Docker: 1. **Create tournaments directory:** ```bash mkdir -p ../tournaments chmod 755 ../tournaments ``` 2. **Deploy to web server:** - Upload entire application to web-accessible directory - Ensure `/api` and `/tournaments` directories are accessible - Verify PHP is enabled for `.php` files 3. **Test endpoints:** - List: `https://yourdomain.com/api/list-tournaments.php` - Upload: POST to `https://yourdomain.com/api/upload-tournament.php` ## Endpoints ### GET /api/list-tournaments.php Returns list of available tournaments. **Response:** ```json { "tournaments": [ { "filename": "MyTournament_2025-10-01.json", "name": "My Tournament", "date": "2025-10-01", "players": 16, "status": "completed" } ], "count": 1 } ``` ### POST /api/upload-tournament.php Uploads a tournament to the server. **Request:** ```json { "filename": "MyTournament_2025-10-01.json", "data": { /* tournament data object */ } } ``` **Response:** ```json { "success": true, "filename": "MyTournament_2025-10-01.json", "path": "/tournaments/MyTournament_2025-10-01.json", "message": "Tournament uploaded successfully" } ``` ### GET / POST /api/corrections.php Achievement corrections for Analytics: per tournament, per player, the difference from what was recorded. Analytics applies them when it loads; the register in each browser is never modified. Stored in `tournaments/corrections/corrections.json`. **GET** returns every correction: ```json { "corrections": [ { "tournamentId": "1790000000001", "playerId": "2", "playerName": "Bob", "oneEighties": 1, "tons": -2, "lollipops": 0, "highOuts": { "add": [140], "remove": [121] }, "shortLegs": { "add": [], "remove": [] }, "updatedAt": 1790540598 } ] } ``` **POST** replaces all corrections for one tournament. An empty list removes them. ```json { "tournamentId": "1790000000001", "corrections": [ /* records as above */ ] } ``` Writes are made under a file lock, so simultaneous saves can't overwrite each other. ## Security - **Filename validation**: Only alphanumeric, spaces, hyphens, underscores, and `.json` extension allowed - **Directory traversal prevention**: `basename()` ensures files stay in tournaments directory - **Upload limits**: Payloads over 10 MB are rejected (413); the data must minimally look like a tournament export (`id`, `name`, `players`) - **Relay allowlist (optional)**: Set `NEWTON_RELAY_ALLOWLIST` (comma-separated hostnames) to restrict which remote hosts `relay.php` will forward to; unset allows any host - **API kill switch**: `NEWTON_API_ENABLED` accepts `false`, `0`, `off`, `no` (any case) to disable all endpoints - **CORS headers**: Configured for cross-origin requests (adjust as needed) - **File permissions**: Tournaments directory requires write access (755 recommended) - **API key for writes** (`NEWTON_API_KEY`): when set, upload, delete, corrections (POST) and relay need the `X-API-Key` header (`require_api_key()` in `api-check.php`); reading never does. Unset: no authentication — protect exposed instances at the deployment layer (reverse proxy with basic auth, VPN, or LAN-only) — see DOCKER-QUICKSTART.md § Security ## Local Development These scripts are **not required** for local development. The application works fully offline using browser localStorage. This is a bonus feature for organizations wanting to share tournament data across users. ## Troubleshooting **Upload button doesn't appear:** - Server endpoint `/api/list-tournaments.php` must return valid JSON response - Check browser console for network errors **Upload fails:** - Verify `/tournaments` directory exists and is writable - Check PHP error logs for permission issues - Ensure PHP has file write permissions **CORS errors:** - Adjust `Access-Control-Allow-Origin` header in PHP files - For production, restrict to specific domains