FTP/SFTP management plugin for the GameAP control panel. Installs and manages the gameap-files FTP/SFTP daemon on nodes and manages per-server FTP users, access rules, virtual path mounts and SSH keys.
Rust rewrite of the original Go plugin (plugin-gameap-files). Storage data,
node-side YAML files and the HTTP API are fully compatible — existing installs
keep working after the swap.
Читайте на других языках: Русский
- One-click gameap-files installation on nodes (chained daemon tasks, live status tracking through daemon-task events with a poll/timeout fallback)
- Per-node FTP/SFTP configuration (
config.yamlis patched in place — keys the plugin does not own are preserved) - FTP/SFTP users per game server: create/update/delete, Argon2id password hashing via the panel's crypto host service, one-time generated passwords
- Path access rules (
read/write/delete/list), virtual path mounts, SSH public keys - Users are mirrored to nodes as hot-reloaded YAML drop-ins under
/etc/gameap-files/users.d/ - Admin pages: all nodes with install status, all users grouped by node → server with filters
- Server abilities
ftp-users-view/ftp-users-managefor non-admin access control
| Layer | Module | Responsibility |
|---|---|---|
| ABI | src/lib.rs |
Plugin impl, register_plugin!, embedded frontend |
| Transport | src/http.rs, src/router.rs |
JSON error model, route table, dispatch |
| Handlers | src/handlers/* |
Per-route logic and DTOs, event handling |
| Services | src/services/* |
Users, sync, node setup orchestration, YAML patching, admin aggregation |
| Domain | src/domain/* |
Wire-compatible model, validation |
| Host seam | src/host_api.rs |
HostApi trait + WasmHost (wasm) / MockHost (tests) |
Business logic never touches the host ABI directly — everything goes through
the HostApi trait, so the whole router + handler stack runs natively under
cargo test against an in-memory mock host.
Panel KV storage (compatible with the Go plugin):
| Scope | Key | Contents |
|---|---|---|
| node | ftp:setup_status |
Installation state, task ids, timestamps |
| node | ftp:node_config |
FTP/SFTP configuration |
| server | ftp:users_list |
Username index (JSON array) |
| server | ftp:user:{username} |
Full user document (JSON) |
SERVER_DELETED— removes the server's users from storage and their YAML files from the node (node id taken from the event payload)DAEMON_TASK_COMPLETED/DAEMON_TASK_FAILED— matched against the install/download task ids stored in the node's setup status
Path dependencies require a sibling checkout layout:
gameap-api/ # gameap/gameap — provides web/plugin-sdk for the frontend
gameap-proto/ # gameap/gameap-proto — provides rust/gameap-plugin-sdk
plugin-files/ # this repository
Requirements: Rust (pinned by rust-toolchain.toml, target wasm32-wasip1),
Node.js 22+, optionally binaryen
for wasm-opt.
make build # frontend (npm ci + vite) → cargo build → wasm-opt → files.wasm
make test # cargo test + frontend vitest
make lint # clippy (both targets) + vue-tscDevelopment loop:
cd frontend && npm run dev # rebuild frontend on change
cargo build --target wasm32-wasip1 --release # rebuild wasm
cd frontend && npm run debug # standalone UI against MSW mocksUpload files.wasm via Administration → Plugins or drop it into the
panel's plugins directory and restart GameAP.
All routes live under /api/plugins/files. See
openapi/openapi.yaml for the full specification:
node setup/status/config, user CRUD, access rules, virtual paths, SSH keys
and the admin endpoints.
- Bump
versioninCargo.tomlandfrontend/package.json(must match). - Merge, create a GitHub release with tag
v<version>. - The release workflow builds, GPG-signs and publishes the wasm to
plugins.gameap.dev (requires the
GPG_SIGNING_KEY/GAMEAP_DEPLOY_TOKENsecrets and theGAMEAP_PLUGIN_IDrepository variable).
MIT