admin: submissions page, download endpoint, uploads search by app_id
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -18,7 +18,7 @@ import (
|
||||
"spark-mcp-go/internal/uploads"
|
||||
)
|
||||
|
||||
func newTestAdminUploads(t *testing.T) (*gin.Engine, *storage.UploadRepo, *audit.Repo, *uploads.Store) {
|
||||
func newTestAdminUploads(t *testing.T) (*gin.Engine, *storage.UploadRepo, *storage.SubmissionRepo, *audit.Repo, *uploads.Store) {
|
||||
t.Helper()
|
||||
db, err := storage.Open(":memory:")
|
||||
if err != nil {
|
||||
@@ -32,12 +32,12 @@ func newTestAdminUploads(t *testing.T) (*gin.Engine, *storage.UploadRepo, *audit
|
||||
}
|
||||
|
||||
r := gin.New()
|
||||
Mount(r, db.Clusters(), db.Uploads(), audit.NewRepo(db), &uploadStore, []string{"good-token"})
|
||||
return r, db.Uploads(), audit.NewRepo(db), &uploadStore
|
||||
Mount(r, db.Clusters(), db.Uploads(), db.Submissions(), audit.NewRepo(db), &uploadStore, []string{"good-token"})
|
||||
return r, db.Uploads(), db.Submissions(), audit.NewRepo(db), &uploadStore
|
||||
}
|
||||
|
||||
func TestUploadsWeb_RequiresAuth(t *testing.T) {
|
||||
r, _, _, _ := newTestAdminUploads(t)
|
||||
r, _, _, _, _ := newTestAdminUploads(t)
|
||||
|
||||
w := doReq(t, r, "GET", "/admin/uploads", "", nil)
|
||||
if w.Code != http.StatusUnauthorized {
|
||||
@@ -62,7 +62,7 @@ func TestUploadsWeb_RequiresAuth(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestListUploads(t *testing.T) {
|
||||
r, repo, _, _ := newTestAdminUploads(t)
|
||||
r, repo, _, _, _ := newTestAdminUploads(t)
|
||||
ctx := context.Background()
|
||||
|
||||
uploadedAt := time.Unix(0, time.Now().UnixNano())
|
||||
@@ -98,7 +98,7 @@ func TestListUploads(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteUpload(t *testing.T) {
|
||||
r, repo, auditRepo, store := newTestAdminUploads(t)
|
||||
r, repo, _, auditRepo, store := newTestAdminUploads(t)
|
||||
ctx := context.Background()
|
||||
|
||||
id := "00000000000000000000000000000003"
|
||||
@@ -152,3 +152,45 @@ func TestDeleteUpload(t *testing.T) {
|
||||
t.Errorf("missing upload.delete audit entry")
|
||||
}
|
||||
}
|
||||
|
||||
func TestListUploads_SearchByAppID(t *testing.T) {
|
||||
r, uploadRepo, subRepo, _, _ := newTestAdminUploads(t)
|
||||
ctx := context.Background()
|
||||
|
||||
uploadedAt := time.Unix(0, time.Now().UnixNano())
|
||||
if err := uploadRepo.Create(ctx, "00000000000000000000000000000010", "gamma.py", 10, "deadbeef", uploadedAt); err != nil {
|
||||
t.Fatalf("create upload: %v", err)
|
||||
}
|
||||
if err := uploadRepo.Create(ctx, "00000000000000000000000000000011", "delta.py", 20, "cafebabe", uploadedAt.Add(time.Second)); err != nil {
|
||||
t.Fatalf("create upload: %v", err)
|
||||
}
|
||||
|
||||
// Only gamma.py has an associated submission; searching by app_id should
|
||||
// still return it even though the filename doesn't match the query.
|
||||
if err := subRepo.Create(ctx, storage.Submission{
|
||||
FileID: "00000000000000000000000000000010",
|
||||
AppID: "application_gamma_0001",
|
||||
TrackingURL: "http://gamma",
|
||||
ClusterID: "c1",
|
||||
ExitCode: 0,
|
||||
DurationMS: 100,
|
||||
SubmittedAt: time.Now(),
|
||||
}); err != nil {
|
||||
t.Fatalf("create submission: %v", err)
|
||||
}
|
||||
|
||||
w := doReq(t, r, "GET", "/admin/uploads/api?search=application_gamma", "good-token", nil)
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("search by app_id: got status %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
var list []map[string]any
|
||||
if err := json.Unmarshal(w.Body.Bytes(), &list); err != nil {
|
||||
t.Fatalf("unmarshal search: %v", err)
|
||||
}
|
||||
if len(list) != 1 {
|
||||
t.Errorf("search by app_id result: got %d, want 1", len(list))
|
||||
}
|
||||
if len(list) > 0 && list[0]["file_id"] != "00000000000000000000000000000010" {
|
||||
t.Errorf("file_id=%v, want upload 10", list[0]["file_id"])
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user