package httpapi import "strings" // 枚举型入参的取值校验集中在本文件。 // // 这些列在迁移里都写了 CHECK (col IN (...)),但 CHECK 是最后一道闸:非法值一路落到 // SQLite 才被拒,报出来的是原始约束错误,被统一错误处理当成服务端异常,前端看到 // 「服务端异常」而不是「这个值不合法」。必须在这一层拦下来,才能给出 400 与字段名。 // // 每个函数都直接调用 badRequest:拦截点靠它捕获调用栈,中间再包一层错误构造 helper // 会让拦截点退化成 response.go 里的构造函数(有测试钉着,见 intercept_log_test.go)。 // 空值一律给建表默认值,与原先 orDefault(...) 的默认值保持一致;返回值做 TrimSpace, // 避免「前后带空格」这种近失值又落回 CHECK。 // normalizeEventType 校验 events.event_type。 // 取值来自 0004 的 CHECK,0016 用 writable_schema 追加了 individual_team。 func normalizeEventType(v string) (string, error) { switch strings.TrimSpace(v) { case "": return "individual", nil case "individual", "team", "match", "individual_team": return strings.TrimSpace(v), nil default: return "", badRequest("eventType 只能是 individual / team / match / individual_team", v) } } // normalizeResultMode 校验 events.result_mode(0004 的 CHECK)。 func normalizeResultMode(v string) (string, error) { switch strings.TrimSpace(v) { case "": return "auto", nil case "auto", "manual": return strings.TrimSpace(v), nil default: return "", badRequest("resultMode 只能是 auto / manual", v) } } // normalizeResultType 校验 events.result_type(0004 的 CHECK)。 func normalizeResultType(v string) (string, error) { switch strings.TrimSpace(v) { case "": return "none", nil case "time", "distance", "count", "score", "none": return strings.TrimSpace(v), nil default: return "", badRequest("resultType 只能是 time / distance / count / score / none", v) } } // normalizeCompare 校验 events.compare(0004 的 CHECK)。 func normalizeCompare(v string) (string, error) { switch strings.TrimSpace(v) { case "": return "none", nil case "asc", "desc", "none": return strings.TrimSpace(v), nil default: return "", badRequest("compare 只能是 asc / desc / none", v) } } // normalizeEventStatus 校验 events.status(0004 的 CHECK)。 // 与 entries.status / results.status 同名但取值不同,故单独一个函数。 func normalizeEventStatus(v string) (string, error) { switch strings.TrimSpace(v) { case "": return "pending", nil case "pending", "ongoing", "finished", "published": return strings.TrimSpace(v), nil default: return "", badRequest("status 只能是 pending / ongoing / finished / published", v) } } // normalizeTieMode 校验 scoring_profiles.tie_mode(0003 的 CHECK)。 func normalizeTieMode(v string) (string, error) { switch strings.TrimSpace(v) { case "": return "skip", nil case "skip", "average", "higher": return strings.TrimSpace(v), nil default: return "", badRequest("tieMode 只能是 skip / average / higher", v) } } // normalizeRecordBonusMode 校验 scoring_profiles.record_bonus_mode(0003 的 CHECK)。 func normalizeRecordBonusMode(v string) (string, error) { switch strings.TrimSpace(v) { case "": return "max", nil case "max", "sum": return strings.TrimSpace(v), nil default: return "", badRequest("recordBonusMode 只能是 max / sum", v) } } // normalizeResultStatus 校验 results.status(0005 的 CHECK)。 func normalizeResultStatus(v string) (string, error) { switch strings.TrimSpace(v) { case "": return "ok", nil case "ok", "dq", "dns", "dnf", "withdrawn": return strings.TrimSpace(v), nil default: return "", badRequest("status 只能是 ok / dq / dns / dnf / withdrawn", v) } }