Init V4 community edition (#2265)
* Init V4 community edition * Init V4 community edition
This commit is contained in:
@@ -1,150 +1,90 @@
|
||||
package share
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"context"
|
||||
"time"
|
||||
|
||||
model "github.com/cloudreve/Cloudreve/v3/models"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/hashid"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/serializer"
|
||||
"github.com/cloudreve/Cloudreve/v4/application/dependency"
|
||||
"github.com/cloudreve/Cloudreve/v4/ent"
|
||||
"github.com/cloudreve/Cloudreve/v4/inventory"
|
||||
"github.com/cloudreve/Cloudreve/v4/inventory/types"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/fs"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/manager"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/serializer"
|
||||
"github.com/cloudreve/Cloudreve/v4/service/explorer"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ShareCreateService 创建新分享服务
|
||||
type ShareCreateService struct {
|
||||
SourceID string `json:"id" binding:"required"`
|
||||
IsDir bool `json:"is_dir"`
|
||||
Password string `json:"password" binding:"max=255"`
|
||||
RemainDownloads int `json:"downloads"`
|
||||
Expire int `json:"expire"`
|
||||
Preview bool `json:"preview"`
|
||||
type (
|
||||
// ShareCreateService 创建新分享服务
|
||||
ShareCreateService struct {
|
||||
Uri string `json:"uri" binding:"required"`
|
||||
IsPrivate bool `json:"is_private"`
|
||||
RemainDownloads int `json:"downloads"`
|
||||
Expire int `json:"expire"`
|
||||
}
|
||||
ShareCreateParamCtx struct{}
|
||||
)
|
||||
|
||||
// Upsert 创建或更新分享
|
||||
func (service *ShareCreateService) Upsert(c *gin.Context, existed int) (string, error) {
|
||||
dep := dependency.FromContext(c)
|
||||
user := inventory.UserFromContext(c)
|
||||
m := manager.NewFileManager(dep, user)
|
||||
defer m.Recycle()
|
||||
|
||||
// Check group permission for creating share link
|
||||
if !user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionShare)) {
|
||||
return "", serializer.NewError(serializer.CodeGroupNotAllowed, "Group permission denied", nil)
|
||||
}
|
||||
|
||||
uri, err := fs.NewUriFromString(service.Uri)
|
||||
if err != nil {
|
||||
return "", serializer.NewError(serializer.CodeParamErr, "unknown uri", err)
|
||||
}
|
||||
|
||||
var expires *time.Time
|
||||
if service.Expire > 0 {
|
||||
expires = new(time.Time)
|
||||
*expires = time.Now().Add(time.Duration(service.Expire) * time.Second)
|
||||
}
|
||||
|
||||
share, err := m.CreateOrUpdateShare(c, uri, &manager.CreateShareArgs{
|
||||
IsPrivate: service.IsPrivate,
|
||||
RemainDownloads: service.RemainDownloads,
|
||||
Expire: expires,
|
||||
ExistedShareID: existed,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
base := dep.SettingProvider().SiteURL(c)
|
||||
return explorer.BuildShareLink(share, dep.HashIDEncoder(), base), nil
|
||||
}
|
||||
|
||||
// ShareUpdateService 分享更新服务
|
||||
type ShareUpdateService struct {
|
||||
Prop string `json:"prop" binding:"required,eq=password|eq=preview_enabled"`
|
||||
Value string `json:"value" binding:"max=255"`
|
||||
}
|
||||
func DeleteShare(c *gin.Context, shareId int) error {
|
||||
dep := dependency.FromContext(c)
|
||||
user := inventory.UserFromContext(c)
|
||||
shareClient := dep.ShareClient()
|
||||
|
||||
// Delete 删除分享
|
||||
func (service *Service) Delete(c *gin.Context, user *model.User) serializer.Response {
|
||||
share := model.GetShareByHashID(c.Param("id"))
|
||||
if share == nil || share.Creator().ID != user.ID {
|
||||
return serializer.Err(serializer.CodeShareLinkNotFound, "", nil)
|
||||
}
|
||||
|
||||
if err := share.Delete(); err != nil {
|
||||
return serializer.DBErr("Failed to delete share record", err)
|
||||
}
|
||||
|
||||
return serializer.Response{}
|
||||
}
|
||||
|
||||
// Update 更新分享属性
|
||||
func (service *ShareUpdateService) Update(c *gin.Context) serializer.Response {
|
||||
shareCtx, _ := c.Get("share")
|
||||
share := shareCtx.(*model.Share)
|
||||
|
||||
switch service.Prop {
|
||||
case "password":
|
||||
err := share.Update(map[string]interface{}{"password": service.Value})
|
||||
if err != nil {
|
||||
return serializer.DBErr("Failed to update share record", err)
|
||||
}
|
||||
case "preview_enabled":
|
||||
value := service.Value == "true"
|
||||
err := share.Update(map[string]interface{}{"preview_enabled": value})
|
||||
if err != nil {
|
||||
return serializer.DBErr("Failed to update share record", err)
|
||||
}
|
||||
return serializer.Response{
|
||||
Data: value,
|
||||
}
|
||||
}
|
||||
return serializer.Response{
|
||||
Data: service.Value,
|
||||
}
|
||||
}
|
||||
|
||||
// Create 创建新分享
|
||||
func (service *ShareCreateService) Create(c *gin.Context) serializer.Response {
|
||||
userCtx, _ := c.Get("user")
|
||||
user := userCtx.(*model.User)
|
||||
|
||||
// 是否拥有权限
|
||||
if !user.Group.ShareEnabled {
|
||||
return serializer.Err(serializer.CodeGroupNotAllowed, "", nil)
|
||||
}
|
||||
|
||||
// 源对象真实ID
|
||||
ctx := context.WithValue(c, inventory.LoadShareFile{}, true)
|
||||
var (
|
||||
sourceID uint
|
||||
sourceName string
|
||||
err error
|
||||
share *ent.Share
|
||||
err error
|
||||
)
|
||||
if service.IsDir {
|
||||
sourceID, err = hashid.DecodeHashID(service.SourceID, hashid.FolderID)
|
||||
if user.Edges.Group.Permissions.Enabled(int(types.GroupPermissionIsAdmin)) {
|
||||
share, err = shareClient.GetByID(ctx, shareId)
|
||||
} else {
|
||||
sourceID, err = hashid.DecodeHashID(service.SourceID, hashid.FileID)
|
||||
share, err = shareClient.GetByIDUser(ctx, shareId, user.ID)
|
||||
}
|
||||
if err != nil {
|
||||
return serializer.Err(serializer.CodeNotFound, "", nil)
|
||||
return serializer.NewError(serializer.CodeNotFound, "share not found", err)
|
||||
}
|
||||
|
||||
// 对象是否存在
|
||||
exist := true
|
||||
if service.IsDir {
|
||||
folder, err := model.GetFoldersByIDs([]uint{sourceID}, user.ID)
|
||||
if err != nil || len(folder) == 0 {
|
||||
exist = false
|
||||
} else {
|
||||
sourceName = folder[0].Name
|
||||
}
|
||||
} else {
|
||||
file, err := model.GetFilesByIDs([]uint{sourceID}, user.ID)
|
||||
if err != nil || len(file) == 0 {
|
||||
exist = false
|
||||
} else {
|
||||
sourceName = file[0].Name
|
||||
}
|
||||
}
|
||||
if !exist {
|
||||
return serializer.Err(serializer.CodeNotFound, "", nil)
|
||||
}
|
||||
|
||||
newShare := model.Share{
|
||||
Password: service.Password,
|
||||
IsDir: service.IsDir,
|
||||
UserID: user.ID,
|
||||
SourceID: sourceID,
|
||||
RemainDownloads: -1,
|
||||
PreviewEnabled: service.Preview,
|
||||
SourceName: sourceName,
|
||||
}
|
||||
|
||||
// 如果开启了自动过期
|
||||
if service.RemainDownloads > 0 {
|
||||
expires := time.Now().Add(time.Duration(service.Expire) * time.Second)
|
||||
newShare.RemainDownloads = service.RemainDownloads
|
||||
newShare.Expires = &expires
|
||||
}
|
||||
|
||||
// 创建分享
|
||||
id, err := newShare.Create()
|
||||
if err != nil {
|
||||
return serializer.DBErr("Failed to create share link record", err)
|
||||
}
|
||||
|
||||
// 获取分享的唯一id
|
||||
uid := hashid.HashID(id, hashid.ShareID)
|
||||
// 最终得到分享链接
|
||||
siteURL := model.GetSiteURL()
|
||||
sharePath, _ := url.Parse("/s/" + uid)
|
||||
shareURL := siteURL.ResolveReference(sharePath)
|
||||
|
||||
return serializer.Response{
|
||||
Code: 0,
|
||||
Data: shareURL.String(),
|
||||
if err := shareClient.Delete(c, share.ID); err != nil {
|
||||
return serializer.NewError(serializer.CodeDBError, "Failed to delete share", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user