From 68704f86461b51033ffa9efab90e66b0d37c0863 Mon Sep 17 00:00:00 2001 From: HFO4 <912394456@qq.com> Date: Wed, 29 Jan 2020 11:03:09 +0800 Subject: [PATCH] Feat: options to disable preview in file sharing --- models/share.go | 25 ++++++++++++++++++++----- models/user.go | 1 + pkg/filesystem/driver/onedrive/api.go | 2 -- pkg/filesystem/filesystem.go | 2 +- pkg/serializer/share.go | 3 +++ service/share/manage.go | 2 ++ service/share/visit.go | 26 ++++++++++++++++++++------ 7 files changed, 47 insertions(+), 14 deletions(-) diff --git a/models/share.go b/models/share.go index 4286c22..f74c23a 100644 --- a/models/share.go +++ b/models/share.go @@ -6,6 +6,7 @@ import ( "github.com/HFO4/cloudreve/pkg/cache" "github.com/HFO4/cloudreve/pkg/hashid" "github.com/HFO4/cloudreve/pkg/util" + "github.com/gin-gonic/gin" "github.com/jinzhu/gorm" "time" ) @@ -22,6 +23,7 @@ type Share struct { RemainDownloads int // 剩余下载配额,负值标识无限制 Expires *time.Time // 过期时间,空值表示无过期时间 Score int // 每人次下载扣除积分 + PreviewEnabled bool // 是否允许直接预览 // 数据库忽略字段 User User `gorm:"PRELOAD:false,association_autoupdate:false"` @@ -138,14 +140,19 @@ func (share *Share) CanBeDownloadBy(user *User) error { } // WasDownloadedBy 返回分享是否已被用户下载过 -func (share *Share) WasDownloadedBy(user *User) bool { - _, exist := cache.Get(fmt.Sprintf("share_%d_%d", share.ID, user.ID)) +func (share *Share) WasDownloadedBy(user *User, c *gin.Context) (exist bool) { + if user.IsAnonymous() { + exist = util.GetSession(c, fmt.Sprintf("share_%d_%d", share.ID, user.ID)) != nil + } else { + _, exist = cache.Get(fmt.Sprintf("share_%d_%d", share.ID, user.ID)) + } + return exist } // DownloadBy 增加下载次数、检查积分等,匿名用户不会缓存 -func (share *Share) DownloadBy(user *User) error { - if !share.WasDownloadedBy(user) { +func (share *Share) DownloadBy(user *User, c *gin.Context) error { + if !share.WasDownloadedBy(user, c) { if err := share.Purchase(user); err != nil { return err } @@ -153,6 +160,8 @@ func (share *Share) DownloadBy(user *User) error { if !user.IsAnonymous() { cache.Set(fmt.Sprintf("share_%d_%d", share.ID, user.ID), true, GetIntSetting("share_download_session_timeout", 2073600)) + } else { + util.SetSession(c, map[string]interface{}{fmt.Sprintf("share_%d_%d", share.ID, user.ID): true}) } } return nil @@ -182,5 +191,11 @@ func (share *Share) Viewed() { // Downloaded 增加下载次数 func (share *Share) Downloaded() { share.Downloads++ - DB.Model(share).UpdateColumn("downloads", gorm.Expr("downloads + ?", 1)) + if share.RemainDownloads > 0 { + share.RemainDownloads-- + } + DB.Model(share).Updates(map[string]interface{}{ + "downloads": share.Downloads, + "remain_downloads": share.RemainDownloads, + }) } diff --git a/models/user.go b/models/user.go index f60d6ac..1b0299c 100644 --- a/models/user.go +++ b/models/user.go @@ -253,6 +253,7 @@ func (user *User) SetPassword(password string) error { // TODO 测试 func NewAnonymousUser() *User { user := User{} + user.Policy.Type = "anonymous" user.Group, _ = GetGroupByID(3) return &user } diff --git a/pkg/filesystem/driver/onedrive/api.go b/pkg/filesystem/driver/onedrive/api.go index 6a6ec7c..a624646 100644 --- a/pkg/filesystem/driver/onedrive/api.go +++ b/pkg/filesystem/driver/onedrive/api.go @@ -407,8 +407,6 @@ func (client *Client) MonitorUpload(uploadURL, callbackKey, path string, size ui } return } - util.Log().Debug("无法获取上传会话状态,%s", err.Error()) - return } util.Log().Debug("无法获取上传会话状态,继续下一轮,%s", err.Error()) } diff --git a/pkg/filesystem/filesystem.go b/pkg/filesystem/filesystem.go index bf59502..2468c19 100644 --- a/pkg/filesystem/filesystem.go +++ b/pkg/filesystem/filesystem.go @@ -156,7 +156,7 @@ func (fs *FileSystem) DispatchHandler() error { } switch policyType { - case "mock": + case "mock", "anonymous": return nil case "local": fs.Handler = local.Driver{ diff --git a/pkg/serializer/share.go b/pkg/serializer/share.go index 0735ba8..9eba5c3 100644 --- a/pkg/serializer/share.go +++ b/pkg/serializer/share.go @@ -16,6 +16,7 @@ type Share struct { Downloads int `json:"downloads"` Views int `json:"views"` Expire int64 `json:"expire"` + Preview bool `json:"preview"` Creator *shareCreator `json:"creator,omitempty"` Source *shareSource `json:"source,omitempty"` } @@ -53,6 +54,8 @@ func BuildShareResponse(share *model.Share, unlocked bool) Share { resp.IsDir = share.IsDir resp.Downloads = share.Downloads resp.Views = share.Views + resp.Preview = share.PreviewEnabled + if share.Expires != nil { resp.Expire = share.Expires.Unix() - time.Now().Unix() } diff --git a/service/share/manage.go b/service/share/manage.go index eb0bd1d..2247ca8 100644 --- a/service/share/manage.go +++ b/service/share/manage.go @@ -17,6 +17,7 @@ type ShareCreateService struct { RemainDownloads int `json:"downloads"` Expire int `json:"expire"` Score int `json:"score" binding:"gte=0"` + Preview bool `json:"preview"` } // Create 创建新分享 @@ -52,6 +53,7 @@ func (service *ShareCreateService) Create(c *gin.Context) serializer.Response { SourceID: service.SourceID, Score: service.Score, RemainDownloads: -1, + PreviewEnabled: service.Preview, } // 如果开启了自动过期 diff --git a/service/share/visit.go b/service/share/visit.go index b8612e9..9bf8d14 100644 --- a/service/share/visit.go +++ b/service/share/visit.go @@ -2,6 +2,7 @@ package share import ( "context" + "errors" "fmt" model "github.com/HFO4/cloudreve/models" "github.com/HFO4/cloudreve/pkg/filesystem" @@ -49,7 +50,7 @@ func (service *ShareGetService) Get(c *gin.Context) serializer.Response { } // 如果已经下载过,不需要付积分 - if share.WasDownloadedBy(user) { + if share.WasDownloadedBy(user, c) { share.Score = 0 } @@ -68,7 +69,7 @@ func (service *SingleFileService) CreateDownloadSession(c *gin.Context) serializ } // 检查用户是否可以下载此分享的文件 - err := CheckBeforeGetShare(share, user) + err := CheckBeforeGetShare(share, user, c) if err != nil { return serializer.Err(serializer.CodeNoPermissionErr, err.Error(), nil) } @@ -107,13 +108,17 @@ func (service *SingleFileService) PreviewContent(ctx context.Context, c *gin.Con return serializer.Err(serializer.CodeNotFound, "分享不存在或已被取消", nil) } + if !share.PreviewEnabled { + return serializer.Err(serializer.CodeNoPermissionErr, "此分享无法预览", nil) + } + // 检查用户是否可以下载此分享的文件 - err := CheckBeforeGetShare(share, user) + err := CheckBeforeGetShare(share, user, c) if err != nil { return serializer.Err(serializer.CodeNoPermissionErr, err.Error(), nil) } - // 用于调用子service + // 用于调下层service ctx = context.WithValue(ctx, fsctx.FileModelCtx, share.GetSource()) subService := explorer.SingleFileService{ Path: "", @@ -123,15 +128,24 @@ func (service *SingleFileService) PreviewContent(ctx context.Context, c *gin.Con } // CheckBeforeGetShare 获取分享内容/下载前进行的一系列检查 -func CheckBeforeGetShare(share *model.Share, user *model.User) error { +func CheckBeforeGetShare(share *model.Share, user *model.User, c *gin.Context) error { // 检查用户是否可以下载此分享的文件 err := share.CanBeDownloadBy(user) if err != nil { return err } + // 分享是否已解锁 + if share.Password != "" { + sessionKey := fmt.Sprintf("share_unlock_%d", share.ID) + unlocked := util.GetSession(c, sessionKey) != nil + if !unlocked { + return errors.New("无权访问此分享") + } + } + // 对积分、下载次数进行更新 - err = share.DownloadBy(user) + err = share.DownloadBy(user, c) if err != nil { return err }