mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 04:22:33 +08:00
refactor: 重命名备份存储
This commit is contained in:
@@ -91,7 +91,7 @@ func initWeb() (*app.Web, error) {
|
||||
databaseUserService := service.NewDatabaseUserService(databaseUserRepo)
|
||||
backupService := service.NewBackupService(locale, backupRepo)
|
||||
backupAccountRepo := data.NewBackupAccountRepo(locale, db, logger, settingRepo)
|
||||
backupAccountService := service.NewBackupAccountService(locale, backupAccountRepo)
|
||||
backupAccountService := service.NewBackupStorageService(locale, backupAccountRepo)
|
||||
certService := service.NewCertService(locale, certRepo)
|
||||
certDNSRepo := data.NewCertDNSRepo(db, logger)
|
||||
certDNSService := service.NewCertDNSService(certDNSRepo)
|
||||
|
||||
@@ -24,7 +24,7 @@ type BackupRepo interface {
|
||||
Delete(ctx context.Context, typ BackupType, name string) error
|
||||
Restore(ctx context.Context, typ BackupType, backup, target string) error
|
||||
ClearExpired(path, prefix string, save uint) error
|
||||
ClearAccountExpired(account uint, typ BackupType, prefix string, save uint) error
|
||||
ClearStorageExpired(account uint, typ BackupType, prefix string, save uint) error
|
||||
CutoffLog(path, target string) error
|
||||
GetDefaultPath(typ BackupType) string
|
||||
FixPanel() error
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
package biz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/acepanel/panel/internal/http/request"
|
||||
"github.com/acepanel/panel/pkg/types"
|
||||
)
|
||||
|
||||
type BackupAccountType string
|
||||
|
||||
const (
|
||||
BackupAccountTypeLocal BackupAccountType = "local"
|
||||
BackupAccountTypeS3 BackupAccountType = "s3"
|
||||
BackupAccountTypeSFTP BackupAccountType = "sftp"
|
||||
BackupAccountTypeWebDav BackupAccountType = "webdav"
|
||||
)
|
||||
|
||||
type BackupAccount struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Type BackupAccountType `gorm:"not null;default:''" json:"type"`
|
||||
Name string `gorm:"not null;default:''" json:"name"`
|
||||
Info types.BackupAccountInfo `gorm:"not null;default:'{}';serializer:json" json:"info"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type BackupAccountRepo interface {
|
||||
List(page, limit uint) ([]*BackupAccount, int64, error)
|
||||
Get(id uint) (*BackupAccount, error)
|
||||
Create(ctx context.Context, req *request.BackupAccountCreate) (*BackupAccount, error)
|
||||
Update(ctx context.Context, req *request.BackupAccountUpdate) error
|
||||
Delete(ctx context.Context, id uint) error
|
||||
}
|
||||
35
internal/biz/backup_storage.go
Normal file
35
internal/biz/backup_storage.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package biz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/acepanel/panel/internal/http/request"
|
||||
"github.com/acepanel/panel/pkg/types"
|
||||
)
|
||||
|
||||
type BackupStorageType string
|
||||
|
||||
const (
|
||||
BackupStorageTypeLocal BackupStorageType = "local"
|
||||
BackupStorageTypeS3 BackupStorageType = "s3"
|
||||
BackupStorageTypeSFTP BackupStorageType = "sftp"
|
||||
BackupStorageTypeWebDAV BackupStorageType = "webdav"
|
||||
)
|
||||
|
||||
type BackupStorage struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Type BackupStorageType `gorm:"not null;default:''" json:"type"`
|
||||
Name string `gorm:"not null;default:''" json:"name"`
|
||||
Info types.BackupStorageInfo `gorm:"not null;default:'{}';serializer:json" json:"info"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
type BackupAccountRepo interface {
|
||||
List(page, limit uint) ([]*BackupStorage, int64, error)
|
||||
Get(id uint) (*BackupStorage, error)
|
||||
Create(ctx context.Context, req *request.BackupStorageCreate) (*BackupStorage, error)
|
||||
Update(ctx context.Context, req *request.BackupStorageUpdate) error
|
||||
Delete(ctx context.Context, id uint) error
|
||||
}
|
||||
@@ -75,28 +75,28 @@ func (r *backupRepo) List(typ biz.BackupType) ([]*types.BackupFile, error) {
|
||||
// Create 创建备份
|
||||
// typ 备份类型
|
||||
// target 目标名称
|
||||
// account 备份账号ID
|
||||
func (r *backupRepo) Create(ctx context.Context, typ biz.BackupType, target string, account uint) error {
|
||||
// 取备份账号,0 为本地备份
|
||||
backupAccount := new(biz.BackupAccount)
|
||||
if account != 0 {
|
||||
if err := r.db.First(backupAccount, account).Error; err != nil {
|
||||
// storage 备份存储ID
|
||||
func (r *backupRepo) Create(ctx context.Context, typ biz.BackupType, target string, storage uint) error {
|
||||
// 取备份存储,0 为本地备份
|
||||
backupStorage := new(biz.BackupStorage)
|
||||
if storage != 0 {
|
||||
if err := r.db.First(backupStorage, storage).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.New(r.t.Get("backup account not found"))
|
||||
return errors.New(r.t.Get("backup storage not found"))
|
||||
}
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
backupAccount = &biz.BackupAccount{
|
||||
backupStorage = &biz.BackupStorage{
|
||||
Name: r.t.Get("Local Storage"),
|
||||
Type: biz.BackupAccountTypeLocal,
|
||||
Info: types.BackupAccountInfo{
|
||||
Type: biz.BackupStorageTypeLocal,
|
||||
Info: types.BackupStorageInfo{
|
||||
Path: filepath.Dir(r.GetDefaultPath(typ)), // 需要取根目录
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
client, err := r.getStorage(*backupAccount)
|
||||
client, err := r.getStorage(*backupStorage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -108,7 +108,7 @@ func (r *backupRepo) Create(ctx context.Context, typ biz.BackupType, target stri
|
||||
fmt.Println(r.t.Get("★ Start backup [%s]", start.Format(time.DateTime)))
|
||||
fmt.Println(r.hr)
|
||||
fmt.Println(r.t.Get("|-Backup type: %s", string(typ)))
|
||||
fmt.Println(r.t.Get("|-Backup account: %s", backupAccount.Name))
|
||||
fmt.Println(r.t.Get("|-Backup storage: %s", backupStorage.Name))
|
||||
fmt.Println(r.t.Get("|-Backup target: %s", target))
|
||||
}
|
||||
|
||||
@@ -326,17 +326,17 @@ func (r *backupRepo) ClearExpired(path, prefix string, save uint) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ClearAccountExpired 清理备份账号过期备份
|
||||
func (r *backupRepo) ClearAccountExpired(account uint, typ biz.BackupType, prefix string, save uint) error {
|
||||
backupAccount := new(biz.BackupAccount)
|
||||
if err := r.db.First(backupAccount, account).Error; err != nil {
|
||||
// ClearStorageExpired 清理备份账号过期备份
|
||||
func (r *backupRepo) ClearStorageExpired(storage uint, typ biz.BackupType, prefix string, save uint) error {
|
||||
backupStorage := new(biz.BackupStorage)
|
||||
if err := r.db.First(backupStorage, storage).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.New(r.t.Get("backup account not found"))
|
||||
return errors.New(r.t.Get("backup storage not found"))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := r.getStorage(*backupAccount)
|
||||
client, err := r.getStorage(*backupStorage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -391,35 +391,35 @@ func (r *backupRepo) ClearAccountExpired(account uint, typ biz.BackupType, prefi
|
||||
}
|
||||
|
||||
// getStorage 获取存储器
|
||||
func (r *backupRepo) getStorage(account biz.BackupAccount) (storage.Storage, error) {
|
||||
switch account.Type {
|
||||
case biz.BackupAccountTypeLocal:
|
||||
return storage.NewLocal(account.Info.Path)
|
||||
case biz.BackupAccountTypeS3:
|
||||
func (r *backupRepo) getStorage(backupStorage biz.BackupStorage) (storage.Storage, error) {
|
||||
switch backupStorage.Type {
|
||||
case biz.BackupStorageTypeLocal:
|
||||
return storage.NewLocal(backupStorage.Info.Path)
|
||||
case biz.BackupStorageTypeS3:
|
||||
return storage.NewS3(storage.S3Config{
|
||||
Region: account.Info.Region,
|
||||
Bucket: account.Info.Bucket,
|
||||
AccessKeyID: account.Info.AccessKey,
|
||||
SecretAccessKey: account.Info.SecretKey,
|
||||
Endpoint: account.Info.Endpoint,
|
||||
BasePath: account.Info.Path,
|
||||
AddressingStyle: storage.S3AddressingStyle(account.Info.Style),
|
||||
Region: backupStorage.Info.Region,
|
||||
Bucket: backupStorage.Info.Bucket,
|
||||
AccessKeyID: backupStorage.Info.AccessKey,
|
||||
SecretAccessKey: backupStorage.Info.SecretKey,
|
||||
Endpoint: backupStorage.Info.Endpoint,
|
||||
BasePath: backupStorage.Info.Path,
|
||||
AddressingStyle: storage.S3AddressingStyle(backupStorage.Info.Style),
|
||||
})
|
||||
case biz.BackupAccountTypeSFTP:
|
||||
case biz.BackupStorageTypeSFTP:
|
||||
return storage.NewSFTP(storage.SFTPConfig{
|
||||
Host: account.Info.Host,
|
||||
Port: account.Info.Port,
|
||||
Username: account.Info.Username,
|
||||
Password: account.Info.Password,
|
||||
PrivateKey: account.Info.PrivateKey,
|
||||
BasePath: account.Info.Path,
|
||||
Host: backupStorage.Info.Host,
|
||||
Port: backupStorage.Info.Port,
|
||||
Username: backupStorage.Info.Username,
|
||||
Password: backupStorage.Info.Password,
|
||||
PrivateKey: backupStorage.Info.PrivateKey,
|
||||
BasePath: backupStorage.Info.Path,
|
||||
})
|
||||
case biz.BackupAccountTypeWebDav:
|
||||
case biz.BackupStorageTypeWebDAV:
|
||||
return storage.NewWebDav(storage.WebDavConfig{
|
||||
URL: account.Info.URL,
|
||||
Username: account.Info.Username,
|
||||
Password: account.Info.Password,
|
||||
BasePath: account.Info.Path,
|
||||
URL: backupStorage.Info.URL,
|
||||
Username: backupStorage.Info.Username,
|
||||
Password: backupStorage.Info.Password,
|
||||
BasePath: backupStorage.Info.Path,
|
||||
})
|
||||
default:
|
||||
return nil, errors.New(r.t.Get("unknown storage type"))
|
||||
|
||||
@@ -28,20 +28,20 @@ func NewBackupAccountRepo(t *gotext.Locale, db *gorm.DB, log *slog.Logger, setti
|
||||
}
|
||||
}
|
||||
|
||||
func (r backupAccountRepo) List(page, limit uint) ([]*biz.BackupAccount, int64, error) {
|
||||
func (r backupAccountRepo) List(page, limit uint) ([]*biz.BackupStorage, int64, error) {
|
||||
// 本地存储
|
||||
localStorage, err := r.Get(0)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var dbAccounts []*biz.BackupAccount
|
||||
var dbAccounts []*biz.BackupStorage
|
||||
var total int64
|
||||
if err = r.db.Model(&biz.BackupAccount{}).Order("id asc").Count(&total).Offset(int((page - 1) * limit)).Limit(int(limit)).Find(&dbAccounts).Error; err != nil {
|
||||
if err = r.db.Model(&biz.BackupStorage{}).Order("id asc").Count(&total).Offset(int((page - 1) * limit)).Limit(int(limit)).Find(&dbAccounts).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
accounts := make([]*biz.BackupAccount, 0, len(dbAccounts)+1)
|
||||
accounts := make([]*biz.BackupStorage, 0, len(dbAccounts)+1)
|
||||
if page == 1 {
|
||||
accounts = append(accounts, localStorage)
|
||||
}
|
||||
@@ -50,30 +50,30 @@ func (r backupAccountRepo) List(page, limit uint) ([]*biz.BackupAccount, int64,
|
||||
return accounts, total + 1, nil
|
||||
}
|
||||
|
||||
func (r backupAccountRepo) Get(id uint) (*biz.BackupAccount, error) {
|
||||
func (r backupAccountRepo) Get(id uint) (*biz.BackupStorage, error) {
|
||||
if id == 0 {
|
||||
path, err := r.setting.Get(biz.SettingKeyBackupPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &biz.BackupAccount{
|
||||
return &biz.BackupStorage{
|
||||
ID: 0,
|
||||
Type: biz.BackupAccountTypeLocal,
|
||||
Type: biz.BackupStorageTypeLocal,
|
||||
Name: r.t.Get("Local Storage"),
|
||||
Info: types.BackupAccountInfo{
|
||||
Info: types.BackupStorageInfo{
|
||||
Path: path,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
account := new(biz.BackupAccount)
|
||||
err := r.db.Model(&biz.BackupAccount{}).Where("id = ?", id).First(account).Error
|
||||
account := new(biz.BackupStorage)
|
||||
err := r.db.Model(&biz.BackupStorage{}).Where("id = ?", id).First(account).Error
|
||||
return account, err
|
||||
}
|
||||
|
||||
func (r backupAccountRepo) Create(ctx context.Context, req *request.BackupAccountCreate) (*biz.BackupAccount, error) {
|
||||
account := &biz.BackupAccount{
|
||||
Type: biz.BackupAccountType(req.Type),
|
||||
func (r backupAccountRepo) Create(ctx context.Context, req *request.BackupStorageCreate) (*biz.BackupStorage, error) {
|
||||
account := &biz.BackupStorage{
|
||||
Type: biz.BackupStorageType(req.Type),
|
||||
Name: req.Name,
|
||||
Info: req.Info,
|
||||
}
|
||||
@@ -82,18 +82,18 @@ func (r backupAccountRepo) Create(ctx context.Context, req *request.BackupAccoun
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r.log.Info("backup account created", slog.String("type", biz.OperationTypeBackup), slog.Uint64("operator_id", getOperatorID(ctx)), slog.Uint64("id", uint64(account.ID)), slog.String("account_type", req.Type), slog.String("name", req.Name))
|
||||
r.log.Info("backup storage created", slog.String("type", biz.OperationTypeBackup), slog.Uint64("operator_id", getOperatorID(ctx)), slog.Uint64("id", uint64(account.ID)), slog.String("account_type", req.Type), slog.String("name", req.Name))
|
||||
|
||||
return account, nil
|
||||
}
|
||||
|
||||
func (r backupAccountRepo) Update(ctx context.Context, req *request.BackupAccountUpdate) error {
|
||||
func (r backupAccountRepo) Update(ctx context.Context, req *request.BackupStorageUpdate) error {
|
||||
account, err := r.Get(req.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
account.Type = biz.BackupAccountType(req.Type)
|
||||
account.Type = biz.BackupStorageType(req.Type)
|
||||
account.Name = req.Name
|
||||
account.Info = req.Info
|
||||
|
||||
@@ -101,17 +101,17 @@ func (r backupAccountRepo) Update(ctx context.Context, req *request.BackupAccoun
|
||||
return err
|
||||
}
|
||||
|
||||
r.log.Info("backup account updated", slog.String("type", biz.OperationTypeBackup), slog.Uint64("operator_id", getOperatorID(ctx)), slog.Uint64("id", uint64(req.ID)), slog.String("account_type", req.Type))
|
||||
r.log.Info("backup storage updated", slog.String("type", biz.OperationTypeBackup), slog.Uint64("operator_id", getOperatorID(ctx)), slog.Uint64("id", uint64(req.ID)), slog.String("account_type", req.Type))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r backupAccountRepo) Delete(ctx context.Context, id uint) error {
|
||||
if err := r.db.Model(&biz.BackupAccount{}).Where("id = ?", id).Delete(&biz.BackupAccount{}).Error; err != nil {
|
||||
if err := r.db.Model(&biz.BackupStorage{}).Where("id = ?", id).Delete(&biz.BackupStorage{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.log.Info("backup account deleted", slog.String("type", biz.OperationTypeBackup), slog.Uint64("operator_id", getOperatorID(ctx)), slog.Uint64("id", uint64(id)))
|
||||
r.log.Info("backup storage deleted", slog.String("type", biz.OperationTypeBackup), slog.Uint64("operator_id", getOperatorID(ctx)), slog.Uint64("id", uint64(id)))
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -66,17 +66,17 @@ func (r *cronRepo) Create(ctx context.Context, req *request.CronCreate) error {
|
||||
script = fmt.Sprintf(`#!/bin/bash
|
||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH
|
||||
|
||||
acepanel backup website -n '%s' -a '%d'
|
||||
acepanel backup clear -t website -f '%s' -s '%d' -a '%d'
|
||||
`, req.Target, req.BackupAccount, req.Target, req.Save, req.BackupAccount)
|
||||
acepanel backup website -n '%s' -s '%d'
|
||||
acepanel backup clear -t website -f '%s' -k '%d' -s '%d'
|
||||
`, req.Target, req.BackupStorage, req.Target, req.Keep, req.BackupStorage)
|
||||
}
|
||||
if req.BackupType == "mysql" || req.BackupType == "postgres" {
|
||||
script = fmt.Sprintf(`#!/bin/bash
|
||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH
|
||||
|
||||
acepanel backup database -t '%s' -n '%s' -a '%d'
|
||||
acepanel backup clear -t '%s' -f '%s' -s '%d' -a '%d'
|
||||
`, req.BackupType, req.Target, req.BackupAccount, req.BackupType, req.Target, req.Save, req.BackupAccount)
|
||||
acepanel backup database -t '%s' -n '%s' -s '%d'
|
||||
acepanel backup clear -t '%s' -f '%s' -k '%d' -s '%d'
|
||||
`, req.BackupType, req.Target, req.BackupStorage, req.BackupType, req.Target, req.Keep, req.BackupStorage)
|
||||
}
|
||||
}
|
||||
if req.Type == "cutoff" {
|
||||
@@ -84,8 +84,8 @@ acepanel backup clear -t '%s' -f '%s' -s '%d' -a '%d'
|
||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH
|
||||
|
||||
acepanel cutoff website -n '%s'
|
||||
acepanel cutoff clear -t website -n '%s' -s '%d'
|
||||
`, req.Target, req.Target, req.Save)
|
||||
acepanel cutoff clear -t website -n '%s' -k '%d'
|
||||
`, req.Target, req.Target, req.Keep)
|
||||
}
|
||||
if req.Type == "shell" {
|
||||
script = req.Script
|
||||
|
||||
@@ -7,9 +7,9 @@ type BackupList struct {
|
||||
}
|
||||
|
||||
type BackupCreate struct {
|
||||
Type string `uri:"type" form:"type" validate:"required|in:website,mysql,postgres,redis,panel"`
|
||||
Target string `json:"target" form:"target" validate:"required|regex:^[a-zA-Z0-9_-]+$"`
|
||||
AccountID uint `form:"account_id" json:"account_id" validate:"required|exists:backup_accounts,id"`
|
||||
Type string `uri:"type" form:"type" validate:"required|in:website,mysql,postgres,redis,panel"`
|
||||
Target string `json:"target" form:"target" validate:"required|regex:^[a-zA-Z0-9_-]+$"`
|
||||
Storage uint `form:"storage" json:"storage" validate:"required|exists:backup_storages,id"`
|
||||
}
|
||||
|
||||
type BackupUpload struct {
|
||||
|
||||
@@ -2,15 +2,15 @@ package request
|
||||
|
||||
import "github.com/acepanel/panel/pkg/types"
|
||||
|
||||
type BackupAccountCreate struct {
|
||||
type BackupStorageCreate struct {
|
||||
Type string `form:"type" json:"type" validate:"required|in:s3,sftp,webdav"`
|
||||
Name string `form:"name" json:"name" validate:"required"`
|
||||
Info types.BackupAccountInfo `form:"info" json:"info"`
|
||||
Info types.BackupStorageInfo `form:"info" json:"info"`
|
||||
}
|
||||
|
||||
type BackupAccountUpdate struct {
|
||||
ID uint `form:"id" json:"id" validate:"required|exists:backup_accounts,id"`
|
||||
type BackupStorageUpdate struct {
|
||||
ID uint `form:"id" json:"id" validate:"required|exists:backup_storages,id"`
|
||||
Type string `form:"type" json:"type" validate:"required|in:s3,sftp,webdav"`
|
||||
Name string `form:"name" json:"name" validate:"required"`
|
||||
Info types.BackupAccountInfo `form:"info" json:"info"`
|
||||
Info types.BackupStorageInfo `form:"info" json:"info"`
|
||||
}
|
||||
@@ -6,9 +6,9 @@ type CronCreate struct {
|
||||
Time string `form:"time" json:"time" validate:"required|cron"`
|
||||
Script string `form:"script" json:"script"`
|
||||
BackupType string `form:"backup_type" json:"backup_type" validate:"requiredIf:Type,backup"`
|
||||
BackupAccount uint `form:"backup_account" json:"backup_account"`
|
||||
BackupStorage uint `form:"backup_storage" json:"backup_storage"`
|
||||
Target string `form:"target" json:"target" validate:"requiredIf:Type,backup,cutoff"`
|
||||
Save int `form:"save" json:"save" validate:"required"`
|
||||
Keep uint `form:"keep" json:"keep" validate:"required"`
|
||||
}
|
||||
|
||||
type CronUpdate struct {
|
||||
|
||||
@@ -62,14 +62,10 @@ func init() {
|
||||
Migrations = append(Migrations, &gormigrate.Migration{
|
||||
ID: "20260120-add-backup",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(
|
||||
&biz.BackupAccount{},
|
||||
)
|
||||
return tx.AutoMigrate(&biz.BackupStorage{})
|
||||
},
|
||||
Rollback: func(tx *gorm.DB) error {
|
||||
return tx.Migrator().DropTable(
|
||||
&biz.BackupAccount{},
|
||||
)
|
||||
return tx.Migrator().DropTable(&biz.BackupStorage{})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -302,9 +302,9 @@ func (route *Cli) Commands() []*cli.Command {
|
||||
Required: true,
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "account",
|
||||
Aliases: []string{"a"},
|
||||
Usage: route.t.Get("Account ID (default account if not filled)"),
|
||||
Name: "storage",
|
||||
Aliases: []string{"s"},
|
||||
Usage: route.t.Get("Storage ID (local storage if not filled)"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -326,9 +326,9 @@ func (route *Cli) Commands() []*cli.Command {
|
||||
Required: true,
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "account",
|
||||
Aliases: []string{"a"},
|
||||
Usage: route.t.Get("Account ID (default account if not filled)"),
|
||||
Name: "storage",
|
||||
Aliases: []string{"s"},
|
||||
Usage: route.t.Get("Storage ID (local storage if not filled)"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -356,15 +356,15 @@ func (route *Cli) Commands() []*cli.Command {
|
||||
Required: true,
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "save",
|
||||
Aliases: []string{"s"},
|
||||
Name: "keep",
|
||||
Aliases: []string{"k"},
|
||||
Usage: route.t.Get("Number of backups to keep"),
|
||||
Required: true,
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "account",
|
||||
Aliases: []string{"a"},
|
||||
Usage: route.t.Get("Account ID (default account if not filled)"),
|
||||
Name: "storage",
|
||||
Aliases: []string{"s"},
|
||||
Usage: route.t.Get("Storage ID (local storage if not filled)"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -410,8 +410,8 @@ func (route *Cli) Commands() []*cli.Command {
|
||||
Required: true,
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "save",
|
||||
Aliases: []string{"s"},
|
||||
Name: "keep",
|
||||
Aliases: []string{"k"},
|
||||
Usage: route.t.Get("Number of logs to keep"),
|
||||
Required: true,
|
||||
},
|
||||
|
||||
@@ -27,7 +27,7 @@ type Http struct {
|
||||
databaseServer *service.DatabaseServerService
|
||||
databaseUser *service.DatabaseUserService
|
||||
backup *service.BackupService
|
||||
backupAccount *service.BackupAccountService
|
||||
backupStorage *service.BackupStorageService
|
||||
cert *service.CertService
|
||||
certDNS *service.CertDNSService
|
||||
certAccount *service.CertAccountService
|
||||
@@ -75,7 +75,7 @@ func NewHttp(
|
||||
databaseServer *service.DatabaseServerService,
|
||||
databaseUser *service.DatabaseUserService,
|
||||
backup *service.BackupService,
|
||||
backupAccount *service.BackupAccountService,
|
||||
backupStorage *service.BackupStorageService,
|
||||
cert *service.CertService,
|
||||
certDNS *service.CertDNSService,
|
||||
certAccount *service.CertAccountService,
|
||||
@@ -122,7 +122,7 @@ func NewHttp(
|
||||
databaseServer: databaseServer,
|
||||
databaseUser: databaseUser,
|
||||
backup: backup,
|
||||
backupAccount: backupAccount,
|
||||
backupStorage: backupStorage,
|
||||
cert: cert,
|
||||
certDNS: certDNS,
|
||||
certAccount: certAccount,
|
||||
@@ -268,12 +268,12 @@ func (route *Http) Register(r *chi.Mux) {
|
||||
r.Post("/{type}/restore", route.backup.Restore)
|
||||
})
|
||||
|
||||
r.Route("/backup_account", func(r chi.Router) {
|
||||
r.Get("/", route.backupAccount.List)
|
||||
r.Post("/", route.backupAccount.Create)
|
||||
r.Put("/{id}", route.backupAccount.Update)
|
||||
r.Get("/{id}", route.backupAccount.Get)
|
||||
r.Delete("/{id}", route.backupAccount.Delete)
|
||||
r.Route("/backup_storage", func(r chi.Router) {
|
||||
r.Get("/", route.backupStorage.List)
|
||||
r.Post("/", route.backupStorage.Create)
|
||||
r.Put("/{id}", route.backupStorage.Update)
|
||||
r.Get("/{id}", route.backupStorage.Get)
|
||||
r.Delete("/{id}", route.backupStorage.Delete)
|
||||
})
|
||||
|
||||
r.Route("/cert", func(r chi.Router) {
|
||||
|
||||
@@ -55,7 +55,7 @@ func (s *BackupService) Create(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if err = s.backupRepo.Create(r.Context(), biz.BackupType(req.Type), req.Target, req.AccountID); err != nil {
|
||||
if err = s.backupRepo.Create(r.Context(), biz.BackupType(req.Type), req.Target, req.Storage); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -13,19 +13,19 @@ import (
|
||||
"github.com/acepanel/panel/pkg/types"
|
||||
)
|
||||
|
||||
type BackupAccountService struct {
|
||||
type BackupStorageService struct {
|
||||
t *gotext.Locale
|
||||
backupAccountRepo biz.BackupAccountRepo
|
||||
}
|
||||
|
||||
func NewBackupAccountService(t *gotext.Locale, backupAccount biz.BackupAccountRepo) *BackupAccountService {
|
||||
return &BackupAccountService{
|
||||
func NewBackupStorageService(t *gotext.Locale, backupAccount biz.BackupAccountRepo) *BackupStorageService {
|
||||
return &BackupStorageService{
|
||||
t: t,
|
||||
backupAccountRepo: backupAccount,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *BackupAccountService) List(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *BackupStorageService) List(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.Paginate](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -44,8 +44,8 @@ func (s *BackupAccountService) List(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *BackupAccountService) Create(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.BackupAccountCreate](r)
|
||||
func (s *BackupStorageService) Create(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.BackupStorageCreate](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
@@ -65,8 +65,8 @@ func (s *BackupAccountService) Create(w http.ResponseWriter, r *http.Request) {
|
||||
Success(w, account)
|
||||
}
|
||||
|
||||
func (s *BackupAccountService) Update(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.BackupAccountUpdate](r)
|
||||
func (s *BackupStorageService) Update(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.BackupStorageUpdate](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
@@ -85,7 +85,7 @@ func (s *BackupAccountService) Update(w http.ResponseWriter, r *http.Request) {
|
||||
Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *BackupAccountService) Get(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *BackupStorageService) Get(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.ID](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -101,7 +101,7 @@ func (s *BackupAccountService) Get(w http.ResponseWriter, r *http.Request) {
|
||||
Success(w, account)
|
||||
}
|
||||
|
||||
func (s *BackupAccountService) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *BackupStorageService) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.ID](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
@@ -116,13 +116,13 @@ func (s *BackupAccountService) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
Success(w, nil)
|
||||
}
|
||||
|
||||
// validateStorage 验证存储账号配置是否正确
|
||||
func (s *BackupAccountService) validateStorage(accountType string, info types.BackupAccountInfo) error {
|
||||
// validateStorage 验证存储配置是否正确
|
||||
func (s *BackupStorageService) validateStorage(accountType string, info types.BackupStorageInfo) error {
|
||||
var err error
|
||||
var client storage.Storage
|
||||
|
||||
switch biz.BackupAccountType(accountType) {
|
||||
case biz.BackupAccountTypeS3:
|
||||
switch biz.BackupStorageType(accountType) {
|
||||
case biz.BackupStorageTypeS3:
|
||||
client, err = storage.NewS3(storage.S3Config{
|
||||
Region: info.Region,
|
||||
Bucket: info.Bucket,
|
||||
@@ -135,7 +135,7 @@ func (s *BackupAccountService) validateStorage(accountType string, info types.Ba
|
||||
if err != nil {
|
||||
return errors.New(s.t.Get("s3 configuration error: %v", err))
|
||||
}
|
||||
case biz.BackupAccountTypeSFTP:
|
||||
case biz.BackupStorageTypeSFTP:
|
||||
client, err = storage.NewSFTP(storage.SFTPConfig{
|
||||
Host: info.Host,
|
||||
Port: info.Port,
|
||||
@@ -147,7 +147,7 @@ func (s *BackupAccountService) validateStorage(accountType string, info types.Ba
|
||||
if err != nil {
|
||||
return errors.New(s.t.Get("sftp configuration error: %v", err))
|
||||
}
|
||||
case biz.BackupAccountTypeWebDav:
|
||||
case biz.BackupStorageTypeWebDAV:
|
||||
client, err = storage.NewWebDav(storage.WebDavConfig{
|
||||
URL: info.URL,
|
||||
Username: info.Username,
|
||||
@@ -628,12 +628,12 @@ func (s *CliService) DatabaseDeleteServer(ctx context.Context, cmd *cli.Command)
|
||||
}
|
||||
|
||||
func (s *CliService) BackupWebsite(ctx context.Context, cmd *cli.Command) error {
|
||||
_ = s.backupRepo.Create(ctx, biz.BackupTypeWebsite, cmd.String("name"), cmd.Uint("account"))
|
||||
_ = s.backupRepo.Create(ctx, biz.BackupTypeWebsite, cmd.String("name"), cmd.Uint("storage"))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *CliService) BackupDatabase(ctx context.Context, cmd *cli.Command) error {
|
||||
_ = s.backupRepo.Create(ctx, biz.BackupType(cmd.String("type")), cmd.String("name"), cmd.Uint("account"))
|
||||
_ = s.backupRepo.Create(ctx, biz.BackupType(cmd.String("type")), cmd.String("name"), cmd.Uint("storage"))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -658,15 +658,15 @@ func (s *CliService) BackupClear(ctx context.Context, cmd *cli.Command) error {
|
||||
fmt.Println(s.hr)
|
||||
fmt.Println(s.t.Get("|-Cleaning type: %s", cmd.String("type")))
|
||||
fmt.Println(s.t.Get("|-Cleaning target: %s", cmd.String("file")))
|
||||
fmt.Println(s.t.Get("|-Keep count: %d", cmd.Uint("save")))
|
||||
fmt.Println(s.t.Get("|-Keep count: %d", cmd.Uint("keep")))
|
||||
|
||||
if cmd.Uint("account") != 0 {
|
||||
if err := s.backupRepo.ClearAccountExpired(cmd.Uint("account"), biz.BackupType(cmd.String("type")), cmd.String("file"), cmd.Uint("save")); err != nil {
|
||||
if cmd.Uint("storage") != 0 {
|
||||
if err := s.backupRepo.ClearStorageExpired(cmd.Uint("storage"), biz.BackupType(cmd.String("type")), cmd.String("file"), cmd.Uint("keep")); err != nil {
|
||||
return errors.New(s.t.Get("Cleaning failed: %v", err))
|
||||
}
|
||||
} else {
|
||||
path := s.backupRepo.GetDefaultPath(biz.BackupType(cmd.String("type")))
|
||||
if err := s.backupRepo.ClearExpired(path, cmd.String("file"), cmd.Uint("save")); err != nil {
|
||||
if err := s.backupRepo.ClearExpired(path, cmd.String("file"), cmd.Uint("keep")); err != nil {
|
||||
return errors.New(s.t.Get("Cleaning failed: %v", err))
|
||||
}
|
||||
}
|
||||
@@ -724,11 +724,11 @@ func (s *CliService) CutoffClear(ctx context.Context, cmd *cli.Command) error {
|
||||
fmt.Println(s.hr)
|
||||
fmt.Println(s.t.Get("|-Cleaning type: %s", cmd.String("type")))
|
||||
fmt.Println(s.t.Get("|-Cleaning target: %s", website.Name))
|
||||
fmt.Println(s.t.Get("|-Keep count: %d", cmd.Uint("save")))
|
||||
if err = s.backupRepo.ClearExpired(path, "access.log", cmd.Uint("save")); err != nil {
|
||||
fmt.Println(s.t.Get("|-Keep count: %d", cmd.Uint("keep")))
|
||||
if err = s.backupRepo.ClearExpired(path, "access.log", cmd.Uint("keep")); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = s.backupRepo.ClearExpired(path, "error.log", cmd.Uint("save")); err != nil {
|
||||
if err = s.backupRepo.ClearExpired(path, "error.log", cmd.Uint("keep")); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(s.hr)
|
||||
|
||||
@@ -6,7 +6,7 @@ import "github.com/google/wire"
|
||||
var ProviderSet = wire.NewSet(
|
||||
NewAppService,
|
||||
NewBackupService,
|
||||
NewBackupAccountService,
|
||||
NewBackupStorageService,
|
||||
NewCertService,
|
||||
NewCertAccountService,
|
||||
NewCertDNSService,
|
||||
|
||||
@@ -26,27 +26,27 @@ func (_m *BackupAccountRepo) EXPECT() *BackupAccountRepo_Expecter {
|
||||
}
|
||||
|
||||
// Create provides a mock function with given fields: ctx, req
|
||||
func (_m *BackupAccountRepo) Create(ctx context.Context, req *request.BackupAccountCreate) (*biz.BackupAccount, error) {
|
||||
func (_m *BackupAccountRepo) Create(ctx context.Context, req *request.BackupStorageCreate) (*biz.BackupStorage, error) {
|
||||
ret := _m.Called(ctx, req)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Create")
|
||||
}
|
||||
|
||||
var r0 *biz.BackupAccount
|
||||
var r0 *biz.BackupStorage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *request.BackupAccountCreate) (*biz.BackupAccount, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *request.BackupStorageCreate) (*biz.BackupStorage, error)); ok {
|
||||
return rf(ctx, req)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *request.BackupAccountCreate) *biz.BackupAccount); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *request.BackupStorageCreate) *biz.BackupStorage); ok {
|
||||
r0 = rf(ctx, req)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*biz.BackupAccount)
|
||||
r0 = ret.Get(0).(*biz.BackupStorage)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *request.BackupAccountCreate) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *request.BackupStorageCreate) error); ok {
|
||||
r1 = rf(ctx, req)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
@@ -62,24 +62,24 @@ type BackupAccountRepo_Create_Call struct {
|
||||
|
||||
// Create is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - req *request.BackupAccountCreate
|
||||
// - req *request.BackupStorageCreate
|
||||
func (_e *BackupAccountRepo_Expecter) Create(ctx interface{}, req interface{}) *BackupAccountRepo_Create_Call {
|
||||
return &BackupAccountRepo_Create_Call{Call: _e.mock.On("Create", ctx, req)}
|
||||
}
|
||||
|
||||
func (_c *BackupAccountRepo_Create_Call) Run(run func(ctx context.Context, req *request.BackupAccountCreate)) *BackupAccountRepo_Create_Call {
|
||||
func (_c *BackupAccountRepo_Create_Call) Run(run func(ctx context.Context, req *request.BackupStorageCreate)) *BackupAccountRepo_Create_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*request.BackupAccountCreate))
|
||||
run(args[0].(context.Context), args[1].(*request.BackupStorageCreate))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *BackupAccountRepo_Create_Call) Return(_a0 *biz.BackupAccount, _a1 error) *BackupAccountRepo_Create_Call {
|
||||
func (_c *BackupAccountRepo_Create_Call) Return(_a0 *biz.BackupStorage, _a1 error) *BackupAccountRepo_Create_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *BackupAccountRepo_Create_Call) RunAndReturn(run func(context.Context, *request.BackupAccountCreate) (*biz.BackupAccount, error)) *BackupAccountRepo_Create_Call {
|
||||
func (_c *BackupAccountRepo_Create_Call) RunAndReturn(run func(context.Context, *request.BackupStorageCreate) (*biz.BackupStorage, error)) *BackupAccountRepo_Create_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
@@ -132,23 +132,23 @@ func (_c *BackupAccountRepo_Delete_Call) RunAndReturn(run func(context.Context,
|
||||
}
|
||||
|
||||
// Get provides a mock function with given fields: id
|
||||
func (_m *BackupAccountRepo) Get(id uint) (*biz.BackupAccount, error) {
|
||||
func (_m *BackupAccountRepo) Get(id uint) (*biz.BackupStorage, error) {
|
||||
ret := _m.Called(id)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Get")
|
||||
}
|
||||
|
||||
var r0 *biz.BackupAccount
|
||||
var r0 *biz.BackupStorage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(uint) (*biz.BackupAccount, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(uint) (*biz.BackupStorage, error)); ok {
|
||||
return rf(id)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(uint) *biz.BackupAccount); ok {
|
||||
if rf, ok := ret.Get(0).(func(uint) *biz.BackupStorage); ok {
|
||||
r0 = rf(id)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*biz.BackupAccount)
|
||||
r0 = ret.Get(0).(*biz.BackupStorage)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,35 +179,35 @@ func (_c *BackupAccountRepo_Get_Call) Run(run func(id uint)) *BackupAccountRepo_
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *BackupAccountRepo_Get_Call) Return(_a0 *biz.BackupAccount, _a1 error) *BackupAccountRepo_Get_Call {
|
||||
func (_c *BackupAccountRepo_Get_Call) Return(_a0 *biz.BackupStorage, _a1 error) *BackupAccountRepo_Get_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *BackupAccountRepo_Get_Call) RunAndReturn(run func(uint) (*biz.BackupAccount, error)) *BackupAccountRepo_Get_Call {
|
||||
func (_c *BackupAccountRepo_Get_Call) RunAndReturn(run func(uint) (*biz.BackupStorage, error)) *BackupAccountRepo_Get_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// List provides a mock function with given fields: page, limit
|
||||
func (_m *BackupAccountRepo) List(page uint, limit uint) ([]*biz.BackupAccount, int64, error) {
|
||||
func (_m *BackupAccountRepo) List(page uint, limit uint) ([]*biz.BackupStorage, int64, error) {
|
||||
ret := _m.Called(page, limit)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for List")
|
||||
}
|
||||
|
||||
var r0 []*biz.BackupAccount
|
||||
var r0 []*biz.BackupStorage
|
||||
var r1 int64
|
||||
var r2 error
|
||||
if rf, ok := ret.Get(0).(func(uint, uint) ([]*biz.BackupAccount, int64, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(uint, uint) ([]*biz.BackupStorage, int64, error)); ok {
|
||||
return rf(page, limit)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(uint, uint) []*biz.BackupAccount); ok {
|
||||
if rf, ok := ret.Get(0).(func(uint, uint) []*biz.BackupStorage); ok {
|
||||
r0 = rf(page, limit)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*biz.BackupAccount)
|
||||
r0 = ret.Get(0).([]*biz.BackupStorage)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,18 +245,18 @@ func (_c *BackupAccountRepo_List_Call) Run(run func(page uint, limit uint)) *Bac
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *BackupAccountRepo_List_Call) Return(_a0 []*biz.BackupAccount, _a1 int64, _a2 error) *BackupAccountRepo_List_Call {
|
||||
func (_c *BackupAccountRepo_List_Call) Return(_a0 []*biz.BackupStorage, _a1 int64, _a2 error) *BackupAccountRepo_List_Call {
|
||||
_c.Call.Return(_a0, _a1, _a2)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *BackupAccountRepo_List_Call) RunAndReturn(run func(uint, uint) ([]*biz.BackupAccount, int64, error)) *BackupAccountRepo_List_Call {
|
||||
func (_c *BackupAccountRepo_List_Call) RunAndReturn(run func(uint, uint) ([]*biz.BackupStorage, int64, error)) *BackupAccountRepo_List_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Update provides a mock function with given fields: ctx, req
|
||||
func (_m *BackupAccountRepo) Update(ctx context.Context, req *request.BackupAccountUpdate) error {
|
||||
func (_m *BackupAccountRepo) Update(ctx context.Context, req *request.BackupStorageUpdate) error {
|
||||
ret := _m.Called(ctx, req)
|
||||
|
||||
if len(ret) == 0 {
|
||||
@@ -264,7 +264,7 @@ func (_m *BackupAccountRepo) Update(ctx context.Context, req *request.BackupAcco
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *request.BackupAccountUpdate) error); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *request.BackupStorageUpdate) error); ok {
|
||||
r0 = rf(ctx, req)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
@@ -280,14 +280,14 @@ type BackupAccountRepo_Update_Call struct {
|
||||
|
||||
// Update is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - req *request.BackupAccountUpdate
|
||||
// - req *request.BackupStorageUpdate
|
||||
func (_e *BackupAccountRepo_Expecter) Update(ctx interface{}, req interface{}) *BackupAccountRepo_Update_Call {
|
||||
return &BackupAccountRepo_Update_Call{Call: _e.mock.On("Update", ctx, req)}
|
||||
}
|
||||
|
||||
func (_c *BackupAccountRepo_Update_Call) Run(run func(ctx context.Context, req *request.BackupAccountUpdate)) *BackupAccountRepo_Update_Call {
|
||||
func (_c *BackupAccountRepo_Update_Call) Run(run func(ctx context.Context, req *request.BackupStorageUpdate)) *BackupAccountRepo_Update_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].(*request.BackupAccountUpdate))
|
||||
run(args[0].(context.Context), args[1].(*request.BackupStorageUpdate))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
@@ -297,7 +297,7 @@ func (_c *BackupAccountRepo_Update_Call) Return(_a0 error) *BackupAccountRepo_Up
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *BackupAccountRepo_Update_Call) RunAndReturn(run func(context.Context, *request.BackupAccountUpdate) error) *BackupAccountRepo_Update_Call {
|
||||
func (_c *BackupAccountRepo_Update_Call) RunAndReturn(run func(context.Context, *request.BackupStorageUpdate) error) *BackupAccountRepo_Update_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
@@ -25,12 +25,12 @@ func (_m *BackupRepo) EXPECT() *BackupRepo_Expecter {
|
||||
return &BackupRepo_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// ClearAccountExpired provides a mock function with given fields: account, typ, prefix, save
|
||||
func (_m *BackupRepo) ClearAccountExpired(account uint, typ biz.BackupType, prefix string, save uint) error {
|
||||
// ClearStorageExpired provides a mock function with given fields: account, typ, prefix, save
|
||||
func (_m *BackupRepo) ClearStorageExpired(account uint, typ biz.BackupType, prefix string, save uint) error {
|
||||
ret := _m.Called(account, typ, prefix, save)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ClearAccountExpired")
|
||||
panic("no return value specified for ClearStorageExpired")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
@@ -43,33 +43,33 @@ func (_m *BackupRepo) ClearAccountExpired(account uint, typ biz.BackupType, pref
|
||||
return r0
|
||||
}
|
||||
|
||||
// BackupRepo_ClearAccountExpired_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ClearAccountExpired'
|
||||
type BackupRepo_ClearAccountExpired_Call struct {
|
||||
// BackupRepo_ClearStorageExpired_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ClearStorageExpired'
|
||||
type BackupRepo_ClearStorageExpired_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ClearAccountExpired is a helper method to define mock.On call
|
||||
// ClearStorageExpired is a helper method to define mock.On call
|
||||
// - account uint
|
||||
// - typ biz.BackupType
|
||||
// - prefix string
|
||||
// - save uint
|
||||
func (_e *BackupRepo_Expecter) ClearAccountExpired(account interface{}, typ interface{}, prefix interface{}, save interface{}) *BackupRepo_ClearAccountExpired_Call {
|
||||
return &BackupRepo_ClearAccountExpired_Call{Call: _e.mock.On("ClearAccountExpired", account, typ, prefix, save)}
|
||||
func (_e *BackupRepo_Expecter) ClearStorageExpired(account interface{}, typ interface{}, prefix interface{}, save interface{}) *BackupRepo_ClearStorageExpired_Call {
|
||||
return &BackupRepo_ClearStorageExpired_Call{Call: _e.mock.On("ClearStorageExpired", account, typ, prefix, save)}
|
||||
}
|
||||
|
||||
func (_c *BackupRepo_ClearAccountExpired_Call) Run(run func(account uint, typ biz.BackupType, prefix string, save uint)) *BackupRepo_ClearAccountExpired_Call {
|
||||
func (_c *BackupRepo_ClearStorageExpired_Call) Run(run func(account uint, typ biz.BackupType, prefix string, save uint)) *BackupRepo_ClearStorageExpired_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(uint), args[1].(biz.BackupType), args[2].(string), args[3].(uint))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *BackupRepo_ClearAccountExpired_Call) Return(_a0 error) *BackupRepo_ClearAccountExpired_Call {
|
||||
func (_c *BackupRepo_ClearStorageExpired_Call) Return(_a0 error) *BackupRepo_ClearStorageExpired_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *BackupRepo_ClearAccountExpired_Call) RunAndReturn(run func(uint, biz.BackupType, string, uint) error) *BackupRepo_ClearAccountExpired_Call {
|
||||
func (_c *BackupRepo_ClearStorageExpired_Call) RunAndReturn(run func(uint, biz.BackupType, string, uint) error) *BackupRepo_ClearStorageExpired_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package types
|
||||
|
||||
import "time"
|
||||
|
||||
type BackupAccountInfo struct {
|
||||
type BackupStorageInfo struct {
|
||||
// S3
|
||||
AccessKey string `json:"access_key"` // 访问密钥
|
||||
SecretKey string `json:"secret_key"` // 私钥
|
||||
|
||||
15
web/src/api/panel/backup-storage/index.ts
Normal file
15
web/src/api/panel/backup-storage/index.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 获取备份账号列表
|
||||
list: (page: number, limit: number): any =>
|
||||
http.Get('/backup_storage', { params: { page, limit } }),
|
||||
// 获取备份账号
|
||||
get: (id: number): any => http.Get(`/backup_storage/${id}`),
|
||||
// 创建备份账号
|
||||
create: (data: any): any => http.Post('/backup_storage', data),
|
||||
// 更新备份账号
|
||||
update: (id: number, data: any): any => http.Put(`/backup_storage/${id}`, data),
|
||||
// 删除备份账号
|
||||
delete: (id: number): any => http.Delete(`/backup_storage/${id}`)
|
||||
}
|
||||
@@ -5,8 +5,8 @@ export default {
|
||||
list: (type: string, page: number, limit: number): any =>
|
||||
http.Get(`/backup/${type}`, { params: { page, limit } }),
|
||||
// 创建备份
|
||||
create: (type: string, target: string, account_id: number): any =>
|
||||
http.Post(`/backup/${type}`, { target, account_id }),
|
||||
create: (type: string, target: string, storage: number): any =>
|
||||
http.Post(`/backup/${type}`, { target, storage }),
|
||||
// 上传备份
|
||||
upload: (type: string, formData: FormData): any => http.Post(`/backup/${type}/upload`, formData),
|
||||
// 删除备份
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 获取备份账号列表
|
||||
list: (page: number, limit: number): any =>
|
||||
http.Get('/backup_account', { params: { page, limit } }),
|
||||
// 获取备份账号
|
||||
get: (id: number): any => http.Get(`/backup_account/${id}`),
|
||||
// 创建备份账号
|
||||
create: (data: any): any => http.Post('/backup_account', data),
|
||||
// 更新备份账号
|
||||
update: (id: number, data: any): any => http.Put(`/backup_account/${id}`, data),
|
||||
// 删除备份账号
|
||||
delete: (id: number): any => http.Delete(`/backup_account/${id}`)
|
||||
}
|
||||
@@ -5,7 +5,7 @@ defineOptions({
|
||||
|
||||
import home from '@/api/panel/home'
|
||||
import ListView from '@/views/backup/ListView.vue'
|
||||
import AccountView from '@/views/backup/AccountView.vue'
|
||||
import StorageView from '@/views/backup/StorageView.vue'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
@@ -38,10 +38,10 @@ const postgreSQLInstalled = computed(() => {
|
||||
<n-tab name="website" :tab="$gettext('Website')" />
|
||||
<n-tab v-if="mySQLInstalled" name="mysql" tab="MySQL" />
|
||||
<n-tab v-if="postgreSQLInstalled" name="postgres" tab="PostgreSQL" />
|
||||
<n-tab name="account" :tab="$gettext('Account')" />
|
||||
<n-tab name="storage" :tab="$gettext('Storage')" />
|
||||
</n-tabs>
|
||||
</template>
|
||||
<list-view v-if="currentTab !== 'account'" v-model:type="currentTab" />
|
||||
<account-view v-else />
|
||||
<list-view v-if="currentTab !== 'storage'" v-model:type="currentTab" />
|
||||
<storage-view v-else />
|
||||
</common-page>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import backup from '@/api/panel/backup'
|
||||
import backupAccount from '@/api/panel/backupAccount'
|
||||
import storage from '@/api/panel/backup-storage'
|
||||
import type { MessageReactive } from 'naive-ui'
|
||||
import { NButton, NDataTable, NFlex, NInput, NPopconfirm } from 'naive-ui'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
@@ -20,10 +20,10 @@ const uploadModal = ref(false)
|
||||
const createModal = ref(false)
|
||||
const createModel = ref({
|
||||
target: '',
|
||||
account_id: 0
|
||||
storage: 0
|
||||
})
|
||||
|
||||
const accounts = ref<any[]>([])
|
||||
const storages = ref<any[]>([])
|
||||
|
||||
const restoreModal = ref(false)
|
||||
const restoreModel = ref({
|
||||
@@ -118,13 +118,13 @@ const { loading, data, page, total, pageSize, pageCount, refresh } = usePaginati
|
||||
)
|
||||
|
||||
const handleCreate = () => {
|
||||
useRequest(backup.create(type.value, createModel.value.target, createModel.value.account_id)).onSuccess(
|
||||
() => {
|
||||
createModal.value = false
|
||||
window.$bus.emit('backup:refresh')
|
||||
window.$message.success($gettext('Created successfully'))
|
||||
}
|
||||
)
|
||||
useRequest(
|
||||
backup.create(type.value, createModel.value.target, createModel.value.storage)
|
||||
).onSuccess(() => {
|
||||
createModal.value = false
|
||||
window.$bus.emit('backup:refresh')
|
||||
window.$message.success($gettext('Created successfully'))
|
||||
})
|
||||
}
|
||||
|
||||
const handleRestore = () => {
|
||||
@@ -181,14 +181,14 @@ onMounted(() => {
|
||||
})
|
||||
}
|
||||
})
|
||||
useRequest(backupAccount.list(1, 10000)).onSuccess(({ data }: { data: any }) => {
|
||||
useRequest(storage.list(1, 10000)).onSuccess(({ data }: { data: any }) => {
|
||||
for (const item of data.items) {
|
||||
accounts.value.push({
|
||||
storages.value.push({
|
||||
label: item.name,
|
||||
value: item.id
|
||||
})
|
||||
}
|
||||
createModel.value.account_id = accounts.value[0]?.value || 0
|
||||
createModel.value.storage = storages.value[0]?.value || 0
|
||||
})
|
||||
refresh()
|
||||
window.$bus.on('backup:refresh', refresh)
|
||||
@@ -202,7 +202,11 @@ onUnmounted(() => {
|
||||
<template>
|
||||
<n-flex vertical :size="20">
|
||||
<n-alert type="info">
|
||||
{{ $gettext('Only local backups are displayed here. Remote backups are stored in the corresponding backup account.') }}
|
||||
{{
|
||||
$gettext(
|
||||
'Only local backups are displayed here. Remote backups are stored in the corresponding backup storage.'
|
||||
)
|
||||
}}
|
||||
</n-alert>
|
||||
<n-flex>
|
||||
<n-button type="primary" @click="createModal = true">{{
|
||||
@@ -259,11 +263,11 @@ onUnmounted(() => {
|
||||
:placeholder="$gettext('Enter database name')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item path="account_id" :label="$gettext('Backup Account')">
|
||||
<n-form-item path="storage" :label="$gettext('Backup Storage')">
|
||||
<n-select
|
||||
v-model:value="createModel.account_id"
|
||||
:options="accounts"
|
||||
:placeholder="$gettext('Select backup account')"
|
||||
v-model:value="createModel.storage"
|
||||
:options="storages"
|
||||
:placeholder="$gettext('Select backup storage')"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import backupAccount from '@/api/panel/backupAccount'
|
||||
import storage from '@/api/panel/backup-storage'
|
||||
import { formatDateTime } from '@/utils'
|
||||
import { NButton, NDataTable, NPopconfirm } from 'naive-ui'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
@@ -106,7 +106,7 @@ const columns: any = [
|
||||
onPositiveClick: () => handleDelete(row.id)
|
||||
},
|
||||
{
|
||||
default: () => $gettext('Are you sure you want to delete this account?'),
|
||||
default: () => $gettext('Are you sure you want to delete this storage?'),
|
||||
trigger: () =>
|
||||
h(
|
||||
NButton,
|
||||
@@ -128,7 +128,7 @@ const columns: any = [
|
||||
]
|
||||
|
||||
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
|
||||
(page, pageSize) => backupAccount.list(page, pageSize),
|
||||
(page, pageSize) => storage.list(page, pageSize),
|
||||
{
|
||||
initialData: { total: 0, list: [] },
|
||||
initialPageSize: 20,
|
||||
@@ -138,7 +138,7 @@ const { loading, data, page, total, pageSize, pageCount, refresh } = usePaginati
|
||||
)
|
||||
|
||||
const handleCreate = () => {
|
||||
useRequest(backupAccount.create(createModel.value)).onSuccess(() => {
|
||||
useRequest(storage.create(createModel.value)).onSuccess(() => {
|
||||
createModal.value = false
|
||||
createModel.value = { ...defaultModel, info: { ...defaultModel.info } }
|
||||
refresh()
|
||||
@@ -157,7 +157,7 @@ const handleEdit = (row: any) => {
|
||||
}
|
||||
|
||||
const handleUpdate = () => {
|
||||
useRequest(backupAccount.update(editId.value, editModel.value)).onSuccess(() => {
|
||||
useRequest(storage.update(editId.value, editModel.value)).onSuccess(() => {
|
||||
editModal.value = false
|
||||
refresh()
|
||||
window.$message.success($gettext('Updated successfully'))
|
||||
@@ -165,7 +165,7 @@ const handleUpdate = () => {
|
||||
}
|
||||
|
||||
const handleDelete = (id: number) => {
|
||||
useRequest(backupAccount.delete(id)).onSuccess(() => {
|
||||
useRequest(storage.delete(id)).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success($gettext('Deleted successfully'))
|
||||
})
|
||||
@@ -179,7 +179,7 @@ onMounted(() => {
|
||||
<template>
|
||||
<n-flex vertical :size="20">
|
||||
<n-flex>
|
||||
<n-button type="primary" @click="createModal = true">{{ $gettext('Add Account') }}</n-button>
|
||||
<n-button type="primary" @click="createModal = true">{{ $gettext('Add Storage') }}</n-button>
|
||||
</n-flex>
|
||||
<n-data-table
|
||||
striped
|
||||
@@ -207,7 +207,7 @@ onMounted(() => {
|
||||
<n-modal
|
||||
v-model:show="createModal"
|
||||
preset="card"
|
||||
:title="$gettext('Add Account')"
|
||||
:title="$gettext('Add Storage')"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
@@ -216,7 +216,7 @@ onMounted(() => {
|
||||
>
|
||||
<n-form :model="createModel">
|
||||
<n-form-item :label="$gettext('Name')" required>
|
||||
<n-input v-model:value="createModel.name" :placeholder="$gettext('Enter account name')" />
|
||||
<n-input v-model:value="createModel.name" :placeholder="$gettext('Enter storage name')" />
|
||||
</n-form-item>
|
||||
<n-form-item :label="$gettext('Type')" required>
|
||||
<n-select v-model:value="createModel.type" :options="typeOptions" />
|
||||
@@ -358,7 +358,7 @@ onMounted(() => {
|
||||
<n-modal
|
||||
v-model:show="editModal"
|
||||
preset="card"
|
||||
:title="$gettext('Edit Account')"
|
||||
:title="$gettext('Edit Storage')"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
@@ -367,7 +367,7 @@ onMounted(() => {
|
||||
>
|
||||
<n-form :model="editModel">
|
||||
<n-form-item :label="$gettext('Name')" required>
|
||||
<n-input v-model:value="editModel.name" :placeholder="$gettext('Enter account name')" />
|
||||
<n-input v-model:value="editModel.name" :placeholder="$gettext('Enter storage name')" />
|
||||
</n-form-item>
|
||||
<n-form-item :label="$gettext('Type')" required>
|
||||
<n-select v-model:value="editModel.type" :options="typeOptions" />
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import app from '@/api/panel/app'
|
||||
import backupAccount from '@/api/panel/backupAccount'
|
||||
import storage from '@/api/panel/backup-storage'
|
||||
import cron from '@/api/panel/cron'
|
||||
import home from '@/api/panel/home'
|
||||
import website from '@/api/panel/website'
|
||||
@@ -16,15 +16,15 @@ const createModel = ref({
|
||||
name: '',
|
||||
type: 'shell',
|
||||
target: '',
|
||||
save: 1,
|
||||
keep: 1,
|
||||
backup_type: 'website',
|
||||
backup_account: 0,
|
||||
backup_storage: 0,
|
||||
script: $gettext('# Enter your script content here'),
|
||||
time: '* * * * *'
|
||||
})
|
||||
|
||||
const websites = ref<any>([])
|
||||
const accounts = ref<any[]>([])
|
||||
const storages = ref<any[]>([])
|
||||
|
||||
const { data: installedEnvironment } = useRequest(home.installedEnvironment, {
|
||||
initialData: {
|
||||
@@ -79,7 +79,9 @@ const generateTaskName = () => {
|
||||
const prefix = backupTypeMap[createModel.value.backup_type] || $gettext('Backup')
|
||||
createModel.value.name = target ? `${prefix} - ${target}` : prefix
|
||||
} else if (type === 'cutoff') {
|
||||
createModel.value.name = target ? `${$gettext('Log Rotation')} - ${target}` : $gettext('Log Rotation')
|
||||
createModel.value.name = target
|
||||
? `${$gettext('Log Rotation')} - ${target}`
|
||||
: $gettext('Log Rotation')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,14 +106,14 @@ onMounted(() => {
|
||||
})
|
||||
}
|
||||
})
|
||||
useRequest(backupAccount.list(1, 10000)).onSuccess(({ data }: { data: any }) => {
|
||||
useRequest(storage.list(1, 10000)).onSuccess(({ data }: { data: any }) => {
|
||||
for (const item of data.items) {
|
||||
accounts.value.push({
|
||||
storages.value.push({
|
||||
label: item.name,
|
||||
value: item.id
|
||||
})
|
||||
}
|
||||
createModel.value.backup_account = accounts.value[0]?.value || 0
|
||||
createModel.value.backup_storage = storages.value[0]?.value || 0
|
||||
})
|
||||
})
|
||||
</script>
|
||||
@@ -178,15 +180,15 @@ onMounted(() => {
|
||||
>
|
||||
<n-input v-model:value="createModel.target" :placeholder="$gettext('Database Name')" />
|
||||
</n-form-item>
|
||||
<n-form-item v-if="createModel.type === 'backup'" :label="$gettext('Backup Account')">
|
||||
<n-form-item v-if="createModel.type === 'backup'" :label="$gettext('Backup Storage')">
|
||||
<n-select
|
||||
v-model:value="createModel.backup_account"
|
||||
:options="accounts"
|
||||
:placeholder="$gettext('Select backup account')"
|
||||
v-model:value="createModel.backup_storage"
|
||||
:options="storages"
|
||||
:placeholder="$gettext('Select backup storage')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item v-if="createModel.type !== 'shell'" :label="$gettext('Retention Count')">
|
||||
<n-input-number v-model:value="createModel.save" />
|
||||
<n-input-number v-model:value="createModel.keep" />
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-button type="info" :loading="loading" @click="handleSubmit" mt-10 block>
|
||||
|
||||
Reference in New Issue
Block a user