111 lines
3.1 KiB
Go
111 lines
3.1 KiB
Go
package service
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"filestoragesystem/internal/config"
|
|
"filestoragesystem/internal/model"
|
|
"filestoragesystem/internal/repository"
|
|
"filestoragesystem/pkg/apperr"
|
|
)
|
|
|
|
// ProjectService 项目服务
|
|
type ProjectService struct {
|
|
cfg *config.Config
|
|
projectRepo *repository.ProjectRepo
|
|
fileRepo *repository.FileRepo
|
|
settingRepo *repository.SettingRepo
|
|
opLogRepo *repository.OpLogRepo
|
|
webhookSvc *WebhookService
|
|
}
|
|
|
|
// Create 创建项目
|
|
func (s *ProjectService) Create(userID uint, name, description string, storageLimit int64) (*model.Project, error) {
|
|
if name == "" || len(name) > 100 {
|
|
return nil, fmt.Errorf("项目名称不能为空且不超过100字符")
|
|
}
|
|
if _, err := s.projectRepo.FindByName(userID, name); err == nil {
|
|
return nil, apperr.ErrProjectExists
|
|
}
|
|
if storageLimit <= 0 {
|
|
storageLimit = 5368709120 // 5GB
|
|
if v, err := s.settingRepo.GetValue("default_project_limit"); err == nil {
|
|
var n int64
|
|
if _, e := fmt.Sscanf(v, "%d", &n); e == nil && n > 0 {
|
|
storageLimit = n
|
|
}
|
|
}
|
|
}
|
|
p := &model.Project{
|
|
UserID: userID, Name: name, Description: description,
|
|
StorageLimit: storageLimit, Status: 1,
|
|
}
|
|
if err := s.projectRepo.Create(p); err != nil {
|
|
return nil, err
|
|
}
|
|
return p, nil
|
|
}
|
|
|
|
// List 项目列表,all=true时管理员查看全部
|
|
func (s *ProjectService) List(userID uint, keyword string, all bool, page, pageSize int) ([]model.Project, int64, error) {
|
|
return s.projectRepo.List(userID, keyword, all, page, pageSize)
|
|
}
|
|
|
|
// Get 项目详情(所有者或管理员)
|
|
func (s *ProjectService) Get(userID uint, id uint, isAdmin bool) (*model.Project, error) {
|
|
p, err := s.projectRepo.FindByID(id)
|
|
if err != nil {
|
|
return nil, apperr.ErrNotFound
|
|
}
|
|
if !isAdmin && p.UserID != userID {
|
|
return nil, apperr.ErrForbidden
|
|
}
|
|
return p, nil
|
|
}
|
|
|
|
// Update 更新项目
|
|
func (s *ProjectService) Update(userID uint, id uint, isAdmin bool, name, description string, storageLimit int64) (*model.Project, error) {
|
|
p, err := s.Get(userID, id, isAdmin)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if name != "" && name != p.Name {
|
|
if _, err := s.projectRepo.FindByName(userID, name); err == nil {
|
|
return nil, apperr.ErrProjectExists
|
|
}
|
|
p.Name = name
|
|
}
|
|
if description != "" {
|
|
p.Description = description
|
|
}
|
|
if storageLimit > 0 {
|
|
p.StorageLimit = storageLimit
|
|
}
|
|
if err := s.projectRepo.Update(p); err != nil {
|
|
return nil, err
|
|
}
|
|
return p, nil
|
|
}
|
|
|
|
// Delete 删除项目及其全部文件(硬删除)
|
|
func (s *ProjectService) Delete(userID uint, id uint, isAdmin bool) error {
|
|
if _, err := s.Get(userID, id, isAdmin); err != nil {
|
|
return err
|
|
}
|
|
// 删除物理文件
|
|
files, _ := s.fileRepo.ListByProject(id)
|
|
seen := make(map[string]bool)
|
|
for _, f := range files {
|
|
if f.StoredPath != "" && !seen[f.StoredPath] {
|
|
seen[f.StoredPath] = true
|
|
_ = os.Remove(filepath.Join(s.cfg.Storage.Root, f.StoredPath))
|
|
}
|
|
}
|
|
_ = s.fileRepo.DB.Exec("DELETE FROM files WHERE project_id = ?", id).Error
|
|
_ = s.fileRepo.DB.Exec("DELETE FROM temp_links WHERE file_id IN (SELECT id FROM files WHERE project_id = ?)", id).Error
|
|
|
|
return s.projectRepo.Delete(id)
|
|
}
|