mirror of https://github.com/cloudreve/Cloudreve
173 lines
5.6 KiB
Go
173 lines
5.6 KiB
Go
package share
|
|
|
|
import (
|
|
"context"
|
|
|
|
"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/cluster/routes"
|
|
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/fs"
|
|
"github.com/cloudreve/Cloudreve/v4/pkg/filemanager/manager"
|
|
"github.com/cloudreve/Cloudreve/v4/pkg/hashid"
|
|
"github.com/cloudreve/Cloudreve/v4/pkg/serializer"
|
|
"github.com/cloudreve/Cloudreve/v4/service/explorer"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type (
|
|
ShortLinkRedirectService struct {
|
|
ID string `uri:"id" binding:"required"`
|
|
Password string `uri:"password"`
|
|
}
|
|
ShortLinkRedirectParamCtx struct{}
|
|
)
|
|
|
|
func (s *ShortLinkRedirectService) RedirectTo(c *gin.Context) string {
|
|
return routes.MasterShareLongUrl(s.ID, s.Password).String()
|
|
}
|
|
|
|
type (
|
|
ShareInfoService struct {
|
|
Password string `form:"password"`
|
|
CountViews bool `form:"count_views"`
|
|
OwnerExtended bool `form:"owner_extended"`
|
|
}
|
|
ShareInfoParamCtx struct{}
|
|
)
|
|
|
|
func (s *ShareInfoService) Get(c *gin.Context) (*explorer.Share, error) {
|
|
dep := dependency.FromContext(c)
|
|
u := inventory.UserFromContext(c)
|
|
shareClient := dep.ShareClient()
|
|
|
|
ctx := context.WithValue(c, inventory.LoadShareUser{}, true)
|
|
ctx = context.WithValue(ctx, inventory.LoadShareFile{}, true)
|
|
share, err := shareClient.GetByID(ctx, hashid.FromContext(c))
|
|
if err != nil {
|
|
if ent.IsNotFound(err) {
|
|
return nil, serializer.NewError(serializer.CodeNotFound, "Share not found", nil)
|
|
}
|
|
return nil, serializer.NewError(serializer.CodeDBError, "Failed to get share", err)
|
|
}
|
|
|
|
if err := inventory.IsValidShare(share); err != nil {
|
|
return nil, serializer.NewError(serializer.CodeNotFound, "Share link expired", err)
|
|
}
|
|
|
|
if s.CountViews {
|
|
_ = shareClient.Viewed(c, share)
|
|
}
|
|
|
|
unlocked := true
|
|
// Share requires password
|
|
if share.Password != "" && s.Password != share.Password && share.Edges.User.ID != u.ID {
|
|
unlocked = false
|
|
}
|
|
|
|
base := dep.SettingProvider().SiteURL(c)
|
|
res := explorer.BuildShare(share, base, dep.HashIDEncoder(), u, share.Edges.User, share.Edges.File.Name,
|
|
types.FileType(share.Edges.File.Type), unlocked, false)
|
|
|
|
if s.OwnerExtended && share.Edges.User.ID == u.ID {
|
|
// Add more information about the shared file
|
|
m := manager.NewFileManager(dep, u)
|
|
defer m.Recycle()
|
|
|
|
shareUri, err := fs.NewUriFromString(fs.NewShareUri(res.ID, s.Password))
|
|
if err != nil {
|
|
return nil, serializer.NewError(serializer.CodeInternalSetting, "Invalid share url", err)
|
|
}
|
|
|
|
root, err := m.Get(c, shareUri)
|
|
if err != nil {
|
|
return nil, serializer.NewError(serializer.CodeNotFound, "File not found", err)
|
|
}
|
|
|
|
res.SourceUri = root.Uri(true).String()
|
|
}
|
|
|
|
return res, nil
|
|
|
|
}
|
|
|
|
type (
|
|
ListShareService struct {
|
|
PageSize int `form:"page_size" binding:"required,min=10,max=100"`
|
|
OrderBy string `uri:"order_by" form:"order_by" json:"order_by"`
|
|
OrderDirection string `uri:"order_direction" form:"order_direction" json:"order_direction"`
|
|
NextPageToken string `form:"next_page_token"`
|
|
}
|
|
ListShareParamCtx struct{}
|
|
)
|
|
|
|
func (s *ListShareService) List(c *gin.Context) (*ListShareResponse, error) {
|
|
dep := dependency.FromContext(c)
|
|
user := inventory.UserFromContext(c)
|
|
hasher := dep.HashIDEncoder()
|
|
shareClient := dep.ShareClient()
|
|
|
|
args := &inventory.ListShareArgs{
|
|
PaginationArgs: &inventory.PaginationArgs{
|
|
UseCursorPagination: true,
|
|
PageToken: s.NextPageToken,
|
|
PageSize: s.PageSize,
|
|
Order: inventory.OrderDirection(s.OrderDirection),
|
|
OrderBy: s.OrderBy,
|
|
},
|
|
UserID: user.ID,
|
|
}
|
|
|
|
ctx := context.WithValue(c, inventory.LoadShareUser{}, true)
|
|
ctx = context.WithValue(ctx, inventory.LoadShareFile{}, true)
|
|
ctx = context.WithValue(ctx, inventory.LoadFileMetadata{}, true)
|
|
res, err := shareClient.List(ctx, args)
|
|
if err != nil {
|
|
return nil, serializer.NewError(serializer.CodeDBError, "Failed to list shares", err)
|
|
}
|
|
|
|
base := dep.SettingProvider().SiteURL(ctx)
|
|
return BuildListShareResponse(res, hasher, base, user, true), nil
|
|
}
|
|
|
|
func (s *ListShareService) ListInUserProfile(c *gin.Context, uid int) (*ListShareResponse, error) {
|
|
dep := dependency.FromContext(c)
|
|
user := inventory.UserFromContext(c)
|
|
hasher := dep.HashIDEncoder()
|
|
shareClient := dep.ShareClient()
|
|
|
|
targetUser, err := dep.UserClient().GetActiveByID(c, uid)
|
|
if err != nil {
|
|
return nil, serializer.NewError(serializer.CodeDBError, "Failed to get user", err)
|
|
}
|
|
|
|
if targetUser.Settings != nil && targetUser.Settings.ShareLinksInProfile == types.ProfileHideShare {
|
|
return nil, serializer.NewError(serializer.CodeParamErr, "User has disabled share links in profile", nil)
|
|
}
|
|
|
|
publicOnly := targetUser.Settings == nil || targetUser.Settings.ShareLinksInProfile == types.ProfilePublicShareOnly
|
|
args := &inventory.ListShareArgs{
|
|
PaginationArgs: &inventory.PaginationArgs{
|
|
UseCursorPagination: true,
|
|
PageToken: s.NextPageToken,
|
|
PageSize: s.PageSize,
|
|
Order: inventory.OrderDirection(s.OrderDirection),
|
|
OrderBy: s.OrderBy,
|
|
},
|
|
UserID: uid,
|
|
PublicOnly: publicOnly,
|
|
}
|
|
|
|
ctx := context.WithValue(c, inventory.LoadShareUser{}, true)
|
|
ctx = context.WithValue(ctx, inventory.LoadShareFile{}, true)
|
|
ctx = context.WithValue(ctx, inventory.LoadFileMetadata{}, true)
|
|
res, err := shareClient.List(ctx, args)
|
|
if err != nil {
|
|
return nil, serializer.NewError(serializer.CodeDBError, "Failed to list shares", err)
|
|
}
|
|
|
|
base := dep.SettingProvider().SiteURL(ctx)
|
|
return BuildListShareResponse(res, hasher, base, user, false), nil
|
|
}
|