feat: 文件上传权限优化 (#4441)

Refs https://github.com/1Panel-dev/1Panel/issues/4362
This commit is contained in:
zhengkunwang 2024-04-09 16:36:09 +08:00 committed by GitHub
parent 0751326b46
commit 1e22769c8b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 82 additions and 27 deletions

View file

@ -301,7 +301,7 @@ func (b *BaseApi) UploadFiles(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return return
} }
files := form.File["file"] uploadFiles := form.File["file"]
paths := form.Value["path"] paths := form.Value["path"]
overwrite := true overwrite := true
@ -317,16 +317,41 @@ func (b *BaseApi) UploadFiles(c *gin.Context) {
return return
} }
dir := path.Dir(paths[0]) dir := path.Dir(paths[0])
if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(dir, os.ModePerm); err != nil { info, err := os.Stat(dir)
if err != nil && os.IsNotExist(err) {
mode, err := files.GetParentMode(dir)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
if err = os.MkdirAll(dir, mode); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, fmt.Errorf("mkdir %s failed, err: %v", dir, err)) helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, fmt.Errorf("mkdir %s failed, err: %v", dir, err))
return return
} }
} }
info, err = os.Stat(dir)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
mode := info.Mode()
fileOp := files.NewFileOp()
success := 0 success := 0
failures := make(buserr.MultiErr) failures := make(buserr.MultiErr)
for _, file := range files { for _, file := range uploadFiles {
dstFilename := path.Join(paths[0], file.Filename) dstFilename := path.Join(paths[0], file.Filename)
dstDir := path.Dir(dstFilename)
if !fileOp.Stat(dstDir) {
if err = fileOp.CreateDir(dstDir, mode); err != nil {
e := fmt.Errorf("create dir [%s] failed, err: %v", path.Dir(dstFilename), err)
failures[file.Filename] = e
global.LOG.Error(e)
continue
}
}
tmpFilename := dstFilename + ".tmp" tmpFilename := dstFilename + ".tmp"
if err := c.SaveUploadedFile(file, tmpFilename); err != nil { if err := c.SaveUploadedFile(file, tmpFilename); err != nil {
_ = os.Remove(tmpFilename) _ = os.Remove(tmpFilename)
@ -335,7 +360,7 @@ func (b *BaseApi) UploadFiles(c *gin.Context) {
global.LOG.Error(e) global.LOG.Error(e)
continue continue
} }
stat, statErr := os.Stat(dstFilename) dstInfo, statErr := os.Stat(dstFilename)
if overwrite { if overwrite {
_ = os.Remove(dstFilename) _ = os.Remove(dstFilename)
} }
@ -349,7 +374,9 @@ func (b *BaseApi) UploadFiles(c *gin.Context) {
continue continue
} }
if statErr == nil { if statErr == nil {
_ = os.Chmod(dstFilename, stat.Mode()) _ = os.Chmod(dstFilename, dstInfo.Mode())
} else {
_ = os.Chmod(dstFilename, mode)
} }
success++ success++
} }
@ -567,16 +594,20 @@ func (b *BaseApi) Size(c *gin.Context) {
func mergeChunks(fileName string, fileDir string, dstDir string, chunkCount int) error { func mergeChunks(fileName string, fileDir string, dstDir string, chunkCount int) error {
op := files.NewFileOp() op := files.NewFileOp()
dstDir = strings.TrimSpace(dstDir) dstDir = strings.TrimSpace(dstDir)
mode, _ := files.GetParentMode(dstDir)
if mode == 0 {
mode = os.ModePerm
}
if _, err := os.Stat(dstDir); err != nil && os.IsNotExist(err) { if _, err := os.Stat(dstDir); err != nil && os.IsNotExist(err) {
if err = op.CreateDir(dstDir, os.ModePerm); err != nil { if err = op.CreateDir(dstDir, mode); err != nil {
return err return err
} }
} }
targetFile, err := os.Create(filepath.Join(dstDir, fileName))
targetFile, err := os.OpenFile(filepath.Join(dstDir, fileName), os.O_RDWR|os.O_CREATE, mode)
if err != nil { if err != nil {
return err return err
} }
defer targetFile.Close()
for i := 0; i < chunkCount; i++ { for i := 0; i < chunkCount; i++ {
chunkPath := filepath.Join(fileDir, fmt.Sprintf("%s.%d", fileName, i)) chunkPath := filepath.Join(fileDir, fmt.Sprintf("%s.%d", fileName, i))

View file

@ -2,6 +2,7 @@ package files
import ( import (
"bufio" "bufio"
"fmt"
"github.com/spf13/afero" "github.com/spf13/afero"
"io" "io"
"net/http" "net/http"
@ -117,3 +118,26 @@ func ReadFileByLine(filename string, page, pageSize int) ([]string, bool, error)
return lines, isEndOfFile, nil return lines, isEndOfFile, nil
} }
func GetParentMode(path string) (os.FileMode, error) {
absPath, err := filepath.Abs(path)
if err != nil {
return 0, err
}
for {
fileInfo, err := os.Stat(absPath)
if err == nil {
return fileInfo.Mode(), nil
}
if !os.IsNotExist(err) {
return 0, err
}
parentDir := filepath.Dir(absPath)
if parentDir == absPath {
return 0, fmt.Errorf("no existing directory found in the path: %s", path)
}
absPath = parentDir
}
}