mirror of
https://github.com/halejohn/Cloudreve.git
synced 2026-01-26 17:41:57 +08:00
Feat: delete objects
This commit is contained in:
@@ -3,6 +3,7 @@ package model
|
||||
import (
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
"github.com/jinzhu/gorm"
|
||||
"path"
|
||||
)
|
||||
|
||||
// File 文件
|
||||
@@ -31,7 +32,7 @@ func (file *File) Create() (uint, error) {
|
||||
return file.ID, nil
|
||||
}
|
||||
|
||||
// GetFileByPathAndName 给定路径、文件名、用户ID,查找文件
|
||||
// GetFileByPathAndName 给定路径(s)、文件名、用户ID,查找文件
|
||||
func GetFileByPathAndName(path string, name string, uid uint) (File, error) {
|
||||
var file File
|
||||
result := DB.Where("user_id = ? AND dir = ? AND name=?", uid, path, name).First(&file)
|
||||
@@ -45,6 +46,20 @@ func (folder *Folder) GetChildFile() ([]File, error) {
|
||||
return files, result.Error
|
||||
}
|
||||
|
||||
// GetChildFilesOfFolders 批量检索目录子文件
|
||||
func GetChildFilesOfFolders(folders *[]Folder) ([]File, error) {
|
||||
// 将所有待删除目录ID抽离,以便检索文件
|
||||
folderIDs := make([]uint, 0, len(*folders))
|
||||
for _, value := range *folders {
|
||||
folderIDs = append(folderIDs, value.ID)
|
||||
}
|
||||
|
||||
// 检索文件
|
||||
var files []File
|
||||
result := DB.Where("folder_id in (?)", folderIDs).Find(&files)
|
||||
return files, result.Error
|
||||
}
|
||||
|
||||
// GetPolicy 获取文件所属策略
|
||||
// TODO:test
|
||||
func (file *File) GetPolicy() *Policy {
|
||||
@@ -53,3 +68,52 @@ func (file *File) GetPolicy() *Policy {
|
||||
}
|
||||
return &file.Policy
|
||||
}
|
||||
|
||||
// GetFileByPaths 根据给定的文件路径(s)查找文件
|
||||
func GetFileByPaths(paths []string, uid uint) ([]File, error) {
|
||||
var files []File
|
||||
tx := DB
|
||||
for _, value := range paths {
|
||||
base := path.Base(value)
|
||||
dir := path.Dir(value)
|
||||
tx = tx.Or("dir = ? and name = ? and user_id = ?", dir, base, uid)
|
||||
}
|
||||
result := tx.Find(&files)
|
||||
return files, result.Error
|
||||
}
|
||||
|
||||
// RemoveFilesWithSoftLinks 去除给定的文件列表中有软链接的文件
|
||||
func RemoveFilesWithSoftLinks(files []File) ([]File, error) {
|
||||
// 结果值
|
||||
filteredFiles := make([]File, 0)
|
||||
|
||||
// 查询软链接的文件
|
||||
var filesWithSoftLinks []File
|
||||
tx := DB
|
||||
for _, value := range files {
|
||||
tx = tx.Or("source_name = ? and policy_id = ? and id != ?", value.SourceName, value.GetPolicy().ID, value.ID)
|
||||
}
|
||||
result := tx.Find(&filesWithSoftLinks)
|
||||
if result.Error != nil {
|
||||
return nil, result.Error
|
||||
}
|
||||
|
||||
// 过滤具有软连接的文件
|
||||
for i := 0; i < len(files); i++ {
|
||||
for _, value := range filesWithSoftLinks {
|
||||
if value.PolicyID != files[i].PolicyID || value.SourceName != files[i].SourceName {
|
||||
filteredFiles = append(filteredFiles, files[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filteredFiles, nil
|
||||
|
||||
}
|
||||
|
||||
// DeleteFileByIDs 根据给定ID批量删除文件记录
|
||||
func DeleteFileByIDs(ids []uint) error {
|
||||
result := DB.Where("id in (?)", ids).Delete(&File{})
|
||||
return result.Error
|
||||
}
|
||||
|
||||
@@ -38,3 +38,17 @@ func (folder *Folder) GetChildFolder() ([]Folder, error) {
|
||||
result := DB.Where("parent_id = ?", folder.ID).Find(&folders)
|
||||
return folders, result.Error
|
||||
}
|
||||
|
||||
// GetRecursiveChildFolder 查找所有递归子目录
|
||||
func GetRecursiveChildFolder(dirs []string, uid uint) ([]Folder, error) {
|
||||
folders := make([]Folder, 0, len(dirs))
|
||||
search := util.BuildRegexp(dirs, "^", "/", "|")
|
||||
result := DB.Where("(owner_id = ? and position_absolute REGEXP ?) or position_absolute in (?)", uid, search, dirs).Find(&folders)
|
||||
return folders, result.Error
|
||||
}
|
||||
|
||||
// DeleteFolderByIDs 根据给定ID批量删除目录记录
|
||||
func DeleteFolderByIDs(ids []uint) error {
|
||||
result := DB.Where("id in (?)", ids).Delete(&Folder{})
|
||||
return result.Error
|
||||
}
|
||||
|
||||
@@ -54,17 +54,17 @@ func migration() {
|
||||
}
|
||||
|
||||
func addDefaultPolicy() {
|
||||
_, err := GetPolicyByID(1)
|
||||
_, err := GetPolicyByID(uint(1))
|
||||
// 未找到初始存储策略时,则创建
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
defaultPolicy := Policy{
|
||||
Name: "默认上传策略",
|
||||
Name: "默认存储策略",
|
||||
Type: "local",
|
||||
Server: "/Api/V3/File/Upload",
|
||||
Server: "/api/v3/file/upload",
|
||||
BaseURL: "http://cloudreve.org/public/uploads/",
|
||||
MaxSize: 10 * 1024 * 1024 * 1024,
|
||||
AutoRename: true,
|
||||
DirNameRule: "{date}/{uid}",
|
||||
DirNameRule: "uploads/{uid}/{path}",
|
||||
FileNameRule: "{uid}_{randomkey8}_{originname}",
|
||||
IsOriginLinkEnable: false,
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"github.com/jinzhu/gorm"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -41,16 +42,36 @@ type PolicyOption struct {
|
||||
RangeTransferEnabled bool `json:"range_transfer_enabled"`
|
||||
}
|
||||
|
||||
// 存储策略缓存,部分情况下需要频繁查询存储策略
|
||||
var policyCache = make(map[uint]Policy)
|
||||
var rw sync.RWMutex
|
||||
|
||||
// GetPolicyByID 用ID获取存储策略
|
||||
func GetPolicyByID(ID interface{}) (Policy, error) {
|
||||
// 尝试读取缓存
|
||||
rw.RLock()
|
||||
if policy, ok := policyCache[ID.(uint)]; ok {
|
||||
rw.RUnlock()
|
||||
return policy, nil
|
||||
}
|
||||
rw.RUnlock()
|
||||
|
||||
var policy Policy
|
||||
result := DB.First(&policy, ID)
|
||||
|
||||
// 写入缓存
|
||||
if result.Error == nil {
|
||||
rw.Lock()
|
||||
policyCache[policy.ID] = policy
|
||||
rw.Unlock()
|
||||
}
|
||||
|
||||
return policy, result.Error
|
||||
}
|
||||
|
||||
// AfterFind 找到上传策略后的钩子
|
||||
// AfterFind 找到存储策略后的钩子
|
||||
func (policy *Policy) AfterFind() (err error) {
|
||||
// 解析上传策略设置到OptionsSerialized
|
||||
// 解析存储策略设置到OptionsSerialized
|
||||
err = json.Unmarshal([]byte(policy.Options), &policy.OptionsSerialized)
|
||||
if policy.OptionsSerialized.FileType == nil {
|
||||
policy.OptionsSerialized.FileType = []string{}
|
||||
|
||||
@@ -13,16 +13,16 @@ func TestGetPolicyByID(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
|
||||
rows := sqlmock.NewRows([]string{"name", "type", "options"}).
|
||||
AddRow("默认上传策略", "local", "{\"op_name\":\"123\"}")
|
||||
AddRow("默认存储策略", "local", "{\"op_name\":\"123\"}")
|
||||
mock.ExpectQuery("^SELECT \\* FROM `(.+)` WHERE `(.+)`\\.`deleted_at` IS NULL AND \\(\\(`policies`.`id` = 1\\)\\)(.+)$").WillReturnRows(rows)
|
||||
policy, err := GetPolicyByID(1)
|
||||
policy, err := GetPolicyByID(uint(1))
|
||||
asserts.NoError(err)
|
||||
asserts.Equal("默认上传策略", policy.Name)
|
||||
asserts.Equal("默认存储策略", policy.Name)
|
||||
asserts.Equal("123", policy.OptionsSerialized.OPName)
|
||||
|
||||
rows = sqlmock.NewRows([]string{"name", "type", "options"})
|
||||
mock.ExpectQuery("^SELECT \\* FROM `(.+)` WHERE `(.+)`\\.`deleted_at` IS NULL AND \\(\\(`policies`.`id` = 1\\)\\)(.+)$").WillReturnRows(rows)
|
||||
policy, err = GetPolicyByID(1)
|
||||
policy, err = GetPolicyByID(uint(1))
|
||||
asserts.Error(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ func (user *User) GetRemainingCapacity() uint64 {
|
||||
return user.Group.MaxStorage - user.Storage
|
||||
}
|
||||
|
||||
// GetPolicyID 获取用户当前的上传策略ID
|
||||
// GetPolicyID 获取用户当前的存储策略ID
|
||||
func (user *User) GetPolicyID() uint {
|
||||
// 用户未指定时,返回可用的第一个
|
||||
if user.OptionsSerialized.PreferredPolicy == 0 {
|
||||
|
||||
@@ -22,7 +22,7 @@ func TestGetUserByID(t *testing.T) {
|
||||
mock.ExpectQuery("^SELECT (.+)").WillReturnRows(groupRows)
|
||||
|
||||
policyRows := sqlmock.NewRows([]string{"id", "name"}).
|
||||
AddRow(1, "默认上传策略")
|
||||
AddRow(1, "默认存储策略")
|
||||
mock.ExpectQuery("^SELECT (.+)").WillReturnRows(policyRows)
|
||||
|
||||
user, err := GetUserByID(1)
|
||||
@@ -50,7 +50,7 @@ func TestGetUserByID(t *testing.T) {
|
||||
OptionsSerialized: PolicyOption{
|
||||
FileType: []string{},
|
||||
},
|
||||
Name: "默认上传策略",
|
||||
Name: "默认存储策略",
|
||||
},
|
||||
}, user)
|
||||
|
||||
@@ -105,7 +105,7 @@ func TestUser_AfterFind(t *testing.T) {
|
||||
asserts := assert.New(t)
|
||||
|
||||
policyRows := sqlmock.NewRows([]string{"id", "name"}).
|
||||
AddRow(1, "默认上传策略")
|
||||
AddRow(1, "默认存储策略")
|
||||
mock.ExpectQuery("^SELECT (.+)").WillReturnRows(policyRows)
|
||||
|
||||
newUser := NewUser()
|
||||
@@ -117,7 +117,7 @@ func TestUser_AfterFind(t *testing.T) {
|
||||
asserts.NoError(err)
|
||||
asserts.NoError(mock.ExpectationsWereMet())
|
||||
asserts.Equal(expected, newUser.OptionsSerialized)
|
||||
asserts.Equal("默认上传策略", newUser.Policy.Name)
|
||||
asserts.Equal("默认存储策略", newUser.Policy.Name)
|
||||
}
|
||||
|
||||
func TestUser_BeforeSave(t *testing.T) {
|
||||
@@ -199,7 +199,7 @@ func TestUser_DeductionCapacity(t *testing.T) {
|
||||
mock.ExpectQuery("^SELECT (.+)").WillReturnRows(groupRows)
|
||||
|
||||
policyRows := sqlmock.NewRows([]string{"id", "name"}).
|
||||
AddRow(1, "默认上传策略")
|
||||
AddRow(1, "默认存储策略")
|
||||
mock.ExpectQuery("^SELECT (.+)").WillReturnRows(policyRows)
|
||||
|
||||
newUser, err := GetUserByID(1)
|
||||
|
||||
Reference in New Issue
Block a user