fix: align WebDAV overwrite authorization
This commit is contained in:
@@ -1061,12 +1061,13 @@ func (f *webdavStorageFS) Copy(ctx context.Context, name, dest string, opts *web
|
|||||||
if sameOrDescendantPath(src, dst) {
|
if sameOrDescendantPath(src, dst) {
|
||||||
return false, webdav.NewHTTPError(http.StatusConflict, fmt.Errorf("destination is inside source"))
|
return false, webdav.NewHTTPError(http.StatusConflict, fmt.Errorf("destination is inside source"))
|
||||||
}
|
}
|
||||||
if opts != nil && opts.NoOverwrite {
|
_, dstErr := f.store.Stat(dst)
|
||||||
if _, err := f.store.Stat(dst); err == nil {
|
dstExists := dstErr == nil
|
||||||
return false, webdav.NewHTTPError(http.StatusPreconditionFailed, fmt.Errorf("destination exists"))
|
if dstErr != nil && !os.IsNotExist(dstErr) {
|
||||||
} else if !os.IsNotExist(err) {
|
return false, dstErr
|
||||||
return false, err
|
}
|
||||||
}
|
if opts != nil && opts.NoOverwrite && dstExists {
|
||||||
|
return false, webdav.NewHTTPError(http.StatusPreconditionFailed, fmt.Errorf("destination exists"))
|
||||||
}
|
}
|
||||||
if m, ok := f.store.(storage.Multi); ok {
|
if m, ok := f.store.(storage.Multi); ok {
|
||||||
srcRoot, _, srcOK := m.FindRoot(src)
|
srcRoot, _, srcOK := m.FindRoot(src)
|
||||||
@@ -1094,7 +1095,7 @@ func (f *webdavStorageFS) Copy(ctx context.Context, name, dest string, opts *web
|
|||||||
}
|
}
|
||||||
_ = created
|
_ = created
|
||||||
}
|
}
|
||||||
return true, nil
|
return !dstExists, nil
|
||||||
}
|
}
|
||||||
in, err := f.store.Open(src)
|
in, err := f.store.Open(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1114,7 +1115,7 @@ func (f *webdavStorageFS) Copy(ctx context.Context, name, dest string, opts *web
|
|||||||
if closeErr != nil {
|
if closeErr != nil {
|
||||||
return false, closeErr
|
return false, closeErr
|
||||||
}
|
}
|
||||||
return true, nil
|
return !dstExists, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *webdavStorageFS) Move(ctx context.Context, name, dest string, opts *webdav.MoveOptions) (bool, error) {
|
func (f *webdavStorageFS) Move(ctx context.Context, name, dest string, opts *webdav.MoveOptions) (bool, error) {
|
||||||
@@ -1129,12 +1130,12 @@ func (f *webdavStorageFS) Move(ctx context.Context, name, dest string, opts *web
|
|||||||
if sameOrDescendantPath(src, dst) {
|
if sameOrDescendantPath(src, dst) {
|
||||||
return false, webdav.NewHTTPError(http.StatusConflict, fmt.Errorf("destination is inside source"))
|
return false, webdav.NewHTTPError(http.StatusConflict, fmt.Errorf("destination is inside source"))
|
||||||
}
|
}
|
||||||
if opts == nil || opts.NoOverwrite {
|
if _, err := f.store.Stat(dst); err == nil {
|
||||||
if _, err := f.store.Stat(dst); err == nil {
|
// CHFS v4 MOVE does not overwrite an existing destination, even when
|
||||||
return false, webdav.NewHTTPError(http.StatusPreconditionFailed, fmt.Errorf("destination exists"))
|
// Overwrite is omitted/T and the caller has delete permission.
|
||||||
} else if !os.IsNotExist(err) {
|
return false, webdav.NewHTTPError(http.StatusPreconditionFailed, fmt.Errorf("destination exists"))
|
||||||
return false, err
|
} else if !os.IsNotExist(err) {
|
||||||
}
|
return false, err
|
||||||
}
|
}
|
||||||
if m, ok := f.store.(storage.Multi); ok {
|
if m, ok := f.store.(storage.Multi); ok {
|
||||||
srcRoot, _, srcOK := m.FindRoot(src)
|
srcRoot, _, srcOK := m.FindRoot(src)
|
||||||
@@ -1370,6 +1371,15 @@ func (f *webdavAuthFS) Create(ctx context.Context, name string, body io.ReadClos
|
|||||||
if err := f.allow(parent, auth.Write); err != nil {
|
if err := f.allow(parent, auth.Write); err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
// CHFS permits PUT to overwrite an existing file only when the target
|
||||||
|
// itself is writable. A writable parent alone is enough for creation.
|
||||||
|
if _, err := f.inner.Stat(ctx, name); err == nil {
|
||||||
|
if err := f.allow(name, auth.Write); err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
} else if !os.IsNotExist(err) {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
return f.inner.Create(ctx, name, body, opts)
|
return f.inner.Create(ctx, name, body, opts)
|
||||||
}
|
}
|
||||||
func (f *webdavAuthFS) RemoveAll(ctx context.Context, name string, opts *webdav.RemoveAllOptions) error {
|
func (f *webdavAuthFS) RemoveAll(ctx context.Context, name string, opts *webdav.RemoveAllOptions) error {
|
||||||
|
|||||||
Reference in New Issue
Block a user