grafana/pkg/infra/filestorage/api.go
Artur Wierzbicki a8b90d9a25
FileStore: add basic file storage API (#46051)
* #45498: fs API alpha

* #45498: remove grafanaDS changes for filestorage.go

* #45498: fix lint

* #45498: fix lint

* #45498: remove db file storage migration

* #45498: linting

* #45498: linting

* #45498: linting

* #45498: fix imports

* #45498: add comment

* remove StorageName abstractions

* FileStore: add dummy implementation (#46071)

* #45498: bring back grafanaDs changes, add dummy filestorage

* #45498: rename grafanaDs to public

* #45498: modify join

* #45498: review fix

* #45498:  unnecessary leading newline (whitespace) IMPORTANT FIX

* #45498: fix belongsToStorage

* #45498: fix removeStoragePrefix so that it works with abs paths

Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
2022-03-03 10:53:26 +04:00

102 lines
2.1 KiB
Go

package filestorage
import (
"context"
"errors"
"strings"
"time"
)
type StorageName string
const (
StorageNamePublic StorageName = "public"
)
var (
ErrRelativePath = errors.New("path cant be relative")
ErrNonCanonicalPath = errors.New("path must be canonical")
ErrPathTooLong = errors.New("path is too long")
ErrPathInvalid = errors.New("path is invalid")
ErrPathEndsWithDelimiter = errors.New("path can not end with delimiter")
Delimiter = "/"
)
func Join(parts ...string) string {
return Delimiter + strings.Join(parts, Delimiter)
}
func belongsToStorage(path string, storageName StorageName) bool {
return strings.HasPrefix(path, Delimiter+string(storageName))
}
type File struct {
Contents []byte
FileMetadata
}
type FileMetadata struct {
Name string
FullPath string
MimeType string
Modified time.Time
Created time.Time
Size int64
Properties map[string]string
}
type ListFilesResponse struct {
Files []FileMetadata
HasMore bool
LastPath string
}
type Paging struct {
After string
First int
}
type UpsertFileCommand struct {
Path string
MimeType string
Contents *[]byte
Properties map[string]string
}
type PathFilters struct {
allowedPrefixes []string
}
func (f *PathFilters) isAllowed(path string) bool {
if f == nil || f.allowedPrefixes == nil {
return true
}
for i := range f.allowedPrefixes {
if strings.HasPrefix(path, strings.ToLower(f.allowedPrefixes[i])) {
return true
}
}
return false
}
type ListOptions struct {
Recursive bool
PathFilters
}
type FileStorage interface {
Get(ctx context.Context, path string) (*File, error)
Delete(ctx context.Context, path string) error
Upsert(ctx context.Context, command *UpsertFileCommand) error
ListFiles(ctx context.Context, folderPath string, paging *Paging, options *ListOptions) (*ListFilesResponse, error)
ListFolders(ctx context.Context, folderPath string, options *ListOptions) ([]FileMetadata, error)
CreateFolder(ctx context.Context, path string) error
DeleteFolder(ctx context.Context, path string) error
close() error
}