Files
DoGaMa-serv/internal/importexport/service_test.go
T

77 lines
2.2 KiB
Go

package importexport_test
import (
"archive/zip"
"bytes"
"context"
"io"
"os"
"path/filepath"
"testing"
"git.zaynet.fr/DoGaMa/DoGaMa-serv/internal/auth"
"git.zaynet.fr/DoGaMa/DoGaMa-serv/internal/importexport"
"git.zaynet.fr/DoGaMa/DoGaMa-serv/internal/persistence/sqlite"
)
func TestStageValidZIPAndRejectTraversal(t *testing.T) {
ctx := context.Background()
root := t.TempDir()
db, err := sqlite.Open(ctx, filepath.Join(root, "dogama.db"))
if err != nil {
t.Fatal(err)
}
defer db.Close()
authService := auth.New(db)
if err := authService.BootstrapAdmin(ctx, "admin", "correct horse battery staple"); err != nil {
t.Fatal(err)
}
session, err := authService.Login(ctx, "admin", "correct horse battery staple", "192.0.2.1:1234")
if err != nil {
t.Fatal(err)
}
actor, err := authService.Authenticate(ctx, session.Token)
if err != nil {
t.Fatal(err)
}
service, err := importexport.New(sqlite.NewRepository(db), filepath.Join(root, "imports"))
if err != nil {
t.Fatal(err)
}
policy := importexport.Policy{AcceptedFormats: []string{"zip"}, MaxExpandedBytes: 1 << 20, RequiredPaths: []string{"Level.sav", "Players"}}
valid := zipBytes(t, map[string]string{"Save/Level.sav": "world", "Save/Players/player.sav": "player"})
result, err := service.Stage(ctx, actor.ID, "zip", bytes.NewReader(valid), policy)
if err != nil {
t.Fatal(err)
}
if result.Status != "validated" || result.Confidence != "confirmed" || result.FileCount != 2 {
t.Fatalf("import = %#v", result)
}
unsafe := zipBytes(t, map[string]string{"../escape": "bad", "Level.sav": "world", "Players/player": "player"})
if _, err := service.Stage(ctx, actor.ID, "zip", bytes.NewReader(unsafe), policy); err == nil {
t.Fatal("traversal archive was accepted")
}
if _, err := os.Stat(filepath.Join(root, "escape")); !os.IsNotExist(err) {
t.Fatalf("escape path exists: %v", err)
}
}
func zipBytes(t *testing.T, files map[string]string) []byte {
t.Helper()
var buffer bytes.Buffer
writer := zip.NewWriter(&buffer)
for name, body := range files {
entry, err := writer.Create(name)
if err != nil {
t.Fatal(err)
}
if _, err := io.WriteString(entry, body); err != nil {
t.Fatal(err)
}
}
if err := writer.Close(); err != nil {
t.Fatal(err)
}
return buffer.Bytes()
}