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
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:
@@ -88,7 +88,8 @@ func AdminReserveSlotHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
var err error
|
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)
|
svcDuration, err = calculateServiceDurationWithOverrides(r.Context(), allIDs, req.ServiceOverrides)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to calculate duration: %v", err)
|
log.Printf("Failed to calculate duration: %v", err)
|
||||||
|
|||||||
@@ -646,7 +646,8 @@ func AdminCreateBookingForUserHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for overlapping confirmed/in_progress/completed bookings
|
// 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
|
var dur int
|
||||||
err := db.Conn.QueryRow(r.Context(), `
|
err := db.Conn.QueryRow(r.Context(), `
|
||||||
SELECT COALESCE(SUM(dur), 0) FROM (
|
SELECT COALESCE(SUM(dur), 0) FROM (
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ import (
|
|||||||
|
|
||||||
const MaxInputLength = 256
|
const MaxInputLength = 256
|
||||||
|
|
||||||
|
var filterRegexp = regexp.MustCompile(`^filter\[(.+)\]$`)
|
||||||
|
var timestampRegexp = regexp.MustCompile(`^\d{15,20}$`)
|
||||||
|
|
||||||
func mimeTypeForField(fieldName string) string {
|
func mimeTypeForField(fieldName string) string {
|
||||||
switch fieldName {
|
switch fieldName {
|
||||||
case "file_full_avif", "file_thumb_avif":
|
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] == "" {
|
if len(values) == 0 || values[0] == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
match, _ := regexp.Compile(`^filter\[(.+)\]$`)
|
match := filterRegexp.FindStringSubmatch(key)
|
||||||
if match != nil {
|
if len(match) == 2 {
|
||||||
matches := match.FindStringSubmatch(key)
|
category := match[1]
|
||||||
if len(matches) == 2 {
|
|
||||||
category := matches[1]
|
|
||||||
value := values[0]
|
value := values[0]
|
||||||
|
|
||||||
// Validate category exists
|
// Validate category exists
|
||||||
@@ -193,8 +194,7 @@ func ListImages(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
filterClauses.WriteString(fmt.Sprintf(" AND $%d::text = ANY(tag_names)", len(filterArgs)+1))
|
filterClauses.WriteString(fmt.Sprintf(" AND $%d::text = ANY(tag_names)", len(filterArgs)+1))
|
||||||
filterArgs = append(filterArgs, category+":"+value)
|
filterArgs = append(filterArgs, category+":"+value)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +203,8 @@ func ListImages(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
const formatCols = `, full_avif_url, full_webp_url, full_jpg_url, full_jxl_url, thumb_avif_url, thumb_webp_url, thumb_jpg_url`
|
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, ",")
|
tagList := strings.Split(tagsFilter, ",")
|
||||||
cleanTags := make([]string, len(tagList))
|
cleanTags := make([]string, len(tagList))
|
||||||
for i, t := range 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
|
queryArgs[len(filterArgs)+len(cleanTags)+len(cursorArgs)] = limit
|
||||||
args = queryArgs
|
args = queryArgs
|
||||||
} else if tagFilter != "" {
|
case tagFilter != "":
|
||||||
argOffset := len(filterArgs)
|
argOffset := len(filterArgs)
|
||||||
searchPattern := "%" + tagFilter + "%"
|
searchPattern := "%" + tagFilter + "%"
|
||||||
searchIdx := argOffset + 1
|
searchIdx := argOffset + 1
|
||||||
@@ -289,7 +290,7 @@ func ListImages(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
queryArgs[searchIdx+len(cursorArgs)] = limit
|
queryArgs[searchIdx+len(cursorArgs)] = limit
|
||||||
args = queryArgs
|
args = queryArgs
|
||||||
} else {
|
default:
|
||||||
argOffset := len(filterArgs)
|
argOffset := len(filterArgs)
|
||||||
query = fmt.Sprintf(`
|
query = fmt.Sprintf(`
|
||||||
SELECT id, url, thumbnail_url, tag_names, created_at%s, 0 as match_count, 0.0 as relevance
|
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)
|
// Lookup by timestamp (nanosecond Unix epoch from URL)
|
||||||
// Only allow numeric timestamps to prevent pattern enumeration
|
// Only allow numeric timestamps to prevent pattern enumeration
|
||||||
timestampMatch, _ := regexp.Compile(`^\d{15,20}$`)
|
if !timestampRegexp.MatchString(imageID) {
|
||||||
if !timestampMatch.MatchString(imageID) {
|
|
||||||
log.Printf("Invalid image ID format: %s", imageID)
|
log.Printf("Invalid image ID format: %s", imageID)
|
||||||
http.Error(w, "Image not found", http.StatusNotFound)
|
http.Error(w, "Image not found", http.StatusNotFound)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -189,11 +189,12 @@ func (s *Scheduler) wrapJob(job Job) func() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
n, err := job.Handler(ctx)
|
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)))
|
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)))
|
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)))
|
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)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,13 +89,14 @@ func (prl *ProgressiveRateLimiter) Check(ip string) (delayMs int) {
|
|||||||
|
|
||||||
// Progressive delay based on how far over the sustained limit they are
|
// Progressive delay based on how far over the sustained limit they are
|
||||||
// Rate = requests per minute
|
// Rate = requests per minute
|
||||||
if sustainedCount <= 140 {
|
switch {
|
||||||
|
case sustainedCount <= 140:
|
||||||
return 500 // 500ms - scraping but not too aggressively
|
return 500 // 500ms - scraping but not too aggressively
|
||||||
} else if sustainedCount <= 200 {
|
case sustainedCount <= 200:
|
||||||
return 2000 // 2s - moderate spam
|
return 2000 // 2s - moderate spam
|
||||||
} else if sustainedCount <= 300 {
|
case sustainedCount <= 300:
|
||||||
return 5000 // 5s - heavy spam
|
return 5000 // 5s - heavy spam
|
||||||
} else {
|
default:
|
||||||
return 10000 // 10s - abuse
|
return 10000 // 10s - abuse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user