Files
ARTEX/server/task_intercept.go
BaaRai e233c02314 Translate all Chinese text to English
Comments, doc comments, UI labels, log and error messages, LLM prompt
strings, markdown docs, test data and assertions. Identifiers, enum
keys, routes, placeholders and code structure are unchanged.

Notes:
- docs/漏洞流量证据.md renamed to docs/vulnerability-traffic-evidence.md
- tests that exercised CJK specific handling (GBK zip names, Chinese
  full text search) now use ASCII equivalents; go build passes and the
  test suite matches the pre translation baseline (remaining failures
  need a PostgreSQL DSN and fail identically on the original)
- frontend mention syntax now uses English kinds (finding, asset, ...)
  matching the backend, chat mentions tests pass
2026-10-08 23:14:34 +02:00

193 lines
4.7 KiB
Go

package server
import (
"fmt"
"net/http"
"github.com/Autumn-27/artex/db"
)
// CRUD for task-level asset intercept/allow rules. Rules belong to a task_id
// and only apply to that task: action=block intercepts (testing forbidden),
// action=allow allows (whitelist). Enforcement lives in db.EvaluateAssetGate.
type taskInterceptRuleReq struct {
Enabled bool `json:"enabled"`
Action string `json:"action"` // block | allow
Kind string `json:"kind"`
Pattern string `json:"pattern"`
Note string `json:"note"`
}
// validateTaskInterceptRuleReq normalizes and validates; it reuses the global
// rule's kind/pattern validators.
func validateTaskInterceptRuleReq(req *taskInterceptRuleReq) error {
if req.Action == "" {
req.Action = "block"
}
if req.Action != "block" && req.Action != "allow" {
return fmt.Errorf("action must be block or allow")
}
v := assetInterceptRuleReq{Enabled: req.Enabled, Kind: req.Kind, Pattern: req.Pattern, Note: req.Note}
if err := validateAssetInterceptRuleReq(&v); err != nil {
return err
}
req.Pattern = v.Pattern // already trimmed
return nil
}
// buildTaskInterceptRules validates the task-level rules entered at task
// creation and converts them to the db input shape.
func buildTaskInterceptRules(reqs []taskInterceptRuleReq) ([]db.TaskInterceptRuleInput, error) {
if len(reqs) == 0 {
return nil, nil
}
out := make([]db.TaskInterceptRuleInput, 0, len(reqs))
for i := range reqs {
rq := reqs[i]
if err := validateTaskInterceptRuleReq(&rq); err != nil {
return nil, err
}
out = append(out, db.TaskInterceptRuleInput{
Enabled: rq.Enabled,
Action: rq.Action,
Kind: rq.Kind,
Pattern: rq.Pattern,
Note: rq.Note,
})
}
return out, nil
}
func (s *Server) taskInterceptListRules(w http.ResponseWriter, r *http.Request) {
pg := s.pg(w)
if pg == nil {
return
}
taskID, ok := pathInt(r, "id")
if !ok || taskID <= 0 {
writeErr(w, 400, "bad task id")
return
}
rules, err := pg.Assets().ListTaskInterceptRules(taskID)
if err != nil {
writeErr(w, 500, err.Error())
return
}
if rules == nil {
rules = []db.AssetInterceptRule{}
}
writeJSON(w, 200, map[string]any{"rules": rules})
}
func (s *Server) taskInterceptCreateRule(w http.ResponseWriter, r *http.Request) {
pg := s.pg(w)
if pg == nil {
return
}
taskID, ok := pathInt(r, "id")
if !ok || taskID <= 0 {
writeErr(w, 400, "bad task id")
return
}
var req taskInterceptRuleReq
if err := decode(r, &req); err != nil {
writeErr(w, 400, err.Error())
return
}
if err := validateTaskInterceptRuleReq(&req); err != nil {
writeErr(w, 400, err.Error())
return
}
rule, err := pg.Assets().CreateTaskInterceptRule(taskID, req.Action, req.Kind, req.Pattern, req.Note, req.Enabled)
if err != nil {
writeErr(w, 500, err.Error())
return
}
writeJSON(w, 200, rule)
}
func (s *Server) taskInterceptUpdateRule(w http.ResponseWriter, r *http.Request) {
pg := s.pg(w)
if pg == nil {
return
}
taskID, ok := pathInt(r, "id")
if !ok || taskID <= 0 {
writeErr(w, 400, "bad task id")
return
}
ruleID, ok := pathInt(r, "rid")
if !ok || ruleID <= 0 {
writeErr(w, 400, "bad rule id")
return
}
var req taskInterceptRuleReq
if err := decode(r, &req); err != nil {
writeErr(w, 400, err.Error())
return
}
if err := validateTaskInterceptRuleReq(&req); err != nil {
writeErr(w, 400, err.Error())
return
}
rule, err := pg.Assets().UpdateTaskInterceptRule(taskID, ruleID, req.Action, req.Kind, req.Pattern, req.Note, req.Enabled)
if err != nil {
writeErr(w, 500, err.Error())
return
}
writeJSON(w, 200, rule)
}
func (s *Server) taskInterceptDeleteRule(w http.ResponseWriter, r *http.Request) {
pg := s.pg(w)
if pg == nil {
return
}
taskID, ok := pathInt(r, "id")
if !ok || taskID <= 0 {
writeErr(w, 400, "bad task id")
return
}
ruleID, ok := pathInt(r, "rid")
if !ok || ruleID <= 0 {
writeErr(w, 400, "bad rule id")
return
}
deleted, err := pg.Assets().DeleteTaskInterceptRule(taskID, ruleID)
if err != nil {
writeErr(w, 500, err.Error())
return
}
writeJSON(w, 200, map[string]any{"deleted": deleted})
}
func (s *Server) taskInterceptToggleRule(w http.ResponseWriter, r *http.Request) {
pg := s.pg(w)
if pg == nil {
return
}
taskID, ok := pathInt(r, "id")
if !ok || taskID <= 0 {
writeErr(w, 400, "bad task id")
return
}
ruleID, ok := pathInt(r, "rid")
if !ok || ruleID <= 0 {
writeErr(w, 400, "bad rule id")
return
}
var req struct {
Enabled bool `json:"enabled"`
}
if err := decode(r, &req); err != nil {
writeErr(w, 400, err.Error())
return
}
if err := pg.Assets().ToggleTaskInterceptRule(taskID, ruleID, req.Enabled); err != nil {
writeErr(w, 500, err.Error())
return
}
writeJSON(w, 200, map[string]any{"ok": true, "enabled": req.Enabled})
}