diff --git a/models/file.go b/models/file.go index d842e22..67777ed 100644 --- a/models/file.go +++ b/models/file.go @@ -22,7 +22,7 @@ type File struct { Policy Policy `gorm:"PRELOAD:false,association_autoupdate:false"` // 数据库忽略字段 - PositionTemp string `gorm:"-"` + Position string `gorm:"-"` } // Create 创建文件记录 @@ -40,7 +40,7 @@ func (folder *Folder) GetChildFile(name string) (*File, error) { result := DB.Where("folder_id = ? AND name = ?", folder.ID, name).Find(&file) if result.Error == nil { - file.PositionTemp = path.Join(folder.PositionTemp, folder.Name, file.Name) + file.Position = path.Join(folder.Position, folder.Name, file.Name) } return &file, result.Error } diff --git a/models/file_test.go b/models/file_test.go index 4e9054a..7bfd2c4 100644 --- a/models/file_test.go +++ b/models/file_test.go @@ -44,7 +44,7 @@ func TestFolder_GetChildFile(t *testing.T) { asserts.NoError(mock.ExpectationsWereMet()) asserts.NoError(err) asserts.Equal("1.txt", file.Name) - asserts.Equal("/1.txt", file.PositionTemp) + asserts.Equal("/1.txt", file.Position) } // 不存在 diff --git a/models/folder.go b/models/folder.go index 4d89cf2..5d93760 100644 --- a/models/folder.go +++ b/models/folder.go @@ -16,7 +16,7 @@ type Folder struct { OwnerID uint `gorm:"index:owner_id"` // 数据库忽略字段 - PositionTemp string `gorm:"-"` + Position string `gorm:"-"` } // Create 创建目录 @@ -37,7 +37,7 @@ func (folder *Folder) GetChild(name string) (*Folder, error) { // 将子目录的路径传递下去 if err == nil { - resFolder.PositionTemp = path.Join(folder.PositionTemp, folder.Name) + resFolder.Position = path.Join(folder.Position, folder.Name) } return &resFolder, err } diff --git a/models/folder_test.go b/models/folder_test.go index 4416ad9..65e99a5 100644 --- a/models/folder_test.go +++ b/models/folder_test.go @@ -51,7 +51,7 @@ func TestFolder_GetChild(t *testing.T) { asserts.NoError(mock.ExpectationsWereMet()) asserts.NoError(err) asserts.Equal(sub.Name, "sub") - asserts.Equal("/", sub.PositionTemp) + asserts.Equal("/", sub.Position) } // 目录不存在 diff --git a/pkg/filesystem/file_test.go b/pkg/filesystem/file_test.go index 2c889ea..cd3c656 100644 --- a/pkg/filesystem/file_test.go +++ b/pkg/filesystem/file_test.go @@ -22,7 +22,6 @@ func TestFileSystem_AddFile(t *testing.T) { Model: gorm.Model{ ID: 1, }, - PositionAbsolute: "/我的文件", } fs := FileSystem{ User: &model.User{ @@ -79,26 +78,35 @@ func TestFileSystem_GetContent(t *testing.T) { asserts.NoError(err) _ = file.Close() + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1). + WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1)) mock.ExpectQuery("SELECT(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "policy_id"}).AddRow(1, "TestFileSystem_GetContent.txt", 1)) mock.ExpectQuery("SELECT(.+)poli(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "type"}).AddRow(1, "unknown")) - rs, err = fs.GetContent(ctx, "TestFileSystem_GetContent.txt") + rs, err = fs.GetContent(ctx, "/TestFileSystem_GetContent.txt") asserts.Error(err) asserts.NoError(mock.ExpectationsWereMet()) // 打开文件失败 + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1). + WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1)) mock.ExpectQuery("SELECT(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "policy_id"}).AddRow(1, "TestFileSystem_GetContent.txt", 1)) mock.ExpectQuery("SELECT(.+)poli(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "type", "source_name"}).AddRow(1, "local", "not exist")) - rs, err = fs.GetContent(ctx, "TestFileSystem_GetContent.txt") + rs, err = fs.GetContent(ctx, "/TestFileSystem_GetContent.txt") asserts.Equal(serializer.CodeIOFailed, err.(serializer.AppError).Code) asserts.NoError(mock.ExpectationsWereMet()) // 打开成功 + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1). + WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1)) mock.ExpectQuery("SELECT(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "policy_id", "source_name"}).AddRow(1, "TestFileSystem_GetContent.txt", 1, "TestFileSystem_GetContent.txt")) mock.ExpectQuery("SELECT(.+)poli(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "type"}).AddRow(1, "local")) - rs, err = fs.GetContent(ctx, "TestFileSystem_GetContent.txt") + rs, err = fs.GetContent(ctx, "/TestFileSystem_GetContent.txt") asserts.NoError(err) asserts.NoError(mock.ExpectationsWereMet()) } @@ -122,20 +130,26 @@ func TestFileSystem_GetDownloadContent(t *testing.T) { asserts.NoError(err) _ = file.Close() + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1). + WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1)) mock.ExpectQuery("SELECT(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "policy_id", "source_name"}).AddRow(1, "TestFileSystem_GetDownloadContent.txt", 1, "TestFileSystem_GetDownloadContent.txt")) mock.ExpectQuery("SELECT(.+)poli(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "type"}).AddRow(1, "local")) // 无限速 - _, err = fs.GetDownloadContent(ctx, "TestFileSystem_GetDownloadContent.txt") + _, err = fs.GetDownloadContent(ctx, "/TestFileSystem_GetDownloadContent.txt") asserts.NoError(err) asserts.NoError(mock.ExpectationsWereMet()) // 有限速 + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1). + WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1)) mock.ExpectQuery("SELECT(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "name", "policy_id", "source_name"}).AddRow(1, "TestFileSystem_GetDownloadContent.txt", 1, "TestFileSystem_GetDownloadContent.txt")) mock.ExpectQuery("SELECT(.+)poli(.+)").WillReturnRows(sqlmock.NewRows([]string{"id", "type"}).AddRow(1, "local")) fs.User.Group.SpeedLimit = 1 - _, err = fs.GetDownloadContent(ctx, "TestFileSystem_GetDownloadContent.txt") + _, err = fs.GetDownloadContent(ctx, "/TestFileSystem_GetDownloadContent.txt") asserts.NoError(err) asserts.NoError(mock.ExpectationsWereMet()) } diff --git a/pkg/filesystem/hooks.go b/pkg/filesystem/hooks.go index 558ac04..4dc6d83 100644 --- a/pkg/filesystem/hooks.go +++ b/pkg/filesystem/hooks.go @@ -4,7 +4,6 @@ import ( "context" "errors" "github.com/HFO4/cloudreve/pkg/util" - "path" ) // Hook 钩子函数 @@ -118,10 +117,10 @@ func GenericAfterUpload(ctx context.Context, fs *FileSystem) error { } // 检查文件是否存在 - if ok, _ := fs.IsFileExist(path.Join( - virtualPath, + if ok, _ := fs.IsChildFileExist( + folder, ctx.Value(FileHeaderCtx).(FileHeader).GetFileName(), - )); ok { + ); ok { return ErrFileExisted } diff --git a/pkg/filesystem/hooks_test.go b/pkg/filesystem/hooks_test.go index b0da5e9..a04135f 100644 --- a/pkg/filesystem/hooks_test.go +++ b/pkg/filesystem/hooks_test.go @@ -104,9 +104,13 @@ func TestGenericAfterUpload(t *testing.T) { ctx = context.WithValue(ctx, SavePathCtx, "") // 正常 - mock.ExpectQuery("SELECT(.+)folders(.+)").WillReturnRows( - mock.NewRows([]string{"name"}).AddRow("我的文件"), - ) + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1). + WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) + // 1 + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1, 1, "我的文件"). + WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(2, 1)) mock.ExpectQuery("SELECT(.+)files(.+)").WillReturnError(errors.New("not found")) mock.ExpectBegin() mock.ExpectExec("INSERT(.+)files(.+)").WillReturnResult(sqlmock.NewResult(1, 1)) @@ -125,9 +129,13 @@ func TestGenericAfterUpload(t *testing.T) { asserts.NoError(mock.ExpectationsWereMet()) // 文件已存在 - mock.ExpectQuery("SELECT(.+)folders(.+)").WillReturnRows( - mock.NewRows([]string{"name"}).AddRow("我的文件"), - ) + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1). + WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) + // 1 + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1, 1, "我的文件"). + WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(2, 1)) mock.ExpectQuery("SELECT(.+)files(.+)").WillReturnRows( mock.NewRows([]string{"name"}).AddRow("test.txt"), ) @@ -136,9 +144,14 @@ func TestGenericAfterUpload(t *testing.T) { asserts.NoError(mock.ExpectationsWereMet()) // 插入失败 - mock.ExpectQuery("SELECT(.+)folders(.+)").WillReturnRows( - mock.NewRows([]string{"name"}).AddRow("我的文件"), - ) + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1). + WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) + // 1 + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1, 1, "我的文件"). + WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(2, 1)) + mock.ExpectQuery("SELECT(.+)files(.+)").WillReturnError(errors.New("not found")) mock.ExpectBegin() mock.ExpectExec("INSERT(.+)files(.+)").WillReturnError(errors.New("error")) @@ -217,7 +230,10 @@ func TestHookIsFileExist(t *testing.T) { }} ctx := context.WithValue(context.Background(), PathCtx, "/test.txt") { - mock.ExpectQuery("SELECT(.+)").WithArgs(uint(1), "/", "test.txt").WillReturnRows( + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1). + WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) + mock.ExpectQuery("SELECT(.+)").WithArgs(uint(1), "test.txt").WillReturnRows( sqlmock.NewRows([]string{"Name"}).AddRow("s"), ) err := HookIsFileExist(ctx, fs) @@ -225,7 +241,10 @@ func TestHookIsFileExist(t *testing.T) { asserts.NoError(err) } { - mock.ExpectQuery("SELECT(.+)").WithArgs(uint(1), "/", "test.txt").WillReturnRows( + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1). + WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) + mock.ExpectQuery("SELECT(.+)").WithArgs(uint(1), "test.txt").WillReturnRows( sqlmock.NewRows([]string{"Name"}), ) err := HookIsFileExist(ctx, fs) diff --git a/pkg/filesystem/manage.go b/pkg/filesystem/manage.go index 2448cb6..f0cbe1e 100644 --- a/pkg/filesystem/manage.go +++ b/pkg/filesystem/manage.go @@ -238,7 +238,7 @@ func (fs *FileSystem) List(ctx context.Context, dirPath string, pathProcessor fu return []Object{}, nil } - var parentPath = path.Join(folder.PositionTemp, folder.Name) + var parentPath = path.Join(folder.Position, folder.Name) var childFolders []model.Folder var childFiles []model.File diff --git a/pkg/filesystem/manage_test.go b/pkg/filesystem/manage_test.go index 14f04f3..f9bd6ec 100644 --- a/pkg/filesystem/manage_test.go +++ b/pkg/filesystem/manage_test.go @@ -392,26 +392,37 @@ func TestFileSystem_Copy(t *testing.T) { // 目录不存在 { - mock.ExpectQuery("SELECT(.+)").WithArgs(uint(1), "/dst").WillReturnRows( + mock.ExpectQuery("SELECT(.+)").WillReturnRows( sqlmock.NewRows([]string{"name"}), ) - mock.ExpectQuery("SELECT(.+)").WithArgs(uint(1), "/src").WillReturnRows( + mock.ExpectQuery("SELECT(.+)").WillReturnRows( sqlmock.NewRows([]string{"name"}), ) - err := fs.Copy(ctx, []string{}, []string{}, "/src", "/dst") + err := fs.Copy(ctx, []uint{}, []uint{}, "/src", "/dst") asserts.Equal(ErrPathNotExist, err) asserts.NoError(mock.ExpectationsWereMet()) } // 复制目录出错 { - mock.ExpectQuery("SELECT(.+)").WithArgs(uint(1), "/src").WillReturnRows( - sqlmock.NewRows([]string{"name"}).AddRow("123"), - ) - mock.ExpectQuery("SELECT(.+)").WithArgs(uint(1), "/dst").WillReturnRows( - sqlmock.NewRows([]string{"name"}).AddRow("123"), - ) - err := fs.Copy(ctx, []string{"test"}, []string{}, "/src", "/dst") + // 根目录 + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1). + WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) + // 1 + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1, 1, "src"). + WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(2, 1)) + // 根目录 + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1). + WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) + // 1 + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1, 1, "dst"). + WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(2, 1)) + + err := fs.Copy(ctx, []uint{1}, []uint{}, "/src", "/dst") asserts.Error(err) } @@ -434,20 +445,30 @@ func TestFileSystem_Move(t *testing.T) { mock.ExpectQuery("SELECT(.+)").WillReturnRows( sqlmock.NewRows([]string{"name"}), ) - err := fs.Move(ctx, []string{}, []string{}, "/src", "/dst") + err := fs.Move(ctx, []uint{}, []uint{}, "/src", "/dst") asserts.Equal(ErrPathNotExist, err) asserts.NoError(mock.ExpectationsWereMet()) } // 移动目录出错 { - mock.ExpectQuery("SELECT(.+)").WithArgs(uint(1), "/src").WillReturnRows( - sqlmock.NewRows([]string{"name"}).AddRow("123"), - ) - mock.ExpectQuery("SELECT(.+)").WithArgs(uint(1), "/dst").WillReturnRows( - sqlmock.NewRows([]string{"name"}).AddRow("123"), - ) - err := fs.Move(ctx, []string{"test"}, []string{}, "/src", "/dst") + // 根目录 + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1). + WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) + // 1 + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1, 1, "src"). + WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(2, 1)) + // 根目录 + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1). + WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(1, 1)) + // 1 + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1, 1, "dst"). + WillReturnRows(sqlmock.NewRows([]string{"id", "owner_id"}).AddRow(2, 1)) + err := fs.Move(ctx, []uint{1}, []uint{}, "/src", "/dst") asserts.Error(err) } } diff --git a/pkg/filesystem/path.go b/pkg/filesystem/path.go index b9dbfad..65f0a26 100644 --- a/pkg/filesystem/path.go +++ b/pkg/filesystem/path.go @@ -20,6 +20,7 @@ func (fs *FileSystem) IsPathExist(path string) (bool, *model.Folder) { } // 递归步入目录 + // TODO:装入树形缓存 var currentFolder *model.Folder for _, folderName := range pathList { var err error diff --git a/pkg/filesystem/path_test.go b/pkg/filesystem/path_test.go index c867a6a..91b5414 100644 --- a/pkg/filesystem/path_test.go +++ b/pkg/filesystem/path_test.go @@ -128,3 +128,25 @@ func TestFileSystem_IsPathExist(t *testing.T) { } } + +func TestFileSystem_IsChildFileExist(t *testing.T) { + asserts := assert.New(t) + fs := &FileSystem{User: &model.User{ + Model: gorm.Model{ + ID: 1, + }, + }} + folder := model.Folder{ + Model: gorm.Model{ID: 1}, + Name: "123", + Position: "/", + } + + mock.ExpectQuery("SELECT(.+)"). + WithArgs(1, "321"). + WillReturnRows(sqlmock.NewRows([]string{"id", "name"}).AddRow(2, "321")) + exist, childFile := fs.IsChildFileExist(&folder, "321") + asserts.NoError(mock.ExpectationsWereMet()) + asserts.True(exist) + asserts.Equal("/123/321", childFile.Position) +} diff --git a/pkg/util/path_test.go b/pkg/util/path_test.go index 8470398..d633dc7 100644 --- a/pkg/util/path_test.go +++ b/pkg/util/path_test.go @@ -19,3 +19,11 @@ func TestFillSlash(t *testing.T) { asserts.Equal("/", FillSlash("")) asserts.Equal("/123/", FillSlash("/123")) } + +func TestSplitPath(t *testing.T) { + asserts := assert.New(t) + asserts.Equal([]string{}, SplitPath("")) + asserts.Equal([]string{}, SplitPath("1")) + asserts.Equal([]string{"/"}, SplitPath("/")) + asserts.Equal([]string{"/", "123", "321"}, SplitPath("/123/321")) +} diff --git a/routers/file_router_test.go b/routers/file_router_test.go index fabac28..9a99e85 100644 --- a/routers/file_router_test.go +++ b/routers/file_router_test.go @@ -124,8 +124,8 @@ func TestObjectDelete(t *testing.T) { // 路径不存在,返回无错误 { GetRequest: func() *http.Request { - body := explorer.ItemServiceTemp{ - Items: []string{"/TestObjectDelete.txt"}, + body := explorer.ItemService{ + Items: []uint{1}, } bodyStr, _ := json.Marshal(body) req, _ := http.NewRequest( @@ -139,10 +139,10 @@ func TestObjectDelete(t *testing.T) { }, // 文件删除失败,返回203 { - Mock: []string{"INSERT INTO `files` (`id`, `created_at`, `updated_at`, `deleted_at`, `name`, `source_name`, `user_id`, `size`, `pic_info`, `folder_id`, `policy_id`, `dir`) VALUES(5, '2019-11-30 07:08:33', '2019-11-30 07:08:33', NULL, 'pigeon.zip', '65azil3B_pigeon.zip', 1, 1667217, '', 1, 1, '/');"}, + Mock: []string{"INSERT INTO `files` (`id`, `created_at`, `updated_at`, `deleted_at`, `name`, `source_name`, `user_id`, `size`, `pic_info`, `folder_id`, `policy_id`) VALUES(5, '2019-11-30 07:08:33', '2019-11-30 07:08:33', NULL, 'pigeon.zip', '65azil3B_pigeon.zip', 1, 1667217, '', 1, 1);"}, GetRequest: func() *http.Request { - body := explorer.ItemServiceTemp{ - Items: []string{"/pigeon.zip"}, + body := explorer.ItemService{ + Items: []uint{5}, } bodyStr, _ := json.Marshal(body) req, _ := http.NewRequest(