diff --git a/models/folder.go b/models/folder.go index 96cf516..1366f71 100644 --- a/models/folder.go +++ b/models/folder.go @@ -60,7 +60,7 @@ func (folder *Folder) GetChildFolder() ([]Folder, error) { func GetRecursiveChildFolder(dirs []uint, uid uint, includeSelf bool) ([]Folder, error) { folders := make([]Folder, 0, len(dirs)) var err error - // SQLite 下使用递归查询 + var parFolders []Folder result := DB.Where("owner_id = ? and id in (?)", uid, dirs).Find(&parFolders) if result.Error != nil { @@ -139,6 +139,7 @@ func (folder *Folder) MoveOrCopyFileTo(files []uint, dstFolder *Folder, isCopy b for _, oldFile := range originFiles { oldFile.Model = gorm.Model{} oldFile.FolderID = dstFolder.ID + oldFile.UserID = dstFolder.OwnerID if err := DB.Create(&oldFile).Error; err != nil { return copiedSize, err @@ -203,6 +204,7 @@ func (folder *Folder) CopyFolderTo(folderID uint, dstFolder *Folder) (size uint6 oldID := folder.ID folder.Model = gorm.Model{} folder.ParentID = &newID + folder.OwnerID = dstFolder.OwnerID if err = DB.Create(&folder).Error; err != nil { return size, err } @@ -225,7 +227,7 @@ func (folder *Folder) CopyFolderTo(folderID uint, dstFolder *Folder) (size uint6 for _, oldFile := range originFiles { oldFile.Model = gorm.Model{} oldFile.FolderID = newIDCache[oldFile.FolderID] - + oldFile.UserID = dstFolder.OwnerID if err := DB.Create(&oldFile).Error; err != nil { return size, err } @@ -262,40 +264,6 @@ func (folder *Folder) Rename(new string) error { return nil } -// CopyChildFrom 将给定文件和拷贝至自身,并更改所有者ID -func (folder *Folder) CopyChildFrom(folders []Folder, files []File) error { - // 开启事务 - tx := DB.Begin() - defer func() { - if r := recover(); r != nil { - tx.Rollback() - } - }() - - // 记录文件父目录对应复制的新目录ID - var newParent = make(map[uint]uint, len(folders)) - - // TODO 复制目录结构 - - // 复制子文件 - for _, file := range files { - file.ID = 0 - file.UserID = folder.OwnerID - if newParentID, ok := newParent[file.FolderID]; ok { - file.FolderID = newParentID - } else { - file.FolderID = folder.ID - } - if err := tx.Create(&file).Error; err != nil { - tx.Rollback() - return err - } - } - - return tx.Commit().Error - -} - /* 实现 FileInfo.FileInfo 接口 TODO 测试 diff --git a/models/share.go b/models/share.go index f74c23a..fb3d89a 100644 --- a/models/share.go +++ b/models/share.go @@ -8,6 +8,7 @@ import ( "github.com/HFO4/cloudreve/pkg/util" "github.com/gin-gonic/gin" "github.com/jinzhu/gorm" + "math" "time" ) @@ -170,7 +171,7 @@ func (share *Share) DownloadBy(user *User, c *gin.Context) error { // Purchase 使用积分购买分享 func (share *Share) Purchase(user *User) error { // 不需要付积分 - if share.Score == 0 || user.Group.OptionsSerialized.ShareFreeEnabled { + if share.Score == 0 || user.Group.OptionsSerialized.ShareFreeEnabled || user.ID == share.UserID { return nil } @@ -179,6 +180,10 @@ func (share *Share) Purchase(user *User) error { return errors.New("积分不足") } + scoreRate := GetIntSetting("share_score_rate", 100) + gainedScore := int(math.Ceil(float64(share.Score*scoreRate) / 100)) + share.GetCreator().AddScore(gainedScore) + return nil } diff --git a/models/user.go b/models/user.go index 8f0947f..e4956e4 100644 --- a/models/user.go +++ b/models/user.go @@ -108,6 +108,13 @@ func (user *User) PayScore(score int) bool { return false } +// AddScore 增加积分 +// todo 测试 +func (user *User) AddScore(score int) { + user.Score += score + DB.Model(user).UpdateColumn("score", gorm.Expr("score + ?", score)) +} + // IncreaseStorageWithoutCheck 忽略可用容量,增加用户已用容量 func (user *User) IncreaseStorageWithoutCheck(size uint64) { if size == 0 { diff --git a/pkg/filesystem/errors.go b/pkg/filesystem/errors.go index 0e204e0..7fa54f8 100644 --- a/pkg/filesystem/errors.go +++ b/pkg/filesystem/errors.go @@ -13,7 +13,7 @@ var ( ErrIllegalObjectName = errors.New("目标名称非法") ErrClientCanceled = errors.New("客户端取消操作") ErrInsertFileRecord = serializer.NewError(serializer.CodeDBError, "无法插入文件记录", nil) - ErrFileExisted = serializer.NewError(serializer.CodeObjectExist, "同名文件已存在", nil) + ErrFileExisted = serializer.NewError(serializer.CodeObjectExist, "同名文件或目录已存在", nil) ErrFolderExisted = serializer.NewError(serializer.CodeObjectExist, "同名目录已存在", nil) ErrPathNotExist = serializer.NewError(404, "路径不存在", nil) ErrObjectNotExist = serializer.NewError(404, "文件不存在", nil) diff --git a/pkg/filesystem/filesystem.go b/pkg/filesystem/filesystem.go index 2468c19..398f7ef 100644 --- a/pkg/filesystem/filesystem.go +++ b/pkg/filesystem/filesystem.go @@ -76,6 +76,8 @@ type FileSystem struct { FileTarget []model.File // 当前正在处理的目录对象 DirTarget []model.Folder + // 相对根目录 + Root *model.Folder /* 钩子函数 @@ -107,6 +109,7 @@ func (fs *FileSystem) reset() { fs.Policy = nil fs.Hooks = nil fs.Handler = nil + fs.Root = nil } // NewFileSystem 初始化一个文件系统 diff --git a/pkg/filesystem/manage.go b/pkg/filesystem/manage.go index 3b24bae..6a21f14 100644 --- a/pkg/filesystem/manage.go +++ b/pkg/filesystem/manage.go @@ -377,22 +377,24 @@ func (fs *FileSystem) SaveTo(ctx context.Context, path string) error { return ErrPathNotExist } - // TODO 列目录 - - // 计算要复制的总大小 - var totalSize uint64 - for _, file := range fs.FileTarget { - totalSize += file.Size + var ( + totalSize uint64 + err error + ) + + if len(fs.DirTarget) > 0 { + totalSize, err = fs.DirTarget[0].CopyFolderTo(fs.DirTarget[0].ID, folder) + } else { + parent := model.Folder{ + OwnerID: fs.FileTarget[0].UserID, + } + parent.ID = fs.FileTarget[0].FolderID + totalSize, err = parent.MoveOrCopyFileTo([]uint{fs.FileTarget[0].ID}, folder, true) } // 扣除用户容量 - if !fs.User.IncreaseStorage(totalSize) { - return ErrInsufficientCapacity - } - - err := folder.CopyChildFrom(fs.DirTarget, fs.FileTarget) + fs.User.IncreaseStorageWithoutCheck(totalSize) if err != nil { - fs.User.DeductionStorage(totalSize) return ErrFileExisted.WithError(err) } diff --git a/pkg/filesystem/path.go b/pkg/filesystem/path.go index 438704d..a57a57e 100644 --- a/pkg/filesystem/path.go +++ b/pkg/filesystem/path.go @@ -23,9 +23,9 @@ func (fs *FileSystem) IsPathExist(path string) (bool, *model.Folder) { // TODO:测试新增 var currentFolder *model.Folder - // 如果已设定目录对象,则从给定目录向下遍历 - if len(fs.DirTarget) > 0 { - currentFolder = &fs.DirTarget[0] + // 如果已设定跟目录对象,则从给定目录向下遍历 + if fs.Root != nil { + currentFolder = fs.Root } for _, folderName := range pathList { diff --git a/pkg/serializer/share.go b/pkg/serializer/share.go index c33e46d..f2b6ef3 100644 --- a/pkg/serializer/share.go +++ b/pkg/serializer/share.go @@ -47,6 +47,7 @@ func BuildShareResponse(share *model.Share, unlocked bool) Share { CreateDate: share.CreatedAt.Format("2006-01-02 15:04:05"), } + // 未解锁时只返回基本信息 if !unlocked { return resp } diff --git a/service/explorer/file.go b/service/explorer/file.go index bce2940..3eba150 100644 --- a/service/explorer/file.go +++ b/service/explorer/file.go @@ -133,9 +133,9 @@ func (service *SingleFileService) CreateDocPreviewSession(ctx context.Context, c fs.SetTargetFile(&[]model.File{*file}) } - // 如果上下文中已有Folder对象,则重设目标 + // 重设根目录 if folder, ok := ctx.Value(fsctx.FolderModelCtx).(*model.Folder); ok { - fs.SetTargetDir(&[]model.Folder{*folder}) + fs.Root = folder } // 获取文件临时下载地址 @@ -233,9 +233,9 @@ func (service *SingleFileService) PreviewContent(ctx context.Context, c *gin.Con fs.SetTargetFile(&[]model.File{*file}) } - // 如果上下文中已有Folder对象,则重设目标 + // 如果上下文中已有Folder对象,则重设根目录 if folder, ok := ctx.Value(fsctx.FolderModelCtx).(*model.Folder); ok { - fs.SetTargetDir(&[]model.Folder{*folder}) + fs.Root = folder } // 获取文件预览响应 diff --git a/service/share/visit.go b/service/share/visit.go index f79eb1e..4e3509b 100644 --- a/service/share/visit.go +++ b/service/share/visit.go @@ -50,8 +50,8 @@ func (service *ShareGetService) Get(c *gin.Context) serializer.Response { share.Viewed() } - // 如果已经下载过,不需要付积分 - if share.WasDownloadedBy(user, c) { + // 如果已经下载过或者是自己的分享,不需要付积分 + if share.UserID == user.ID || share.WasDownloadedBy(user, c) { share.Score = 0 } @@ -81,6 +81,11 @@ func (service *ShareService) CreateDownloadSession(c *gin.Context) serializer.Re return serializer.Err(serializer.CodePolicyNotAllowed, "源文件不存在", err) } + // 重设根目录 + if share.IsDir { + fs.Root = &fs.DirTarget[0] + } + // 取得下载地址 downloadURL, err := fs.GetDownloadURL(context.Background(), service.Path, "download_timeout") if err != nil { @@ -189,8 +194,8 @@ func (service *ShareService) List(c *gin.Context) serializer.Response { defer cancel() // 重设根目录 - fs.SetTargetDir(&[]model.Folder{*share.GetSource().(*model.Folder)}) - fs.DirTarget[0].Name = "/" + fs.Root = share.GetSource().(*model.Folder) + fs.Root.Name = "/" // 分享Key上下文 ctx = context.WithValue(ctx, fsctx.ShareKeyCtx, hashid.HashID(share.ID, hashid.ShareID))