Files
openfsd/web/README.md
2025-05-23 12:07:55 -07:00

549 lines
13 KiB
Markdown

# 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 relevant.
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.
NOTE: Do not use this endpoint for programmatic access from an external application.
Instead, generate an API token using the Configure Server menu via the frontend.
**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.
NOTE: Do not use this endpoint for programmatic access from an external application.
Instead, generate an API token using the Configure Server menu via the frontend.
**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.
The CID itself is immutable and is only provided as reference of the user to update.
**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.
Upon successfully calling this endpoint, this effectively invalidates *all* previously-administered authentication tokens. All users using the frontend will be logged out. All previously-generated API tokens will be invalidated.
**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.