mirror of
				https://github.com/1Panel-dev/1Panel.git
				synced 2025-10-31 11:15:58 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			245 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			245 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package service
 | |
| 
 | |
| import (
 | |
| 	"os"
 | |
| 	"sort"
 | |
| 
 | |
| 	"github.com/1Panel-dev/1Panel/backend/app/dto"
 | |
| 	"github.com/1Panel-dev/1Panel/backend/app/model"
 | |
| 	"github.com/1Panel-dev/1Panel/backend/constant"
 | |
| 	"github.com/1Panel-dev/1Panel/backend/utils/encrypt"
 | |
| 	"github.com/1Panel-dev/1Panel/backend/utils/toolbox"
 | |
| 	"github.com/jinzhu/copier"
 | |
| 	"github.com/pkg/errors"
 | |
| )
 | |
| 
 | |
| type FtpService struct{}
 | |
| 
 | |
| type IFtpService interface {
 | |
| 	LoadBaseInfo() (dto.FtpBaseInfo, error)
 | |
| 	SearchWithPage(search dto.SearchWithPage) (int64, interface{}, error)
 | |
| 	Operate(operation string) error
 | |
| 	Create(req dto.FtpCreate) (uint, error)
 | |
| 	Delete(req dto.BatchDeleteReq) error
 | |
| 	Update(req dto.FtpUpdate) error
 | |
| 	Sync() error
 | |
| 	LoadLog(req dto.FtpLogSearch) (int64, interface{}, error)
 | |
| }
 | |
| 
 | |
| func NewIFtpService() IFtpService {
 | |
| 	return &FtpService{}
 | |
| }
 | |
| 
 | |
| func (f *FtpService) LoadBaseInfo() (dto.FtpBaseInfo, error) {
 | |
| 	var baseInfo dto.FtpBaseInfo
 | |
| 	client, err := toolbox.NewFtpClient()
 | |
| 	if err != nil {
 | |
| 		return baseInfo, err
 | |
| 	}
 | |
| 	baseInfo.IsActive, baseInfo.IsExist = client.Status()
 | |
| 	return baseInfo, nil
 | |
| }
 | |
| 
 | |
| func (f *FtpService) LoadLog(req dto.FtpLogSearch) (int64, interface{}, error) {
 | |
| 	client, err := toolbox.NewFtpClient()
 | |
| 	if err != nil {
 | |
| 		return 0, nil, err
 | |
| 	}
 | |
| 	logItem, err := client.LoadLogs(req.User, req.Operation)
 | |
| 	if err != nil {
 | |
| 		return 0, nil, err
 | |
| 	}
 | |
| 	sort.Slice(logItem, func(i, j int) bool {
 | |
| 		return logItem[i].Time > logItem[j].Time
 | |
| 	})
 | |
| 	var logs []toolbox.FtpLog
 | |
| 	total, start, end := len(logItem), (req.Page-1)*req.PageSize, req.Page*req.PageSize
 | |
| 	if start > total {
 | |
| 		logs = make([]toolbox.FtpLog, 0)
 | |
| 	} else {
 | |
| 		if end >= total {
 | |
| 			end = total
 | |
| 		}
 | |
| 		logs = logItem[start:end]
 | |
| 	}
 | |
| 	return int64(total), logs, nil
 | |
| }
 | |
| 
 | |
| func (u *FtpService) Operate(operation string) error {
 | |
| 	client, err := toolbox.NewFtpClient()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	return client.Operate(operation)
 | |
| }
 | |
| 
 | |
| func (f *FtpService) SearchWithPage(req dto.SearchWithPage) (int64, interface{}, error) {
 | |
| 	total, lists, err := ftpRepo.Page(req.Page, req.PageSize, ftpRepo.WithByUser(req.Info), commonRepo.WithOrderBy("created_at desc"))
 | |
| 	if err != nil {
 | |
| 		return 0, nil, err
 | |
| 	}
 | |
| 	var users []dto.FtpInfo
 | |
| 	for _, user := range lists {
 | |
| 		var item dto.FtpInfo
 | |
| 		if err := copier.Copy(&item, &user); err != nil {
 | |
| 			return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
 | |
| 		}
 | |
| 		item.Password, _ = encrypt.StringDecrypt(item.Password)
 | |
| 		users = append(users, item)
 | |
| 	}
 | |
| 	return total, users, err
 | |
| }
 | |
| 
 | |
| func (f *FtpService) Sync() error {
 | |
| 	client, err := toolbox.NewFtpClient()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	lists, err := client.LoadList()
 | |
| 	if err != nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	listsInDB, err := ftpRepo.GetList()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	sameData := make(map[string]struct{})
 | |
| 	for _, item := range lists {
 | |
| 		for _, itemInDB := range listsInDB {
 | |
| 			if item.User == itemInDB.User {
 | |
| 				sameData[item.User] = struct{}{}
 | |
| 				if item.Path != itemInDB.Path || item.Status != itemInDB.Status {
 | |
| 					_ = ftpRepo.Update(itemInDB.ID, map[string]interface{}{"path": item.Path, "status": item.Status})
 | |
| 				}
 | |
| 				break
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	for _, item := range lists {
 | |
| 		if _, ok := sameData[item.User]; !ok {
 | |
| 			_ = ftpRepo.Create(&model.Ftp{User: item.User, Path: item.Path, Status: item.Status})
 | |
| 		}
 | |
| 	}
 | |
| 	for _, item := range listsInDB {
 | |
| 		if _, ok := sameData[item.User]; !ok {
 | |
| 			_ = ftpRepo.Update(item.ID, map[string]interface{}{"status": "deleted"})
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (f *FtpService) Create(req dto.FtpCreate) (uint, error) {
 | |
| 	if _, err := os.Stat(req.Path); err != nil {
 | |
| 		if os.IsNotExist(err) {
 | |
| 			if err := os.MkdirAll(req.Path, os.ModePerm); err != nil {
 | |
| 				return 0, err
 | |
| 			}
 | |
| 		} else {
 | |
| 			return 0, err
 | |
| 		}
 | |
| 	}
 | |
| 	pass, err := encrypt.StringEncrypt(req.Password)
 | |
| 	if err != nil {
 | |
| 		return 0, err
 | |
| 	}
 | |
| 	userInDB, _ := ftpRepo.Get(hostRepo.WithByUser(req.User))
 | |
| 	if userInDB.ID != 0 {
 | |
| 		return 0, constant.ErrRecordExist
 | |
| 	}
 | |
| 	client, err := toolbox.NewFtpClient()
 | |
| 	if err != nil {
 | |
| 		return 0, err
 | |
| 	}
 | |
| 	if err := client.UserAdd(req.User, req.Password, req.Path); err != nil {
 | |
| 		return 0, err
 | |
| 	}
 | |
| 	var ftp model.Ftp
 | |
| 	if err := copier.Copy(&ftp, &req); err != nil {
 | |
| 		return 0, errors.WithMessage(constant.ErrStructTransform, err.Error())
 | |
| 	}
 | |
| 	ftp.Status = constant.StatusEnable
 | |
| 	ftp.Password = pass
 | |
| 	if err := ftpRepo.Create(&ftp); err != nil {
 | |
| 		return 0, err
 | |
| 	}
 | |
| 	return ftp.ID, nil
 | |
| }
 | |
| 
 | |
| func (f *FtpService) Delete(req dto.BatchDeleteReq) error {
 | |
| 	client, err := toolbox.NewFtpClient()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	for _, id := range req.Ids {
 | |
| 		ftpItem, err := ftpRepo.Get(commonRepo.WithByID(id))
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		_ = client.UserDel(ftpItem.User)
 | |
| 		_ = ftpRepo.Delete(commonRepo.WithByID(id))
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (f *FtpService) Update(req dto.FtpUpdate) error {
 | |
| 	if _, err := os.Stat(req.Path); err != nil {
 | |
| 		if os.IsNotExist(err) {
 | |
| 			if err := os.MkdirAll(req.Path, os.ModePerm); err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 		} else {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	pass, err := encrypt.StringEncrypt(req.Password)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	ftpItem, _ := ftpRepo.Get(commonRepo.WithByID(req.ID))
 | |
| 	if ftpItem.ID == 0 {
 | |
| 		return constant.ErrRecordNotFound
 | |
| 	}
 | |
| 	passItem, err := encrypt.StringDecrypt(ftpItem.Password)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	client, err := toolbox.NewFtpClient()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	needReload := false
 | |
| 	updates := make(map[string]interface{})
 | |
| 	if req.Password != passItem {
 | |
| 		if err := client.SetPasswd(ftpItem.User, req.Password); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		updates["password"] = pass
 | |
| 		needReload = true
 | |
| 	}
 | |
| 	if req.Status != ftpItem.Status {
 | |
| 		if err := client.SetStatus(ftpItem.User, req.Status); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		updates["status"] = req.Status
 | |
| 		needReload = true
 | |
| 	}
 | |
| 	if req.Path != ftpItem.Path {
 | |
| 		if err := client.SetPath(ftpItem.User, req.Path); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		updates["path"] = req.Path
 | |
| 		needReload = true
 | |
| 	}
 | |
| 	if req.Description != ftpItem.Description {
 | |
| 		updates["description"] = req.Description
 | |
| 	}
 | |
| 	if needReload {
 | |
| 		_ = client.Reload()
 | |
| 	}
 | |
| 	if len(updates) != 0 {
 | |
| 		return ftpRepo.Update(ftpItem.ID, updates)
 | |
| 	}
 | |
| 	return nil
 | |
| }
 |