mirror of
https://github.com/cloudreve/cloudreve.git
synced 2025-11-02 20:14:02 +08:00
Init V4 community edition (#2265)
* Init V4 community edition * Init V4 community edition
This commit is contained in:
@ -2,14 +2,22 @@ package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"path"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
model "github.com/cloudreve/Cloudreve/v3/models"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem/fsctx"
|
||||
"github.com/cloudreve/Cloudreve/v3/pkg/serializer"
|
||||
"github.com/cloudreve/Cloudreve/v3/service/explorer"
|
||||
"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/filemanager/manager/entitysource"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/hashid"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/serializer"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
// FileService 文件ID服务
|
||||
@ -33,176 +41,495 @@ type ListFolderService struct {
|
||||
|
||||
// List 列出指定路径下的目录
|
||||
func (service *ListFolderService) List(c *gin.Context) serializer.Response {
|
||||
if service.Type == "policy" {
|
||||
// 列取存储策略中的目录
|
||||
policy, err := model.GetPolicyByID(service.ID)
|
||||
if err != nil {
|
||||
return serializer.Err(serializer.CodePolicyNotExist, "", err)
|
||||
}
|
||||
//if service.Type == "policy" {
|
||||
// // 列取存储策略中的目录
|
||||
// policy, err := model.GetPolicyByID(service.ID)
|
||||
// if err != nil {
|
||||
// return serializer.ErrDeprecated(serializer.CodePolicyNotExist, "", err)
|
||||
// }
|
||||
//
|
||||
// // 创建文件系统
|
||||
// fs, err := filesystem.NewAnonymousFileSystem()
|
||||
// if err != nil {
|
||||
// return serializer.ErrDeprecated(serializer.CodeCreateFSError, "", err)
|
||||
// }
|
||||
// defer fs.Recycle()
|
||||
//
|
||||
// // 列取存储策略中的文件
|
||||
// fs.Policy = &policy
|
||||
// res, err := fs.ListPhysical(c.Request.Context(), service.Path)
|
||||
// if err != nil {
|
||||
// return serializer.ErrDeprecated(serializer.CodeListFilesError, "", err)
|
||||
// }
|
||||
//
|
||||
// return serializer.Response{
|
||||
// Data: serializer.BuildObjectList(0, res, nil),
|
||||
// }
|
||||
//
|
||||
//}
|
||||
//
|
||||
//// 列取用户空间目录
|
||||
//// 查找用户
|
||||
//user, err := model.GetUserByID(service.ID)
|
||||
//if err != nil {
|
||||
// return serializer.ErrDeprecated(serializer.CodeUserNotFound, "", err)
|
||||
//}
|
||||
//
|
||||
//// 创建文件系统
|
||||
//fs, err := filesystem.NewFileSystem(&user)
|
||||
//if err != nil {
|
||||
// return serializer.ErrDeprecated(serializer.CodeCreateFSError, "", err)
|
||||
//}
|
||||
//defer fs.Recycle()
|
||||
//
|
||||
//// 列取目录
|
||||
//res, err := fs.List(c.Request.Context(), service.Path, nil)
|
||||
//if err != nil {
|
||||
// return serializer.ErrDeprecated(serializer.CodeListFilesError, "", err)
|
||||
//}
|
||||
|
||||
// 创建文件系统
|
||||
fs, err := filesystem.NewAnonymousFileSystem()
|
||||
if err != nil {
|
||||
return serializer.Err(serializer.CodeCreateFSError, "", err)
|
||||
}
|
||||
defer fs.Recycle()
|
||||
//return serializer.Response{
|
||||
// Data: serializer.BuildObjectList(0, res, nil),
|
||||
//}
|
||||
|
||||
// 列取存储策略中的文件
|
||||
fs.Policy = &policy
|
||||
res, err := fs.ListPhysical(c.Request.Context(), service.Path)
|
||||
if err != nil {
|
||||
return serializer.Err(serializer.CodeListFilesError, "", err)
|
||||
}
|
||||
|
||||
return serializer.Response{
|
||||
Data: serializer.BuildObjectList(0, res, nil),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 列取用户空间目录
|
||||
// 查找用户
|
||||
user, err := model.GetUserByID(service.ID)
|
||||
if err != nil {
|
||||
return serializer.Err(serializer.CodeUserNotFound, "", err)
|
||||
}
|
||||
|
||||
// 创建文件系统
|
||||
fs, err := filesystem.NewFileSystem(&user)
|
||||
if err != nil {
|
||||
return serializer.Err(serializer.CodeCreateFSError, "", err)
|
||||
}
|
||||
defer fs.Recycle()
|
||||
|
||||
// 列取目录
|
||||
res, err := fs.List(c.Request.Context(), service.Path, nil)
|
||||
if err != nil {
|
||||
return serializer.Err(serializer.CodeListFilesError, "", err)
|
||||
}
|
||||
|
||||
return serializer.Response{
|
||||
Data: serializer.BuildObjectList(0, res, nil),
|
||||
}
|
||||
return serializer.Response{}
|
||||
}
|
||||
|
||||
// Delete 删除文件
|
||||
func (service *FileBatchService) Delete(c *gin.Context) serializer.Response {
|
||||
files, err := model.GetFilesByIDs(service.ID, 0)
|
||||
if err != nil {
|
||||
return serializer.DBErr("Failed to list files for deleting", err)
|
||||
}
|
||||
|
||||
// 根据用户分组
|
||||
userFile := make(map[uint][]model.File)
|
||||
for i := 0; i < len(files); i++ {
|
||||
if _, ok := userFile[files[i].UserID]; !ok {
|
||||
userFile[files[i].UserID] = []model.File{}
|
||||
}
|
||||
userFile[files[i].UserID] = append(userFile[files[i].UserID], files[i])
|
||||
}
|
||||
|
||||
// 异步执行删除
|
||||
go func(files map[uint][]model.File) {
|
||||
for uid, file := range files {
|
||||
var (
|
||||
fs *filesystem.FileSystem
|
||||
err error
|
||||
)
|
||||
user, err := model.GetUserByID(uid)
|
||||
if err != nil {
|
||||
fs, err = filesystem.NewAnonymousFileSystem()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
fs, err = filesystem.NewFileSystem(&user)
|
||||
if err != nil {
|
||||
fs.Recycle()
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// 汇总文件ID
|
||||
ids := make([]uint, 0, len(file))
|
||||
for i := 0; i < len(file); i++ {
|
||||
ids = append(ids, file[i].ID)
|
||||
}
|
||||
|
||||
// 执行删除
|
||||
fs.Delete(context.Background(), []uint{}, ids, service.Force, service.UnlinkOnly)
|
||||
fs.Recycle()
|
||||
}
|
||||
}(userFile)
|
||||
//files, err := model.GetFilesByIDs(service.ID, 0)
|
||||
//if err != nil {
|
||||
// return serializer.DBErrDeprecated("Failed to list files for deleting", err)
|
||||
//}
|
||||
//
|
||||
//// 根据用户分组
|
||||
//userFile := make(map[uint][]model.File)
|
||||
//for i := 0; i < len(files); i++ {
|
||||
// if _, ok := userFile[files[i].UserID]; !ok {
|
||||
// userFile[files[i].UserID] = []model.File{}
|
||||
// }
|
||||
// userFile[files[i].UserID] = append(userFile[files[i].UserID], files[i])
|
||||
//}
|
||||
//
|
||||
//// 异步执行删除
|
||||
//go func(files map[uint][]model.File) {
|
||||
// for uid, file := range files {
|
||||
// var (
|
||||
// fs *filesystem.FileSystem
|
||||
// err error
|
||||
// )
|
||||
// user, err := model.GetUserByID(uid)
|
||||
// if err != nil {
|
||||
// fs, err = filesystem.NewAnonymousFileSystem()
|
||||
// if err != nil {
|
||||
// continue
|
||||
// }
|
||||
// } else {
|
||||
// fs, err = filesystem.NewFileSystem(&user)
|
||||
// if err != nil {
|
||||
// fs.Recycle()
|
||||
// continue
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 汇总文件ID
|
||||
// ids := make([]uint, 0, len(file))
|
||||
// for i := 0; i < len(file); i++ {
|
||||
// ids = append(ids, file[i].ID)
|
||||
// }
|
||||
//
|
||||
// // 执行删除
|
||||
// fs.Delete(context.Background(), []uint{}, ids, service.Force, service.UnlinkOnly)
|
||||
// fs.Recycle()
|
||||
// }
|
||||
//}(userFile)
|
||||
|
||||
// 分组执行删除
|
||||
return serializer.Response{}
|
||||
|
||||
}
|
||||
|
||||
// Get 预览文件
|
||||
func (service *FileService) Get(c *gin.Context) serializer.Response {
|
||||
file, err := model.GetFilesByIDs([]uint{service.ID}, 0)
|
||||
if err != nil {
|
||||
return serializer.Err(serializer.CodeFileNotFound, "", err)
|
||||
}
|
||||
const (
|
||||
fileNameCondition = "file_name"
|
||||
fileUserCondition = "file_user"
|
||||
filePolicyCondition = "file_policy"
|
||||
)
|
||||
|
||||
ctx := context.WithValue(context.Background(), fsctx.FileModelCtx, &file[0])
|
||||
var subService explorer.FileIDService
|
||||
res := subService.PreviewContent(ctx, c, false)
|
||||
func (service *AdminListService) Files(c *gin.Context) (*ListFileResponse, error) {
|
||||
dep := dependency.FromContext(c)
|
||||
hasher := dep.HashIDEncoder()
|
||||
fileClient := dep.FileClient()
|
||||
|
||||
return res
|
||||
}
|
||||
ctx := context.WithValue(c, inventory.LoadFileEntity{}, true)
|
||||
ctx = context.WithValue(ctx, inventory.LoadFileMetadata{}, true)
|
||||
ctx = context.WithValue(ctx, inventory.LoadFileShare{}, true)
|
||||
ctx = context.WithValue(ctx, inventory.LoadFileUser{}, true)
|
||||
ctx = context.WithValue(ctx, inventory.LoadFileDirectLink{}, true)
|
||||
|
||||
// Files 列出文件
|
||||
func (service *AdminListService) Files() serializer.Response {
|
||||
var res []model.File
|
||||
total := 0
|
||||
var (
|
||||
err error
|
||||
userID int
|
||||
policyID int
|
||||
)
|
||||
|
||||
tx := model.DB.Model(&model.File{})
|
||||
if service.OrderBy != "" {
|
||||
tx = tx.Order(service.OrderBy)
|
||||
}
|
||||
|
||||
for k, v := range service.Conditions {
|
||||
tx = tx.Where(k+" = ?", v)
|
||||
}
|
||||
|
||||
if len(service.Searches) > 0 {
|
||||
search := ""
|
||||
for k, v := range service.Searches {
|
||||
search += k + " like '%" + v + "%' OR "
|
||||
if service.Conditions[fileUserCondition] != "" {
|
||||
userID, err = strconv.Atoi(service.Conditions[fileUserCondition])
|
||||
if err != nil {
|
||||
return nil, serializer.NewError(serializer.CodeParamErr, "Invalid user ID", err)
|
||||
}
|
||||
search = strings.TrimSuffix(search, " OR ")
|
||||
tx = tx.Where(search)
|
||||
}
|
||||
|
||||
// 计算总数用于分页
|
||||
tx.Count(&total)
|
||||
|
||||
// 查询记录
|
||||
tx.Limit(service.PageSize).Offset((service.Page - 1) * service.PageSize).Find(&res)
|
||||
|
||||
// 查询对应用户
|
||||
users := make(map[uint]model.User)
|
||||
for _, file := range res {
|
||||
users[file.UserID] = model.User{}
|
||||
if service.Conditions[filePolicyCondition] != "" {
|
||||
policyID, err = strconv.Atoi(service.Conditions[filePolicyCondition])
|
||||
if err != nil {
|
||||
return nil, serializer.NewError(serializer.CodeParamErr, "Invalid policy ID", err)
|
||||
}
|
||||
}
|
||||
|
||||
userIDs := make([]uint, 0, len(users))
|
||||
for k := range users {
|
||||
userIDs = append(userIDs, k)
|
||||
res, err := fileClient.FlattenListFiles(ctx, &inventory.FlattenListFileParameters{
|
||||
PaginationArgs: &inventory.PaginationArgs{
|
||||
Page: service.Page - 1,
|
||||
PageSize: service.PageSize,
|
||||
OrderBy: service.OrderBy,
|
||||
Order: inventory.OrderDirection(service.OrderDirection),
|
||||
},
|
||||
UserID: userID,
|
||||
StoragePolicyID: policyID,
|
||||
Name: service.Conditions[fileNameCondition],
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, serializer.NewError(serializer.CodeDBError, "Failed to list files", err)
|
||||
}
|
||||
|
||||
var userList []model.User
|
||||
model.DB.Where("id in (?)", userIDs).Find(&userList)
|
||||
|
||||
for _, v := range userList {
|
||||
users[v.ID] = v
|
||||
}
|
||||
|
||||
return serializer.Response{Data: map[string]interface{}{
|
||||
"total": total,
|
||||
"items": res,
|
||||
"users": users,
|
||||
}}
|
||||
return &ListFileResponse{
|
||||
Pagination: res.PaginationResults,
|
||||
Files: lo.Map(res.Files, func(file *ent.File, _ int) GetFileResponse {
|
||||
return GetFileResponse{
|
||||
File: file,
|
||||
UserHashID: hashid.EncodeUserID(hasher, file.OwnerID),
|
||||
}
|
||||
}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type (
|
||||
SingleFileService struct {
|
||||
ID int `uri:"id" json:"id" binding:"required"`
|
||||
}
|
||||
SingleFileParamCtx struct{}
|
||||
)
|
||||
|
||||
func (service *SingleFileService) Get(c *gin.Context) (*GetFileResponse, error) {
|
||||
dep := dependency.FromContext(c)
|
||||
hasher := dep.HashIDEncoder()
|
||||
fileClient := dep.FileClient()
|
||||
|
||||
ctx := context.WithValue(c, inventory.LoadFileEntity{}, true)
|
||||
ctx = context.WithValue(ctx, inventory.LoadFileMetadata{}, true)
|
||||
ctx = context.WithValue(ctx, inventory.LoadFileShare{}, true)
|
||||
ctx = context.WithValue(ctx, inventory.LoadFileUser{}, true)
|
||||
ctx = context.WithValue(ctx, inventory.LoadEntityUser{}, true)
|
||||
ctx = context.WithValue(ctx, inventory.LoadEntityStoragePolicy{}, true)
|
||||
ctx = context.WithValue(ctx, inventory.LoadFileDirectLink{}, true)
|
||||
|
||||
file, err := fileClient.GetByID(ctx, service.ID)
|
||||
if err != nil {
|
||||
if ent.IsNotFound(err) {
|
||||
return nil, serializer.NewError(serializer.CodeNotFound, "File not found", nil)
|
||||
}
|
||||
|
||||
return nil, serializer.NewError(serializer.CodeDBError, "Failed to get file", err)
|
||||
}
|
||||
|
||||
directLinkMap := make(map[int]string)
|
||||
siteURL := dep.SettingProvider().SiteURL(c)
|
||||
for _, directLink := range file.Edges.DirectLinks {
|
||||
directLinkMap[directLink.ID] = routes.MasterDirectLink(siteURL, hashid.EncodeSourceLinkID(hasher, directLink.ID), directLink.Name).String()
|
||||
}
|
||||
|
||||
return &GetFileResponse{
|
||||
File: file,
|
||||
UserHashID: hashid.EncodeUserID(hasher, file.OwnerID),
|
||||
DirectLinkMap: directLinkMap,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type (
|
||||
UpsertFileService struct {
|
||||
File *ent.File `json:"file" binding:"required"`
|
||||
}
|
||||
UpsertFileParamCtx struct{}
|
||||
)
|
||||
|
||||
func (s *UpsertFileService) Update(c *gin.Context) (*GetFileResponse, error) {
|
||||
dep := dependency.FromContext(c)
|
||||
fileClient := dep.FileClient()
|
||||
|
||||
fc, tx, ctx, err := inventory.WithTx(c, fileClient)
|
||||
if err != nil {
|
||||
return nil, serializer.NewError(serializer.CodeDBError, "Failed to start transaction", err)
|
||||
}
|
||||
|
||||
newFile, err := fc.Update(ctx, s.File)
|
||||
if err != nil {
|
||||
_ = inventory.Rollback(tx)
|
||||
return nil, serializer.NewError(serializer.CodeDBError, "Failed to update file", err)
|
||||
}
|
||||
|
||||
if err := inventory.Commit(tx); err != nil {
|
||||
return nil, serializer.NewError(serializer.CodeDBError, "Failed to commit transaction", err)
|
||||
}
|
||||
|
||||
service := &SingleFileService{ID: newFile.ID}
|
||||
return service.Get(c)
|
||||
}
|
||||
|
||||
func (s *SingleFileService) Url(c *gin.Context) (string, error) {
|
||||
dep := dependency.FromContext(c)
|
||||
fileClient := dep.FileClient()
|
||||
|
||||
ctx := context.WithValue(c, inventory.LoadFileEntity{}, true)
|
||||
file, err := fileClient.GetByID(ctx, s.ID)
|
||||
if err != nil {
|
||||
return "", serializer.NewError(serializer.CodeDBError, "Failed to get file", err)
|
||||
}
|
||||
|
||||
// find primary entity
|
||||
var primaryEntity *ent.Entity
|
||||
for _, entity := range file.Edges.Entities {
|
||||
if entity.Type == int(types.EntityTypeVersion) && entity.ID == file.PrimaryEntity {
|
||||
primaryEntity = entity
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if primaryEntity == nil {
|
||||
return "", serializer.NewError(serializer.CodeNotFound, "Primary entity not exist", nil)
|
||||
}
|
||||
|
||||
// find policy
|
||||
policy, err := dep.StoragePolicyClient().GetPolicyByID(ctx, primaryEntity.StoragePolicyEntities)
|
||||
if err != nil {
|
||||
return "", serializer.NewError(serializer.CodeDBError, "Failed to get policy", err)
|
||||
}
|
||||
|
||||
m := manager.NewFileManager(dep, inventory.UserFromContext(c))
|
||||
defer m.Recycle()
|
||||
|
||||
driver, err := m.GetStorageDriver(ctx, policy)
|
||||
if err != nil {
|
||||
return "", serializer.NewError(serializer.CodeInternalSetting, "Failed to get storage driver", err)
|
||||
}
|
||||
|
||||
es := entitysource.NewEntitySource(fs.NewEntity(primaryEntity), driver, policy, dep.GeneralAuth(),
|
||||
dep.SettingProvider(), dep.HashIDEncoder(), dep.RequestClient(), dep.Logger(), dep.ConfigProvider(), dep.MimeDetector(ctx))
|
||||
|
||||
expire := time.Now().Add(time.Hour * 1)
|
||||
url, err := es.Url(ctx, entitysource.WithExpire(&expire), entitysource.WithDisplayName(file.Name))
|
||||
if err != nil {
|
||||
return "", serializer.NewError(serializer.CodeInternalSetting, "Failed to get url", err)
|
||||
}
|
||||
|
||||
return url.Url, nil
|
||||
}
|
||||
|
||||
type (
|
||||
BatchFileService struct {
|
||||
IDs []int `json:"ids" binding:"min=1"`
|
||||
}
|
||||
BatchFileParamCtx struct{}
|
||||
)
|
||||
|
||||
func (s *BatchFileService) Delete(c *gin.Context) error {
|
||||
dep := dependency.FromContext(c)
|
||||
fileClient := dep.FileClient()
|
||||
|
||||
ctx := context.WithValue(c, inventory.LoadFileEntity{}, true)
|
||||
files, _, err := fileClient.GetByIDs(ctx, s.IDs, 0)
|
||||
if err != nil {
|
||||
return serializer.NewError(serializer.CodeDBError, "Failed to get files", err)
|
||||
}
|
||||
|
||||
fc, tx, ctx, err := inventory.WithTx(c, fileClient)
|
||||
if err != nil {
|
||||
return serializer.NewError(serializer.CodeDBError, "Failed to start transaction", err)
|
||||
}
|
||||
|
||||
_, diff, err := fc.Delete(ctx, files, nil)
|
||||
if err != nil {
|
||||
_ = inventory.Rollback(tx)
|
||||
return serializer.NewError(serializer.CodeDBError, "Failed to delete files", err)
|
||||
}
|
||||
|
||||
tx.AppendStorageDiff(diff)
|
||||
if err := inventory.CommitWithStorageDiff(ctx, tx, dep.Logger(), dep.UserClient()); err != nil {
|
||||
return serializer.NewError(serializer.CodeDBError, "Failed to commit transaction", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
entityUserCondition = "entity_user"
|
||||
entityPolicyCondition = "entity_policy"
|
||||
entityTypeCondition = "entity_type"
|
||||
)
|
||||
|
||||
func (s *AdminListService) Entities(c *gin.Context) (*ListEntityResponse, error) {
|
||||
dep := dependency.FromContext(c)
|
||||
fileClient := dep.FileClient()
|
||||
hasher := dep.HashIDEncoder()
|
||||
ctx := context.WithValue(c, inventory.LoadEntityUser{}, true)
|
||||
ctx = context.WithValue(ctx, inventory.LoadEntityStoragePolicy{}, true)
|
||||
|
||||
var (
|
||||
userID int
|
||||
policyID int
|
||||
err error
|
||||
entityType *types.EntityType
|
||||
)
|
||||
|
||||
if s.Conditions[entityUserCondition] != "" {
|
||||
userID, err = strconv.Atoi(s.Conditions[entityUserCondition])
|
||||
if err != nil {
|
||||
return nil, serializer.NewError(serializer.CodeParamErr, "Invalid user ID", err)
|
||||
}
|
||||
}
|
||||
|
||||
if s.Conditions[entityPolicyCondition] != "" {
|
||||
policyID, err = strconv.Atoi(s.Conditions[entityPolicyCondition])
|
||||
if err != nil {
|
||||
return nil, serializer.NewError(serializer.CodeParamErr, "Invalid policy ID", err)
|
||||
}
|
||||
}
|
||||
|
||||
if s.Conditions[entityTypeCondition] != "" {
|
||||
typeId, err := strconv.Atoi(s.Conditions[entityTypeCondition])
|
||||
if err != nil {
|
||||
return nil, serializer.NewError(serializer.CodeParamErr, "Invalid entity type", err)
|
||||
}
|
||||
|
||||
t := types.EntityType(typeId)
|
||||
entityType = &t
|
||||
}
|
||||
|
||||
res, err := fileClient.ListEntities(ctx, &inventory.ListEntityParameters{
|
||||
PaginationArgs: &inventory.PaginationArgs{
|
||||
Page: s.Page - 1,
|
||||
PageSize: s.PageSize,
|
||||
OrderBy: s.OrderBy,
|
||||
Order: inventory.OrderDirection(s.OrderDirection),
|
||||
},
|
||||
UserID: userID,
|
||||
StoragePolicyID: policyID,
|
||||
EntityType: entityType,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, serializer.NewError(serializer.CodeDBError, "Failed to list entities", err)
|
||||
}
|
||||
|
||||
return &ListEntityResponse{
|
||||
Pagination: res.PaginationResults,
|
||||
Entities: lo.Map(res.Entities, func(entity *ent.Entity, _ int) GetEntityResponse {
|
||||
return GetEntityResponse{
|
||||
Entity: entity,
|
||||
UserHashID: hashid.EncodeUserID(hasher, entity.CreatedBy),
|
||||
}
|
||||
}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type (
|
||||
SingleEntityService struct {
|
||||
ID int `uri:"id" json:"id" binding:"required"`
|
||||
}
|
||||
SingleEntityParamCtx struct{}
|
||||
)
|
||||
|
||||
func (s *SingleEntityService) Get(c *gin.Context) (*GetEntityResponse, error) {
|
||||
dep := dependency.FromContext(c)
|
||||
fileClient := dep.FileClient()
|
||||
hasher := dep.HashIDEncoder()
|
||||
|
||||
ctx := context.WithValue(c, inventory.LoadEntityUser{}, true)
|
||||
ctx = context.WithValue(ctx, inventory.LoadEntityStoragePolicy{}, true)
|
||||
ctx = context.WithValue(ctx, inventory.LoadEntityFile{}, true)
|
||||
ctx = context.WithValue(ctx, inventory.LoadFileUser{}, true)
|
||||
|
||||
userHashIDMap := make(map[int]string)
|
||||
entity, err := fileClient.GetEntityByID(ctx, s.ID)
|
||||
if err != nil {
|
||||
if ent.IsNotFound(err) {
|
||||
return nil, serializer.NewError(serializer.CodeNotFound, "Entity not found", nil)
|
||||
}
|
||||
return nil, serializer.NewError(serializer.CodeDBError, "Failed to get entity", err)
|
||||
}
|
||||
|
||||
for _, file := range entity.Edges.File {
|
||||
userHashIDMap[file.OwnerID] = hashid.EncodeUserID(hasher, file.OwnerID)
|
||||
}
|
||||
|
||||
return &GetEntityResponse{
|
||||
Entity: entity,
|
||||
UserHashID: hashid.EncodeUserID(hasher, entity.CreatedBy),
|
||||
UserHashIDMap: userHashIDMap,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type (
|
||||
BatchEntityService struct {
|
||||
IDs []int `json:"ids" binding:"min=1"`
|
||||
Force bool `json:"force"`
|
||||
}
|
||||
BatchEntityParamCtx struct{}
|
||||
)
|
||||
|
||||
func (s *BatchEntityService) Delete(c *gin.Context) error {
|
||||
dep := dependency.FromContext(c)
|
||||
m := manager.NewFileManager(dep, inventory.UserFromContext(c))
|
||||
defer m.Recycle()
|
||||
|
||||
err := m.RecycleEntities(c.Request.Context(), s.Force, s.IDs...)
|
||||
if err != nil {
|
||||
return serializer.NewError(serializer.CodeDBError, "Failed to recycle entities", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SingleEntityService) Url(c *gin.Context) (string, error) {
|
||||
dep := dependency.FromContext(c)
|
||||
fileClient := dep.FileClient()
|
||||
|
||||
entity, err := fileClient.GetEntityByID(c, s.ID)
|
||||
if err != nil {
|
||||
return "", serializer.NewError(serializer.CodeDBError, "Failed to get file", err)
|
||||
}
|
||||
|
||||
// find policy
|
||||
policy, err := dep.StoragePolicyClient().GetPolicyByID(c, entity.StoragePolicyEntities)
|
||||
if err != nil {
|
||||
return "", serializer.NewError(serializer.CodeDBError, "Failed to get policy", err)
|
||||
}
|
||||
|
||||
m := manager.NewFileManager(dep, inventory.UserFromContext(c))
|
||||
defer m.Recycle()
|
||||
|
||||
driver, err := m.GetStorageDriver(c, policy)
|
||||
if err != nil {
|
||||
return "", serializer.NewError(serializer.CodeInternalSetting, "Failed to get storage driver", err)
|
||||
}
|
||||
|
||||
es := entitysource.NewEntitySource(fs.NewEntity(entity), driver, policy, dep.GeneralAuth(),
|
||||
dep.SettingProvider(), dep.HashIDEncoder(), dep.RequestClient(), dep.Logger(), dep.ConfigProvider(), dep.MimeDetector(c))
|
||||
|
||||
expire := time.Now().Add(time.Hour * 1)
|
||||
url, err := es.Url(c, entitysource.WithDownload(true), entitysource.WithExpire(&expire), entitysource.WithDisplayName(path.Base(entity.Source)))
|
||||
if err != nil {
|
||||
return "", serializer.NewError(serializer.CodeInternalSetting, "Failed to get url", err)
|
||||
}
|
||||
|
||||
return url.Url, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user