octopus/internal/service/doc_folder.go
2023-03-23 22:28:17 +08:00

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
}