mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-24 08:33:41 +01:00
feat(save-transfer): add saveutil CLI and token-gated import endpoint
Adds two complementary paths for transferring character save data between
Erupe instances without breaking the SHA-256 integrity check system:
- `cmd/saveutil/`: admin CLI with `import`, `export`, `grant-import`, and
`revoke-import` subcommands. Direct DB access; no server running required.
- `POST /v2/characters/{id}/import`: player-facing API endpoint gated behind
a one-time token issued by `saveutil grant-import` (default TTL 24 h).
Token is validated and consumed atomically to prevent TOCTOU races.
- Migration `0013_save_transfer`: `savedata_import_token` and
`savedata_import_token_expiry` columns on `characters` table.
- Both paths decompress incoming savedata and recompute the SHA-256 hash
server-side, so the integrity check remains valid after import.
- README documents both methods and the per-character hash-reset workaround.
Closes #183.
This commit is contained in:
58
README.md
58
README.md
@@ -130,6 +130,64 @@ Edit `config.json` before starting the server. The essential settings are:
|
||||
|
||||
`config.example.json` is intentionally minimal — all other settings have sane defaults built into the server. For the full configuration reference (gameplay multipliers, debug options, Discord integration, in-game commands, entrance/channel definitions), see [config.reference.json](./config.reference.json) and the [Erupe Wiki](https://github.com/Mezeporta/Erupe/wiki).
|
||||
|
||||
## Save Transfers
|
||||
|
||||
To move a character from one Erupe instance to another, use the `saveutil` admin tool.
|
||||
|
||||
### Build saveutil
|
||||
|
||||
```bash
|
||||
go build -o saveutil ./cmd/saveutil/
|
||||
```
|
||||
|
||||
### Method 1: Direct admin import (recommended)
|
||||
|
||||
This method does not require the server to be running.
|
||||
|
||||
**On the source server**, export the character:
|
||||
```bash
|
||||
./saveutil export --config config.json --char-id <SOURCE_ID> --output my_character.json
|
||||
```
|
||||
|
||||
**On the destination server**, find the target character ID (use pgAdmin or `psql`), then import:
|
||||
```bash
|
||||
./saveutil import --config config.json --char-id <DEST_ID> --file my_character.json
|
||||
```
|
||||
|
||||
### Method 2: Player self-service via API
|
||||
|
||||
This method lets players import their own save without admin DB access, but requires the admin to grant a one-time token first.
|
||||
|
||||
**Admin step** — grant a token (valid for 24 hours by default):
|
||||
```bash
|
||||
./saveutil grant-import --config config.json --char-id <DEST_ID> [--ttl 48h]
|
||||
# → Import token for character 42: abc123...
|
||||
```
|
||||
|
||||
Give the printed token to the player. They then call the import endpoint:
|
||||
```bash
|
||||
curl -X POST http://<server>:8080/v2/characters/<DEST_ID>/import \
|
||||
-H "Authorization: Bearer <player_token>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"import_token": "<admin_token>",
|
||||
"character": <paste contents of my_character.json .character field here>
|
||||
}'
|
||||
```
|
||||
|
||||
The token is consumed on success and cannot be reused. To cancel a pending grant:
|
||||
```bash
|
||||
./saveutil revoke-import --config config.json --char-id <DEST_ID>
|
||||
```
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
**"savedata integrity check failed"** — the character was imported directly into the DB without going through `saveutil`. Fix by clearing the stored hash:
|
||||
```sql
|
||||
UPDATE characters SET savedata_hash = NULL WHERE id = <char_id>;
|
||||
```
|
||||
The correct hash will be recomputed on the next save.
|
||||
|
||||
## Features
|
||||
|
||||
- **Multi-version Support**: Compatible with all Monster Hunter Frontier versions from Season 6.0 to ZZ
|
||||
|
||||
Reference in New Issue
Block a user