205 lines
6.1 KiB
Go
205 lines
6.1 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"octopus/internal/dal"
|
|
"octopus/internal/dal/model"
|
|
"octopus/internal/dal/query"
|
|
"octopus/internal/schema"
|
|
"octopus/pkg/utils"
|
|
|
|
"github.com/casdoor/casdoor-go-sdk/casdoorsdk"
|
|
"gorm.io/gen/field"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func GetDocFolderTree(ctx context.Context, auth *casdoorsdk.User, param *schema.GetDocFolderTree) ([]*model.DocFolderWithChildren, error) {
|
|
parentPath := ""
|
|
parentID := ""
|
|
if param.ParentID != nil {
|
|
parent, err := GetDocFolder(ctx, auth, *param.ParentID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get parent folder: %w", err)
|
|
}
|
|
parentPath = parent.ParentPath
|
|
parentID = parent.ID
|
|
}
|
|
|
|
folders, err := query.DocFolder.
|
|
Where(
|
|
query.DocFolder.OrgID.Eq(auth.Owner),
|
|
query.DocFolder.ParentPath.Like(parentPath+"%"),
|
|
).
|
|
Order(query.DocFolder.ParentPath).
|
|
Find()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get doc folders: %w", err)
|
|
}
|
|
|
|
// 如果没有的话,就创建一个默认的分组
|
|
if utils.Unptr(param.ParentID) == "" && len(folders) == 0 {
|
|
folder := model.DocFolder{
|
|
Base: model.Base{OrgID: auth.Owner},
|
|
Name: "默认分组",
|
|
IsDefault: true,
|
|
ParentPath: parentPath,
|
|
CreatedBy: auth.Id,
|
|
}
|
|
if err := query.DocFolder.Create(&folder); err != nil {
|
|
return nil, fmt.Errorf("failed to create doc folder: %w", err)
|
|
}
|
|
|
|
folders = append(folders, &folder)
|
|
}
|
|
|
|
return composeFolders(parentID, folders), nil
|
|
}
|
|
|
|
func GetDocFolder(ctx context.Context, auth *casdoorsdk.User, id string) (*model.DocFolder, error) {
|
|
folder, err := query.DocFolder.Where(query.DocFolder.OrgID.Eq(auth.Owner), query.DocFolder.ID.Eq(id)).Take()
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, fmt.Errorf("specified doc folder not exists")
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return folder, nil
|
|
}
|
|
|
|
func GetDocFolderChildren(ctx context.Context, auth *casdoorsdk.User, id string) ([]*model.DocFolder, error) {
|
|
folder, err := GetDocFolder(ctx, auth, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return query.DocFolder.Where(query.DocFolder.OrgID.Eq(auth.Owner), query.DocFolder.ParentPath.Like(folder.ParentPath+"%")).Find()
|
|
}
|
|
|
|
func CreateDocFolder(ctx context.Context, auth *casdoorsdk.User, param *schema.CreateDocFolder) (*model.DocFolder, error) {
|
|
path := ""
|
|
if param.ParentID != "" {
|
|
parent, err := GetDocFolder(ctx, auth, param.ParentID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get parent folder: %w", err)
|
|
}
|
|
path = fmt.Sprintf("%s/%s", parent.ParentPath, parent.ID)
|
|
}
|
|
|
|
folder := model.DocFolder{
|
|
Base: model.Base{OrgID: auth.Owner},
|
|
Name: param.Name,
|
|
ParentPath: path,
|
|
CreatedBy: auth.Id,
|
|
}
|
|
if err := query.DocFolder.Create(&folder); err != nil {
|
|
return nil, fmt.Errorf("failed to create doc folder: %w", err)
|
|
}
|
|
return &folder, nil
|
|
}
|
|
|
|
func UpdateDocFolder(ctx context.Context, auth *casdoorsdk.User, id string, param *schema.UpdateDocFolder) (*model.DocFolder, error) {
|
|
folder, err := GetDocFolder(ctx, auth, id)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get doc folder: %w", err)
|
|
}
|
|
|
|
var updates []field.AssignExpr
|
|
|
|
if param.ParentID != nil {
|
|
if folder.IsDefault {
|
|
return nil, fmt.Errorf("cannot move the default folder")
|
|
}
|
|
|
|
parent, err := GetDocFolder(ctx, auth, *param.ParentID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get parent folder: %w", err)
|
|
}
|
|
newParentPath := fmt.Sprintf("%s/%s", parent.ParentPath, parent.ID)
|
|
updates = append(updates, query.DocFolder.ParentPath.Value(newParentPath))
|
|
}
|
|
|
|
if param.Name != nil {
|
|
updates = append(updates, query.DocFolder.Name.Value(*param.Name))
|
|
}
|
|
if _, err := query.DocFolder.Where(query.DocFolder.ID.Eq(id)).UpdateSimple(updates...); err != nil {
|
|
return nil, fmt.Errorf("failed to update doc folder: %w", err)
|
|
}
|
|
return GetDocFolder(ctx, auth, id)
|
|
}
|
|
|
|
func DeleteDocFolder(ctx context.Context, auth *casdoorsdk.User, id string) error {
|
|
folder, err := GetDocFolder(ctx, auth, id)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get doc folder: %w", err)
|
|
}
|
|
// if folder.IsDefault {
|
|
// return fmt.Errorf("cannot delete the default folder")
|
|
// }
|
|
subFolders, err := GetDocFolderChildren(ctx, auth, id)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get doc folder children: %w", err)
|
|
}
|
|
|
|
allFolderIDs := make([]string, 0, len(subFolders)+1)
|
|
allFolderIDs = append(allFolderIDs, folder.ID)
|
|
for _, subFolder := range subFolders {
|
|
allFolderIDs = append(allFolderIDs, subFolder.ID)
|
|
}
|
|
|
|
// 需要把文件和对应的对象存储中的文件一并删除
|
|
docs, err := query.Doc.Where(query.Doc.OrgID.Eq(auth.Owner), query.Doc.FolderID.In(allFolderIDs...)).Find()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get docs: %w", err)
|
|
}
|
|
|
|
objectNames := make([]string, 0, len(docs))
|
|
docIDs := make([]string, 0, len(docs))
|
|
for _, doc := range docs {
|
|
objectNames = append(objectNames, doc.ObjectName)
|
|
docIDs = append(docIDs, doc.ID)
|
|
}
|
|
|
|
if len(objectNames) > 0 {
|
|
if errs := dal.GetStorage().DeleteObjects(ctx, objectNames); len(errs) != 0 {
|
|
err := errors.New("failed to delete objects")
|
|
for _, e := range errs {
|
|
err = fmt.Errorf("failed to delete object %s: %w", e.ObjectName, e.Err)
|
|
}
|
|
return err
|
|
}
|
|
}
|
|
if len(docIDs) > 0 {
|
|
if _, err := query.Doc.Where(query.Doc.ID.In(docIDs...)).Delete(); err != nil {
|
|
return fmt.Errorf("failed to delete docs: %w", err)
|
|
}
|
|
}
|
|
|
|
if _, err := query.DocFolder.Where(query.DocFolder.ID.In(allFolderIDs...)).Delete(); err != nil {
|
|
return fmt.Errorf("failed to delete doc folder: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// composeFolders() 用于把文件夹列表转换成树形结构
|
|
func composeFolders(topID string, folders []*model.DocFolder) []*model.DocFolderWithChildren {
|
|
m := make(map[string]*model.DocFolderWithChildren)
|
|
for _, folder := range folders {
|
|
m[folder.ID] = &model.DocFolderWithChildren{DocFolder: folder}
|
|
}
|
|
|
|
results := make([]*model.DocFolderWithChildren, 0)
|
|
for _, folder := range folders {
|
|
parentID := folder.ParentID()
|
|
if parentID == topID {
|
|
results = append(results, m[folder.ID])
|
|
continue
|
|
}
|
|
if parent, ok := m[parentID]; ok {
|
|
parent.Children = append(parent.Children, m[folder.ID])
|
|
}
|
|
}
|
|
return results
|
|
}
|