mirror of
https://github.com/renorris/openfsd
synced 2026-03-22 23:05:36 +08:00
initial READMEs
This commit is contained in:
46
README.md
46
README.md
@@ -1 +1,45 @@
|
||||
# openfsd
|
||||
# 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.
|
||||
|
||||
541
web/README.md
541
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 <access_token>
|
||||
```
|
||||
- **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.
|
||||
|
||||
Reference in New Issue
Block a user