Remove usages of AppError on filesstore service (#15841)

* Remove usages of AppError on filesstore service

* Fixing a golint error

* Fixing shadowed variable

* Adding err.Error() to the NewAppError calls

* Fixing tests

* Adding missed translations

* Fix error handling and updating the translation that affects it

* Fixing two typos
Этот коммит содержится в:
Jesús Espino
2020-12-20 12:53:07 +01:00
коммит произвёл GitHub
родитель 10be00f005
Коммит 7419898449
13 изменённых файлов: 366 добавлений и 289 удалений

Просмотреть файл

@@ -5,7 +5,8 @@ package filesstore
import (
"io"
"net/http"
"github.com/pkg/errors"
"github.com/mattermost/mattermost-server/v5/model"
)
@@ -16,28 +17,28 @@ type ReadCloseSeeker interface {
}
type FileBackend interface {
TestConnection() *model.AppError
TestConnection() error
Reader(path string) (ReadCloseSeeker, *model.AppError)
ReadFile(path string) ([]byte, *model.AppError)
FileExists(path string) (bool, *model.AppError)
FileSize(path string) (int64, *model.AppError)
CopyFile(oldPath, newPath string) *model.AppError
MoveFile(oldPath, newPath string) *model.AppError
WriteFile(fr io.Reader, path string) (int64, *model.AppError)
AppendFile(fr io.Reader, path string) (int64, *model.AppError)
RemoveFile(path string) *model.AppError
Reader(path string) (ReadCloseSeeker, error)
ReadFile(path string) ([]byte, error)
FileExists(path string) (bool, error)
FileSize(path string) (int64, error)
CopyFile(oldPath, newPath string) error
MoveFile(oldPath, newPath string) error
WriteFile(fr io.Reader, path string) (int64, error)
AppendFile(fr io.Reader, path string) (int64, error)
RemoveFile(path string) error
ListDirectory(path string) (*[]string, *model.AppError)
RemoveDirectory(path string) *model.AppError
ListDirectory(path string) (*[]string, error)
RemoveDirectory(path string) error
}
func NewFileBackend(settings *model.FileSettings, enableComplianceFeatures bool) (FileBackend, *model.AppError) {
func NewFileBackend(settings *model.FileSettings, enableComplianceFeatures bool) (FileBackend, error) {
switch *settings.DriverName {
case model.IMAGE_DRIVER_S3:
backend, err := NewS3FileBackend(settings, enableComplianceFeatures)
if err != nil {
return nil, model.NewAppError("NewFileBackend", "api.file.new_backend.s3.app_error", nil, err.Error(), http.StatusInternalServerError)
return nil, errors.Wrap(err, "unable to connect to the s3 backend")
}
return backend, nil
case model.IMAGE_DRIVER_LOCAL:
@@ -45,5 +46,5 @@ func NewFileBackend(settings *model.FileSettings, enableComplianceFeatures bool)
directory: *settings.Directory,
}, nil
}
return nil, model.NewAppError("NewFileBackend", "api.file.no_driver.app_error", nil, "", http.StatusInternalServerError)
return nil, errors.New("no valid filestorage driver found")
}

Просмотреть файл

@@ -7,12 +7,12 @@ import (
"bytes"
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"github.com/pkg/errors"
"github.com/mattermost/mattermost-server/v5/mlog"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/mattermost/mattermost-server/v5/utils"
)
@@ -24,33 +24,33 @@ type LocalFileBackend struct {
directory string
}
func (b *LocalFileBackend) TestConnection() *model.AppError {
func (b *LocalFileBackend) TestConnection() error {
f := bytes.NewReader([]byte("testingwrite"))
if _, err := writeFileLocally(f, filepath.Join(b.directory, TEST_FILE_PATH)); err != nil {
return model.NewAppError("TestFileConnection", "api.file.test_connection.local.connection.app_error", nil, err.Error(), http.StatusInternalServerError)
return errors.Wrap(err, "unable to write to the local filesystem storage")
}
os.Remove(filepath.Join(b.directory, TEST_FILE_PATH))
mlog.Debug("Able to write files to local storage.")
return nil
}
func (b *LocalFileBackend) Reader(path string) (ReadCloseSeeker, *model.AppError) {
func (b *LocalFileBackend) Reader(path string) (ReadCloseSeeker, error) {
f, err := os.Open(filepath.Join(b.directory, path))
if err != nil {
return nil, model.NewAppError("Reader", "api.file.reader.reading_local.app_error", nil, err.Error(), http.StatusInternalServerError)
return nil, errors.Wrapf(err, "unable to open file %s", path)
}
return f, nil
}
func (b *LocalFileBackend) ReadFile(path string) ([]byte, *model.AppError) {
func (b *LocalFileBackend) ReadFile(path string) ([]byte, error) {
f, err := ioutil.ReadFile(filepath.Join(b.directory, path))
if err != nil {
return nil, model.NewAppError("ReadFile", "api.file.read_file.reading_local.app_error", nil, err.Error(), http.StatusInternalServerError)
return nil, errors.Wrapf(err, "unable to read file %s", path)
}
return f, nil
}
func (b *LocalFileBackend) FileExists(path string) (bool, *model.AppError) {
func (b *LocalFileBackend) FileExists(path string) (bool, error) {
_, err := os.Stat(filepath.Join(b.directory, path))
if os.IsNotExist(err) {
@@ -58,91 +58,91 @@ func (b *LocalFileBackend) FileExists(path string) (bool, *model.AppError) {
}
if err != nil {
return false, model.NewAppError("ReadFile", "api.file.file_exists.exists_local.app_error", nil, err.Error(), http.StatusInternalServerError)
return false, errors.Wrapf(err, "unable to know if file %s exists", path)
}
return true, nil
}
func (b *LocalFileBackend) FileSize(path string) (int64, *model.AppError) {
func (b *LocalFileBackend) FileSize(path string) (int64, error) {
info, err := os.Stat(filepath.Join(b.directory, path))
if err != nil {
return 0, model.NewAppError("FileSize", "api.file.file_size.local.app_error", nil, err.Error(), http.StatusInternalServerError)
return 0, errors.Wrapf(err, "unable to get file size for %s", path)
}
return info.Size(), nil
}
func (b *LocalFileBackend) CopyFile(oldPath, newPath string) *model.AppError {
func (b *LocalFileBackend) CopyFile(oldPath, newPath string) error {
if err := utils.CopyFile(filepath.Join(b.directory, oldPath), filepath.Join(b.directory, newPath)); err != nil {
return model.NewAppError("copyFile", "api.file.move_file.rename.app_error", nil, err.Error(), http.StatusInternalServerError)
return errors.Wrapf(err, "unable to copy file from %s to %s", oldPath, newPath)
}
return nil
}
func (b *LocalFileBackend) MoveFile(oldPath, newPath string) *model.AppError {
func (b *LocalFileBackend) MoveFile(oldPath, newPath string) error {
if err := os.MkdirAll(filepath.Dir(filepath.Join(b.directory, newPath)), 0750); err != nil {
return model.NewAppError("moveFile", "api.file.move_file.rename.app_error", nil, err.Error(), http.StatusInternalServerError)
return errors.Wrapf(err, "unable to create the new destination directory %s", filepath.Dir(newPath))
}
if err := os.Rename(filepath.Join(b.directory, oldPath), filepath.Join(b.directory, newPath)); err != nil {
return model.NewAppError("moveFile", "api.file.move_file.rename.app_error", nil, err.Error(), http.StatusInternalServerError)
return errors.Wrapf(err, "unable to move the file to %s to the destination directory", newPath)
}
return nil
}
func (b *LocalFileBackend) WriteFile(fr io.Reader, path string) (int64, *model.AppError) {
func (b *LocalFileBackend) WriteFile(fr io.Reader, path string) (int64, error) {
return writeFileLocally(fr, filepath.Join(b.directory, path))
}
func writeFileLocally(fr io.Reader, path string) (int64, *model.AppError) {
func writeFileLocally(fr io.Reader, path string) (int64, error) {
if err := os.MkdirAll(filepath.Dir(path), 0750); err != nil {
directory, _ := filepath.Abs(filepath.Dir(path))
return 0, model.NewAppError("WriteFile", "api.file.write_file_locally.create_dir.app_error", nil, "directory="+directory+", err="+err.Error(), http.StatusInternalServerError)
return 0, errors.Wrapf(err, "unable to create the directory %s for the file %s", directory, path)
}
fw, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return 0, model.NewAppError("WriteFile", "api.file.write_file_locally.writing.app_error", nil, err.Error(), http.StatusInternalServerError)
return 0, errors.Wrapf(err, "unable to open the file %s to write the data", path)
}
defer fw.Close()
written, err := io.Copy(fw, fr)
if err != nil {
return written, model.NewAppError("WriteFile", "api.file.write_file_locally.writing.app_error", nil, err.Error(), http.StatusInternalServerError)
return written, errors.Wrapf(err, "unable write the data in the file %s", path)
}
return written, nil
}
func (b *LocalFileBackend) AppendFile(fr io.Reader, path string) (int64, *model.AppError) {
func (b *LocalFileBackend) AppendFile(fr io.Reader, path string) (int64, error) {
fp := filepath.Join(b.directory, path)
if _, err := os.Stat(fp); err != nil {
return 0, model.NewAppError("AppendFile", "api.file.append_file.no_exist.app_error", nil, err.Error(), http.StatusInternalServerError)
return 0, errors.Wrapf(err, "unable to find the file %s to append the data", path)
}
fw, err := os.OpenFile(fp, os.O_WRONLY|os.O_APPEND, 0600)
if err != nil {
return 0, model.NewAppError("AppendFile", "api.file.append_file.opening.app_error", nil, err.Error(), http.StatusInternalServerError)
return 0, errors.Wrapf(err, "unable to open the file %s to append the data", path)
}
defer fw.Close()
written, err := io.Copy(fw, fr)
if err != nil {
return written, model.NewAppError("AppendFile", "api.file.append_file.writing.app_error", nil, err.Error(), http.StatusInternalServerError)
return written, errors.Wrapf(err, "unable append the data in the file %s", path)
}
return written, nil
}
func (b *LocalFileBackend) RemoveFile(path string) *model.AppError {
func (b *LocalFileBackend) RemoveFile(path string) error {
if err := os.Remove(filepath.Join(b.directory, path)); err != nil {
return model.NewAppError("RemoveFile", "utils.file.remove_file.local.app_error", nil, err.Error(), http.StatusInternalServerError)
return errors.Wrapf(err, "unable to remove the file %s", path)
}
return nil
}
func (b *LocalFileBackend) ListDirectory(path string) (*[]string, *model.AppError) {
func (b *LocalFileBackend) ListDirectory(path string) (*[]string, error) {
var paths []string
fileInfos, err := ioutil.ReadDir(filepath.Join(b.directory, path))
if err != nil {
if os.IsNotExist(err) {
return &paths, nil
}
return nil, model.NewAppError("ListDirectory", "utils.file.list_directory.local.app_error", nil, err.Error(), http.StatusInternalServerError)
return nil, errors.Wrapf(err, "unable to list the directory %s", path)
}
for _, fileInfo := range fileInfos {
paths = append(paths, filepath.Join(path, fileInfo.Name()))
@@ -150,9 +150,9 @@ func (b *LocalFileBackend) ListDirectory(path string) (*[]string, *model.AppErro
return &paths, nil
}
func (b *LocalFileBackend) RemoveDirectory(path string) *model.AppError {
func (b *LocalFileBackend) RemoveDirectory(path string) error {
if err := os.RemoveAll(filepath.Join(b.directory, path)); err != nil {
return model.NewAppError("RemoveDirectory", "utils.file.remove_directory.local.app_error", nil, err.Error(), http.StatusInternalServerError)
return errors.Wrapf(err, "unable to remove the directory %s", path)
}
return nil
}

Просмотреть файл

@@ -10,8 +10,6 @@ import (
filesstore "github.com/mattermost/mattermost-server/v5/services/filesstore"
mock "github.com/stretchr/testify/mock"
model "github.com/mattermost/mattermost-server/v5/model"
)
// FileBackend is an autogenerated mock type for the FileBackend type
@@ -20,7 +18,7 @@ type FileBackend struct {
}
// AppendFile provides a mock function with given fields: fr, path
func (_m *FileBackend) AppendFile(fr io.Reader, path string) (int64, *model.AppError) {
func (_m *FileBackend) AppendFile(fr io.Reader, path string) (int64, error) {
ret := _m.Called(fr, path)
var r0 int64
@@ -30,36 +28,32 @@ func (_m *FileBackend) AppendFile(fr io.Reader, path string) (int64, *model.AppE
r0 = ret.Get(0).(int64)
}
var r1 *model.AppError
if rf, ok := ret.Get(1).(func(io.Reader, string) *model.AppError); ok {
var r1 error
if rf, ok := ret.Get(1).(func(io.Reader, string) error); ok {
r1 = rf(fr, path)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
}
r1 = ret.Error(1)
}
return r0, r1
}
// CopyFile provides a mock function with given fields: oldPath, newPath
func (_m *FileBackend) CopyFile(oldPath string, newPath string) *model.AppError {
func (_m *FileBackend) CopyFile(oldPath string, newPath string) error {
ret := _m.Called(oldPath, newPath)
var r0 *model.AppError
if rf, ok := ret.Get(0).(func(string, string) *model.AppError); ok {
var r0 error
if rf, ok := ret.Get(0).(func(string, string) error); ok {
r0 = rf(oldPath, newPath)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.AppError)
}
r0 = ret.Error(0)
}
return r0
}
// FileExists provides a mock function with given fields: path
func (_m *FileBackend) FileExists(path string) (bool, *model.AppError) {
func (_m *FileBackend) FileExists(path string) (bool, error) {
ret := _m.Called(path)
var r0 bool
@@ -69,20 +63,18 @@ func (_m *FileBackend) FileExists(path string) (bool, *model.AppError) {
r0 = ret.Get(0).(bool)
}
var r1 *model.AppError
if rf, ok := ret.Get(1).(func(string) *model.AppError); ok {
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(path)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
}
r1 = ret.Error(1)
}
return r0, r1
}
// ListDirectory provides a mock function with given fields: path
func (_m *FileBackend) ListDirectory(path string) (*[]string, *model.AppError) {
func (_m *FileBackend) ListDirectory(path string) (*[]string, error) {
ret := _m.Called(path)
var r0 *[]string
@@ -94,36 +86,32 @@ func (_m *FileBackend) ListDirectory(path string) (*[]string, *model.AppError) {
}
}
var r1 *model.AppError
if rf, ok := ret.Get(1).(func(string) *model.AppError); ok {
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(path)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
}
r1 = ret.Error(1)
}
return r0, r1
}
// MoveFile provides a mock function with given fields: oldPath, newPath
func (_m *FileBackend) MoveFile(oldPath string, newPath string) *model.AppError {
func (_m *FileBackend) MoveFile(oldPath string, newPath string) error {
ret := _m.Called(oldPath, newPath)
var r0 *model.AppError
if rf, ok := ret.Get(0).(func(string, string) *model.AppError); ok {
var r0 error
if rf, ok := ret.Get(0).(func(string, string) error); ok {
r0 = rf(oldPath, newPath)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.AppError)
}
r0 = ret.Error(0)
}
return r0
}
// ReadFile provides a mock function with given fields: path
func (_m *FileBackend) ReadFile(path string) ([]byte, *model.AppError) {
func (_m *FileBackend) ReadFile(path string) ([]byte, error) {
ret := _m.Called(path)
var r0 []byte
@@ -135,20 +123,18 @@ func (_m *FileBackend) ReadFile(path string) ([]byte, *model.AppError) {
}
}
var r1 *model.AppError
if rf, ok := ret.Get(1).(func(string) *model.AppError); ok {
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(path)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
}
r1 = ret.Error(1)
}
return r0, r1
}
// Reader provides a mock function with given fields: path
func (_m *FileBackend) Reader(path string) (filesstore.ReadCloseSeeker, *model.AppError) {
func (_m *FileBackend) Reader(path string) (filesstore.ReadCloseSeeker, error) {
ret := _m.Called(path)
var r0 filesstore.ReadCloseSeeker
@@ -160,68 +146,60 @@ func (_m *FileBackend) Reader(path string) (filesstore.ReadCloseSeeker, *model.A
}
}
var r1 *model.AppError
if rf, ok := ret.Get(1).(func(string) *model.AppError); ok {
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(path)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
}
r1 = ret.Error(1)
}
return r0, r1
}
// RemoveDirectory provides a mock function with given fields: path
func (_m *FileBackend) RemoveDirectory(path string) *model.AppError {
func (_m *FileBackend) RemoveDirectory(path string) error {
ret := _m.Called(path)
var r0 *model.AppError
if rf, ok := ret.Get(0).(func(string) *model.AppError); ok {
var r0 error
if rf, ok := ret.Get(0).(func(string) error); ok {
r0 = rf(path)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.AppError)
}
r0 = ret.Error(0)
}
return r0
}
// RemoveFile provides a mock function with given fields: path
func (_m *FileBackend) RemoveFile(path string) *model.AppError {
func (_m *FileBackend) RemoveFile(path string) error {
ret := _m.Called(path)
var r0 *model.AppError
if rf, ok := ret.Get(0).(func(string) *model.AppError); ok {
var r0 error
if rf, ok := ret.Get(0).(func(string) error); ok {
r0 = rf(path)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.AppError)
}
r0 = ret.Error(0)
}
return r0
}
// TestConnection provides a mock function with given fields:
func (_m *FileBackend) TestConnection() *model.AppError {
func (_m *FileBackend) TestConnection() error {
ret := _m.Called()
var r0 *model.AppError
if rf, ok := ret.Get(0).(func() *model.AppError); ok {
var r0 error
if rf, ok := ret.Get(0).(func() error); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.AppError)
}
r0 = ret.Error(0)
}
return r0
}
// WriteFile provides a mock function with given fields: fr, path
func (_m *FileBackend) WriteFile(fr io.Reader, path string) (int64, *model.AppError) {
func (_m *FileBackend) WriteFile(fr io.Reader, path string) (int64, error) {
ret := _m.Called(fr, path)
var r0 int64
@@ -231,13 +209,11 @@ func (_m *FileBackend) WriteFile(fr io.Reader, path string) (int64, *model.AppEr
r0 = ret.Get(0).(int64)
}
var r1 *model.AppError
if rf, ok := ret.Get(1).(func(io.Reader, string) *model.AppError); ok {
var r1 error
if rf, ok := ret.Get(1).(func(io.Reader, string) error); ok {
r1 = rf(fr, path)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
}
r1 = ret.Error(1)
}
return r0, r1

Просмотреть файл

@@ -5,10 +5,8 @@ package filesstore
import (
"context"
"errors"
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strings"
@@ -16,6 +14,7 @@ import (
s3 "github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"github.com/minio/minio-go/v7/pkg/encrypt"
"github.com/pkg/errors"
"github.com/mattermost/mattermost-server/v5/mlog"
"github.com/mattermost/mattermost-server/v5/model"
@@ -118,7 +117,7 @@ func (b *S3FileBackend) s3New() (*s3.Client, error) {
return s3Clnt, nil
}
func (b *S3FileBackend) TestConnection() *model.AppError {
func (b *S3FileBackend) TestConnection() error {
exists := true
var err error
// If a path prefix is present, we attempt to test the bucket by listing objects under the path
@@ -129,14 +128,14 @@ func (b *S3FileBackend) TestConnection() *model.AppError {
if obj.Err != nil {
typedErr := s3.ToErrorResponse(obj.Err)
if typedErr.Code != bucketNotFound {
return model.NewAppError("TestFileConnection", "api.file.test_connection.s3.list_objects.app_error", nil, obj.Err.Error(), http.StatusInternalServerError)
return errors.Wrap(err, "unable to list objects in the s3 bucket")
}
exists = false
}
} else {
exists, err = b.client.BucketExists(context.Background(), b.bucket)
if err != nil {
return model.NewAppError("TestFileConnection", "api.file.test_connection.s3.bucket_exists.app_error", nil, err.Error(), http.StatusInternalServerError)
return errors.Wrap(err, "unable to check if the s3 bucket exists")
}
}
@@ -146,7 +145,7 @@ func (b *S3FileBackend) TestConnection() *model.AppError {
mlog.Warn("Bucket specified does not exist. Attempting to create...")
err := b.client.MakeBucket(context.Background(), b.bucket, s3.MakeBucketOptions{Region: b.region})
if err != nil {
return model.NewAppError("TestFileConnection", "api.file.test_connection.s3.bucket_create.app_error", nil, err.Error(), http.StatusInternalServerError)
return errors.Wrap(err, "unable to create the s3 bucket")
}
}
@@ -154,32 +153,32 @@ func (b *S3FileBackend) TestConnection() *model.AppError {
}
// Caller must close the first return value
func (b *S3FileBackend) Reader(path string) (ReadCloseSeeker, *model.AppError) {
func (b *S3FileBackend) Reader(path string) (ReadCloseSeeker, error) {
path = filepath.Join(b.pathPrefix, path)
minioObject, err := b.client.GetObject(context.Background(), b.bucket, path, s3.GetObjectOptions{})
if err != nil {
return nil, model.NewAppError("Reader", "api.file.reader.s3.app_error", nil, err.Error(), http.StatusInternalServerError)
return nil, errors.Wrapf(err, "unable to open file %s", path)
}
return minioObject, nil
}
func (b *S3FileBackend) ReadFile(path string) ([]byte, *model.AppError) {
func (b *S3FileBackend) ReadFile(path string) ([]byte, error) {
path = filepath.Join(b.pathPrefix, path)
minioObject, err := b.client.GetObject(context.Background(), b.bucket, path, s3.GetObjectOptions{})
if err != nil {
return nil, model.NewAppError("ReadFile", "api.file.read_file.s3.app_error", nil, err.Error(), http.StatusInternalServerError)
return nil, errors.Wrapf(err, "unable to open file %s", path)
}
defer minioObject.Close()
if f, err := ioutil.ReadAll(minioObject); err != nil {
return nil, model.NewAppError("ReadFile", "api.file.read_file.s3.app_error", nil, err.Error(), http.StatusInternalServerError)
return nil, errors.Wrapf(err, "unable to read file %s", path)
} else {
return f, nil
}
}
func (b *S3FileBackend) FileExists(path string) (bool, *model.AppError) {
func (b *S3FileBackend) FileExists(path string) (bool, error) {
path = filepath.Join(b.pathPrefix, path)
_, err := b.client.StatObject(context.Background(), b.bucket, path, s3.StatObjectOptions{})
@@ -192,21 +191,21 @@ func (b *S3FileBackend) FileExists(path string) (bool, *model.AppError) {
return false, nil
}
return false, model.NewAppError("FileExists", "api.file.file_exists.s3.app_error", nil, err.Error(), http.StatusInternalServerError)
return false, errors.Wrapf(err, "unable to know if file %s exists", path)
}
func (b *S3FileBackend) FileSize(path string) (int64, *model.AppError) {
func (b *S3FileBackend) FileSize(path string) (int64, error) {
path = filepath.Join(b.pathPrefix, path)
info, err := b.client.StatObject(context.Background(), b.bucket, path, s3.StatObjectOptions{})
if err != nil {
return 0, model.NewAppError("FileSize", "api.file.file_size.s3.app_error", nil, err.Error(), http.StatusInternalServerError)
return 0, errors.Wrapf(err, "unable to get file size for %s", path)
}
return info.Size, nil
}
func (b *S3FileBackend) CopyFile(oldPath, newPath string) *model.AppError {
func (b *S3FileBackend) CopyFile(oldPath, newPath string) error {
oldPath = filepath.Join(b.pathPrefix, oldPath)
newPath = filepath.Join(b.pathPrefix, newPath)
srcOpts := s3.CopySrcOptions{
@@ -220,12 +219,12 @@ func (b *S3FileBackend) CopyFile(oldPath, newPath string) *model.AppError {
Encryption: encrypt.NewSSE(),
}
if _, err := b.client.CopyObject(context.Background(), dstOpts, srcOpts); err != nil {
return model.NewAppError("copyFile", "api.file.move_file.copy_within_s3.app_error", nil, err.Error(), http.StatusInternalServerError)
return errors.Wrapf(err, "unable to copy file from %s to %s", oldPath, newPath)
}
return nil
}
func (b *S3FileBackend) MoveFile(oldPath, newPath string) *model.AppError {
func (b *S3FileBackend) MoveFile(oldPath, newPath string) error {
oldPath = filepath.Join(b.pathPrefix, oldPath)
newPath = filepath.Join(b.pathPrefix, newPath)
srcOpts := s3.CopySrcOptions{
@@ -240,17 +239,17 @@ func (b *S3FileBackend) MoveFile(oldPath, newPath string) *model.AppError {
}
if _, err := b.client.CopyObject(context.Background(), dstOpts, srcOpts); err != nil {
return model.NewAppError("moveFile", "api.file.move_file.copy_within_s3.app_error", nil, err.Error(), http.StatusInternalServerError)
return errors.Wrapf(err, "unable to copy the file to %s to the new destionation", newPath)
}
if err := b.client.RemoveObject(context.Background(), b.bucket, oldPath, s3.RemoveObjectOptions{}); err != nil {
return model.NewAppError("moveFile", "api.file.move_file.delete_from_s3.app_error", nil, err.Error(), http.StatusInternalServerError)
return errors.Wrapf(err, "unable to remove the file old file %s", oldPath)
}
return nil
}
func (b *S3FileBackend) WriteFile(fr io.Reader, path string) (int64, *model.AppError) {
func (b *S3FileBackend) WriteFile(fr io.Reader, path string) (int64, error) {
var contentType string
path = filepath.Join(b.pathPrefix, path)
if ext := filepath.Ext(path); model.IsFileExtImage(ext) {
@@ -262,16 +261,16 @@ func (b *S3FileBackend) WriteFile(fr io.Reader, path string) (int64, *model.AppE
options := s3PutOptions(b.encrypt, contentType)
info, err := b.client.PutObject(context.Background(), b.bucket, path, fr, -1, options)
if err != nil {
return info.Size, model.NewAppError("WriteFile", "api.file.write_file.s3.app_error", nil, err.Error(), http.StatusInternalServerError)
return info.Size, errors.Wrapf(err, "unable write the data in the file %s", path)
}
return info.Size, nil
}
func (b *S3FileBackend) AppendFile(fr io.Reader, path string) (int64, *model.AppError) {
func (b *S3FileBackend) AppendFile(fr io.Reader, path string) (int64, error) {
fp := filepath.Join(b.pathPrefix, path)
if _, err := b.client.StatObject(context.Background(), b.bucket, fp, s3.StatObjectOptions{}); err != nil {
return 0, model.NewAppError("AppendFile", "api.file.append_file.s3.app_error", nil, err.Error(), http.StatusInternalServerError)
return 0, errors.Wrapf(err, "unable to find the file %s to append the data", path)
}
var contentType string
@@ -302,23 +301,18 @@ func (b *S3FileBackend) AppendFile(fr io.Reader, path string) (int64, *model.App
}
_, err = b.client.ComposeObject(context.Background(), dstOpts, src1Opts, src2Opts)
if err != nil {
return 0, model.NewAppError("AppendFile", "api.file.append_file.s3.app_error", nil, err.Error(), http.StatusInternalServerError)
return 0, errors.Wrapf(err, "unable append the data in the file %s", path)
}
return info.Size, nil
}
var errString string
if err != nil {
errString = err.Error()
}
return 0, model.NewAppError("AppendFile", "api.file.append_file.s3.app_error", nil, errString, http.StatusInternalServerError)
return 0, errors.Wrapf(err, "unable append the data in the file %s", path)
}
func (b *S3FileBackend) RemoveFile(path string) *model.AppError {
func (b *S3FileBackend) RemoveFile(path string) error {
path = filepath.Join(b.pathPrefix, path)
if err := b.client.RemoveObject(context.Background(), b.bucket, path, s3.RemoveObjectOptions{}); err != nil {
return model.NewAppError("RemoveFile", "utils.file.remove_file.s3.app_error", nil, err.Error(), http.StatusInternalServerError)
return errors.Wrapf(err, "unable to remove the file %s", path)
}
return nil
@@ -344,9 +338,7 @@ func getPathsFromObjectInfos(in <-chan s3.ObjectInfo) <-chan s3.ObjectInfo {
return out
}
func (b *S3FileBackend) ListDirectory(path string) (*[]string, *model.AppError) {
var paths []string
func (b *S3FileBackend) ListDirectory(path string) (*[]string, error) {
path = filepath.Join(b.pathPrefix, path)
if !strings.HasSuffix(path, "/") && len(path) > 0 {
// s3Clnt returns only the path itself when "/" is not present
@@ -357,9 +349,10 @@ func (b *S3FileBackend) ListDirectory(path string) (*[]string, *model.AppError)
opts := s3.ListObjectsOptions{
Prefix: path,
}
var paths []string
for object := range b.client.ListObjects(context.Background(), b.bucket, opts) {
if object.Err != nil {
return nil, model.NewAppError("ListDirectory", "utils.file.list_directory.s3.app_error", nil, object.Err.Error(), http.StatusInternalServerError)
return nil, errors.Wrapf(object.Err, "unable to list the directory %s", path)
}
// We strip the path prefix that gets applied,
// so that it remains transparent to the application.
@@ -373,7 +366,7 @@ func (b *S3FileBackend) ListDirectory(path string) (*[]string, *model.AppError)
return &paths, nil
}
func (b *S3FileBackend) RemoveDirectory(path string) *model.AppError {
func (b *S3FileBackend) RemoveDirectory(path string) error {
opts := s3.ListObjectsOptions{
Prefix: filepath.Join(b.pathPrefix, path),
Recursive: true,
@@ -382,7 +375,7 @@ func (b *S3FileBackend) RemoveDirectory(path string) *model.AppError {
objectsCh := b.client.RemoveObjects(context.Background(), b.bucket, getPathsFromObjectInfos(list), s3.RemoveObjectsOptions{})
for err := range objectsCh {
if err.Err != nil {
return model.NewAppError("RemoveDirectory", "utils.file.remove_directory.s3.app_error", nil, err.Err.Error(), http.StatusInternalServerError)
return errors.Wrapf(err.Err, "unable to remove the directory %s", path)
}
}
@@ -402,9 +395,9 @@ func s3PutOptions(encrypted bool, contentType string) s3.PutObjectOptions {
return options
}
func CheckMandatoryS3Fields(settings *model.FileSettings) *model.AppError {
func CheckMandatoryS3Fields(settings *model.FileSettings) error {
if settings.AmazonS3Bucket == nil || len(*settings.AmazonS3Bucket) == 0 {
return model.NewAppError("S3File", "api.admin.test_s3.missing_s3_bucket", nil, "", http.StatusBadRequest)
return errors.New("missing s3 bucket settings")
}
// if S3 endpoint is not set call the set defaults to set that

Просмотреть файл

@@ -15,7 +15,7 @@ func TestCheckMandatoryS3Fields(t *testing.T) {
err := CheckMandatoryS3Fields(&cfg)
require.NotNil(t, err)
require.Equal(t, err.Message, "api.admin.test_s3.missing_s3_bucket", "should've failed with missing s3 bucket")
require.Equal(t, err.Error(), "missing s3 bucket settings", "should've failed with missing s3 bucket")
cfg.AmazonS3Bucket = model.NewString("test-mm")
err = CheckMandatoryS3Fields(&cfg)

Просмотреть файл

@@ -298,9 +298,9 @@ func sendMailUsingConfigAdvanced(mail mailData, config *model.Config, enableComp
defer c.Quit()
defer c.Close()
fileBackend, err := filesstore.NewFileBackend(&config.FileSettings, enableComplianceFeatures)
if err != nil {
return err
fileBackend, nErr := filesstore.NewFileBackend(&config.FileSettings, enableComplianceFeatures)
if nErr != nil {
return model.NewAppError("sendMailUsingConfigAdvanced", "api.file.no_driver.app_error", nil, nErr.Error(), http.StatusInternalServerError)
}
return SendMail(c, mail, fileBackend, time.Now())
@@ -349,14 +349,14 @@ func SendMail(c smtpClient, mail mailData, fileBackend filesstore.FileBackend, d
}
for _, fileInfo := range mail.attachments {
bytes, err := fileBackend.ReadFile(fileInfo.Path)
if err != nil {
return err
bytes, nErr := fileBackend.ReadFile(fileInfo.Path)
if nErr != nil {
return model.NewAppError("SendMail", "api.file.read_file.app_error", nil, nErr.Error(), http.StatusInternalServerError)
}
m.Attach(fileInfo.Name, gomail.SetCopyFunc(func(writer io.Writer) error {
if _, err := writer.Write(bytes); err != nil {
return model.NewAppError("SendMail", "utils.mail.sendMail.attachments.write_error", nil, err.Error(), http.StatusInternalServerError)
if _, nErr = writer.Write(bytes); nErr != nil {
return model.NewAppError("SendMail", "utils.mail.sendMail.attachments.write_error", nil, nErr.Error(), http.StatusInternalServerError)
}
return nil
}))