mirror of https://github.com/cloudreve/Cloudreve
fix(directlink): direct link should not be accessible if the parent file is in trash bin (#2415)
parent
ec53769e33
commit
65095855c1
|
@ -45,7 +45,7 @@ type (
|
|||
func NewDatabaseFS(u *ent.User, fileClient inventory.FileClient, shareClient inventory.ShareClient,
|
||||
l logging.Logger, ls lock.LockSystem, settingClient setting.Provider,
|
||||
storagePolicyClient inventory.StoragePolicyClient, hasher hashid.Encoder, userClient inventory.UserClient,
|
||||
cache, stateKv cache.Driver) fs.FileSystem {
|
||||
cache, stateKv cache.Driver, directLinkClient inventory.DirectLinkClient) fs.FileSystem {
|
||||
return &DBFS{
|
||||
user: u,
|
||||
navigators: make(map[string]Navigator),
|
||||
|
@ -59,6 +59,7 @@ func NewDatabaseFS(u *ent.User, fileClient inventory.FileClient, shareClient inv
|
|||
userClient: userClient,
|
||||
cache: cache,
|
||||
stateKv: stateKv,
|
||||
directLinkClient: directLinkClient,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,6 +70,7 @@ type DBFS struct {
|
|||
userClient inventory.UserClient
|
||||
storagePolicyClient inventory.StoragePolicyClient
|
||||
shareClient inventory.ShareClient
|
||||
directLinkClient inventory.DirectLinkClient
|
||||
l logging.Logger
|
||||
ls lock.LockSystem
|
||||
settingClient setting.Provider
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/cloudreve/Cloudreve/v4/ent"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent/user"
|
||||
"github.com/cloudreve/Cloudreve/v4/inventory"
|
||||
"github.com/cloudreve/Cloudreve/v4/inventory/types"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/fs"
|
||||
|
@ -608,6 +609,38 @@ func (f *DBFS) MoveOrCopy(ctx context.Context, path []*fs.URI, dst *fs.URI, isCo
|
|||
return ae.Aggregate()
|
||||
}
|
||||
|
||||
func (f *DBFS) GetFileFromDirectLink(ctx context.Context, dl *ent.DirectLink) (fs.File, error) {
|
||||
fileModel, err := dl.Edges.FileOrErr()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
owner, err := fileModel.Edges.OwnerOrErr()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// File owner must be active
|
||||
if owner.Status != user.StatusActive {
|
||||
return nil, fs.ErrDirectLinkInvalid.WithError(fmt.Errorf("file owner is not active"))
|
||||
}
|
||||
|
||||
file := newFile(nil, fileModel)
|
||||
|
||||
// Traverse to the root file
|
||||
baseNavigator := newBaseNavigator(f.fileClient, defaultFilter, f.user, f.hasher, f.settingClient.DBFS(ctx))
|
||||
root, err := baseNavigator.findRoot(ctx, file)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find root file: %w", err)
|
||||
}
|
||||
|
||||
if root.Name() != inventory.RootFolderName {
|
||||
return nil, serializer.NewError(serializer.CodeNotFound, "direct link not found", err)
|
||||
}
|
||||
|
||||
return file, nil
|
||||
}
|
||||
|
||||
func (f *DBFS) deleteEntity(ctx context.Context, target *File, entityId int) (inventory.StorageDiff, error) {
|
||||
if target.PrimaryEntityID() == entityId {
|
||||
return nil, fs.ErrNotSupportedAction.WithError(fmt.Errorf("cannot delete current version"))
|
||||
|
|
|
@ -197,6 +197,25 @@ func (b *baseNavigator) walkNext(ctx context.Context, root *File, next string, i
|
|||
return newFile(root, child), nil
|
||||
}
|
||||
|
||||
// findRoot finds the root folder of the given child.
|
||||
func (b *baseNavigator) findRoot(ctx context.Context, child *File) (*File, error) {
|
||||
root := child
|
||||
for {
|
||||
newRoot, err := b.walkUp(ctx, root)
|
||||
if err != nil {
|
||||
if !ent.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
root = newRoot
|
||||
}
|
||||
|
||||
return root, nil
|
||||
}
|
||||
|
||||
func (b *baseNavigator) walkUp(ctx context.Context, child *File) (*File, error) {
|
||||
parent, err := b.fileClient.GetParentFile(ctx, child.Model, false)
|
||||
if err != nil {
|
||||
|
|
|
@ -300,25 +300,6 @@ func (n *shareNavigator) ExecuteHook(ctx context.Context, hookType fs.HookType,
|
|||
return nil
|
||||
}
|
||||
|
||||
// findRoot finds the root folder of the given child.
|
||||
func (n *shareNavigator) findRoot(ctx context.Context, child *File) (*File, error) {
|
||||
root := child
|
||||
for {
|
||||
newRoot, err := n.baseNavigator.walkUp(ctx, root)
|
||||
if err != nil {
|
||||
if !ent.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
root = newRoot
|
||||
}
|
||||
|
||||
return root, nil
|
||||
}
|
||||
|
||||
func (n *shareNavigator) Walk(ctx context.Context, levelFiles []*File, limit, depth int, f WalkFunc) error {
|
||||
return n.baseNavigator.walk(ctx, levelFiles, limit, depth, f)
|
||||
}
|
||||
|
|
|
@ -93,6 +93,8 @@ type (
|
|||
// - `delete` is false: set version as current version;
|
||||
// - `delete` is true: delete version.
|
||||
VersionControl(ctx context.Context, path *URI, versionId int, delete bool) error
|
||||
// GetFileFromDirectLink gets a file from a direct link.
|
||||
GetFileFromDirectLink(ctx context.Context, dl *ent.DirectLink) (File, error)
|
||||
}
|
||||
|
||||
UploadManager interface {
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/cloudreve/Cloudreve/v4/ent"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent/user"
|
||||
"github.com/cloudreve/Cloudreve/v4/inventory/types"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/cluster/routes"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/driver"
|
||||
|
@ -147,34 +146,19 @@ func (m *manager) GetUrlForRedirectedDirectLink(ctx context.Context, dl *ent.Dir
|
|||
opt.Apply(o)
|
||||
}
|
||||
|
||||
file, err := dl.Edges.FileOrErr()
|
||||
file, err := m.fs.GetFileFromDirectLink(ctx, dl)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
owner, err := file.Edges.OwnerOrErr()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
entities, err := file.Edges.EntitiesOrErr()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
// File owner must be active
|
||||
if owner.Status != user.StatusActive {
|
||||
return "", nil, fs.ErrDirectLinkInvalid.WithError(fmt.Errorf("file owner is not active"))
|
||||
}
|
||||
|
||||
// Find primary entity
|
||||
target, found := lo.Find(entities, func(entity *ent.Entity) bool {
|
||||
return entity.ID == file.PrimaryEntity
|
||||
target, found := lo.Find(file.Entities(), func(entity fs.Entity) bool {
|
||||
return entity.ID() == file.PrimaryEntityID()
|
||||
})
|
||||
if !found {
|
||||
return "", nil, fs.ErrDirectLinkInvalid.WithError(fmt.Errorf("primary entity not found"))
|
||||
}
|
||||
primaryEntity := fs.NewEntity(target)
|
||||
primaryEntity := target
|
||||
|
||||
// Generate url
|
||||
var (
|
||||
|
|
|
@ -137,7 +137,7 @@ func NewFileManager(dep dependency.Dep, u *ent.User) FileManager {
|
|||
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.SettingProvider(), dep.StoragePolicyClient(), dep.HashIDEncoder(), dep.UserClient(), dep.KV(), dep.NavigatorStateKV(), dep.DirectLinkClient()),
|
||||
kv: dep.KV(),
|
||||
config: config,
|
||||
auth: dep.GeneralAuth(),
|
||||
|
|
Loading…
Reference in New Issue