Converts Spring Boot 4.0.3 ARMA Server Web GUI to FastAPI/Python. Each phase file is fully self-contained: lists Java source files to read, output files to create, implementation patterns, REST endpoint contracts, and a completion checklist. A future agent can execute any single phase without rescanning the Java project. Phases: - 01: Foundation — SQLAlchemy models, Alembic, settings, base schemas - 02: Auth & Users — JWT middleware, RBAC, user CRUD - 03: CFG parser + server process — server.cfg round-trip, start/stop - 04: Server settings — general/network/logging/security/difficulty - 05: Mod management — mod CRUD, presets, settings, WebSocket progress - 06: Steam integration — SteamCMD queue, Workshop API, python-a2s - 07: Missions, CDLC, Discord, APScheduler jobs - 08: Middleware & polish — global exception handler, SPA redirect, structlog - 09: Testing — pytest-asyncio, respx, 80% coverage target
5.4 KiB
5.4 KiB
ASWG Python Conversion — Master Plan
Source project: E:\TestScript\ARMA-Server-Web-Gui (Java 25 / Spring Boot 4.0.3)
Target project: E:\TestScript\Arma_Server_Web_Manager (Python / FastAPI)
Goal: Identical REST API so the Angular 21 frontend works without any changes.
Server port: 8085 (same as Java app)
Phase Status Tracker
Update each phase's Status field when starting (IN_PROGRESS) and finishing (DONE).
Each phase file is self-contained — read only the phase file for the current phase.
| Phase | File | Status |
|---|---|---|
| 1 — Skeleton + DB | phases/phase-01-skeleton-db.md |
PENDING |
| 2 — Auth + Security | phases/phase-02-auth-security.md |
PENDING |
| 3 — CFG Parser + Server Process | phases/phase-03-cfg-parser-process.md |
PENDING |
| 4 — Server Settings Subdomains | phases/phase-04-server-settings.md |
PENDING |
| 5 — Mod Management | phases/phase-05-mod-management.md |
PENDING |
| 6 — Steam Integration | phases/phase-06-steam-integration.md |
PENDING |
| 7 — Missions, CDLC, Discord, Jobs | phases/phase-07-missions-cdlc-discord-jobs.md |
PENDING |
| 8 — Middleware + Polish | phases/phase-08-middleware-polish.md |
PENDING |
| 9 — Testing | phases/phase-09-testing.md |
PENDING |
Global Technology Stack
# pyproject.toml dependencies
fastapi = ">=0.115"
uvicorn = {extras = ["standard"], version = ">=0.30"}
pydantic = ">=2.7"
pydantic-settings = ">=2.3"
sqlalchemy = ">=2.0"
alembic = ">=1.13"
aiosqlite = ">=0.20"
PyJWT = ">=2.8"
passlib = {extras = ["bcrypt"], version = ">=1.7"}
cryptography = ">=43"
httpx = ">=0.27"
psutil = ">=5.9"
apscheduler = ">=3.10"
cachetools = ">=5.3"
python-a2s = ">=1.7"
structlog = ">=24"
jproperties = ">=2.1"
[dev]
pytest = ">=8.2"
pytest-asyncio = ">=0.23"
pytest-cov = ">=5.0"
respx = ">=0.21"
ruff = ">=0.4"
Java Source Root Abbreviation
All Java files are under:
E:\TestScript\ARMA-Server-Web-Gui\src\main\java\pl\bartlomiejstepien\armaserverwebgui\
In phase files this is written as <JAVA_SRC>.
Database Schema (all 12 tables)
installed_mod (id BIGINT PK, workshop_file_id BIGINT, name VARCHAR, directory_path VARCHAR,
preview_url VARCHAR, created_date TIMESTAMP, enabled BOOLEAN, server_mod BOOLEAN,
last_workshop_update_date TIMESTAMP, last_workshop_update_attempt_date TIMESTAMP,
dependencies_ids VARCHAR)
mod_preset (id BIGINT PK, name VARCHAR UNIQUE)
mod_preset_entry (id BIGINT PK, mod_preset_id BIGINT FK→mod_preset, mod_id BIGINT, mod_name VARCHAR)
difficulty_profile (id BIGINT PK, name VARCHAR UNIQUE, active BOOLEAN)
mission (id BIGINT PK, name VARCHAR UNIQUE, template VARCHAR, enabled BOOLEAN, difficulty VARCHAR)
mod_settings (id BIGINT PK, name VARCHAR, content TEXT)
invalid_jwt_token (id BIGINT PK, jwt VARCHAR UNIQUE, invalidated_datetime TIMESTAMP,
expiration_datetime TIMESTAMP)
aswg_user (id BIGINT PK, username VARCHAR UNIQUE, password VARCHAR, locked BOOLEAN,
created_datetime TIMESTAMP, last_success_login_datetime TIMESTAMP)
authority (id BIGINT PK, code VARCHAR UNIQUE)
aswg_user_authority (user_id BIGINT FK→aswg_user, authority_id BIGINT FK→authority)
cdlc (id BIGINT PK, name VARCHAR UNIQUE, enabled BOOLEAN)
job_execution (id BIGINT PK, job_name VARCHAR, start_date TIMESTAMP, finish_date TIMESTAMP,
status VARCHAR, message VARCHAR)
API Contract Rules (CRITICAL — do not deviate)
The Angular 21 frontend will NOT be changed. Every endpoint must match exactly:
- URL path, HTTP method, request field names (camelCase), response field names (camelCase)
- HTTP status codes: 200 OK, 201 Created, 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 409 Conflict, 500 Internal Server Error
- Error response shape:
{"code": "ERROR_CODE", "message": "Human readable message"}
Apply to all Pydantic schemas:
from pydantic import ConfigDict
from pydantic.alias_generators import to_camel
class BaseSchema(BaseModel):
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
Global Java→Python Concept Map
| Java / Spring | Python / FastAPI |
|---|---|
@RestController + @RequestMapping |
APIRouter(prefix="/api/v1/...") |
@GetMapping / @PostMapping / @DeleteMapping / @PutMapping |
@router.get() / .post() / .delete() / .put() |
@RequestBody |
Pydantic model as function parameter |
@PathVariable |
Path param {name} in route string |
@RequestParam |
Query(...) |
@RequestPart multipart |
UploadFile + Form(...) |
@HasPermission* annotation |
Depends(has_permission(AswgAuthority.XYZ)) |
@Service / @Component |
Plain class, instantiated in dependencies.py |
@Transactional |
async with session.begin(): |
JPA @Entity |
SQLAlchemy Base subclass |
Optional<T> |
T | None |
Lombok @Builder |
@dataclass or Pydantic with defaults |
@Value("${prop}") |
settings.prop (Pydantic BaseSettings) |
ResponseEntity<T> with status |
Return value + status_code= on route |
SseEmitter |
StreamingResponse(media_type="text/event-stream") |
| Spring WebSocket | FastAPI WebSocket route parameter |
@ConditionalOnProperty |
if settings.prop: guard at startup/registration |