Files
Crussell/backend/internal/s3/s3.go
T
popertots 3029fd5179
CI / Nginx config check (push) Successful in 13s
CI / Env docs check (push) Successful in 15s
CI / Docker compose check (push) Successful in 15s
CI / Frontend major deps (push) Failing after 24s
CI / Frontend deps check (push) Successful in 30s
CI / Secrets scan (push) Successful in 38s
CI / Go build (push) Successful in 39s
CI / Frontend build (push) Successful in 1m3s
CI / Knip (push) Successful in 45s
CI / Go vet (prod) (push) Failing after 1m42s
CI / Frontend a11y check (push) Successful in 2m34s
CI / Go vet (dev) (push) Successful in 2m29s
CI / Staticcheck (prod) (push) Failing after 2m38s
CI / go mod tidy (push) Successful in 1m3s
CI / Staticcheck (dev) (push) Successful in 2m55s
CI / Frontend QC (audit) (push) Successful in 51s
CI / golangci-lint (push) Successful in 3m22s
CI / Go vulnerabilities (push) Successful in 1m26s
CI / Frontend QC (typecheck) (push) Successful in 2m18s
CI / Security scan (prod) (push) Successful in 4m18s
CI / Security scan (dev) (push) Successful in 4m40s
CI / Tests (prod) (push) Has been skipped
CI / Tests (dev) (push) Has been skipped
CI / Race (prod) (push) Has been skipped
CI / Race (dev) (push) Has been skipped
CI / Frontend QC (lint) (push) Successful in 2m18s
CI / Svelte strict check (push) Successful in 43s
test: add coverage tests across backend + fix mock for PENDING checkout support
New test files cover previously untested paths across DAV, validators,
S3, Square, mw, bookings, user, and payments packages.

Includes mock fix: HoldCheckouts flag on MockClient allows tests to
pause auto-complete goroutine for testing PENDING checkout states.

Coverage: 50.4% → 65.0% (+14.6pp)
2026-07-10 18:13:44 +01:00

90 lines
2.3 KiB
Go

//go:build !dev
package s3
import (
"context"
"fmt"
"io"
"log"
"os"
)
var Client Uploader
type Uploader interface {
Upload(ctx context.Context, bucket, key string, body io.Reader, contentType string) error
Download(ctx context.Context, bucket, key string, w io.Writer) error
Delete(ctx context.Context, bucket, key string) error
GetURL(ctx context.Context, bucket, key string) (string, error)
HealthCheck(ctx context.Context) error
}
type S3Client struct {
bucket string
endpoint string
region string
accessKey string
secretKey string
publicURL string
}
func Connect() error {
endpoint := os.Getenv("R2_ENDPOINT")
if endpoint == "" {
log.Println("WARNING: R2_ENDPOINT not set, S3 client not initialized")
return nil
}
Client = &S3Client{
endpoint: endpoint,
bucket: getEnv("R2_BUCKET", ""),
region: getEnv("AWS_REGION", "auto"),
accessKey: getEnv("R2_ACCESS_KEY", ""),
secretKey: getEnv("R2_SECRET_KEY", ""),
publicURL: getEnv("R2_PUBLIC_URL", ""),
}
log.Printf("Connected to R2: bucket=%s, endpoint=%s", Client.(*S3Client).bucket, endpoint)
return nil
}
func (s *S3Client) Upload(ctx context.Context, bucket, key string, body io.Reader, contentType string) error {
// TODO: Wire in AWS SDK v2 for production S3 uploads.
// Currently only available under //go:build dev via RUSTFS.
return nil
}
func (s *S3Client) Download(ctx context.Context, bucket, key string, w io.Writer) error {
// TODO: Wire in AWS SDK v2 for production S3 downloads.
return nil
}
func (s *S3Client) Delete(ctx context.Context, bucket, key string) error {
// TODO: Wire in AWS SDK v2 for production S3 deletes.
return nil
}
func (s *S3Client) GetURL(ctx context.Context, bucket, key string) (string, error) {
return fmt.Sprintf("%s/%s/%s", s.publicURL, bucket, key), nil
}
func (s *S3Client) HealthCheck(_ context.Context) error {
if s.endpoint == "" {
return fmt.Errorf("S3 client not initialized: R2_ENDPOINT not set")
}
// Production stub — can't perform a real check without the SDK.
// Actual operations (Upload, Download, Delete) will return errors.
return nil
}
func getEnv(key, fallback string) string {
if val := os.Getenv(key); val != "" {
return val
}
if fallback != "" {
return fallback
}
panic("Environment variable not set: " + key)
}