You've already forked openaccounting-server
forked from cybercinch/openaccounting-server
Consolidates storage backends into a single S3-compatible driver that supports: - AWS S3 (native) - Backblaze B2 (S3-compatible API) - Cloudflare R2 (S3-compatible API) - MinIO and other S3-compatible services - Local filesystem for development This replaces the previous separate B2 driver with a unified approach, reducing dependencies and complexity while adding support for more services. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
106 lines
2.9 KiB
Go
106 lines
2.9 KiB
Go
package storage
|
|
|
|
import (
|
|
"io"
|
|
"time"
|
|
)
|
|
|
|
// Storage defines the interface for file storage backends
|
|
type Storage interface {
|
|
// Store saves a file and returns the storage path/key
|
|
Store(filename string, content io.Reader, contentType string) (string, error)
|
|
|
|
// Retrieve gets a file by its storage path/key
|
|
Retrieve(path string) (io.ReadCloser, error)
|
|
|
|
// Delete removes a file by its storage path/key
|
|
Delete(path string) error
|
|
|
|
// GetURL returns a URL for accessing the file (may be signed/temporary)
|
|
GetURL(path string, expiry time.Duration) (string, error)
|
|
|
|
// Exists checks if a file exists at the given path
|
|
Exists(path string) (bool, error)
|
|
|
|
// GetMetadata returns file metadata (size, last modified, etc.)
|
|
GetMetadata(path string) (*FileMetadata, error)
|
|
}
|
|
|
|
// FileMetadata contains information about a stored file
|
|
type FileMetadata struct {
|
|
Size int64
|
|
LastModified time.Time
|
|
ContentType string
|
|
ETag string
|
|
}
|
|
|
|
// Config holds configuration for storage backends
|
|
type Config struct {
|
|
// Storage backend type: "local", "s3"
|
|
Backend string `mapstructure:"backend"`
|
|
|
|
// Local filesystem configuration
|
|
Local LocalConfig `mapstructure:"local"`
|
|
|
|
// S3-compatible storage configuration (S3, B2, R2, etc.)
|
|
S3 S3Config `mapstructure:"s3"`
|
|
}
|
|
|
|
// LocalConfig configures local filesystem storage
|
|
type LocalConfig struct {
|
|
// Root directory for file storage
|
|
RootDir string `mapstructure:"root_dir"`
|
|
|
|
// Base URL for serving files (optional)
|
|
BaseURL string `mapstructure:"base_url"`
|
|
}
|
|
|
|
// S3Config configures S3-compatible storage (AWS S3, Backblaze B2, Cloudflare R2, etc.)
|
|
type S3Config struct {
|
|
// AWS Region (use "auto" for Cloudflare R2)
|
|
Region string `mapstructure:"region"`
|
|
|
|
// S3 Bucket name
|
|
Bucket string `mapstructure:"bucket"`
|
|
|
|
// Optional prefix for all objects
|
|
Prefix string `mapstructure:"prefix"`
|
|
|
|
// Access Key ID
|
|
AccessKeyID string `mapstructure:"access_key_id"`
|
|
|
|
// Secret Access Key
|
|
SecretAccessKey string `mapstructure:"secret_access_key"`
|
|
|
|
// Custom endpoint URL for S3-compatible services:
|
|
// - Backblaze B2: https://s3.us-west-004.backblazeb2.com
|
|
// - Cloudflare R2: https://<account-id>.r2.cloudflarestorage.com
|
|
// - MinIO: http://localhost:9000
|
|
// Leave empty for AWS S3
|
|
Endpoint string `mapstructure:"endpoint"`
|
|
|
|
// Use path-style addressing (required for some S3-compatible services)
|
|
PathStyle bool `mapstructure:"path_style"`
|
|
}
|
|
|
|
|
|
// NewStorage creates a new storage backend based on configuration
|
|
func NewStorage(config Config) (Storage, error) {
|
|
switch config.Backend {
|
|
case "local", "":
|
|
return NewLocalStorage(config.Local)
|
|
case "s3":
|
|
return NewS3Storage(config.S3)
|
|
default:
|
|
return nil, &UnsupportedBackendError{Backend: config.Backend}
|
|
}
|
|
}
|
|
|
|
// UnsupportedBackendError is returned when an unknown storage backend is requested
|
|
type UnsupportedBackendError struct {
|
|
Backend string
|
|
}
|
|
|
|
func (e *UnsupportedBackendError) Error() string {
|
|
return "unsupported storage backend: " + e.Backend
|
|
} |