admin: uploads list view with search, sort, and delete

Add /admin/uploads HTML page and JSON API backed by the upload_files

DB index. The page lists file_id, name, size (KB), uploaded_at, and

sha256 with client-side search by name, column sort, and per-row delete.

DELETE /admin/uploads/:id removes the DB index row and the on-disk

data file plus .meta.json sidecar. Admin deletes are written to the

audit log.

Wire the new dependencies through admin.Mount and main.go, and run

the backfill step on startup so pre-existing sidecars are indexed.

Tests cover auth, HTML rendering, JSON search, delete removing all

artifacts, and audit entry creation.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
tao.chen
2026-07-14 11:39:56 +08:00
co-authored by Claude
parent 876f1c9edb
commit df9b01272f
8 changed files with 646 additions and 10 deletions
+15 -1
View File
@@ -84,6 +84,19 @@ func run() error {
logger.Info("uploads.sweep", "deleted", n)
}
backfillCtx, backfillCancel := context.WithTimeout(context.Background(), startupSweepTimeout)
n, err = uploadStore.Backfill(backfillCtx, db.Uploads())
backfillCancel()
if errors.Is(err, context.DeadlineExceeded) {
logger.Warn("uploads.backfill.timeout", "inserted", n, "err", err)
} else if err != nil {
logger.Error("uploads.backfill", "err", err)
} else {
logger.Info("uploads.backfill", "inserted", n)
}
uploadStore.SetRepo(db.Uploads())
gin.SetMode(cfg.GinMode)
r := gin.New()
r.Use(gin.Recovery())
@@ -92,10 +105,11 @@ func run() error {
c.JSON(http.StatusOK, gin.H{"ok": true, "version": "0.0.0"})
})
admin.Mount(r, db.Clusters(), audit.NewRepo(db), cfg.AdminTokens)
admin.Mount(r, db.Clusters(), db.Uploads(), audit.NewRepo(db), &uploadStore, cfg.AdminTokens)
mcpHandler, err := mcpsrv.Handler(&tools.Deps{
Logger: logger.With("component", "mcp"),
AuditRepo: audit.NewRepo(db),
ClusterRepo: db.Clusters(),
SparkSubmitTimeout: cfg.SparkSubmitTimeout,
HTTPClient: httpclient.New(httpclient.Config{