2020-10-21 11:32:13 +02:00
|
|
|
package app
|
|
|
|
|
|
|
|
import (
|
2022-06-13 10:05:42 +02:00
|
|
|
"errors"
|
2020-10-21 11:32:13 +02:00
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
2020-11-09 14:19:03 +02:00
|
|
|
|
2023-03-07 06:51:53 +02:00
|
|
|
"github.com/mattermost/focalboard/server/model"
|
2022-06-13 10:05:42 +02:00
|
|
|
mmModel "github.com/mattermost/mattermost-server/v6/model"
|
2021-08-25 22:08:01 +02:00
|
|
|
|
2022-06-13 10:05:42 +02:00
|
|
|
"github.com/mattermost/focalboard/server/utils"
|
2021-08-24 12:13:58 +02:00
|
|
|
"github.com/mattermost/mattermost-server/v6/shared/filestore"
|
2022-06-13 10:05:42 +02:00
|
|
|
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
2020-10-21 11:32:13 +02:00
|
|
|
)
|
|
|
|
|
2022-06-13 10:05:42 +02:00
|
|
|
const emptyString = "empty"
|
|
|
|
|
|
|
|
var errEmptyFilename = errors.New("IsFileArchived: empty filename not allowed")
|
2022-10-05 22:16:03 +02:00
|
|
|
var ErrFileNotFound = errors.New("file not found")
|
2022-06-13 10:05:42 +02:00
|
|
|
|
2022-03-22 16:24:34 +02:00
|
|
|
func (a *App) SaveFile(reader io.Reader, teamID, rootID, filename string) (string, error) {
|
2020-10-21 11:32:13 +02:00
|
|
|
// NOTE: File extension includes the dot
|
|
|
|
fileExtension := strings.ToLower(filepath.Ext(filename))
|
|
|
|
if fileExtension == ".jpeg" {
|
|
|
|
fileExtension = ".jpg"
|
|
|
|
}
|
|
|
|
|
2022-06-13 10:05:42 +02:00
|
|
|
createdFilename := utils.NewID(utils.IDTypeNone)
|
|
|
|
fullFilename := fmt.Sprintf(`%s%s`, createdFilename, fileExtension)
|
2023-03-07 06:51:53 +02:00
|
|
|
filePath := filepath.Join(utils.GetBaseFilePath(), fullFilename)
|
2020-10-21 11:32:13 +02:00
|
|
|
|
2022-06-13 10:05:42 +02:00
|
|
|
fileSize, appErr := a.filesBackend.WriteFile(reader, filePath)
|
2020-10-21 11:32:13 +02:00
|
|
|
if appErr != nil {
|
2021-07-09 03:09:02 +02:00
|
|
|
return "", fmt.Errorf("unable to store the file in the files storage: %w", appErr)
|
2020-10-21 11:32:13 +02:00
|
|
|
}
|
2020-10-22 15:22:36 +02:00
|
|
|
|
2022-06-13 10:05:42 +02:00
|
|
|
now := utils.GetMillis()
|
|
|
|
|
|
|
|
fileInfo := &mmModel.FileInfo{
|
|
|
|
Id: createdFilename[1:],
|
|
|
|
CreatorId: "boards",
|
|
|
|
PostId: emptyString,
|
|
|
|
ChannelId: emptyString,
|
|
|
|
CreateAt: now,
|
|
|
|
UpdateAt: now,
|
|
|
|
DeleteAt: 0,
|
2023-03-07 06:51:53 +02:00
|
|
|
Path: filePath,
|
2022-06-13 10:05:42 +02:00
|
|
|
ThumbnailPath: emptyString,
|
|
|
|
PreviewPath: emptyString,
|
|
|
|
Name: filename,
|
|
|
|
Extension: fileExtension,
|
|
|
|
Size: fileSize,
|
|
|
|
MimeType: emptyString,
|
|
|
|
Width: 0,
|
|
|
|
Height: 0,
|
|
|
|
HasPreviewImage: false,
|
|
|
|
MiniPreview: nil,
|
|
|
|
Content: "",
|
|
|
|
RemoteId: nil,
|
|
|
|
}
|
2023-03-07 06:51:53 +02:00
|
|
|
|
2022-06-13 10:05:42 +02:00
|
|
|
err := a.store.SaveFileInfo(fileInfo)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
return fullFilename, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *App) GetFileInfo(filename string) (*mmModel.FileInfo, error) {
|
|
|
|
if len(filename) == 0 {
|
|
|
|
return nil, errEmptyFilename
|
|
|
|
}
|
|
|
|
|
|
|
|
// filename is in the format 7<some-alphanumeric-string>.<extension>
|
|
|
|
// we want to extract the <some-alphanumeric-string> part of this as this
|
|
|
|
// will be the fileinfo id.
|
|
|
|
parts := strings.Split(filename, ".")
|
|
|
|
fileInfoID := parts[0][1:]
|
2023-03-07 06:51:53 +02:00
|
|
|
|
2022-06-13 10:05:42 +02:00
|
|
|
fileInfo, err := a.store.GetFileInfo(fileInfoID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return fileInfo, nil
|
2020-10-21 11:32:13 +02:00
|
|
|
}
|
|
|
|
|
2023-03-07 06:51:53 +02:00
|
|
|
func (a *App) GetFile(teamID, rootID, fileName string) (*mmModel.FileInfo, filestore.ReadCloseSeeker, error) {
|
|
|
|
fileInfo, err := a.GetFileInfo(fileName)
|
|
|
|
if err != nil && !model.IsErrNotFound(err) {
|
|
|
|
a.logger.Error("111")
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var filePath string
|
|
|
|
|
|
|
|
if fileInfo != nil && fileInfo.Path != "" {
|
|
|
|
filePath = fileInfo.Path
|
|
|
|
} else {
|
|
|
|
filePath = filepath.Join(teamID, rootID, fileName)
|
|
|
|
}
|
|
|
|
|
|
|
|
exists, err := a.filesBackend.FileExists(filePath)
|
|
|
|
if err != nil {
|
|
|
|
a.logger.Error(fmt.Sprintf("GetFile: Failed to check if file exists as path. Path: %s, error: %e", filePath, err))
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if !exists {
|
|
|
|
return nil, nil, ErrFileNotFound
|
|
|
|
}
|
|
|
|
|
|
|
|
reader, err := a.filesBackend.Reader(filePath)
|
|
|
|
if err != nil {
|
|
|
|
a.logger.Error(fmt.Sprintf("GetFile: Failed to get file reader of existing file at path: %s, error: %e", filePath, err))
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return fileInfo, reader, nil
|
|
|
|
}
|
|
|
|
|
2022-03-22 16:24:34 +02:00
|
|
|
func (a *App) GetFileReader(teamID, rootID, filename string) (filestore.ReadCloseSeeker, error) {
|
|
|
|
filePath := filepath.Join(teamID, rootID, filename)
|
2021-05-24 19:06:11 +02:00
|
|
|
exists, err := a.filesBackend.FileExists(filePath)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-04-01 00:30:25 +02:00
|
|
|
// FIXUP: Check the deprecated old location
|
2022-03-22 16:24:34 +02:00
|
|
|
if teamID == "0" && !exists {
|
2021-06-21 11:21:42 +02:00
|
|
|
oldExists, err2 := a.filesBackend.FileExists(filename)
|
|
|
|
if err2 != nil {
|
|
|
|
return nil, err2
|
2021-05-24 19:06:11 +02:00
|
|
|
}
|
|
|
|
if oldExists {
|
2021-06-21 11:21:42 +02:00
|
|
|
err2 := a.filesBackend.MoveFile(filename, filePath)
|
|
|
|
if err2 != nil {
|
|
|
|
a.logger.Error("ERROR moving file",
|
|
|
|
mlog.String("old", filename),
|
|
|
|
mlog.String("new", filePath),
|
|
|
|
mlog.Err(err2),
|
|
|
|
)
|
2021-04-01 00:30:25 +02:00
|
|
|
} else {
|
2021-06-21 11:21:42 +02:00
|
|
|
a.logger.Debug("Moved file",
|
|
|
|
mlog.String("old", filename),
|
|
|
|
mlog.String("new", filePath),
|
|
|
|
)
|
2021-04-01 00:30:25 +02:00
|
|
|
}
|
|
|
|
}
|
2022-10-05 22:16:03 +02:00
|
|
|
} else if !exists {
|
|
|
|
return nil, ErrFileNotFound
|
2021-04-01 00:30:25 +02:00
|
|
|
}
|
|
|
|
|
2021-05-24 19:06:11 +02:00
|
|
|
reader, err := a.filesBackend.Reader(filePath)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return reader, nil
|
2021-04-01 00:30:25 +02:00
|
|
|
}
|
2022-10-05 22:16:03 +02:00
|
|
|
|
|
|
|
func (a *App) MoveFile(channelID, teamID, boardID, filename string) error {
|
|
|
|
oldPath := filepath.Join(channelID, boardID, filename)
|
|
|
|
newPath := filepath.Join(teamID, boardID, filename)
|
|
|
|
err := a.filesBackend.MoveFile(oldPath, newPath)
|
|
|
|
if err != nil {
|
|
|
|
a.logger.Error("ERROR moving file",
|
|
|
|
mlog.String("old", oldPath),
|
|
|
|
mlog.String("new", newPath),
|
|
|
|
mlog.Err(err),
|
|
|
|
)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|