Feat: re-save shared folder to user's space
This commit is contained in:
parent
b1a9943b0c
commit
f5d79b1f94
10 changed files with 51 additions and 60 deletions
|
@ -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 测试
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 初始化一个文件系统
|
||||
|
|
|
@ -377,22 +377,24 @@ func (fs *FileSystem) SaveTo(ctx context.Context, path string) error {
|
|||
return ErrPathNotExist
|
||||
}
|
||||
|
||||
// TODO 列目录
|
||||
var (
|
||||
totalSize uint64
|
||||
err error
|
||||
)
|
||||
|
||||
// 计算要复制的总大小
|
||||
var totalSize uint64
|
||||
for _, file := range fs.FileTarget {
|
||||
totalSize += file.Size
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
// 获取文件预览响应
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Add table
Reference in a new issue