Feat: re-save shared folder to user's space

pull/247/head
HFO4 4 years ago
parent b1a9943b0c
commit f5d79b1f94

@ -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
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)
}

@ -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…
Cancel
Save