fix stuff

This commit is contained in:
2026-08-22 18:32:20 +02:00
parent dc124d0d77
commit 85525c76b5
5 changed files with 74 additions and 49 deletions
+1
View File
@@ -12,6 +12,7 @@ SESSION_SECRET=local-development-session-secret-change-me
COOKIE_SECURE=false COOKIE_SECURE=false
STORAGE_ENDPOINT=localhost:9000 STORAGE_ENDPOINT=localhost:9000
STORAGE_PUBLIC_ENDPOINT=
STORAGE_ACCESS_KEY=minioadmin STORAGE_ACCESS_KEY=minioadmin
STORAGE_SECRET_KEY=minioadmin STORAGE_SECRET_KEY=minioadmin
STORAGE_BUCKET=gallery-media STORAGE_BUCKET=gallery-media
+8 -6
View File
@@ -45,12 +45,14 @@ func main() {
defer database.Close() defer database.Close()
objectStorage, err := storage.NewMinIO(storage.Config{ objectStorage, err := storage.NewMinIO(storage.Config{
Endpoint: cfg.StorageEndpoint, Endpoint: cfg.StorageEndpoint,
AccessKey: cfg.StorageAccessKey, PublicEndpoint: cfg.StoragePublicEndpoint,
SecretKey: cfg.StorageSecretKey, AccessKey: cfg.StorageAccessKey,
Bucket: cfg.StorageBucket, SecretKey: cfg.StorageSecretKey,
UseSSL: cfg.StorageUseSSL, Bucket: cfg.StorageBucket,
CORSOrigins: cfg.CORSOrigin, UseSSL: cfg.StorageUseSSL,
PublicUseSSL: true,
CORSOrigins: cfg.CORSOrigin,
}) })
if err != nil { if err != nil {
log.Fatalf("storage unavailable: %v", err) log.Fatalf("storage unavailable: %v", err)
+26 -24
View File
@@ -10,18 +10,19 @@ import (
// Config contains the small set of process-level settings needed by the API. // Config contains the small set of process-level settings needed by the API.
type Config struct { type Config struct {
DBDriver string DBDriver string
Port string Port string
DatabaseURL string DatabaseURL string
SQLitePath string SQLitePath string
CORSOrigin string CORSOrigin string
SessionSecret string SessionSecret string
CookieSecure bool CookieSecure bool
StorageEndpoint string StorageEndpoint string
StorageAccessKey string StoragePublicEndpoint string
StorageSecretKey string StorageAccessKey string
StorageBucket string StorageSecretKey string
StorageUseSSL bool StorageBucket string
StorageUseSSL bool
} }
func Load() Config { func Load() Config {
@@ -32,18 +33,19 @@ func Load() Config {
} }
return Config{ return Config{
DBDriver: envOrDefault("DB_DRIVER", "postgres"), DBDriver: envOrDefault("DB_DRIVER", "postgres"),
Port: envOrDefault("PORT", "8080"), Port: envOrDefault("PORT", "8080"),
DatabaseURL: envOrDefault("DATABASE_URL", "postgres://surprise:surprise_dev_password@localhost:5432/surprise?sslmode=disable"), DatabaseURL: envOrDefault("DATABASE_URL", "postgres://surprise:surprise_dev_password@localhost:5432/surprise?sslmode=disable"),
SQLitePath: envOrDefault("SQLITE_PATH", "./data/surprise.db"), SQLitePath: envOrDefault("SQLITE_PATH", "./data/surprise.db"),
CORSOrigin: envOrDefault("CORS_ORIGIN", "http://localhost:5173,http://127.0.0.1:5173"), CORSOrigin: envOrDefault("CORS_ORIGIN", "http://localhost:5173,http://127.0.0.1:5173"),
SessionSecret: envOrDefault("SESSION_SECRET", "local-development-session-secret-change-me"), SessionSecret: envOrDefault("SESSION_SECRET", "local-development-session-secret-change-me"),
CookieSecure: parseBoolEnv("COOKIE_SECURE", false), CookieSecure: parseBoolEnv("COOKIE_SECURE", false),
StorageEndpoint: envOrDefault("STORAGE_ENDPOINT", "localhost:9000"), StorageEndpoint: envOrDefault("STORAGE_ENDPOINT", "localhost:9000"),
StorageAccessKey: envOrDefault("STORAGE_ACCESS_KEY", "minioadmin"), StoragePublicEndpoint: envOrDefault("STORAGE_PUBLIC_ENDPOINT", ""),
StorageSecretKey: envOrDefault("STORAGE_SECRET_KEY", "minioadmin"), StorageAccessKey: envOrDefault("STORAGE_ACCESS_KEY", "minioadmin"),
StorageBucket: envOrDefault("STORAGE_BUCKET", "gallery-media"), StorageSecretKey: envOrDefault("STORAGE_SECRET_KEY", "minioadmin"),
StorageUseSSL: parseBoolEnv("STORAGE_USE_SSL", false), StorageBucket: envOrDefault("STORAGE_BUCKET", "gallery-media"),
StorageUseSSL: parseBoolEnv("STORAGE_USE_SSL", false),
} }
} }
+38 -19
View File
@@ -13,12 +13,14 @@ import (
) )
type Config struct { type Config struct {
Endpoint string Endpoint string
AccessKey string PublicEndpoint string
SecretKey string AccessKey string
Bucket string SecretKey string
UseSSL bool Bucket string
CORSOrigins string UseSSL bool
PublicUseSSL bool
CORSOrigins string
} }
type ObjectInfo struct { type ObjectInfo struct {
@@ -39,9 +41,10 @@ type Storage interface {
} }
type MinIO struct { type MinIO struct {
client *minio.Client client *minio.Client
bucket string publicClient *minio.Client
corsOrigins string bucket string
corsOrigins string
} }
func NewMinIO(config Config) (*MinIO, error) { func NewMinIO(config Config) (*MinIO, error) {
@@ -55,7 +58,24 @@ func NewMinIO(config Config) (*MinIO, error) {
if config.Bucket == "" { if config.Bucket == "" {
return nil, fmt.Errorf("object storage bucket is required") return nil, fmt.Errorf("object storage bucket is required")
} }
return &MinIO{client: client, bucket: config.Bucket, corsOrigins: config.CORSOrigins}, nil
publicClient := client
if config.PublicEndpoint != "" {
publicClient, err = minio.New(config.PublicEndpoint, &minio.Options{
Creds: credentials.NewStaticV4(config.AccessKey, config.SecretKey, ""),
Secure: config.PublicUseSSL,
})
if err != nil {
return nil, fmt.Errorf("create public object storage client: %w", err)
}
}
return &MinIO{
client: client,
publicClient: publicClient,
bucket: config.Bucket,
corsOrigins: config.CORSOrigins,
}, nil
} }
func (s *MinIO) EnsureBucket(ctx context.Context) error { func (s *MinIO) EnsureBucket(ctx context.Context) error {
@@ -63,13 +83,12 @@ func (s *MinIO) EnsureBucket(ctx context.Context) error {
if err != nil { if err != nil {
return fmt.Errorf("check object storage bucket: %w", err) return fmt.Errorf("check object storage bucket: %w", err)
} }
if exists { if !exists {
return nil if err := s.client.MakeBucket(ctx, s.bucket, minio.MakeBucketOptions{}); err != nil {
} response := minio.ToErrorResponse(err)
if err := s.client.MakeBucket(ctx, s.bucket, minio.MakeBucketOptions{}); err != nil { if response.Code != "BucketAlreadyExists" && response.Code != "BucketAlreadyOwnedByYou" {
response := minio.ToErrorResponse(err) return fmt.Errorf("create object storage bucket: %w", err)
if response.Code != "BucketAlreadyExists" && response.Code != "BucketAlreadyOwnedByYou" { }
return fmt.Errorf("create object storage bucket: %w", err)
} }
} }
origins := make([]string, 0) origins := make([]string, 0)
@@ -95,7 +114,7 @@ func (s *MinIO) EnsureBucket(ctx context.Context) error {
} }
func (s *MinIO) CreateUploadURL(ctx context.Context, key, _ string, expiry time.Duration) (string, error) { func (s *MinIO) CreateUploadURL(ctx context.Context, key, _ string, expiry time.Duration) (string, error) {
url, err := s.client.PresignedPutObject(ctx, s.bucket, key, expiry) url, err := s.publicClient.PresignedPutObject(ctx, s.bucket, key, expiry)
if err != nil { if err != nil {
return "", fmt.Errorf("create upload URL: %w", err) return "", fmt.Errorf("create upload URL: %w", err)
} }
@@ -103,7 +122,7 @@ func (s *MinIO) CreateUploadURL(ctx context.Context, key, _ string, expiry time.
} }
func (s *MinIO) CreateDownloadURL(ctx context.Context, key string, expiry time.Duration) (string, error) { func (s *MinIO) CreateDownloadURL(ctx context.Context, key string, expiry time.Duration) (string, error) {
url, err := s.client.PresignedGetObject(ctx, s.bucket, key, expiry, nil) url, err := s.publicClient.PresignedGetObject(ctx, s.bucket, key, expiry, nil)
if err != nil { if err != nil {
return "", fmt.Errorf("create download URL: %w", err) return "", fmt.Errorf("create download URL: %w", err)
} }
+1
View File
@@ -49,6 +49,7 @@ services:
SESSION_SECRET: "${SESSION_SECRET:-docker-compose-session-secret-change-me}" SESSION_SECRET: "${SESSION_SECRET:-docker-compose-session-secret-change-me}"
COOKIE_SECURE: "${COOKIE_SECURE:-false}" COOKIE_SECURE: "${COOKIE_SECURE:-false}"
STORAGE_ENDPOINT: "minio:9000" STORAGE_ENDPOINT: "minio:9000"
STORAGE_PUBLIC_ENDPOINT: ""
STORAGE_ACCESS_KEY: "${STORAGE_ACCESS_KEY:-minioadmin}" STORAGE_ACCESS_KEY: "${STORAGE_ACCESS_KEY:-minioadmin}"
STORAGE_SECRET_KEY: "${STORAGE_SECRET_KEY:-minioadmin}" STORAGE_SECRET_KEY: "${STORAGE_SECRET_KEY:-minioadmin}"
STORAGE_BUCKET: "${STORAGE_BUCKET:-gallery-media}" STORAGE_BUCKET: "${STORAGE_BUCKET:-gallery-media}"