mirror of https://github.com/cloudreve/Cloudreve
Feat: options to disable preview in file sharing
parent
1ff4d59978
commit
68704f8646
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/HFO4/cloudreve/pkg/cache"
|
"github.com/HFO4/cloudreve/pkg/cache"
|
||||||
"github.com/HFO4/cloudreve/pkg/hashid"
|
"github.com/HFO4/cloudreve/pkg/hashid"
|
||||||
"github.com/HFO4/cloudreve/pkg/util"
|
"github.com/HFO4/cloudreve/pkg/util"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -22,6 +23,7 @@ type Share struct {
|
||||||
RemainDownloads int // 剩余下载配额,负值标识无限制
|
RemainDownloads int // 剩余下载配额,负值标识无限制
|
||||||
Expires *time.Time // 过期时间,空值表示无过期时间
|
Expires *time.Time // 过期时间,空值表示无过期时间
|
||||||
Score int // 每人次下载扣除积分
|
Score int // 每人次下载扣除积分
|
||||||
|
PreviewEnabled bool // 是否允许直接预览
|
||||||
|
|
||||||
// 数据库忽略字段
|
// 数据库忽略字段
|
||||||
User User `gorm:"PRELOAD:false,association_autoupdate:false"`
|
User User `gorm:"PRELOAD:false,association_autoupdate:false"`
|
||||||
|
@ -138,14 +140,19 @@ func (share *Share) CanBeDownloadBy(user *User) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WasDownloadedBy 返回分享是否已被用户下载过
|
// WasDownloadedBy 返回分享是否已被用户下载过
|
||||||
func (share *Share) WasDownloadedBy(user *User) bool {
|
func (share *Share) WasDownloadedBy(user *User, c *gin.Context) (exist bool) {
|
||||||
_, exist := cache.Get(fmt.Sprintf("share_%d_%d", share.ID, user.ID))
|
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
|
return exist
|
||||||
}
|
}
|
||||||
|
|
||||||
// DownloadBy 增加下载次数、检查积分等,匿名用户不会缓存
|
// DownloadBy 增加下载次数、检查积分等,匿名用户不会缓存
|
||||||
func (share *Share) DownloadBy(user *User) error {
|
func (share *Share) DownloadBy(user *User, c *gin.Context) error {
|
||||||
if !share.WasDownloadedBy(user) {
|
if !share.WasDownloadedBy(user, c) {
|
||||||
if err := share.Purchase(user); err != nil {
|
if err := share.Purchase(user); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -153,6 +160,8 @@ func (share *Share) DownloadBy(user *User) error {
|
||||||
if !user.IsAnonymous() {
|
if !user.IsAnonymous() {
|
||||||
cache.Set(fmt.Sprintf("share_%d_%d", share.ID, user.ID), true,
|
cache.Set(fmt.Sprintf("share_%d_%d", share.ID, user.ID), true,
|
||||||
GetIntSetting("share_download_session_timeout", 2073600))
|
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
|
return nil
|
||||||
|
@ -182,5 +191,11 @@ func (share *Share) Viewed() {
|
||||||
// Downloaded 增加下载次数
|
// Downloaded 增加下载次数
|
||||||
func (share *Share) Downloaded() {
|
func (share *Share) Downloaded() {
|
||||||
share.Downloads++
|
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,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,6 +253,7 @@ func (user *User) SetPassword(password string) error {
|
||||||
// TODO 测试
|
// TODO 测试
|
||||||
func NewAnonymousUser() *User {
|
func NewAnonymousUser() *User {
|
||||||
user := User{}
|
user := User{}
|
||||||
|
user.Policy.Type = "anonymous"
|
||||||
user.Group, _ = GetGroupByID(3)
|
user.Group, _ = GetGroupByID(3)
|
||||||
return &user
|
return &user
|
||||||
}
|
}
|
||||||
|
|
|
@ -407,8 +407,6 @@ func (client *Client) MonitorUpload(uploadURL, callbackKey, path string, size ui
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
util.Log().Debug("无法获取上传会话状态,%s", err.Error())
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
util.Log().Debug("无法获取上传会话状态,继续下一轮,%s", err.Error())
|
util.Log().Debug("无法获取上传会话状态,继续下一轮,%s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,7 +156,7 @@ func (fs *FileSystem) DispatchHandler() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch policyType {
|
switch policyType {
|
||||||
case "mock":
|
case "mock", "anonymous":
|
||||||
return nil
|
return nil
|
||||||
case "local":
|
case "local":
|
||||||
fs.Handler = local.Driver{
|
fs.Handler = local.Driver{
|
||||||
|
|
|
@ -16,6 +16,7 @@ type Share struct {
|
||||||
Downloads int `json:"downloads"`
|
Downloads int `json:"downloads"`
|
||||||
Views int `json:"views"`
|
Views int `json:"views"`
|
||||||
Expire int64 `json:"expire"`
|
Expire int64 `json:"expire"`
|
||||||
|
Preview bool `json:"preview"`
|
||||||
Creator *shareCreator `json:"creator,omitempty"`
|
Creator *shareCreator `json:"creator,omitempty"`
|
||||||
Source *shareSource `json:"source,omitempty"`
|
Source *shareSource `json:"source,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -53,6 +54,8 @@ func BuildShareResponse(share *model.Share, unlocked bool) Share {
|
||||||
resp.IsDir = share.IsDir
|
resp.IsDir = share.IsDir
|
||||||
resp.Downloads = share.Downloads
|
resp.Downloads = share.Downloads
|
||||||
resp.Views = share.Views
|
resp.Views = share.Views
|
||||||
|
resp.Preview = share.PreviewEnabled
|
||||||
|
|
||||||
if share.Expires != nil {
|
if share.Expires != nil {
|
||||||
resp.Expire = share.Expires.Unix() - time.Now().Unix()
|
resp.Expire = share.Expires.Unix() - time.Now().Unix()
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ type ShareCreateService struct {
|
||||||
RemainDownloads int `json:"downloads"`
|
RemainDownloads int `json:"downloads"`
|
||||||
Expire int `json:"expire"`
|
Expire int `json:"expire"`
|
||||||
Score int `json:"score" binding:"gte=0"`
|
Score int `json:"score" binding:"gte=0"`
|
||||||
|
Preview bool `json:"preview"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create 创建新分享
|
// Create 创建新分享
|
||||||
|
@ -52,6 +53,7 @@ func (service *ShareCreateService) Create(c *gin.Context) serializer.Response {
|
||||||
SourceID: service.SourceID,
|
SourceID: service.SourceID,
|
||||||
Score: service.Score,
|
Score: service.Score,
|
||||||
RemainDownloads: -1,
|
RemainDownloads: -1,
|
||||||
|
PreviewEnabled: service.Preview,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果开启了自动过期
|
// 如果开启了自动过期
|
||||||
|
|
|
@ -2,6 +2,7 @@ package share
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
model "github.com/HFO4/cloudreve/models"
|
model "github.com/HFO4/cloudreve/models"
|
||||||
"github.com/HFO4/cloudreve/pkg/filesystem"
|
"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
|
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 {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodeNoPermissionErr, err.Error(), 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)
|
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 {
|
if err != nil {
|
||||||
return serializer.Err(serializer.CodeNoPermissionErr, err.Error(), nil)
|
return serializer.Err(serializer.CodeNoPermissionErr, err.Error(), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用于调用子service
|
// 用于调下层service
|
||||||
ctx = context.WithValue(ctx, fsctx.FileModelCtx, share.GetSource())
|
ctx = context.WithValue(ctx, fsctx.FileModelCtx, share.GetSource())
|
||||||
subService := explorer.SingleFileService{
|
subService := explorer.SingleFileService{
|
||||||
Path: "",
|
Path: "",
|
||||||
|
@ -123,15 +128,24 @@ func (service *SingleFileService) PreviewContent(ctx context.Context, c *gin.Con
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckBeforeGetShare 获取分享内容/下载前进行的一系列检查
|
// 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)
|
err := share.CanBeDownloadBy(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue