Harden sessions, uploads, admin demotion, and HTTP timeouts.

Address PR review findings: renew session tokens on auth, sniff/re-encode avatars, serialize last-admin checks, bound server timeouts, rune-safe truncation, and TEST_DATABASE_URL-only integration tests.
This commit is contained in:
2026-08-22 07:24:39 -07:00
parent 247fb05281
commit afd2476f3c
11 changed files with 113 additions and 36 deletions
+19 -4
View File
@@ -311,13 +311,13 @@ func (s *Server) handleSubmit(w http.ResponseWriter, r *http.Request) {
return
}
if len(title) > 120 {
title = title[:120]
title = truncateRunes(title, 120)
}
if len(body) > 8000 {
body = body[:8000]
body = truncateRunes(body, 8000)
}
if len(city) > 80 {
city = city[:80]
city = truncateRunes(city, 80)
}
q := store.NewQuestion(s.db)
q.AuthorID = u.ID
@@ -449,7 +449,7 @@ func (s *Server) handleAnswer(w http.ResponseWriter, r *http.Request) {
return
}
if len(body) > 12000 {
body = body[:12000]
body = truncateRunes(body, 12000)
}
ans := store.NewAnswer(s.db)
ans.QuestionID = id
@@ -518,6 +518,21 @@ func (s *Server) exec(w http.ResponseWriter, name string, data any) {
}
}
// truncateRunes shortens s to at most max runes without splitting a code point.
func truncateRunes(s string, max int) string {
if max <= 0 {
return ""
}
n := 0
for byteIdx := range s {
if n == max {
return s[:byteIdx]
}
n++
}
return s
}
func randomHex(n int) string {
b := make([]byte, n)
if _, err := rand.Read(b); err != nil {