security: fix rate-limit bypass, payment amount check, stats leak, owner-dir collision, video panic guard

- clientIP: stop trusting client-supplied X-Forwarded-For; use gin ClientIP
  with trusted proxies limited to private docker networks
- payment: verify notify money matches order amount; remove hardcoded
  gateway default, fail loudly when api_base is unset
- stats: public endpoint now serves aggregates only; recent files (owner
  names) moved to admin-only /stats/recent
- auth: reject signups whose username/email-local collides with another
  user's media directory namespace
- v1: recover panics in background video jobs, refund + mark failed
This commit is contained in:
dokploy-bot
2026-09-19 22:13:08 +08:00
parent 34f808e7e3
commit 42208c0753
8 changed files with 107 additions and 12 deletions
+11
View File
@@ -10,6 +10,7 @@ import (
"log"
"net/http"
"path/filepath"
"runtime/debug"
"sort"
"strings"
"sync"
@@ -969,6 +970,16 @@ func (s *V1Service) runVideoJob(ctx context.Context, principal *APIPrincipal, in
defer s.inflight.Done(eventID)
startedAt := time.Now()
// A panic in provider fan-out must fail the event (and refund), not
// take down the whole API process with it.
defer func() {
if r := recover(); r != nil {
log.Printf("[v1] panic in runVideoJob event=%s model=%s: %v\n%s", eventID, modelItem.Name, r, debug.Stack())
_ = s.refundIfNeeded(ctx, principal, eventID, price)
_ = s.events.UpdateStatus(ctx, eventID, "failed", fmt.Sprintf("internal error: %v", r), 0)
}
}()
// No-store: capture only the UPSTREAM video URL. /content streams it on demand
// (grok URLs are auth-gated → fetched with the generating account's token).
var videoURL string