fix(security): check user permission to rename files

pull/979/head
Oleg Lobanov 2020-06-06 17:45:51 +02:00
parent b8300b7121
commit 28672c0114
No known key found for this signature in database
GPG Key ID: 7CC64E41212621B0
4 changed files with 40 additions and 36 deletions

View File

@ -14,4 +14,6 @@ var (
ErrIsDirectory = errors.New("file is directory") ErrIsDirectory = errors.New("file is directory")
ErrInvalidOption = errors.New("invalid option") ErrInvalidOption = errors.New("invalid option")
ErrInvalidAuthMethod = errors.New("invalid auth method") ErrInvalidAuthMethod = errors.New("invalid auth method")
ErrPermissionDenied = errors.New("permission denied")
ErrInvalidRequestParams = errors.New("invalid request params")
) )

View File

@ -2,7 +2,7 @@
<div class="item" <div class="item"
role="button" role="button"
tabindex="0" tabindex="0"
draggable="true" :draggable="isDraggable"
@dragstart="dragStart" @dragstart="dragStart"
@dragover="dragOver" @dragover="dragOver"
@drop="drop" @drop="drop"
@ -44,7 +44,7 @@ export default {
}, },
props: ['name', 'isDir', 'url', 'type', 'size', 'modified', 'index'], props: ['name', 'isDir', 'url', 'type', 'size', 'modified', 'index'],
computed: { computed: {
...mapState(['selected', 'req']), ...mapState(['selected', 'req', 'user']),
...mapGetters(['selectedCount']), ...mapGetters(['selectedCount']),
isSelected () { isSelected () {
return (this.selected.indexOf(this.index) !== -1) return (this.selected.indexOf(this.index) !== -1)
@ -56,6 +56,9 @@ export default {
if (this.type === 'video') return 'movie' if (this.type === 'video') return 'movie'
return 'insert_drive_file' return 'insert_drive_file'
}, },
isDraggable () {
return this.user.perm.rename
},
canDrop () { canDrop () {
if (!this.isDir) return false if (!this.isDir) return false

View File

@ -9,9 +9,8 @@ import (
"os" "os"
"strings" "strings"
"github.com/filebrowser/filebrowser/v2/files"
"github.com/filebrowser/filebrowser/v2/errors" "github.com/filebrowser/filebrowser/v2/errors"
"github.com/filebrowser/filebrowser/v2/files"
"github.com/filebrowser/filebrowser/v2/fileutils" "github.com/filebrowser/filebrowser/v2/fileutils"
) )
@ -119,7 +118,6 @@ var resourcePostPutHandler = withUser(func(w http.ResponseWriter, r *http.Reques
return errToStatus(err), err return errToStatus(err), err
}) })
//nolint: goconst
var resourcePatchHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { var resourcePatchHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
src := r.URL.Path src := r.URL.Path
dst := r.URL.Query().Get("destination") dst := r.URL.Query().Get("destination")
@ -134,26 +132,22 @@ var resourcePatchHandler = withUser(func(w http.ResponseWriter, r *http.Request,
return http.StatusForbidden, nil return http.StatusForbidden, nil
} }
err = d.RunHook(func() error {
switch action { switch action {
// TODO: use enum // TODO: use enum
case "copy": case "copy":
if !d.user.Perm.Create { if !d.user.Perm.Create {
return http.StatusForbidden, nil return errors.ErrPermissionDenied
} }
case "rename":
default:
action = "rename"
if !d.user.Perm.Rename {
return http.StatusForbidden, nil
}
}
err = d.RunHook(func() error {
if action == "copy" {
return fileutils.Copy(d.user.Fs, src, dst) return fileutils.Copy(d.user.Fs, src, dst)
case "rename":
if !d.user.Perm.Rename {
return errors.ErrPermissionDenied
} }
return d.user.Fs.Rename(src, dst) return d.user.Fs.Rename(src, dst)
default:
return fmt.Errorf("unsupported action %s: %w", action, errors.ErrInvalidRequestParams)
}
}, action, src, dst, d.user) }, action, src, dst, d.user)
return errToStatus(err), err return errToStatus(err), err

View File

@ -2,12 +2,13 @@ package http
import ( import (
"encoding/json" "encoding/json"
"errors"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
"strings" "strings"
"github.com/filebrowser/filebrowser/v2/errors" libErrors "github.com/filebrowser/filebrowser/v2/errors"
) )
func renderJSON(w http.ResponseWriter, _ *http.Request, data interface{}) (int, error) { func renderJSON(w http.ResponseWriter, _ *http.Request, data interface{}) (int, error) {
@ -31,10 +32,14 @@ func errToStatus(err error) int {
return http.StatusOK return http.StatusOK
case os.IsPermission(err): case os.IsPermission(err):
return http.StatusForbidden return http.StatusForbidden
case os.IsNotExist(err), err == errors.ErrNotExist: case os.IsNotExist(err), err == libErrors.ErrNotExist:
return http.StatusNotFound return http.StatusNotFound
case os.IsExist(err), err == errors.ErrExist: case os.IsExist(err), err == libErrors.ErrExist:
return http.StatusConflict return http.StatusConflict
case errors.Is(err, libErrors.ErrPermissionDenied):
return http.StatusForbidden
case errors.Is(err, libErrors.ErrInvalidRequestParams):
return http.StatusBadRequest
default: default:
return http.StatusInternalServerError return http.StatusInternalServerError
} }