diff --git a/README.md b/README.md index f96e070..f568a98 100644 --- a/README.md +++ b/README.md @@ -1 +1,45 @@ -# openfsd \ No newline at end of file +# openfsd + +**openfsd** is an open-source multiplayer flight simulation server implementing the Flight Sim Daemon (FSD) protocol, compatible with VATSIM's Velocity protocol. It connects pilots and air traffic controllers in a shared virtual environment. + +## Features + +- Facilitate multiplayer flight simulation with VATSIM protocol compatibility. +- Integrate web-based management for users, settings, and connections. +- Support SQLite and PostgreSQL for persistent storage. + +## Quick Start with Docker + +The preferred way to run openfsd is using **Docker** and **Docker Compose**. See the [Deployment Wiki](https://github.com/renorris/openfsd/wiki/Deployment). + +### Prerequisites + +- [Docker](https://docs.docker.com/get-docker/) +- [Docker Compose](https://docs.docker.com/compose/install/) + +### Steps + +1. **Clone the Repository**: + ```bash + git clone https://github.com/renorris/openfsd.git + cd openfsd + ``` + +2. **Start with Docker Compose**: + ```bash + docker-compose up -d + ``` + This launches the FSD server and web server sharing an SQLite database persisted in a named Docker volume. This setup will work great for most people running small servers. + +3. **Configure the Server via Web Interface**: + - Open `http://localhost:8000` in a browser. + - Log in with the default administrator credentials (printed in the FSD server logs on first startup). + - Navigate to the **Configure Server** menu + - Set configuration values. See the [Configuration]() wiki. + +4. **Connect Clients**: + Configure flight simulation clients (e.g., vPilot, Swift, VRC) to connect to `localhost:6809`. See the [Client Connection Wiki](https://github.com/renorris/openfsd/wiki/Client-Connection) for client-specific instructions. + +## API + +The web server exposes APIs under `/api/v1` for authentication, user management, and configuration. Although a basic web interface is provided, users are encouraged to call this API from their own external applications. See the [API Wiki](https://github.com/renorris/openfsd/wiki/api) for documentation. diff --git a/web/README.md b/web/README.md index b4ec66f..615b8b6 100644 --- a/web/README.md +++ b/web/README.md @@ -1 +1,542 @@ # openfsd REST & frontend interface + +## Overview +This API provides programmatic access to manage users, configurations, authentication, and FSD connections. All API endpoints are versioned under `/api/v1` and use JSON for request and response bodies unless otherwise specified. Authentication is primarily handled via JWT bearer tokens. + +--- + +## Authentication +Most endpoints require a valid JWT access token included in the `Authorization` header as a Bearer token: +``` +Authorization: Bearer +``` +- **API tokens** can be created via `/api/v1/config/createtoken` with a custom expiry date. See the **Server Configuration** menu in the frontend UI to generate one. + +--- + +## Network Ratings +The API enforces role-based access control using `NetworkRating` values defined in the `fsd` package. Key thresholds: +- **Supervisor (11)**: Can manage users (create, update, retrieve) and kick active connections. +- **Administrator (12)**: Can manage server configuration, reset JWT secret keys, and create API tokens. + +--- + +## Error Handling +All API responses follow a standard `APIV1Response` structure: +```text +{ + "version": "v1", + "err": string | null, + "data": object | null +} +``` +- **err**: Contains an error message if the request fails; otherwise, null. +- **data**: Contains the response data if the request succeeds; otherwise, null. + +Common HTTP status codes: +- **200 OK**: Request succeeded. +- **201 Created**: Resource created successfully. +- **400 Bad Request**: Invalid request body or parameters. +- **401 Unauthorized**: Invalid or missing credentials. +- **403 Forbidden**: Insufficient permissions. +- **404 Not Found**: Resource not found. +- **500 Internal Server Error**: Server-side error. + +--- + +## Endpoints + +### Authentication + +#### POST /api/v1/auth/login +Obtain access and refresh tokens using FSD login credentials. + +**Request Body**: +```json +{ + "cid": integer, // User certificate ID (min: 1) + "password": string, // User password + "remember_me": boolean // Extend refresh token validity to 30 days if true +} +``` + +**Response (200 OK)**: +```json +{ + "version": "v1", + "err": null, + "data": { + "access_token": string, // JWT access token + "refresh_token": string // JWT refresh token + } +} +``` + +**Errors**: +- **400 Bad Request**: Invalid JSON body. +- **401 Unauthorized**: Invalid CID or password. +- **500 Internal Server Error**: Server-side error generating tokens. + +**Permissions**: None (public endpoint). + +--- + +#### POST /api/v1/auth/refresh +Refresh an access token using a refresh token. + +**Request Body**: +```json +{ + "refresh_token": string // JWT refresh token +} +``` + +**Response (200 OK)**: +```json +{ + "version": "v1", + "err": null, + "data": { + "access_token": string // New JWT access token + } +} +``` + +**Errors**: +- **400 Bad Request**: Invalid JSON body. +- **401 Unauthorized**: Invalid or non-refresh token. +- **500 Internal Server Error**: Server-side error retrieving JWT secret or generating token. + +**Permissions**: None (public endpoint). + +--- + +#### POST /api/v1/fsd-jwt +Obtain an FSD JWT token (see authentication-tokens in the FSD docs). This call matches the functionality of the VATSIM /api/fsd-jwt endpoint. + +**Request Body** (form-encoded or JSON): +```json +{ + "cid": string, // User certificate ID + "password": string // User password +} +``` + +**Response (200 OK)**: +```json +{ + "success": true, + "token": string // FSD JWT token +} +``` + +**Errors**: +- **400 Bad Request**: Invalid CID format. +- **401 Unauthorized**: Invalid CID or password. +- **403 Forbidden**: User certificate is suspended or inactive. +- **500 Internal Server Error**: Server-side error retrieving JWT secret or generating token. + +**Permissions**: None (public endpoint). + +--- + +### User Management + +#### POST /api/v1/user/load +Retrieve user information by CID. + +**Request Body**: +```json +{ + "cid": integer // User certificate ID (min: 1) +} +``` + +**Response (200 OK)**: +```json +{ + "version": "v1", + "err": null, + "data": { + "cid": integer, + "first_name": string, + "last_name": string, + "network_rating": integer // -1 to 12 + } +} +``` + +**Errors**: +- **400 Bad Request**: Invalid JSON body. +- **401 Unauthorized**: Invalid bearer token. +- **403 Forbidden**: Insufficient permissions (non-self CID requires Supervisor rating). +- **404 Not Found**: User not found. +- **500 Internal Server Error**: Database error. + +**Permissions**: Requires valid JWT access token. Users can retrieve their own info; Supervisor rating (11) required for other users' info. + +--- + +#### PATCH /api/v1/user/update +Update user information by CID. + +**Request Body**: +```json +{ + "cid": integer, // User certificate ID (min: 1) + "password": string|null, // New password + "first_name": string|null, // New first name + "last_name": string|null, // New last name + "network_rating": integer|null // New network rating (-1 to 12) +} +``` + +**Response (200 OK)**: +```json +{ + "version": "v1", + "err": null, + "data": { + "cid": integer, + "first_name": string, + "last_name": string, + "network_rating": integer + } +} +``` + +**Errors**: +- **400 Bad Request**: Invalid JSON body. +- **401 Unauthorized**: Invalid bearer token. +- **403 Forbidden**: Insufficient permissions (Supervisor rating required; cannot update users with higher rating). +- **404 Not Found**: User not found. +- **500 Internal Server Error**: Database error. + +**Permissions**: Requires valid JWT access token and Supervisor rating (11). Cannot update users with a higher network rating. + +--- + +#### POST /api/v1/user/create +Create a new user. + +**Request Body**: +```json +{ + "password": string, // Password (min: 8 characters) + "first_name": string|null, // First name + "last_name": string|null, // Last name + "network_rating": integer // Network rating (-1 to 12) +} +``` + +**Response (201 Created)**: +```json +{ + "version": "v1", + "err": null, + "data": { + "cid": integer, // Assigned certificate ID + "first_name": string|null, + "last_name": string|null, + "network_rating": integer + } +} +``` + +**Errors**: +- **400 Bad Request**: Invalid JSON body. +- **401 Unauthorized**: Invalid bearer token. +- **403 Forbidden**: Insufficient permissions (Supervisor rating required; cannot create users with higher rating). +- **500 Internal Server Error**: Database error. + +**Permissions**: Requires valid JWT access token and Supervisor rating (11). Created user's network rating cannot exceed the requester's. + +--- + +### Configuration Management + +#### GET /api/v1/config/load +Retrieve server configuration key-value pairs. + +**Request**: No body required. + +**Response (200 OK)**: +```json +{ + "version": "v1", + "err": null, + "data": { + "key_value_pairs": [ + { + "key": string, // e.g., "welcome_message" + "value": string + } + ] + } +} +``` + +**Supported Keys**: +- `WELCOME_MESSAGE` +- `FSD_SERVER_HOSTNAME` +- `FSD_SERVER_IDENT` +- `FSD_SERVER_LOCATION` +- `API_SERVER_BASE_URL` + +**Errors**: +- **401 Unauthorized**: Invalid bearer token. +- **403 Forbidden**: Insufficient permissions (Administrator rating required). +- **500 Internal Server Error**: Database error. + +**Permissions**: Requires valid JWT access token and Administrator rating (12). + +--- + +#### POST /api/v1/config/update +Update server configuration key-value pairs. + +**Request Body**: +```json +{ + "key_value_pairs": [ + { + "key": string, // Configuration key + "value": string // New value + } + ] +} +``` + +**Response (200 OK)**: +```json +{ + "version": "v1", + "err": null, + "data": null +} +``` + +**Errors**: +- **400 Bad Request**: Invalid JSON body. +- **401 Unauthorized**: Invalid bearer token. +- **403 Forbidden**: Insufficient permissions (Administrator rating required). +- **500 Internal Server Error**: Database error. + +**Permissions**: Requires valid JWT access token and Administrator rating (12). + +--- + +#### POST /api/v1/config/resetsecretkey +Reset the JWT secret key used for signing tokens. + +**Request**: No body required. + +**Response (200 OK)**: +```json +{ + "version": "v1", + "err": null, + "data": null +} +``` + +**Errors**: +- **401 Unauthorized**: Invalid bearer token. +- **403 Forbidden**: Insufficient permissions (Administrator rating required). +- **500 Internal Server Error**: Error generating or storing new secret key. + +**Permissions**: Requires valid JWT access token and Administrator rating (12). + +--- + +#### POST /api/v1/config/createtoken +Create a new API access token with a specified expiry. + +**Request Body**: +```json +{ + "expiry_date_time": string // ISO 8601 format (e.g., "2025-12-31T23:59:59.000Z") +} +``` + +**Response (201 Created)**: +```json +{ + "version": "v1", + "err": null, + "data": { + "token": string // JWT access token + } +} +``` + +**Errors**: +- **400 Bad Request**: Invalid JSON body or expiry date in the past. +- **401 Unauthorized**: Invalid bearer token. +- **403 Forbidden**: Insufficient permissions (Administrator rating required). +- **500 Internal Server Error**: Error generating or signing token. + +**Permissions**: Requires valid JWT access token and Administrator rating (12). + +--- + +### FSD Connection Management + +#### POST /api/v1/fsdconn/kickuser +Kick an active user connection by callsign. + +**Request Body**: +```json +{ + "callsign": string // User callsign +} +``` + +**Response (200 OK)**: +```json +{ + "version": "v1", + "err": null, + "data": null +} +``` + +**Errors**: +- **400 Bad Request**: Invalid JSON body. +- **401 Unauthorized**: Invalid bearer token. +- **403 Forbidden**: Insufficient permissions (Supervisor rating required). +- **404 Not Found**: Callsign not found. +- **500 Internal Server Error**: Error communicating with FSD HTTP service. + +**Permissions**: Requires valid JWT access token and Supervisor rating (11). + +--- + +### Data Endpoints + +#### GET /api/v1/data/status.txt +Retrieve server status in plain text format. Mimics the VATSIM status.txt format. + +**Request**: No body required. + +**Response (200 OK)**: +- Content-Type: `text/plain` +- Body: Template-generated status text with carriage return newlines (`\r\n`). + +**Errors**: +- **500 Internal Server Error**: Error retrieving base URL or generating template. + +**Permissions**: None (public endpoint). + +--- + +#### GET /api/v1/data/status.json +Retrieve server status in JSON format. Mimics the VATSIM status.json format. + +**Response (200 OK)**: +```json +{ + "data": { + "v3": [string], // URL to openfsd-data.json + "servers": [string], // URL to openfsd-servers.json + "servers_sweatbox": [string], // URL to sweatbox-servers.json + "servers_all": [string] // URL to all-servers.json + } +} +``` + +**Errors**: +- **500 Internal Server Error**: Error retrieving base URL or marshaling JSON. + +**Permissions**: None (public endpoint). + +--- + +#### GET /api/v1/data/openfsd-servers.txt +Retrieve server list in plain text format. Mimics the VATSIM vatsim-servers.txt format. + +**Request**: No body required. + +**Response (200 OK)**: +- Content-Type: `text/plain` +- Body: Template-generated server list with carriage return newlines (`\r\n`). + +**Errors**: +- **500 Internal Server Error**: Error retrieving server info or generating template. + +**Permissions**: None (public endpoint). + +--- + +#### GET /api/v1/data/openfsd-servers.json +Retrieve server list in JSON format. Mimics the VATSIM vatsim-servers.json format. + +**Response (200 OK)**: +```json +[ + { + "ident": string, + "hostname_or_ip": string, + "location": string, + "name": string, + "clients_connection_allowed": integer, + "client_connections_allowed": boolean, + "is_sweatbox": boolean + } +] +``` + +**Errors**: +- **500 Internal Server Error**: Error retrieving server info or marshaling JSON. + +**Permissions**: None (public endpoint). + +--- + +#### GET /api/v1/data/sweatbox-servers.json +Retrieve sweatbox server list in JSON format (same as openfsd-servers.json but with `is_sweatbox: true`). + +**Response**: Same as `/openfsd-servers.json`. + +**Errors**: Same as `/openfsd-servers.json`. + +**Permissions**: None (public endpoint). + +--- + +#### GET /api/v1/data/all-servers.json +Retrieve all servers in JSON format (same as openfsd-servers.json). + +**Response**: Same as `/openfsd-servers.json`. + +**Errors**: Same as `/openfsd-servers.json`. + +**Permissions**: None (public endpoint). + +--- + +#### GET /api/v1/data/openfsd-data.json +Retrieve cached datafeed of online pilots and ATC. + +**Response (200 OK)**: +```json +{ + "pilots": [ + { + // fsd.OnlineUserPilot fields + } + ], + "atc": [ + { + // fsd.OnlineUserATC fields + } + ] +} +``` + +**Errors**: +- **500 Internal Server Error**: Datafeed cache not available. + +**Permissions**: None (public endpoint). + +**Notes**: Data is cached and updated every 15 seconds via an internal worker.