test(agent):回填回归测试——原生 SQL 造 NULL 老行走真实心跳+install 接口
This commit is contained in:
@@ -123,6 +123,62 @@ func TestAgentTokenBackfillOnAuthenticatedRequest(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Regression for the production failure of the first V1.0.0 deployment:
|
||||
// rows that existed before item 19 got token_plain from AutoMigrate as
|
||||
// SQL NULL, not ”, and the original guard `token_plain = ”` never
|
||||
// matches NULL — the backfill silently never fired on any legacy node.
|
||||
// Seed the row exactly as production has it (raw SQL, explicit NULL)
|
||||
// instead of through GORM, which would write ”.
|
||||
func TestAgentTokenBackfillFromNullLegacyRow(t *testing.T) {
|
||||
engine, node := setupBackfillTest(t)
|
||||
const token = "legacy-token-backfill-00000000000000000004"
|
||||
db := database.GetDB()
|
||||
if err := db.Exec(
|
||||
"INSERT INTO agent_nodes (token_hash, token_prefix, token_plain, name, node_id, last_seen, created_at, updated_at) VALUES (?, ?, NULL, ?, ?, 0, 0, 0)",
|
||||
hashAgentToken(token), token[:12], "backfill-node", node.Id,
|
||||
).Error; err != nil {
|
||||
t.Fatalf("seed NULL legacy row: %v", err)
|
||||
}
|
||||
var seeded model.AgentNode
|
||||
if err := db.Where("token_hash = ?", hashAgentToken(token)).First(&seeded).Error; err != nil {
|
||||
t.Fatalf("load seeded row: %v", err)
|
||||
}
|
||||
var nullRows int
|
||||
if err := db.Raw("SELECT COUNT(*) FROM agent_nodes WHERE id = ? AND token_plain IS NULL", seeded.Id).Scan(&nullRows).Error; err != nil {
|
||||
t.Fatalf("NULL check: %v", err)
|
||||
}
|
||||
if nullRows != 1 {
|
||||
t.Fatalf("seeded row is not SQL NULL as intended (null rows = %d)", nullRows)
|
||||
}
|
||||
|
||||
if code := heartbeatWith(engine, token); code != http.StatusOK {
|
||||
t.Fatalf("heartbeat with valid token: status %d", code)
|
||||
}
|
||||
if row := reloadAgent(t, seeded.Id); row.TokenPlain != token {
|
||||
t.Fatalf("token not backfilled from NULL legacy row: %q", row.TokenPlain)
|
||||
}
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/panel/api/agent/install/"+strconv.Itoa(node.Id), nil)
|
||||
rec := httptest.NewRecorder()
|
||||
engine.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("install endpoint: status %d", rec.Code)
|
||||
}
|
||||
var resp struct {
|
||||
Success bool `json:"success"`
|
||||
Obj struct {
|
||||
Token string `json:"token"`
|
||||
HasToken bool `json:"hasToken"`
|
||||
} `json:"obj"`
|
||||
}
|
||||
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
|
||||
t.Fatalf("install response not JSON: %v", err)
|
||||
}
|
||||
if !resp.Success || !resp.Obj.HasToken || resp.Obj.Token != token {
|
||||
t.Fatalf("install endpoint did not return the backfilled token: %+v", resp.Obj)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgentTokenNoBackfillOnFailedAuth(t *testing.T) {
|
||||
engine, node := setupBackfillTest(t)
|
||||
const token = "legacy-token-backfill-00000000000000000002"
|
||||
|
||||
Reference in New Issue
Block a user