Files
warpbox-dev/backend/libs/services/storage_local.go
Daniel Legt 61b7c283a4 fix(auth): reject invalid bearer tokens instead of falling back
Modify the authentication handler to return an unauthorized error when
an invalid or disabled bearer token is provided, rather than silently
falling back to an anonymous request.

This ensures that clients attempting to authenticate but failing (due to
expired, malformed, or disabled tokens) are explicitly notified of the
auth failure instead of proceeding anonymously. True anonymous requests
without any Authorization header remain supported.
2026-05-31 13:02:58 +03:00

125 lines
2.8 KiB
Go

package services
import (
"context"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
type localStorageBackend struct {
id string
root string
}
func (b localStorageBackend) ID() string { return b.id }
func (b localStorageBackend) Type() string { return StorageBackendLocal }
func (b localStorageBackend) Put(_ context.Context, key string, body io.Reader, _ int64, _ string) error {
path, err := b.path(key)
if err != nil {
return err
}
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
return err
}
target, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o644)
if err != nil {
return err
}
defer target.Close()
_, err = io.Copy(target, body)
return err
}
func (b localStorageBackend) Get(_ context.Context, key string) (StorageObject, error) {
path, err := b.path(key)
if err != nil {
return StorageObject{}, err
}
source, err := os.Open(path)
if err != nil {
return StorageObject{}, err
}
stat, err := source.Stat()
if err != nil {
source.Close()
return StorageObject{}, err
}
return StorageObject{Key: key, Size: stat.Size(), ModTime: stat.ModTime(), Body: source}, nil
}
func (b localStorageBackend) Delete(_ context.Context, key string) error {
path, err := b.path(key)
if err != nil {
return err
}
if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
return err
}
return nil
}
func (b localStorageBackend) DeletePrefix(_ context.Context, prefix string) error {
path, err := b.path(prefix)
if err != nil {
return err
}
if err := os.RemoveAll(path); err != nil && !os.IsNotExist(err) {
return err
}
return nil
}
func (b localStorageBackend) Usage(_ context.Context) (int64, error) {
var total int64
err := filepath.WalkDir(b.root, func(path string, entry os.DirEntry, err error) error {
if err != nil {
return err
}
if entry.IsDir() {
return nil
}
info, err := entry.Info()
if err != nil {
return err
}
total += info.Size()
return nil
})
if os.IsNotExist(err) {
return 0, nil
}
return total, err
}
func (b localStorageBackend) Test(ctx context.Context) error {
key := ".warpbox-storage-test-" + randomID(6)
if err := b.Put(ctx, key, strings.NewReader("ok"), 2, "text/plain"); err != nil {
return err
}
return b.Delete(ctx, key)
}
func (b localStorageBackend) path(key string) (string, error) {
key = filepath.Clean(strings.TrimPrefix(key, "/"))
if key == "." || strings.HasPrefix(key, "..") || filepath.IsAbs(key) {
return "", fmt.Errorf("invalid storage key")
}
path := filepath.Join(b.root, key)
root, err := filepath.Abs(b.root)
if err != nil {
return "", err
}
abs, err := filepath.Abs(path)
if err != nil {
return "", err
}
if abs != root && !strings.HasPrefix(abs, root+string(os.PathSeparator)) {
return "", fmt.Errorf("invalid storage key")
}
return abs, nil
}