Update application UI and functionality

This commit is contained in:
2026-07-26 16:20:36 +08:00
parent b9aff58f32
commit 97ea6fb7aa
48 changed files with 2790 additions and 628 deletions
@@ -1,6 +1,7 @@
package releases
import (
"errors"
"net/http/httptest"
"os"
"path/filepath"
@@ -132,3 +133,104 @@ func TestSaveUploadedPackageRejectsUnsafeName(t *testing.T) {
t.Fatal("expected unsafe filename to be rejected")
}
}
func TestSavePreparedPackageReplacesExistingFile(t *testing.T) {
service, cfg, cleanup := newPreparedPackageTestService(t)
defer cleanup()
name := "YMhut_Box_WinUI_Setup_2.0.8_x64.exe"
target := filepath.Join(cfg.DownloadsDir, name)
if err := os.MkdirAll(cfg.DownloadsDir, 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(target, []byte("old package"), 0o640); err != nil {
t.Fatal(err)
}
temp := filepath.Join(cfg.DownloadsDir, ".upload-new")
if err := os.WriteFile(temp, []byte("new package"), 0o640); err != nil {
t.Fatal(err)
}
_, err := service.SavePreparedPackage(
httptest.NewRequest("POST", "https://update.ymhut.cn/api/admin/releases/packages", nil),
UploadedPackageFile{TempPath: temp, Size: int64(len("new package")), SHA256: "abc123"},
UploadOptions{FileName: name},
"admin")
if err != nil {
t.Fatal(err)
}
data, err := os.ReadFile(target)
if err != nil {
t.Fatal(err)
}
if string(data) != "new package" {
t.Fatalf("target contains %q, want new package", data)
}
backups, err := filepath.Glob(filepath.Join(cfg.DownloadsDir, "."+name+".backup-*"))
if err != nil {
t.Fatal(err)
}
if len(backups) != 0 {
t.Fatalf("successful replacement left backups: %v", backups)
}
}
func TestSavePreparedPackageRestoresExistingFileWhenManifestFails(t *testing.T) {
service, cfg, cleanup := newPreparedPackageTestService(t)
defer cleanup()
name := "YMhut_Box_WinUI_Setup_2.0.8_x64.exe"
if err := os.MkdirAll(cfg.DownloadsDir, 0o755); err != nil {
t.Fatal(err)
}
target := filepath.Join(cfg.DownloadsDir, name)
if err := os.WriteFile(target, []byte("old package"), 0o640); err != nil {
t.Fatal(err)
}
temp := filepath.Join(cfg.DownloadsDir, ".upload-new")
if err := os.WriteFile(temp, []byte("new package"), 0o640); err != nil {
t.Fatal(err)
}
blocked := filepath.Join(cfg.BaseDir, "manifest-blocked")
if err := os.WriteFile(blocked, []byte("not a directory"), 0o640); err != nil {
t.Fatal(err)
}
cfg.UpdatePublicDir = blocked
_, err := service.SavePreparedPackage(
httptest.NewRequest("POST", "https://update.ymhut.cn/api/admin/releases/packages", nil),
UploadedPackageFile{TempPath: temp, Size: int64(len("new package")), SHA256: "abc123"},
UploadOptions{FileName: name, UpdateManifest: true},
"admin")
if !errors.Is(err, ErrUploadedPackageManifestFailed) {
t.Fatalf("got %v, want manifest failure", err)
}
data, readErr := os.ReadFile(target)
if readErr != nil {
t.Fatal(readErr)
}
if string(data) != "old package" {
t.Fatalf("rollback restored %q, want old package", data)
}
}
func newPreparedPackageTestService(t *testing.T) (*Service, *config.Config, func()) {
t.Helper()
dir := t.TempDir()
cfg := &config.Config{
BaseDir: dir,
StorageDir: filepath.Join(dir, "storage"),
DataDir: filepath.Join(dir, "data"),
UpdatePublicDir: filepath.Join(dir, "data", "update", "public"),
DownloadsDir: filepath.Join(dir, "data", "update", "public", "downloads"),
BaseURL: "https://update.ymhut.cn",
Database: config.DatabaseConfig{
Provider: "sqlite",
SQLitePath: filepath.Join(dir, "storage", "unified.sqlite"),
HealthIntervalSec: 30,
},
}
store, err := db.Open(cfg)
if err != nil {
t.Fatal(err)
}
return NewService(cfg, store), cfg, func() { _ = store.Close() }
}