chore: add api contract
Build and Push Docker Image / build-and-push (push) Has been skipped
Details
Build and Push Docker Image / build-and-push (push) Has been skipped
Details
This commit is contained in:
parent
9c940cedfd
commit
c67c4f749c
|
|
@ -0,0 +1,262 @@
|
|||
# Whitelist API Contract
|
||||
|
||||
API endpoints for managing player whitelist in HubMC gateway.
|
||||
|
||||
**Base Path:** `/api/v1/whitelist`
|
||||
|
||||
**Authentication:** All endpoints require `X-API-Key` header.
|
||||
|
||||
---
|
||||
|
||||
## Endpoints
|
||||
|
||||
### 1. Add Player to Whitelist
|
||||
|
||||
**Endpoint:** `POST /api/v1/whitelist/add`
|
||||
|
||||
**Description:** Add a player to the whitelist. If player exists but is inactive, reactivates them with new data.
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"player_name": "string", // 3-16 chars, alphanumeric + underscore only
|
||||
"added_by": "string", // 1-100 chars, who added the player
|
||||
"added_at": "datetime", // ISO 8601 format, within 1 hour past to 5 min future
|
||||
"expires_at": "datetime|null", // Optional, must be after added_at, max 2 years future
|
||||
"is_active": "boolean", // Default: true
|
||||
"reason": "string|null" // Optional, max 500 chars, whitespace trimmed
|
||||
}
|
||||
```
|
||||
|
||||
**Validation Rules:**
|
||||
- `player_name`: Must match regex `^[a-zA-Z0-9_]{3,16}$`
|
||||
- `added_by`: Cannot be empty or whitespace
|
||||
- `added_at`: Must be between (now - 1 hour) and (now + 5 minutes)
|
||||
- `expires_at`: Must be after `added_at` and before (now + 2 years)
|
||||
- `reason`: Trimmed, null if empty after trim
|
||||
|
||||
**Response:** `201 Created`
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"player_name": "string",
|
||||
"added_by": "string",
|
||||
"added_at": "datetime",
|
||||
"expires_at": "datetime|null",
|
||||
"is_active": true,
|
||||
"reason": "string|null"
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized`: Invalid API key
|
||||
- `400 Bad Request`: Validation error (invalid username format, date constraints, etc.)
|
||||
- `409 Conflict`: Player already exists and is active (`AlreadyExistsError`)
|
||||
|
||||
**Behavior:**
|
||||
- Creates LuckPerms player entry (logs error if fails, continues anyway)
|
||||
- If player exists and is inactive: reactivates with new data
|
||||
- If player exists and is active: returns 409 error
|
||||
- Handles race conditions with IntegrityError retry logic
|
||||
|
||||
---
|
||||
|
||||
### 2. Remove Player from Whitelist
|
||||
|
||||
**Endpoint:** `POST /api/v1/whitelist/remove`
|
||||
|
||||
**Description:** Permanently delete a player from the whitelist.
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"player_name": "string" // 3-16 chars, alphanumeric + underscore only
|
||||
}
|
||||
```
|
||||
|
||||
**Validation Rules:**
|
||||
- `player_name`: Must match regex `^[a-zA-Z0-9_]{3,16}$`
|
||||
|
||||
**Response:** `204 No Content`
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized`: Invalid API key
|
||||
- `400 Bad Request`: Invalid username format
|
||||
- `404 Not Found`: Player not found in whitelist (`NotFoundError`)
|
||||
|
||||
**Behavior:**
|
||||
- Hard deletes the entry from database
|
||||
- Does NOT check if player is active/inactive
|
||||
|
||||
---
|
||||
|
||||
### 3. Check Player Whitelist Status
|
||||
|
||||
**Endpoint:** `POST /api/v1/whitelist/check`
|
||||
|
||||
**Description:** Check if a player is currently whitelisted and active.
|
||||
|
||||
**Request Body:**
|
||||
```json
|
||||
{
|
||||
"player_name": "string" // 3-16 chars, alphanumeric + underscore only
|
||||
}
|
||||
```
|
||||
|
||||
**Validation Rules:**
|
||||
- `player_name`: Must match regex `^[a-zA-Z0-9_]{3,16}$`
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"is_whitelisted": true // true if exists AND is_active=true
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized`: Invalid API key
|
||||
- `400 Bad Request`: Invalid username format
|
||||
|
||||
**Behavior:**
|
||||
- Returns `true` only if entry exists AND `is_active = true`
|
||||
- Returns `false` if player not found OR `is_active = false`
|
||||
|
||||
---
|
||||
|
||||
### 4. List All Whitelisted Players
|
||||
|
||||
**Endpoint:** `GET /api/v1/whitelist/`
|
||||
|
||||
**Description:** Get all whitelist entries (both active and inactive).
|
||||
|
||||
**Query Parameters:** None
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"id": "uuid",
|
||||
"player_name": "string",
|
||||
"added_by": "string",
|
||||
"added_at": "datetime",
|
||||
"expires_at": "datetime|null",
|
||||
"is_active": true,
|
||||
"reason": "string|null"
|
||||
}
|
||||
],
|
||||
"total": 42 // Count of entries array
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized`: Invalid API key
|
||||
|
||||
**Behavior:**
|
||||
- Returns ALL entries (active and inactive)
|
||||
- Sorted by `added_at` descending (newest first)
|
||||
- No pagination implemented
|
||||
|
||||
---
|
||||
|
||||
### 5. Get Whitelist Count
|
||||
|
||||
**Endpoint:** `GET /api/v1/whitelist/count`
|
||||
|
||||
**Description:** Get total count of all whitelist entries.
|
||||
|
||||
**Query Parameters:** None
|
||||
|
||||
**Response:** `200 OK`
|
||||
```json
|
||||
{
|
||||
"total": 42 // Total count of all entries (active + inactive)
|
||||
}
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized`: Invalid API key
|
||||
|
||||
**Behavior:**
|
||||
- Counts ALL entries regardless of `is_active` status
|
||||
|
||||
---
|
||||
|
||||
## Data Types
|
||||
|
||||
**datetime:** ISO 8601 format with timezone
|
||||
```
|
||||
2024-01-15T10:30:00+00:00
|
||||
2024-01-15T10:30:00Z
|
||||
```
|
||||
|
||||
**uuid:** UUID v4 format
|
||||
```
|
||||
550e8400-e29b-41d4-a716-446655440000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Headers
|
||||
|
||||
**Request:**
|
||||
```
|
||||
X-API-Key: your-api-key-here
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Response Format
|
||||
|
||||
All errors follow FastAPI standard format:
|
||||
|
||||
```json
|
||||
{
|
||||
"detail": "Error message description"
|
||||
}
|
||||
```
|
||||
|
||||
**Status Codes:**
|
||||
- `200 OK`: Success (GET)
|
||||
- `201 Created`: Resource created (POST add)
|
||||
- `204 No Content`: Success with no body (POST remove)
|
||||
- `400 Bad Request`: Validation error
|
||||
- `401 Unauthorized`: Invalid/missing API key
|
||||
- `404 Not Found`: Resource not found
|
||||
- `409 Conflict`: Resource already exists
|
||||
- `500 Internal Server Error`: Unexpected server error
|
||||
|
||||
---
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
### Database Model
|
||||
- Table: `hub_whitelist`
|
||||
- Primary Key: `id` (UUID, auto-generated)
|
||||
- Unique Constraint: `player_name`
|
||||
- Indexes: `player_name`, `is_active`, `expires_at`
|
||||
- Auto-timestamps: `created_at`, `updated_at`
|
||||
|
||||
### Race Condition Handling
|
||||
The `add` endpoint handles concurrent requests for the same `player_name`:
|
||||
1. Checks if player exists
|
||||
2. Attempts to create/update
|
||||
3. On `IntegrityError` (race condition), retries check
|
||||
4. Returns appropriate error if now active
|
||||
|
||||
### LuckPerms Integration
|
||||
The `add` endpoint creates a LuckPerms player entry with:
|
||||
- `username`: from `player_name`
|
||||
- `primary_group`: "default"
|
||||
|
||||
Failures are logged but do NOT block whitelist creation.
|
||||
|
||||
### Soft Delete
|
||||
Currently NOT implemented. The `remove` endpoint performs hard delete.
|
||||
Inactive entries are kept until explicitly removed.
|
||||
Loading…
Reference in New Issue