Harden image admission, resource recovery and session renewal

Add exact-image compatibility policy, experimental admission, paginated build history and shared reauthentication checks. Preserve uncertain Docker creation records, bound frontend resource waits and renew runtime sessions proactively.

Lazy-load and split Monaco, add regression and opt-in live Docker fault tests, and record full race and real-browser acceptance results.
This commit is contained in:
2026-10-14 13:41:54 +08:00
parent 66abb76318
commit 9a71772771
62 changed files with 4679 additions and 332 deletions
+167
View File
@@ -0,0 +1,167 @@
package api
import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
func TestBuildHistoryPaginationAndOnDemandLogs(t *testing.T) {
a, sid := imageTestAPI(t, func(w http.ResponseWriter, r *http.Request) { t.Errorf("unexpected Docker request: %s", r.URL) })
buildQueue.Lock()
err := a.ensureBuilds()
buildQueue.Unlock()
if err != nil {
t.Fatal(err)
}
for n := 0; n < 125; n++ {
_, err := a.s.DB.Exec("INSERT INTO image_builds(id,version,status,logs,created_at) VALUES(?,?,?,?,?)", fmt.Sprintf("task-%03d", n), "1.2.3", "failed", "token=secret-value"+string(rune(10))+strings.Repeat("x", buildLogLimit), "2026-01-01")
if err != nil {
t.Fatal(err)
}
}
request := func(target, session, method string) *httptest.ResponseRecorder {
r := httptest.NewRequest(method, target, nil)
if session != "" {
r.AddCookie(&http.Cookie{Name: "dsh_session", Value: session})
addTestAccess(r, session)
}
w := httptest.NewRecorder()
if strings.HasPrefix(r.URL.Path, "/api/builds/") {
a.buildDetail(w, r)
} else {
a.builds(w, r)
}
return w
}
for _, tc := range []struct {
query string
count int
first, more string
}{
{"", 20, "task-124", "true"}, {"?limit=100", 100, "task-124", "true"},
{"?limit=20&offset=120", 5, "task-004", "false"}, {"?offset=125", 0, "", "false"},
{"?limit=20&offset=105", 20, "task-019", "false"}, {"?limit=20&offset=104", 20, "task-020", "true"},
} {
w := request("/api/builds"+tc.query, sid, "GET")
var records []buildRecord
if w.Code != 200 || json.Unmarshal(w.Body.Bytes(), &records) != nil || len(records) != tc.count {
t.Fatalf("%s: %d %s", tc.query, w.Code, w.Body.String())
}
if tc.count > 0 && records[0].ID != tc.first {
t.Fatal(records[0].ID)
}
if w.Header().Get("X-Has-More") != tc.more || strings.Contains(w.Body.String(), "logs") || strings.Contains(w.Body.String(), "secret-value") {
t.Fatal("unbounded or invalid summary response", w.Body.String())
}
}
for _, query := range []string{"?limit=0", "?limit=101", "?limit=-1", "?offset=-1", "?offset=x", "?limit=1&limit=2", "?offset=9999999999999999999999999"} {
if w := request("/api/builds"+query, sid, "GET"); w.Code != 400 {
t.Fatal(query, w.Code)
}
}
w := request("/api/builds/task-000", sid, "GET")
var b buildRecord
if w.Code != 200 || json.Unmarshal(w.Body.Bytes(), &b) != nil || b.ID != "task-000" || b.Logs == "" || len(b.Logs) > buildLogLimit || strings.Contains(b.Logs, "secret-value") {
t.Fatal(w.Code, w.Body.String())
}
for _, path := range []string{"/api/builds/missing", "/api/builds/", "/api/builds/task-000/extra"} {
if w := request(path, sid, "GET"); w.Code != 404 {
t.Fatal(path, w.Code)
}
}
if w := request("/api/builds/task-000", "", "GET"); w.Code != 401 {
t.Fatal(w.Code)
}
if w := request("/api/builds", "", "GET"); w.Code != 401 {
t.Fatal(w.Code)
}
if w := request("/api/builds/task-000", sid, "POST"); w.Code != 405 {
t.Fatal(w.Code)
}
}
func TestBuildDetailRouteAndAccess(t *testing.T) {
a, sid := imageTestAPI(t, func(w http.ResponseWriter, r *http.Request) { t.Error("unexpected Docker call") })
buildQueue.Lock()
err := a.ensureBuilds()
buildQueue.Unlock()
if err != nil {
t.Fatal(err)
}
if _, err = a.s.DB.Exec("INSERT INTO image_builds(id,version,status,created_at) VALUES('task','1.2.3','failed','now')"); err != nil {
t.Fatal(err)
}
_, csrf, err := a.s.SessionUser(sid)
if err != nil {
t.Fatal(err)
}
for _, tc := range []struct {
path, method string
access bool
status int
}{
{"/api/builds/task", "GET", true, 200}, {"/api/builds/task", "GET", false, 401},
{"/api/builds/task", "POST", true, 405}, {"/api/builds/", "GET", true, 404},
{"/api/builds/task%2Fextra", "GET", true, 404}, {"/api/builds/task/extra", "GET", true, 404},
} {
r := httptest.NewRequest(tc.method, tc.path, nil)
r.AddCookie(&http.Cookie{Name: "dsh_session", Value: sid})
if tc.access {
addTestAccess(r, sid)
}
if tc.method != "GET" {
r.Header.Set("Origin", "http://example.com")
r.Header.Set("X-CSRF-Token", csrf)
}
w := httptest.NewRecorder()
a.Handler().ServeHTTP(w, r)
if w.Code != tc.status {
t.Fatalf("%s %s: %d %s", tc.method, tc.path, w.Code, w.Body.String())
}
}
}
func TestBuildPageReconcilesOnlySelectedRecords(t *testing.T) {
unavailable := false
calls := 0
a, sid := imageTestAPI(t, func(w http.ResponseWriter, r *http.Request) {
calls++
if unavailable {
w.WriteHeader(500)
return
}
if !strings.HasPrefix(r.URL.Path, "/v1.47/images/") {
t.Errorf("unexpected request %s", r.URL)
}
w.WriteHeader(404)
})
seedVerifiedImage(t, a, "first-image", "1.2.3")
seedVerifiedImage(t, a, "second-image", "1.2.4")
if _, err := a.s.DB.Exec("UPDATE image_builds SET created_at=CASE version WHEN '1.2.3' THEN 'z' ELSE 'a' END"); err != nil {
t.Fatal(err)
}
request := func(offset int) *httptest.ResponseRecorder {
r := httptest.NewRequest("GET", fmt.Sprintf("/api/builds?limit=1&offset=%d", offset), nil)
r.AddCookie(&http.Cookie{Name: "dsh_session", Value: sid})
addTestAccess(r, sid)
w := httptest.NewRecorder()
a.builds(w, r)
return w
}
w := request(0)
if w.Code != 200 || calls != 1 || !strings.Contains(w.Body.String(), "missing") {
t.Fatal(w.Code, calls, w.Body.String())
}
var state string
if err := a.s.DB.QueryRow("SELECT status FROM image_builds WHERE version='1.2.4'").Scan(&state); err != nil || state != "success" {
t.Fatal(state, err)
}
unavailable = true
if w = request(1); w.Code != 502 {
t.Fatal(w.Code, w.Body.String())
}
}