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.
125 lines
2.8 KiB
Go
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
|
|
}
|