package admin import ( "context" "strconv" "strings" "github.com/cloudreve/Cloudreve/v4/application/dependency" "github.com/cloudreve/Cloudreve/v4/ent" "github.com/cloudreve/Cloudreve/v4/inventory" "github.com/cloudreve/Cloudreve/v4/pkg/cluster/routes" "github.com/cloudreve/Cloudreve/v4/pkg/hashid" "github.com/cloudreve/Cloudreve/v4/pkg/serializer" "github.com/gin-gonic/gin" "github.com/samber/lo" ) const ( shareUserIDCondition = "share_user_id" shareFileIDCondition = "share_file_id" shareIDCondition = "share_id" ) func (s *AdminListService) Shares(c *gin.Context) (*ListShareResponse, error) { dep := dependency.FromContext(c) shareClient := dep.ShareClient() hasher := dep.HashIDEncoder() var ( err error userID int fileID int shareIDs []int ) if s.Conditions[shareUserIDCondition] != "" { userID, err = strconv.Atoi(s.Conditions[shareUserIDCondition]) if err != nil { return nil, serializer.NewError(serializer.CodeParamErr, "Invalid share user ID", err) } } if s.Conditions[shareFileIDCondition] != "" { fileID, err = strconv.Atoi(s.Conditions[shareFileIDCondition]) if err != nil { return nil, serializer.NewError(serializer.CodeParamErr, "Invalid share file ID", err) } } if s.Conditions[shareIDCondition] != "" { shareIdStrs := strings.Split(s.Conditions[shareIDCondition], ",") for _, shareIdStr := range shareIdStrs { shareID, err := strconv.Atoi(shareIdStr) if err != nil { return nil, serializer.NewError(serializer.CodeParamErr, "Invalid share ID", err) } shareIDs = append(shareIDs, shareID) } } ctx := context.WithValue(c, inventory.LoadShareFile{}, true) ctx = context.WithValue(ctx, inventory.LoadShareUser{}, true) res, err := shareClient.List(ctx, &inventory.ListShareArgs{ PaginationArgs: &inventory.PaginationArgs{ Page: s.Page - 1, PageSize: s.PageSize, OrderBy: s.OrderBy, Order: inventory.OrderDirection(s.OrderDirection), }, UserID: userID, FileID: fileID, ShareIDs: shareIDs, }) if err != nil { return nil, serializer.NewError(serializer.CodeDBError, "Failed to list shares", err) } siteUrl := dep.SettingProvider().SiteURL(c) return &ListShareResponse{ Pagination: res.PaginationResults, Shares: lo.Map(res.Shares, func(share *ent.Share, _ int) GetShareResponse { var ( uid string shareLink string ) if share.Edges.User != nil { uid = hashid.EncodeUserID(hasher, share.Edges.User.ID) } shareLink = routes.MasterShareUrl(siteUrl, hashid.EncodeShareID(hasher, share.ID), share.Password).String() return GetShareResponse{ Share: share, UserHashID: uid, ShareLink: shareLink, } }), }, nil } type ( SingleShareService struct { ShareID int `uri:"id" binding:"required"` } SingleShareParamCtx struct{} ) func (s *SingleShareService) Get(c *gin.Context) (*GetShareResponse, error) { dep := dependency.FromContext(c) shareClient := dep.ShareClient() hasher := dep.HashIDEncoder() ctx := context.WithValue(c, inventory.LoadShareFile{}, true) ctx = context.WithValue(ctx, inventory.LoadShareUser{}, true) share, err := shareClient.GetByID(ctx, s.ShareID) if err != nil { return nil, serializer.NewError(serializer.CodeDBError, "Failed to get share", err) } var ( uid string shareLink string ) if share.Edges.User != nil { uid = hashid.EncodeUserID(hasher, share.Edges.User.ID) } siteUrl := dep.SettingProvider().SiteURL(c) shareLink = routes.MasterShareUrl(siteUrl, hashid.EncodeShareID(hasher, share.ID), share.Password).String() return &GetShareResponse{ Share: share, UserHashID: uid, ShareLink: shareLink, }, nil } type ( BatchShareService struct { ShareIDs []int `json:"ids" binding:"required"` } BatchShareParamCtx struct{} ) func (s *BatchShareService) Delete(c *gin.Context) error { dep := dependency.FromContext(c) shareClient := dep.ShareClient() if err := shareClient.DeleteBatch(c, s.ShareIDs); err != nil { return serializer.NewError(serializer.CodeDBError, "Failed to delete shares", err) } return nil }