Cloudreve/pkg/filemanager/manager/manager.go

179 lines
6.3 KiB
Go

package manager
import (
"context"
"io"
"time"
"github.com/cloudreve/Cloudreve/v4/application/dependency"
"github.com/cloudreve/Cloudreve/v4/ent"
"github.com/cloudreve/Cloudreve/v4/inventory"
"github.com/cloudreve/Cloudreve/v4/inventory/types"
"github.com/cloudreve/Cloudreve/v4/pkg/auth"
"github.com/cloudreve/Cloudreve/v4/pkg/cache"
"github.com/cloudreve/Cloudreve/v4/pkg/conf"
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/driver"
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/fs"
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/fs/dbfs"
"github.com/cloudreve/Cloudreve/v4/pkg/hashid"
"github.com/cloudreve/Cloudreve/v4/pkg/logging"
"github.com/cloudreve/Cloudreve/v4/pkg/serializer"
"github.com/cloudreve/Cloudreve/v4/pkg/setting"
)
var (
ErrUnknownPolicyType = serializer.NewError(serializer.CodeInternalSetting, "Unknown policy type", nil)
)
const (
UploadSessionCachePrefix = "callback_"
// Ctx key for upload session
UploadSessionCtx = "uploadSession"
)
type (
FileOperation interface {
// Get gets file object by given path
Get(ctx context.Context, path *fs.URI, opts ...fs.Option) (fs.File, error)
// List lists files under given path
List(ctx context.Context, path *fs.URI, args *ListArgs) (fs.File, *fs.ListFileResult, error)
// Create creates a file or directory
Create(ctx context.Context, path *fs.URI, fileType types.FileType, opt ...fs.Option) (fs.File, error)
// Rename renames a file or directory
Rename(ctx context.Context, path *fs.URI, newName string) (fs.File, error)
// Delete deletes a group of file or directory. UnlinkOnly indicates whether to delete file record in DB only.
Delete(ctx context.Context, path []*fs.URI, opts ...fs.Option) error
// Restore restores a group of files
Restore(ctx context.Context, path ...*fs.URI) error
// MoveOrCopy moves or copies a group of files
MoveOrCopy(ctx context.Context, src []*fs.URI, dst *fs.URI, isCopy bool) error
// Update puts file content. If given file does not exist, it will create a new one.
Update(ctx context.Context, req *fs.UploadRequest, opts ...fs.Option) (fs.File, error)
// Walk walks through given path
Walk(ctx context.Context, path *fs.URI, depth int, f fs.WalkFunc, opts ...fs.Option) error
// UpsertMedata update or insert metadata of given file
PatchMedata(ctx context.Context, path []*fs.URI, data ...fs.MetadataPatch) error
// CreateViewerSession creates a viewer session for given file
CreateViewerSession(ctx context.Context, uri *fs.URI, version string, viewer *types.Viewer) (*ViewerSession, error)
// TraverseFile traverses a file to its root file, return the file with linked root.
TraverseFile(ctx context.Context, fileID int) (fs.File, error)
}
FsManagement interface {
// SharedAddressTranslation translates shared symbolic address to real address. If path does not exist,
// most recent existing parent directory will be returned.
SharedAddressTranslation(ctx context.Context, path *fs.URI, opts ...fs.Option) (fs.File, *fs.URI, error)
// Capacity gets capacity of current file system
Capacity(ctx context.Context) (*fs.Capacity, error)
// CheckIfCapacityExceeded checks if given user's capacity exceeded, and send notification email
CheckIfCapacityExceeded(ctx context.Context) error
// LocalDriver gets local driver for operating local files.
LocalDriver(policy *ent.StoragePolicy) driver.Handler
// CastStoragePolicyOnSlave check if given storage policy need to be casted to another.
// It is used on slave node, when local policy need to cast to remote policy;
// Remote policy with same node ID can be casted to local policy.
CastStoragePolicyOnSlave(ctx context.Context, policy *ent.StoragePolicy) *ent.StoragePolicy
// GetStorageDriver gets storage driver for given policy
GetStorageDriver(ctx context.Context, policy *ent.StoragePolicy) (driver.Handler, error)
// PatchView patches the view setting of a file
PatchView(ctx context.Context, uri *fs.URI, view *types.ExplorerView) error
}
ShareManagement interface {
// CreateShare creates a share link for given path
CreateOrUpdateShare(ctx context.Context, path *fs.URI, args *CreateShareArgs) (*ent.Share, error)
}
Archiver interface {
CreateArchive(ctx context.Context, uris []*fs.URI, writer io.Writer, opts ...fs.Option) (int, error)
}
FileManager interface {
fs.LockSystem
FileOperation
EntityManagement
UploadManagement
FsManagement
ShareManagement
Archiver
// Recycle reset current FileManager object and put back to resource pool
Recycle()
}
// GetEntityUrlArgs single args to get entity url
GetEntityUrlArgs struct {
URI *fs.URI
PreferredEntityID string
}
// CreateShareArgs args to create share link
CreateShareArgs struct {
ExistedShareID int
IsPrivate bool
Password string
RemainDownloads int
Expire *time.Time
ShareView bool
ShowReadMe bool
}
)
type manager struct {
user *ent.User
l logging.Logger
fs fs.FileSystem
settings setting.Provider
kv cache.Driver
config conf.ConfigProvider
stateless bool
auth auth.Auth
hasher hashid.Encoder
policyClient inventory.StoragePolicyClient
dep dependency.Dep
}
func NewFileManager(dep dependency.Dep, u *ent.User) FileManager {
config := dep.ConfigProvider()
if config.System().Mode == conf.SlaveMode || u == nil {
return newStatelessFileManager(dep)
}
return &manager{
l: dep.Logger(),
user: u,
settings: dep.SettingProvider(),
fs: dbfs.NewDatabaseFS(u, dep.FileClient(), dep.ShareClient(), dep.Logger(), dep.LockSystem(),
dep.SettingProvider(), dep.StoragePolicyClient(), dep.HashIDEncoder(), dep.UserClient(), dep.KV(), dep.NavigatorStateKV(), dep.DirectLinkClient()),
kv: dep.KV(),
config: config,
auth: dep.GeneralAuth(),
hasher: dep.HashIDEncoder(),
policyClient: dep.StoragePolicyClient(),
dep: dep,
}
}
func newStatelessFileManager(dep dependency.Dep) FileManager {
return &manager{
l: dep.Logger(),
settings: dep.SettingProvider(),
kv: dep.KV(),
config: dep.ConfigProvider(),
stateless: true,
auth: dep.GeneralAuth(),
dep: dep,
hasher: dep.HashIDEncoder(),
}
}
func (m *manager) Recycle() {
if m.fs != nil {
m.fs.Recycle()
}
}
func newOption() *fs.FsOption {
return &fs.FsOption{}
}