Export and import working
This commit is contained in:
@@ -12,6 +12,7 @@ The transfer package provides character export and import functionality for the
|
||||
- Learning data (all learning_* tables)
|
||||
- Audit log entries
|
||||
- GSM master data (skills, spells, weapons, equipment definitions)
|
||||
- **Security**: Sensitive user data (password, updated_at, reset tokens) is removed from exports
|
||||
|
||||
- **Smart Import**:
|
||||
- Identifies existing GSM data by name (not ID) to avoid duplicates
|
||||
@@ -52,7 +53,9 @@ Imports a character from JSON data
|
||||
|
||||
### Export a Character
|
||||
```bash
|
||||
curl http://localhost:8180/api/transfer/export/18 > character_export.json
|
||||
curl http://localhost:8180/api/transfer/export/18 \
|
||||
-H "Authorization: Bearer XXXXXXXXXXX" \
|
||||
> character_export.json
|
||||
```
|
||||
|
||||
### Download a Character
|
||||
@@ -64,6 +67,7 @@ wget http://localhost:8180/api/transfer/download/18
|
||||
```bash
|
||||
curl -X POST http://localhost:8180/api/transfer/import \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer XXXXXXXXXXX" \
|
||||
-d @character_export.json
|
||||
```
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bamort/database"
|
||||
"bamort/models"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// CharacterExport contains all data needed to export and import a character
|
||||
@@ -61,6 +62,12 @@ func ExportCharacter(characterID uint) (*CharacterExport, error) {
|
||||
return nil, fmt.Errorf("failed to load character: %w", err)
|
||||
}
|
||||
|
||||
// Remove sensitive user information from export
|
||||
char.User.PasswordHash = ""
|
||||
char.User.UpdatedAt = time.Time{}
|
||||
char.User.ResetPwHash = nil
|
||||
char.User.ResetPwHashExpires = nil
|
||||
|
||||
export := &CharacterExport{
|
||||
Character: char,
|
||||
}
|
||||
|
||||
@@ -63,6 +63,15 @@ func TestExportCharacter(t *testing.T) {
|
||||
if reimported.Character.ID != characterID {
|
||||
t.Errorf("After JSON round-trip, expected character ID %d, got %d", characterID, reimported.Character.ID)
|
||||
}
|
||||
|
||||
// Verify sensitive user data is removed
|
||||
if exportData.Character.User.PasswordHash != "" {
|
||||
t.Error("Password hash should be empty in export")
|
||||
}
|
||||
|
||||
if !exportData.Character.User.UpdatedAt.IsZero() {
|
||||
t.Error("UpdatedAt should be zero time in export")
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportCharacterIncludesSkills(t *testing.T) {
|
||||
|
||||
@@ -64,7 +64,7 @@ func DownloadCharacterHandler(c *gin.Context) {
|
||||
// ImportCharacterHandler handles character import requests
|
||||
func ImportCharacterHandler(c *gin.Context) {
|
||||
// Get user ID from context (set by auth middleware)
|
||||
userID, exists := c.Get("user_id")
|
||||
userID, exists := c.Get("userID")
|
||||
if !exists {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "User not authenticated"})
|
||||
return
|
||||
|
||||
@@ -117,11 +117,11 @@ func TestImportCharacterHandlerAPI(t *testing.T) {
|
||||
req, _ := http.NewRequest("POST", "/api/transfer/import", bytes.NewBuffer(jsonData))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
// Mock user_id in context (normally set by auth middleware)
|
||||
// Mock userID in context (normally set by auth middleware)
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Request = req
|
||||
c.Set("user_id", uint(1))
|
||||
c.Set("userID", uint(1))
|
||||
|
||||
ImportCharacterHandler(c)
|
||||
|
||||
@@ -170,7 +170,7 @@ func TestImportInvalidJSONAPI(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Request = req
|
||||
c.Set("user_id", uint(1))
|
||||
c.Set("userID", uint(1))
|
||||
|
||||
ImportCharacterHandler(c)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user