fix: gocritic linter issues (appendAssign, ifElseChain, regexpMust)
CI / Docker compose check (push) Successful in 51s
CI / Env docs check (push) Successful in 52s
CI / Frontend deps check (push) Successful in 54s
CI / Frontend major deps (push) Successful in 53s
CI / Secrets scan (push) Successful in 55s
CI / Nginx config check (push) Successful in 57s
CI / Go build (push) Successful in 1m0s
CI / Frontend build (push) Successful in 1m4s
CI / Knip (push) Successful in 58s
CI / Go vet (dev) (push) Successful in 1m45s
CI / Frontend a11y check (push) Successful in 2m8s
CI / Go vet (prod) (push) Successful in 2m17s
CI / go mod tidy (push) Successful in 36s
CI / Frontend QC (audit) (push) Successful in 47s
CI / Staticcheck (prod) (push) Successful in 3m15s
CI / Go vulnerabilities (push) Successful in 1m22s
CI / golangci-lint (push) Has been cancelled
CI / Staticcheck (dev) (push) Has been cancelled
CI / Security scan (dev) (push) Has been cancelled
CI / Security scan (prod) (push) Has been cancelled
CI / Tests (prod) (push) Has been cancelled
CI / Tests (dev) (push) Has been cancelled
CI / Race (prod) (push) Has been cancelled
CI / Race (dev) (push) Has been cancelled
CI / Svelte strict check (push) Has been cancelled
CI / Frontend QC (typecheck) (push) Has been cancelled
CI / Frontend QC (lint) (push) Has been cancelled

This commit is contained in:
2026-07-11 18:03:05 +01:00
parent 35bc021857
commit bbbffce20d
5 changed files with 26 additions and 22 deletions
+2 -1
View File
@@ -88,7 +88,8 @@ func AdminReserveSlotHandler(w http.ResponseWriter, r *http.Request) {
return
}
var err error
allIDs := append(req.ServiceIDs, req.CustomServiceIDs...)
allIDs := append([]string{}, req.ServiceIDs...)
allIDs = append(allIDs, req.CustomServiceIDs...)
svcDuration, err = calculateServiceDurationWithOverrides(r.Context(), allIDs, req.ServiceOverrides)
if err != nil {
log.Printf("Failed to calculate duration: %v", err)
+2 -1
View File
@@ -646,7 +646,8 @@ func AdminCreateBookingForUserHandler(w http.ResponseWriter, r *http.Request) {
}
// Check for overlapping confirmed/in_progress/completed bookings
allIDs := append(req.ServiceIDs, req.CustomServiceIDs...)
allIDs := append([]string{}, req.ServiceIDs...)
allIDs = append(allIDs, req.CustomServiceIDs...)
var dur int
err := db.Conn.QueryRow(r.Context(), `
SELECT COALESCE(SUM(dur), 0) FROM (
+13 -13
View File
@@ -30,6 +30,9 @@ import (
const MaxInputLength = 256
var filterRegexp = regexp.MustCompile(`^filter\[(.+)\]$`)
var timestampRegexp = regexp.MustCompile(`^\d{15,20}$`)
func mimeTypeForField(fieldName string) string {
switch fieldName {
case "file_full_avif", "file_thumb_avif":
@@ -173,11 +176,9 @@ func ListImages(w http.ResponseWriter, r *http.Request) {
if len(values) == 0 || values[0] == "" {
continue
}
match, _ := regexp.Compile(`^filter\[(.+)\]$`)
if match != nil {
matches := match.FindStringSubmatch(key)
if len(matches) == 2 {
category := matches[1]
match := filterRegexp.FindStringSubmatch(key)
if len(match) == 2 {
category := match[1]
value := values[0]
// Validate category exists
@@ -193,17 +194,17 @@ func ListImages(w http.ResponseWriter, r *http.Request) {
}
filterClauses.WriteString(fmt.Sprintf(" AND $%d::text = ANY(tag_names)", len(filterArgs)+1))
filterArgs = append(filterArgs, category+":"+value)
}
filterArgs = append(filterArgs, category+":"+value)
}
}
var query string
var args []any
const formatCols = `, full_avif_url, full_webp_url, full_jpg_url, full_jxl_url, thumb_avif_url, thumb_webp_url, thumb_jpg_url`
if tagsFilter != "" {
switch {
case tagsFilter != "":
tagList := strings.Split(tagsFilter, ",")
cleanTags := make([]string, len(tagList))
for i, t := range tagList {
@@ -255,7 +256,7 @@ func ListImages(w http.ResponseWriter, r *http.Request) {
}
queryArgs[len(filterArgs)+len(cleanTags)+len(cursorArgs)] = limit
args = queryArgs
} else if tagFilter != "" {
case tagFilter != "":
argOffset := len(filterArgs)
searchPattern := "%" + tagFilter + "%"
searchIdx := argOffset + 1
@@ -289,7 +290,7 @@ func ListImages(w http.ResponseWriter, r *http.Request) {
}
queryArgs[searchIdx+len(cursorArgs)] = limit
args = queryArgs
} else {
default:
argOffset := len(filterArgs)
query = fmt.Sprintf(`
SELECT id, url, thumbnail_url, tag_names, created_at%s, 0 as match_count, 0.0 as relevance
@@ -1098,8 +1099,7 @@ func GetImage(w http.ResponseWriter, r *http.Request) {
// Lookup by timestamp (nanosecond Unix epoch from URL)
// Only allow numeric timestamps to prevent pattern enumeration
timestampMatch, _ := regexp.Compile(`^\d{15,20}$`)
if !timestampMatch.MatchString(imageID) {
if !timestampRegexp.MatchString(imageID) {
log.Printf("Invalid image ID format: %s", imageID)
http.Error(w, "Image not found", http.StatusNotFound)
return
+4 -3
View File
@@ -189,11 +189,12 @@ func (s *Scheduler) wrapJob(job Job) func() {
}
n, err := job.Handler(ctx)
if err != nil {
switch {
case err != nil:
log.Printf("%s[ERROR]%s %s \"%sJOB %s%s%s\" %sfailed%s: %v in %s", colorRed, colorReset, jidStr, colorBoldMagenta, colorRed, job.Name, colorReset, colorDim, colorReset, err, coloredDuration(time.Since(start)))
} else if n > 0 {
case n > 0:
log.Printf("%s[INFO]%s %s \"%sJOB %s%s%s\" %scompleted%s: %d %s in %s", colorGreen, colorReset, jidStr, colorBoldMagenta, colorGreen, job.Name, colorReset, colorDim, colorReset, n, coloredRows(n), coloredDuration(time.Since(start)))
} else {
default:
log.Printf("%s[DEBUG]%s %s \"%sJOB %s%s%s\" %scompleted%s: %s in %s", colorCyan, colorReset, jidStr, colorBoldMagenta, colorGreen, job.Name, colorReset, colorDim, colorReset, coloredRows(0), coloredDuration(time.Since(start)))
}
}
+5 -4
View File
@@ -89,13 +89,14 @@ func (prl *ProgressiveRateLimiter) Check(ip string) (delayMs int) {
// Progressive delay based on how far over the sustained limit they are
// Rate = requests per minute
if sustainedCount <= 140 {
switch {
case sustainedCount <= 140:
return 500 // 500ms - scraping but not too aggressively
} else if sustainedCount <= 200 {
case sustainedCount <= 200:
return 2000 // 2s - moderate spam
} else if sustainedCount <= 300 {
case sustainedCount <= 300:
return 5000 // 5s - heavy spam
} else {
default:
return 10000 // 10s - abuse
}
}