mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-09-24 16:05:44 +08:00
fix: address batch image ci failures
This commit is contained in:
@@ -5,14 +5,14 @@ exceptions:
|
||||
severity: high
|
||||
reason: "Admin export only; switched to dynamic import to reduce exposure (CVE-2023-30533)"
|
||||
mitigation: "Load only on export; restrict export permissions and data scope"
|
||||
expires_on: "2026-07-06"
|
||||
expires_on: "2026-08-06"
|
||||
owner: "security@your-domain"
|
||||
- package: xlsx
|
||||
advisory: "GHSA-5pgg-2g8v-p4x9"
|
||||
severity: high
|
||||
reason: "Admin export only; switched to dynamic import to reduce exposure (CVE-2024-22363)"
|
||||
mitigation: "Load only on export; restrict export permissions and data scope"
|
||||
expires_on: "2026-07-06"
|
||||
expires_on: "2026-08-06"
|
||||
owner: "security@your-domain"
|
||||
- package: lodash
|
||||
advisory: "GHSA-r5fr-rjxr-66jc"
|
||||
|
||||
@@ -147,7 +147,7 @@ func (h *BatchImageHandler) ItemContent(c *gin.Context) {
|
||||
batchImageError(c, err)
|
||||
return
|
||||
}
|
||||
defer stream.Reader.Close()
|
||||
defer func() { _ = stream.Reader.Close() }()
|
||||
|
||||
c.Header("Content-Type", stream.ContentType)
|
||||
c.Header("Content-Disposition", service.BatchImageContentDispositionAttachment(stream.Filename))
|
||||
@@ -181,7 +181,7 @@ func (h *BatchImageHandler) Download(c *gin.Context) {
|
||||
IncludeManifest: true,
|
||||
}, c.Writer)
|
||||
if err != nil {
|
||||
if result == nil || c.Writer.Written() == false {
|
||||
if result == nil || !c.Writer.Written() {
|
||||
batchImageError(c, err)
|
||||
}
|
||||
return
|
||||
|
||||
@@ -62,16 +62,6 @@ func NewBatchImageDownloadLimiter(rdb *redis.Client, cfg *config.Config) service
|
||||
}
|
||||
}
|
||||
|
||||
func newBatchImageDownloadLimiterForTest(rdb *redis.Client, maxActive int, ttl time.Duration) *batchImageDownloadLimiter {
|
||||
if maxActive <= 0 {
|
||||
maxActive = defaultBatchImageDownloadConcurrency
|
||||
}
|
||||
if ttl <= 0 {
|
||||
ttl = defaultBatchImageDownloadActiveTTL
|
||||
}
|
||||
return &batchImageDownloadLimiter{rdb: rdb, activePrefix: defaultBatchImageDownloadActivePrefix, maxActive: maxActive, ttl: ttl}
|
||||
}
|
||||
|
||||
func (l *batchImageDownloadLimiter) Acquire(ctx context.Context, userID string, kind string) (service.BatchImageDownloadPermit, error) {
|
||||
if l == nil || l.rdb == nil {
|
||||
return nil, service.ErrBatchImageDownloadLimited
|
||||
|
||||
@@ -18,7 +18,12 @@ func TestBatchImageDownloadLimiter_AcquireDenyReleaseAndTTL(t *testing.T) {
|
||||
mr := miniredis.RunT(t)
|
||||
rdb := redis.NewClient(&redis.Options{Addr: mr.Addr()})
|
||||
t.Cleanup(func() { _ = rdb.Close() })
|
||||
limiter := newBatchImageDownloadLimiterForTest(rdb, 1, time.Minute)
|
||||
limiter := &batchImageDownloadLimiter{
|
||||
rdb: rdb,
|
||||
activePrefix: defaultBatchImageDownloadActivePrefix,
|
||||
maxActive: 1,
|
||||
ttl: time.Minute,
|
||||
}
|
||||
|
||||
permit, err := limiter.Acquire(ctx, "11", "zip")
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -25,10 +25,6 @@ func NewBatchImageRepository(db *sql.DB) service.BatchImageRepository {
|
||||
return &batchImageRepository{db: db, sql: db}
|
||||
}
|
||||
|
||||
func newBatchImageRepositoryWithSQL(sqlq batchImageSQLExecutor) *batchImageRepository {
|
||||
return &batchImageRepository{sql: sqlq}
|
||||
}
|
||||
|
||||
func (r *batchImageRepository) CreateBatchImageJob(ctx context.Context, params service.CreateBatchImageJobParams) (*service.BatchImageJob, error) {
|
||||
if !service.IsSupportedBatchImageProvider(params.Provider) {
|
||||
return nil, service.ErrBatchImageInvalidProvider
|
||||
@@ -125,7 +121,7 @@ func (r *batchImageRepository) ListBatchImageJobsForOwner(ctx context.Context, u
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
defer func() { _ = rows.Close() }()
|
||||
return scanBatchImageJobs(rows)
|
||||
}
|
||||
|
||||
@@ -449,7 +445,7 @@ func (r *batchImageRepository) batchImageItemPromptPreviews(ctx context.Context,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
defer func() { _ = rows.Close() }()
|
||||
out := make(map[string]string)
|
||||
for rows.Next() {
|
||||
var customID string
|
||||
@@ -486,7 +482,7 @@ func (r *batchImageRepository) ListBatchImageItems(ctx context.Context, batchID
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
defer func() { _ = rows.Close() }()
|
||||
|
||||
var items []*service.BatchImageItem
|
||||
for rows.Next() {
|
||||
@@ -540,7 +536,7 @@ func (r *batchImageRepository) ListBatchImageJobsDueForInputCleanup(ctx context.
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
defer func() { _ = rows.Close() }()
|
||||
return scanBatchImageJobs(rows)
|
||||
}
|
||||
|
||||
@@ -559,7 +555,7 @@ func (r *batchImageRepository) ListBatchImageJobsDueForOutputCleanup(ctx context
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
defer func() { _ = rows.Close() }()
|
||||
return scanBatchImageJobs(rows)
|
||||
}
|
||||
|
||||
@@ -577,7 +573,7 @@ func (r *batchImageRepository) ListStaleUnsubmittedBatchImageJobs(ctx context.Co
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
defer func() { _ = rows.Close() }()
|
||||
return scanBatchImageJobs(rows)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,11 @@ package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -12,6 +16,10 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func newBatchImageRepositoryWithSQL(sqlq batchImageSQLExecutor) *batchImageRepository {
|
||||
return &batchImageRepository{sql: sqlq}
|
||||
}
|
||||
|
||||
func TestBatchImageRepository_CreateJobAndDuplicates(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
tx := testTx(t)
|
||||
@@ -325,7 +333,26 @@ func TestBatchImageRepository_AppendEvent(t *testing.T) {
|
||||
|
||||
func batchImageTestID(t *testing.T, prefix string) string {
|
||||
t.Helper()
|
||||
return "imgbatch_" + uniqueTestValue(t, prefix)
|
||||
safePrefix := batchImageSafeTestIDSegment(prefix, 20)
|
||||
sum := sha1.Sum([]byte(t.Name()))
|
||||
return "imgbatch_" + safePrefix + "_" + hex.EncodeToString(sum[:])[:16]
|
||||
}
|
||||
|
||||
func batchImageSafeTestIDSegment(v string, maxLen int) string {
|
||||
v = strings.ToLower(strings.TrimSpace(v))
|
||||
v = regexp.MustCompile(`[^a-z0-9_-]+`).ReplaceAllString(v, "-")
|
||||
v = strings.Trim(v, "-_")
|
||||
if v == "" {
|
||||
v = "job"
|
||||
}
|
||||
if len(v) > maxLen {
|
||||
v = v[:maxLen]
|
||||
v = strings.Trim(v, "-_")
|
||||
}
|
||||
if v == "" {
|
||||
return "job"
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func batchImageTestStringPtr(v string) *string {
|
||||
|
||||
@@ -144,7 +144,7 @@ func (s *BatchImageDownloadService) OpenItemContent(ctx context.Context, owner B
|
||||
if err != nil {
|
||||
return nil, ErrBatchImageResultMissing.WithCause(err)
|
||||
}
|
||||
defer r.Close()
|
||||
defer func() { _ = r.Close() }()
|
||||
|
||||
line, err := findBatchImageLineImages(r, item.CustomID)
|
||||
if err != nil {
|
||||
@@ -207,7 +207,7 @@ func (s *BatchImageDownloadService) StreamZip(ctx context.Context, owner BatchIm
|
||||
return nil, err
|
||||
}
|
||||
if permit != nil {
|
||||
defer permit.Release(ctx)
|
||||
defer func() { _ = permit.Release(ctx) }()
|
||||
}
|
||||
|
||||
provider, account, err := s.providerAndAccount(ctx, job)
|
||||
@@ -218,7 +218,7 @@ func (s *BatchImageDownloadService) StreamZip(ctx context.Context, owner BatchIm
|
||||
if err != nil {
|
||||
return nil, ErrBatchImageResultMissing.WithCause(err)
|
||||
}
|
||||
defer r.Close()
|
||||
defer func() { _ = r.Close() }()
|
||||
|
||||
streamCtx := ctx
|
||||
cancel := func() {}
|
||||
@@ -546,13 +546,13 @@ func sanitizeBatchImageFilenameBase(value string) string {
|
||||
for _, r := range value {
|
||||
switch {
|
||||
case r == '/' || r == '\\' || r == ':' || r == 0:
|
||||
b.WriteByte('_')
|
||||
_ = b.WriteByte('_')
|
||||
case unicode.IsControl(r):
|
||||
b.WriteByte('_')
|
||||
_ = b.WriteByte('_')
|
||||
case unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' || r == '-' || r == '.':
|
||||
b.WriteRune(r)
|
||||
_, _ = b.WriteRune(r)
|
||||
default:
|
||||
b.WriteByte('_')
|
||||
_ = b.WriteByte('_')
|
||||
}
|
||||
}
|
||||
out := strings.Trim(b.String(), ". ")
|
||||
@@ -577,7 +577,7 @@ func sanitizeBatchImageFilenameExtension(extension string) string {
|
||||
var b strings.Builder
|
||||
for _, r := range extension {
|
||||
if unicode.IsLetter(r) || unicode.IsDigit(r) {
|
||||
b.WriteRune(r)
|
||||
_, _ = b.WriteRune(r)
|
||||
}
|
||||
}
|
||||
out := b.String()
|
||||
|
||||
@@ -285,7 +285,7 @@ func (i *BatchImageResultIndexer) Index(ctx context.Context, job *BatchImageJob,
|
||||
if err != nil {
|
||||
return nil, ErrBatchImageIndexOutputMissing.WithCause(err)
|
||||
}
|
||||
defer r.Close()
|
||||
defer func() { _ = r.Close() }()
|
||||
|
||||
scanner := bufio.NewScanner(r)
|
||||
scanner.Buffer(make([]byte, 0, 64*1024), 16*1024*1024)
|
||||
|
||||
@@ -577,7 +577,7 @@ func (c *GeminiBatchHTTPClient) DownloadFile(ctx context.Context, apiKey string,
|
||||
return nil, "", err
|
||||
}
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
defer resp.Body.Close()
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
return nil, "", readGeminiAPIError(resp)
|
||||
}
|
||||
contentType := resp.Header.Get("Content-Type")
|
||||
@@ -612,7 +612,7 @@ func (c *GeminiBatchHTTPClient) doNoBody(req *http.Request) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
return readGeminiAPIError(resp)
|
||||
}
|
||||
@@ -624,7 +624,7 @@ func (c *GeminiBatchHTTPClient) doJSON(req *http.Request, out any) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
return readGeminiAPIError(resp)
|
||||
}
|
||||
|
||||
@@ -450,11 +450,11 @@ func sanitizeVertexGCSPathSegment(v string) string {
|
||||
for _, r := range v {
|
||||
switch {
|
||||
case r >= 'a' && r <= 'z', r >= 'A' && r <= 'Z', r >= '0' && r <= '9':
|
||||
b.WriteRune(r)
|
||||
_, _ = b.WriteRune(r)
|
||||
case r == '-', r == '_', r == '.':
|
||||
b.WriteRune(r)
|
||||
_, _ = b.WriteRune(r)
|
||||
default:
|
||||
b.WriteByte('-')
|
||||
_ = b.WriteByte('-')
|
||||
}
|
||||
}
|
||||
return b.String()
|
||||
@@ -876,7 +876,7 @@ func (s *VertexGCSObjectStore) OpenObject(ctx context.Context, accessToken strin
|
||||
return nil, "", err
|
||||
}
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
defer resp.Body.Close()
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
return nil, "", readVertexAPIError(resp)
|
||||
}
|
||||
contentType := resp.Header.Get("Content-Type")
|
||||
@@ -955,7 +955,7 @@ func doVertexDecodeJSON(client *http.Client, req *http.Request, out any) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
return readVertexAPIError(resp)
|
||||
}
|
||||
@@ -967,7 +967,7 @@ func doVertexNoBody(client *http.Client, req *http.Request) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
||||
return readVertexAPIError(resp)
|
||||
}
|
||||
|
||||
@@ -310,13 +310,7 @@ func (s *BatchImagePublicService) Submit(ctx context.Context, owner BatchImageOw
|
||||
for _, item := range normalized.Items {
|
||||
refs := make([]BatchImageReference, 0, len(item.ReferenceImages))
|
||||
for _, ref := range item.ReferenceImages {
|
||||
refs = append(refs, BatchImageReference{
|
||||
ID: ref.ID,
|
||||
Type: ref.Type,
|
||||
MimeType: ref.MimeType,
|
||||
Data: ref.Data,
|
||||
FileURI: ref.FileURI,
|
||||
})
|
||||
refs = append(refs, BatchImageReference(ref))
|
||||
}
|
||||
input.Items = append(input.Items, BatchImageInputItem{
|
||||
CustomID: item.CustomID,
|
||||
|
||||
Reference in New Issue
Block a user