From ae295794d3af1bf0b3bc9233812bb23b151a094c Mon Sep 17 00:00:00 2001 From: ssongliu Date: Thu, 2 Mar 2023 13:54:07 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=B0=81=E8=A3=85=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E5=A4=87=E4=BB=BD=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/v1/app_install.go | 49 +- backend/app/api/v1/backup.go | 5 + backend/app/api/v1/file.go | 29 + backend/app/dto/request/file.go | 10 +- backend/app/dto/response/file.go | 10 +- backend/app/model/app_install.go | 34 +- backend/app/model/app_install_backup.go | 11 - backend/app/repo/app_install_backup.go | 49 -- backend/app/repo/entry.go | 1 - backend/app/repo/website.go | 6 + backend/app/service/app_install.go | 33 - backend/app/service/app_utils.go | 19 +- backend/app/service/backup.go | 1 - backend/app/service/backup_app.go | 122 ++- backend/app/service/backup_database.go | 1 + backend/app/service/backup_redis.go | 35 +- backend/app/service/backup_website.go | 110 +-- backend/app/service/database_mysql.go | 2 +- backend/app/service/entry.go | 1 - backend/app/service/file.go | 40 +- backend/app/service/website.go | 28 +- backend/init/migration/migrations/init.go | 2 +- backend/router/ro_app.go | 2 - backend/router/ro_file.go | 1 + cmd/server/docs/docs.go | 781 ++++++++---------- cmd/server/docs/swagger.json | 781 ++++++++---------- cmd/server/docs/swagger.yaml | 527 +++++------- frontend/components.d.ts | 1 + frontend/src/api/interface/app.ts | 15 - frontend/src/api/interface/database.ts | 11 - frontend/src/api/interface/file.ts | 9 + frontend/src/api/interface/website.ts | 16 - frontend/src/api/modules/app.ts | 8 - frontend/src/api/modules/files.ts | 5 + frontend/src/components/backup/index.vue | 4 +- frontend/src/components/upload/index.vue | 252 ++++++ frontend/src/lang/modules/en.ts | 5 +- frontend/src/lang/modules/zh.ts | 6 +- .../src/views/app-store/installed/index.vue | 23 + frontend/src/views/database/mysql/index.vue | 7 +- .../src/views/database/mysql/upload/index.vue | 210 ----- .../host/file-management/upload/index.vue | 60 +- frontend/src/views/website/website/index.vue | 7 +- .../views/website/website/upload/index.vue | 207 ----- 44 files changed, 1494 insertions(+), 2042 deletions(-) delete mode 100644 backend/app/model/app_install_backup.go delete mode 100644 backend/app/repo/app_install_backup.go create mode 100644 frontend/src/components/upload/index.vue delete mode 100644 frontend/src/views/database/mysql/upload/index.vue delete mode 100644 frontend/src/views/website/website/upload/index.vue diff --git a/backend/app/api/v1/app_install.go b/backend/app/api/v1/app_install.go index 31684c87e..3d84b1f20 100644 --- a/backend/app/api/v1/app_install.go +++ b/backend/app/api/v1/app_install.go @@ -20,7 +20,7 @@ import ( // @Param request body request.AppInstalledSearch true "request" // @Success 200 // @Security ApiKeyAuth -// @Router /apps/installed [post] +// @Router /apps/installed/search [post] func (b *BaseApi) SearchAppInstalled(c *gin.Context) { var req request.AppInstalledSearch if err := c.ShouldBindJSON(&req); err != nil { @@ -151,31 +151,6 @@ func (b *BaseApi) SyncInstalled(c *gin.Context) { helper.SuccessWithData(c, "") } -// @Tags App -// @Summary Page installed backups -// @Description 查询已安装备份列表分页 -// @Accept json -// @Param request body request.AppBackupSearch true "request" -// @Success 200 {object} dto.PageResult -// @Security ApiKeyAuth -// @Router /apps/installed/backups [post] -func (b *BaseApi) SearchInstalledBackup(c *gin.Context) { - var req request.AppBackupSearch - if err := c.ShouldBindJSON(&req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - total, list, err := appInstallService.PageInstallBackups(req) - if err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, dto.PageResult{ - Items: list, - Total: total, - }) -} - // @Tags App // @Summary Operate installed app // @Description 操作已安装应用 @@ -198,28 +173,6 @@ func (b *BaseApi) OperateInstalled(c *gin.Context) { helper.SuccessWithData(c, nil) } -// @Tags App -// @Summary Delete app backup record -// @Description 删除应用备份记录 -// @Accept json -// @Param request body request.AppBackupDelete true "request" -// @Success 200 -// @Security ApiKeyAuth -// @Router /apps/installed/backups/del [post] -// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFuntions":[{"input_colume":"id","input_value":"ids","isList":true,"db":"app_install_backups","output_colume":"name","output_value":"names"}],"formatZH":"删除应用备份 [names]","formatEN":"Deleting an Application Backup [names]"} -func (b *BaseApi) DeleteAppBackup(c *gin.Context) { - var req request.AppBackupDelete - if err := c.ShouldBindJSON(&req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) - return - } - if err := appInstallService.DeleteBackup(req); err != nil { - helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) - return - } - helper.SuccessWithData(c, nil) -} - // @Tags App // @Summary Search app service by key // @Description 通过 key 获取应用 service diff --git a/backend/app/api/v1/backup.go b/backend/app/api/v1/backup.go index 9966e4899..01f42a16e 100644 --- a/backend/app/api/v1/backup.go +++ b/backend/app/api/v1/backup.go @@ -354,6 +354,11 @@ func (b *BaseApi) RecoverByUpload(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } + case "app": + if err := backupService.AppRecover(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } case "website": if err := backupService.WebsiteRecover(req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) diff --git a/backend/app/api/v1/file.go b/backend/app/api/v1/file.go index 866324223..afa5a8703 100644 --- a/backend/app/api/v1/file.go +++ b/backend/app/api/v1/file.go @@ -44,6 +44,35 @@ func (b *BaseApi) ListFiles(c *gin.Context) { helper.SuccessWithData(c, files) } +// @Tags File +// @Summary Page file +// @Description 分页获取上传文件 +// @Accept json +// @Param request body request.SearchUploadWithPage true "request" +// @Success 200 {anrry} response.FileInfo +// @Security ApiKeyAuth +// @Router /files/upload/search [post] +func (b *BaseApi) SearchUploadWithPage(c *gin.Context) { + var req request.SearchUploadWithPage + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + total, files, err := fileService.SearchUploadWithPage(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, dto.PageResult{ + Items: files, + Total: total, + }) +} + // @Tags File // @Summary Load files tree // @Description 加载文件树 diff --git a/backend/app/dto/request/file.go b/backend/app/dto/request/file.go index 9ef2c4237..eec6636dd 100644 --- a/backend/app/dto/request/file.go +++ b/backend/app/dto/request/file.go @@ -1,11 +1,19 @@ package request -import "github.com/1Panel-dev/1Panel/backend/utils/files" +import ( + "github.com/1Panel-dev/1Panel/backend/app/dto" + "github.com/1Panel-dev/1Panel/backend/utils/files" +) type FileOption struct { files.FileOption } +type SearchUploadWithPage struct { + dto.PageInfo + Path string `json:"path" validate:"required"` +} + type FileCreate struct { Path string `json:"path" validate:"required"` Content string `json:"content"` diff --git a/backend/app/dto/response/file.go b/backend/app/dto/response/file.go index 95aa9b29e..626ca4c1b 100644 --- a/backend/app/dto/response/file.go +++ b/backend/app/dto/response/file.go @@ -1,11 +1,19 @@ package response -import "github.com/1Panel-dev/1Panel/backend/utils/files" +import ( + "github.com/1Panel-dev/1Panel/backend/utils/files" +) type FileInfo struct { files.FileInfo } +type UploadInfo struct { + Name string `json:"name"` + Size int `json:"size"` + CreatedAt string `json:"createdAt"` +} + type FileTree struct { ID string `json:"id"` Name string `json:"name"` diff --git a/backend/app/model/app_install.go b/backend/app/model/app_install.go index 8a3285950..dbc9e1423 100644 --- a/backend/app/model/app_install.go +++ b/backend/app/model/app_install.go @@ -1,28 +1,28 @@ package model import ( - "github.com/1Panel-dev/1Panel/backend/constant" "path" + + "github.com/1Panel-dev/1Panel/backend/constant" ) type AppInstall struct { BaseModel - Name string `json:"name" gorm:"type:varchar(64);not null;UNIQUE"` - AppId uint `json:"appId" gorm:"type:integer;not null"` - AppDetailId uint `json:"appDetailId" gorm:"type:integer;not null"` - Version string `json:"version" gorm:"type:varchar(64);not null"` - Param string `json:"param" gorm:"type:longtext;"` - Env string `json:"env" gorm:"type:longtext;"` - DockerCompose string `json:"dockerCompose" gorm:"type:longtext;"` - Status string `json:"status" gorm:"type:varchar(256);not null"` - Description string `json:"description" gorm:"type:varchar(256);"` - Message string `json:"message" gorm:"type:longtext;"` - ContainerName string `json:"containerName" gorm:"type:varchar(256);not null"` - ServiceName string `json:"serviceName" gorm:"type:varchar(256);not null"` - HttpPort int `json:"httpPort" gorm:"type:integer;not null"` - HttpsPort int `json:"httpsPort" gorm:"type:integer;not null"` - App App `json:"app" gorm:"-:migration"` - Backups []AppInstallBackup `json:"backups" gorm:"-:migration"` + Name string `json:"name" gorm:"type:varchar(64);not null;UNIQUE"` + AppId uint `json:"appId" gorm:"type:integer;not null"` + AppDetailId uint `json:"appDetailId" gorm:"type:integer;not null"` + Version string `json:"version" gorm:"type:varchar(64);not null"` + Param string `json:"param" gorm:"type:longtext;"` + Env string `json:"env" gorm:"type:longtext;"` + DockerCompose string `json:"dockerCompose" gorm:"type:longtext;"` + Status string `json:"status" gorm:"type:varchar(256);not null"` + Description string `json:"description" gorm:"type:varchar(256);"` + Message string `json:"message" gorm:"type:longtext;"` + ContainerName string `json:"containerName" gorm:"type:varchar(256);not null"` + ServiceName string `json:"serviceName" gorm:"type:varchar(256);not null"` + HttpPort int `json:"httpPort" gorm:"type:integer;not null"` + HttpsPort int `json:"httpsPort" gorm:"type:integer;not null"` + App App `json:"app" gorm:"-:migration"` } func (i *AppInstall) GetPath() string { diff --git a/backend/app/model/app_install_backup.go b/backend/app/model/app_install_backup.go deleted file mode 100644 index f70a21ac3..000000000 --- a/backend/app/model/app_install_backup.go +++ /dev/null @@ -1,11 +0,0 @@ -package model - -type AppInstallBackup struct { - BaseModel - Name string `gorm:"type:varchar(64);not null" json:"name"` - Path string `gorm:"type:varchar(64);not null" json:"path"` - Param string `gorm:"type:longtext;" json:"param"` - AppDetailId uint `gorm:"type:integer;not null" json:"app_detail_id"` - AppInstallId uint `gorm:"type:integer;not null" json:"app_install_id"` - AppDetail AppDetail `json:"-" gorm:"-:migration"` -} diff --git a/backend/app/repo/app_install_backup.go b/backend/app/repo/app_install_backup.go deleted file mode 100644 index bf82f2100..000000000 --- a/backend/app/repo/app_install_backup.go +++ /dev/null @@ -1,49 +0,0 @@ -package repo - -import ( - "context" - "github.com/1Panel-dev/1Panel/backend/app/model" - "gorm.io/gorm" - "gorm.io/gorm/clause" -) - -type AppInstallBackupRepo struct { -} - -func (a AppInstallBackupRepo) WithAppInstallID(appInstallID uint) DBOption { - return func(db *gorm.DB) *gorm.DB { - return db.Where("app_install_id = ?", appInstallID) - } -} - -func (a AppInstallBackupRepo) Create(ctx context.Context, backup model.AppInstallBackup) error { - return getTx(ctx).Omit(clause.Associations).Create(&backup).Error -} - -func (a AppInstallBackupRepo) Delete(ctx context.Context, opts ...DBOption) error { - return getTx(ctx, opts...).Omit(clause.Associations).Delete(&model.AppInstallBackup{}).Error -} - -func (a AppInstallBackupRepo) GetBy(opts ...DBOption) ([]model.AppInstallBackup, error) { - var backups []model.AppInstallBackup - if err := getDb(opts...).Preload("AppDetail").Find(&backups); err != nil { - return backups, nil - } - return backups, nil -} - -func (a AppInstallBackupRepo) GetFirst(opts ...DBOption) (model.AppInstallBackup, error) { - var backup model.AppInstallBackup - db := getDb(opts...).Model(&model.AppInstallBackup{}) - err := db.Preload("AppDetail").First(&backup).Error - return backup, err -} - -func (a AppInstallBackupRepo) Page(page, size int, opts ...DBOption) (int64, []model.AppInstallBackup, error) { - var backups []model.AppInstallBackup - db := getDb(opts...).Model(&model.AppInstallBackup{}) - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Preload("AppDetail").Find(&backups).Error - return count, backups, err -} diff --git a/backend/app/repo/entry.go b/backend/app/repo/entry.go index e120dc052..bbdd155bf 100644 --- a/backend/app/repo/entry.go +++ b/backend/app/repo/entry.go @@ -8,7 +8,6 @@ type RepoGroup struct { AppDetailRepo AppInstallRepo AppInstallResourceRpo - AppInstallBackupRepo ImageRepoRepo ComposeTemplateRepo MysqlRepo diff --git a/backend/app/repo/website.go b/backend/app/repo/website.go index 7b1e88d94..798a8dc3d 100644 --- a/backend/app/repo/website.go +++ b/backend/app/repo/website.go @@ -4,6 +4,7 @@ import ( "context" "github.com/1Panel-dev/1Panel/backend/app/model" + "github.com/1Panel-dev/1Panel/backend/global" "gorm.io/gorm" "gorm.io/gorm/clause" ) @@ -20,6 +21,7 @@ type IWebsiteRepo interface { GetFirst(opts ...DBOption) (model.Website, error) GetBy(opts ...DBOption) ([]model.Website, error) Save(ctx context.Context, app *model.Website) error + SaveWithoutCtx(app *model.Website) error DeleteBy(ctx context.Context, opts ...DBOption) error Create(ctx context.Context, app *model.Website) error } @@ -108,6 +110,10 @@ func (w *WebsiteRepo) Save(ctx context.Context, app *model.Website) error { return getTx(ctx).Omit(clause.Associations).Save(app).Error } +func (w *WebsiteRepo) SaveWithoutCtx(website *model.Website) error { + return global.DB.Save(website).Error +} + func (w *WebsiteRepo) DeleteBy(ctx context.Context, opts ...DBOption) error { return getTx(ctx, opts...).Delete(&model.Website{}).Error } diff --git a/backend/app/service/app_install.go b/backend/app/service/app_install.go index 27398030d..603ee39f0 100644 --- a/backend/app/service/app_install.go +++ b/backend/app/service/app_install.go @@ -1,7 +1,6 @@ package service import ( - "context" "encoding/json" "fmt" "io/ioutil" @@ -23,7 +22,6 @@ import ( "github.com/1Panel-dev/1Panel/backend/utils/common" "github.com/1Panel-dev/1Panel/backend/utils/compose" "github.com/1Panel-dev/1Panel/backend/utils/docker" - "github.com/1Panel-dev/1Panel/backend/utils/files" "github.com/pkg/errors" ) @@ -96,9 +94,6 @@ func (a AppInstallService) CheckExist(key string) (*response.AppInstalledCheck, res.AppInstallID = appInstall.ID res.IsExist = true res.InstallPath = path.Join(constant.AppInstallDir, app.Key, appInstall.Name) - if len(appInstall.Backups) > 0 { - res.LastBackupAt = appInstall.Backups[0].CreatedAt.Format("2006-01-02 15:04:05") - } return res, nil } @@ -224,34 +219,6 @@ func (a AppInstallService) SyncAll() error { return nil } -func (a AppInstallService) PageInstallBackups(req request.AppBackupSearch) (int64, []model.AppInstallBackup, error) { - return appInstallBackupRepo.Page(req.Page, req.PageSize, appInstallBackupRepo.WithAppInstallID(req.AppInstallID)) -} - -func (a AppInstallService) DeleteBackup(req request.AppBackupDelete) error { - backups, err := appInstallBackupRepo.GetBy(commonRepo.WithIdsIn(req.Ids)) - if err != nil { - return err - } - fileOp := files.NewFileOp() - - var errStr strings.Builder - for _, backup := range backups { - dst := path.Join(backup.Path, backup.Name) - if err := fileOp.DeleteFile(dst); err != nil { - errStr.WriteString(err.Error()) - continue - } - if err := appInstallBackupRepo.Delete(context.TODO(), commonRepo.WithIdsIn(req.Ids)); err != nil { - errStr.WriteString(err.Error()) - } - } - if errStr.String() != "" { - return errors.New(errStr.String()) - } - return nil -} - func (a AppInstallService) GetServices(key string) ([]response.AppService, error) { app, err := appRepo.GetFirst(appRepo.WithKey(key)) if err != nil { diff --git a/backend/app/service/app_utils.go b/backend/app/service/app_utils.go index 61d81a61d..bfc94d972 100644 --- a/backend/app/service/app_utils.go +++ b/backend/app/service/app_utils.go @@ -3,6 +3,7 @@ package service import ( "context" "encoding/json" + "fmt" "math" "os" "path" @@ -128,15 +129,23 @@ func deleteAppInstall(ctx context.Context, install model.AppInstall, deleteBacku if err := deleteLink(ctx, &install); err != nil && !forceDelete { return err } + uploadDir := fmt.Sprintf("%s/1panel/uploads/app/%s/%s", global.CONF.System.BaseDir, install.App.Key, install.Name) + if _, err := os.Stat(uploadDir); err == nil { + _ = os.RemoveAll(uploadDir) + } if deleteBackup { - backups, _ := appInstallBackupRepo.GetBy(appInstallBackupRepo.WithAppInstallID(install.ID)) - for _, backup := range backups { - _ = op.DeleteDir(backup.Path) - } - if err := appInstallBackupRepo.Delete(ctx, appInstallBackupRepo.WithAppInstallID(install.ID)); err != nil && !forceDelete { + localDir, err := loadLocalDir() + if err != nil && !forceDelete { return err } + backupDir := fmt.Sprintf("%s/app/%s/%s", localDir, install.App.Key, install.Name) + if _, err := os.Stat(backupDir); err == nil { + _ = os.RemoveAll(backupDir) + } + global.LOG.Infof("delete app %s-%s backups successful", install.App.Key, install.Name) } + _ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType("app"), commonRepo.WithByName(install.App.Key), backupRepo.WithByDetailName(install.Name)) + return nil } diff --git a/backend/app/service/backup.go b/backend/app/service/backup.go index bbeaa48c1..68e145207 100644 --- a/backend/app/service/backup.go +++ b/backend/app/service/backup.go @@ -41,7 +41,6 @@ type IBackupService interface { WebsiteBackup(db dto.CommonBackup) error WebsiteRecover(req dto.CommonRecover) error - WebsiteRecoverByUpload(req dto.CommonRecover) error AppBackup(db dto.CommonBackup) error AppRecover(req dto.CommonRecover) error diff --git a/backend/app/service/backup_app.go b/backend/app/service/backup_app.go index 4dbf1279c..67a6e601d 100644 --- a/backend/app/service/backup_app.go +++ b/backend/app/service/backup_app.go @@ -6,7 +6,6 @@ import ( "io/fs" "os" "path" - "strconv" "strings" "time" @@ -16,9 +15,7 @@ import ( "github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/utils/compose" "github.com/1Panel-dev/1Panel/backend/utils/files" - "github.com/joho/godotenv" "github.com/pkg/errors" - "gopkg.in/yaml.v3" ) func (u *BackupService) AppBackup(req dto.CommonBackup) error { @@ -82,12 +79,6 @@ func (u *BackupService) AppRecover(req dto.CommonRecover) error { return nil } -type AppInfo struct { - AppDetailId uint `json:"appDetailId"` - Param string `json:"param"` - Version string `json:"version"` -} - func handleAppBackup(install *model.AppInstall, backupDir, fileName string) error { fileOp := files.NewFileOp() tmpDir := fmt.Sprintf("%s/%s", backupDir, strings.ReplaceAll(fileName, ".tar.gz", "")) @@ -100,11 +91,7 @@ func handleAppBackup(install *model.AppInstall, backupDir, fileName string) erro _ = os.RemoveAll(tmpDir) }() - var appInfo AppInfo - appInfo.Param = install.Param - appInfo.AppDetailId = install.AppDetailId - appInfo.Version = install.Version - remarkInfo, _ := json.Marshal(appInfo) + remarkInfo, _ := json.Marshal(install) remarkInfoPath := fmt.Sprintf("%s/app.json", tmpDir) if err := fileOp.SaveFile(remarkInfoPath, string(remarkInfo), fs.ModePerm); err != nil { return err @@ -114,6 +101,22 @@ func handleAppBackup(install *model.AppInstall, backupDir, fileName string) erro if err := fileOp.Compress([]string{appPath}, tmpDir, "app.tar.gz", files.TarGz); err != nil { return err } + + resource, _ := appInstallResourceRepo.GetFirst(appInstallResourceRepo.WithAppInstallId(install.ID)) + if resource.ID != 0 { + mysqlInfo, err := appInstallRepo.LoadBaseInfo(constant.AppMysql, "") + if err != nil { + return err + } + db, err := mysqlRepo.Get(commonRepo.WithByID(resource.ResourceId)) + if err != nil { + return err + } + if err := handleMysqlBackup(mysqlInfo, tmpDir, db.Name, fmt.Sprintf("%s.sql.gz", install.Name)); err != nil { + return err + } + } + if err := fileOp.Compress([]string{tmpDir}, backupDir, fileName, files.TarGz); err != nil { return err } @@ -123,17 +126,30 @@ func handleAppBackup(install *model.AppInstall, backupDir, fileName string) erro func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback bool) error { isOk := false fileOp := files.NewFileOp() - if err := fileOp.Decompress(recoverFile, path.Dir(recoverFile), files.TarGz); err != nil { + if err := handleUnTar(recoverFile, path.Dir(recoverFile)); err != nil { return err } tmpPath := strings.ReplaceAll(recoverFile, ".tar.gz", "") defer func() { + _, _ = compose.Up(install.GetComposePath()) _ = os.RemoveAll(strings.ReplaceAll(recoverFile, ".tar.gz", "")) }() if !fileOp.Stat(tmpPath+"/app.json") || !fileOp.Stat(tmpPath+"/app.tar.gz") { return errors.New("the wrong recovery package does not have app.json or app.tar.gz files") } + var oldInstall model.AppInstall + appjson, err := os.ReadFile(tmpPath + "/app.json") + if err != nil { + return err + } + if err := json.Unmarshal(appjson, &oldInstall); err != nil { + return fmt.Errorf("unmarshal app.json failed, err: %v", err) + } + if oldInstall.App.Key != install.App.Key || oldInstall.Name != install.Name || oldInstall.Version != install.Version || oldInstall.ID != install.ID { + return errors.New("the current backup file does not match the application") + } + if !isRollback { rollbackFile := fmt.Sprintf("%s/original/app/%s_%s.tar.gz", global.CONF.System.BaseDir, install.Name, time.Now().Format("20060102150405")) if err := handleAppBackup(install, path.Dir(rollbackFile), path.Base(rollbackFile)); err != nil { @@ -143,6 +159,7 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback if !isOk { if err := handleAppRecover(install, rollbackFile, true); err != nil { global.LOG.Errorf("rollback app %s from %s failed, err: %v", install.Name, rollbackFile, err) + return } global.LOG.Infof("rollback app %s from %s successful", install.Name, rollbackFile) _ = os.RemoveAll(rollbackFile) @@ -152,65 +169,26 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback }() } - appjson, err := os.ReadFile(tmpPath + "/" + "app.json") - if err != nil { - return err - } - var appInfo AppInfo - _ = json.Unmarshal(appjson, &appInfo) - - if err := fileOp.Decompress(tmpPath+"/app.tar.gz", fmt.Sprintf("%s/%s", constant.AppInstallDir, install.App.Key), files.TarGz); err != nil { - return err - } - composeContent, err := os.ReadFile(install.GetComposePath()) - if err != nil { - return err - } - install.DockerCompose = string(composeContent) - envContent, err := os.ReadFile(fmt.Sprintf("%s/%s/%s/.env", constant.AppInstallDir, install.App.Key, install.Name)) - if err != nil { - return err - } - install.Env = string(envContent) - envMaps, err := godotenv.Unmarshal(string(envContent)) - if err != nil { - return err - } - install.HttpPort = 0 - httpPort, ok := envMaps["PANEL_APP_PORT_HTTP"] - if ok { - httpPortN, _ := strconv.Atoi(httpPort) - install.HttpPort = httpPortN - } - install.HttpsPort = 0 - httpsPort, ok := envMaps["PANEL_APP_PORT_HTTPS"] - if ok { - httpsPortN, _ := strconv.Atoi(httpsPort) - install.HttpsPort = httpsPortN - } - - composeMap := make(map[string]interface{}) - if err := yaml.Unmarshal(composeContent, &composeMap); err != nil { - return err - } - servicesMap := composeMap["services"].(map[string]interface{}) - for k, v := range servicesMap { - install.ServiceName = k - value := v.(map[string]interface{}) - install.ContainerName = value["container_name"].(string) - } - - install.Param = appInfo.Param - if out, err := compose.Up(install.GetComposePath()); err != nil { - install.Message = err.Error() - if len(out) != 0 { - install.Message = out + resource, _ := appInstallResourceRepo.GetFirst(appInstallResourceRepo.WithAppInstallId(install.ID)) + if resource.ID != 0 && install.App.Key != "mysql" { + mysqlInfo, err := appInstallRepo.LoadBaseInfo(resource.Key, "") + if err != nil { + return err + } + db, err := mysqlRepo.Get(commonRepo.WithByID(resource.ResourceId)) + if err != nil { + return err + } + if err := handleMysqlRecover(mysqlInfo, tmpPath, db.Name, fmt.Sprintf("%s.sql.gz", install.Name), true); err != nil { + return err } - return errors.New(out) } - install.AppDetailId = appInfo.AppDetailId - install.Version = appInfo.Version - install.Status = constant.Running + + if err := handleUnTar(tmpPath+"/app.tar.gz", fmt.Sprintf("%s/%s", constant.AppInstallDir, install.App.Key)); err != nil { + return err + } + + oldInstall.Status = constant.Running if err := appInstallRepo.Save(install); err != nil { return err } diff --git a/backend/app/service/backup_database.go b/backend/app/service/backup_database.go index d8207c1fb..8601abdb8 100644 --- a/backend/app/service/backup_database.go +++ b/backend/app/service/backup_database.go @@ -152,6 +152,7 @@ func handleMysqlRecover(mysqlInfo *repo.RootInfo, recoverDir, dbName, fileName s if !isOk { if err := handleMysqlRecover(mysqlInfo, path.Dir(rollbackFile), dbName, path.Base(rollbackFile), true); err != nil { global.LOG.Errorf("rollback mysql db %s from %s failed, err: %v", dbName, rollbackFile, err) + return } global.LOG.Infof("rollback mysql db %s from %s successful", dbName, rollbackFile) _ = os.RemoveAll(rollbackFile) diff --git a/backend/app/service/backup_redis.go b/backend/app/service/backup_redis.go index 38b00b3be..a1d0f4f7e 100644 --- a/backend/app/service/backup_redis.go +++ b/backend/app/service/backup_redis.go @@ -113,26 +113,25 @@ func handleRedisRecover(redisInfo *repo.RootInfo, recoverFile string, isRollback global.LOG.Infof("appendonly in redis conf is %s", appendonly) isOk := false if !isRollback { + suffix := "tar.gz" + if appendonly != "yes" { + suffix = "rdb" + } + rollbackFile := fmt.Sprintf("%s/original/database/redis/%s_%s.%s", global.CONF.System.BaseDir, redisInfo.Name, time.Now().Format("20060102150405"), suffix) + if err := handleRedisBackup(redisInfo, path.Dir(rollbackFile), path.Base(rollbackFile)); err != nil { + global.LOG.Errorf("backup database %s for rollback before recover failed, err: %v", redisInfo.Name, err) + } defer func() { - suffix := "tar.gz" - if appendonly != "yes" { - suffix = "rdb" - } - rollbackFile := fmt.Sprintf("%s/original/database/redis/%s_%s.%s", global.CONF.System.BaseDir, redisInfo.Name, time.Now().Format("20060102150405"), suffix) - if err := handleRedisBackup(redisInfo, path.Dir(rollbackFile), path.Base(rollbackFile)); err != nil { - global.LOG.Errorf("backup database %s for rollback before recover failed, err: %v", redisInfo.Name, err) - } - defer func() { - if !isOk { - if err := handleRedisRecover(redisInfo, rollbackFile, true); err != nil { - global.LOG.Errorf("rollback redis from %s failed, err: %v", rollbackFile, err) - } - global.LOG.Infof("rollback redis from %s successful", rollbackFile) - _ = os.RemoveAll(rollbackFile) - } else { - _ = os.RemoveAll(rollbackFile) + if !isOk { + if err := handleRedisRecover(redisInfo, rollbackFile, true); err != nil { + global.LOG.Errorf("rollback redis from %s failed, err: %v", rollbackFile, err) + return } - }() + global.LOG.Infof("rollback redis from %s successful", rollbackFile) + _ = os.RemoveAll(rollbackFile) + } else { + _ = os.RemoveAll(rollbackFile) + } }() } composeDir := fmt.Sprintf("%s/redis/%s", constant.AppInstallDir, redisInfo.Name) diff --git a/backend/app/service/backup_website.go b/backend/app/service/backup_website.go index 2be8eae86..a16bef157 100644 --- a/backend/app/service/backup_website.go +++ b/backend/app/service/backup_website.go @@ -52,34 +52,6 @@ func (u *BackupService) WebsiteBackup(req dto.CommonBackup) error { return nil } -func (u *BackupService) WebsiteRecoverByUpload(req dto.CommonRecover) error { - if err := handleUnTar(req.File, path.Dir(req.File)); err != nil { - return err - } - tmpDir := strings.ReplaceAll(req.File, ".tar.gz", "") - webJson, err := os.ReadFile(fmt.Sprintf("%s/website.json", tmpDir)) - if err != nil { - return err - } - var websiteInfo WebsiteInfo - if err := json.Unmarshal(webJson, &websiteInfo); err != nil { - return err - } - if websiteInfo.WebsiteName != req.Name { - return errors.New("the uploaded file does not match the selected website and cannot be recovered") - } - - website, err := websiteRepo.GetFirst(websiteRepo.WithDomain(req.Name)) - if err != nil { - return err - } - if err := handleWebsiteRecover(&website, tmpDir, false); err != nil { - return err - } - - return nil -} - func (u *BackupService) WebsiteRecover(req dto.CommonRecover) error { website, err := websiteRepo.GetFirst(websiteRepo.WithDomain(req.Name)) if err != nil { @@ -98,23 +70,35 @@ func (u *BackupService) WebsiteRecover(req dto.CommonRecover) error { func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback bool) error { fileOp := files.NewFileOp() - fileDir := strings.ReplaceAll(recoverFile, ".tar.gz", "") - if err := fileOp.Decompress(recoverFile, path.Dir(recoverFile), files.TarGz); err != nil { + tmpPath := strings.ReplaceAll(recoverFile, ".tar.gz", "") + if err := handleUnTar(recoverFile, path.Dir(recoverFile)); err != nil { return err } defer func() { - _ = os.RemoveAll(fileDir) + _ = os.RemoveAll(tmpPath) }() - itemDir := fmt.Sprintf("%s/%s", fileDir, website.Alias) - if !fileOp.Stat(itemDir+".conf") || !fileOp.Stat(itemDir+".web.tar.gz") { + temPathWithName := tmpPath + "/" + website.Alias + if !fileOp.Stat(tmpPath+"/website.json") || !fileOp.Stat(temPathWithName+".conf") || !fileOp.Stat(temPathWithName+".web.tar.gz") { return errors.New("the wrong recovery package does not have .conf or .web.tar.gz files") } if website.Type == constant.Deployment { - if !fileOp.Stat(itemDir+".sql.gz") || !fileOp.Stat(itemDir+".app.tar.gz") { - return errors.New("the wrong recovery package does not have .sql.gz or .app.tar.gz files") + if !fileOp.Stat(temPathWithName + ".app.tar.gz") { + return errors.New("the wrong recovery package does not have .app.tar.gz files") } } + var oldWebsite model.Website + websiteJson, err := os.ReadFile(tmpPath + "/website.json") + if err != nil { + return err + } + if err := json.Unmarshal(websiteJson, &oldWebsite); err != nil { + return fmt.Errorf("unmarshal app.json failed, err: %v", err) + } + if oldWebsite.Alias != website.Alias || oldWebsite.Type != website.Type || oldWebsite.ID != website.ID { + return errors.New("the current backup file does not match the application") + } + isOk := false if !isRollback { rollbackFile := fmt.Sprintf("%s/original/website/%s_%s.tar.gz", global.CONF.System.BaseDir, website.Alias, time.Now().Format("20060102150405")) @@ -125,6 +109,7 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback if !isOk { if err := handleWebsiteRecover(website, rollbackFile, true); err != nil { global.LOG.Errorf("rollback website %s from %s failed, err: %v", website.Alias, rollbackFile, err) + return } global.LOG.Infof("rollback website %s from %s successful", website.Alias, rollbackFile) _ = os.RemoveAll(rollbackFile) @@ -139,31 +124,16 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback return err } nginxConfPath := fmt.Sprintf("%s/openresty/%s/conf/conf.d", constant.AppInstallDir, nginxInfo.Name) - if err := fileOp.CopyFile(fmt.Sprintf("%s/%s.conf", fileDir, website.Alias), nginxConfPath); err != nil { + if err := fileOp.CopyFile(fmt.Sprintf("%s/%s.conf", tmpPath, website.Alias), nginxConfPath); err != nil { return err } if website.Type == constant.Deployment { - mysqlInfo, err := appInstallRepo.LoadBaseInfo(constant.AppMysql, "") - if err != nil { - return err - } - resource, err := appInstallResourceRepo.GetFirst(appInstallResourceRepo.WithAppInstallId(website.AppInstallID)) - if err != nil { - return err - } - db, err := mysqlRepo.Get(commonRepo.WithByID(resource.ResourceId)) - if err != nil { - return err - } - if err := handleMysqlRecover(mysqlInfo, fileDir, db.Name, fmt.Sprintf("%s.sql.gz", website.Alias), isRollback); err != nil { - return err - } app, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) if err != nil { return err } - if err := handleAppRecover(&app, fmt.Sprintf("%s/%s.app.tar.gz", fileDir, website.Alias), isRollback); err != nil { + if err := handleAppRecover(&app, fmt.Sprintf("%s/%s.app.tar.gz", tmpPath, website.Alias), true); err != nil { return err } if _, err := compose.Restart(fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, app.App.Key, app.Name)); err != nil { @@ -171,7 +141,7 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback } } siteDir := fmt.Sprintf("%s/openresty/%s/www/sites", constant.AppInstallDir, nginxInfo.Name) - if err := fileOp.Decompress(fmt.Sprintf("%s/%s.web.tar.gz", fileDir, website.Alias), siteDir, files.TarGz); err != nil { + if err := handleUnTar(fmt.Sprintf("%s/%s.web.tar.gz", tmpPath, website.Alias), siteDir); err != nil { return err } stdout, err := cmd.Execf("docker exec -i %s nginx -s reload", nginxInfo.ContainerName) @@ -179,14 +149,12 @@ func handleWebsiteRecover(website *model.Website, recoverFile string, isRollback return errors.New(string(stdout)) } + if err := websiteRepo.SaveWithoutCtx(&oldWebsite); err != nil { + return err + } return nil } -type WebsiteInfo struct { - WebsiteName string `json:"websiteName"` - WebsiteType string `json:"websiteType"` -} - func handleWebsiteBackup(website *model.Website, backupDir, fileName string) error { fileOp := files.NewFileOp() tmpDir := fmt.Sprintf("%s/%s", backupDir, strings.ReplaceAll(fileName, ".tar.gz", "")) @@ -199,14 +167,11 @@ func handleWebsiteBackup(website *model.Website, backupDir, fileName string) err _ = os.RemoveAll(tmpDir) }() - var websiteInfo WebsiteInfo - websiteInfo.WebsiteType = website.Type - websiteInfo.WebsiteName = website.PrimaryDomain - remarkInfo, _ := json.Marshal(websiteInfo) + remarkInfo, _ := json.Marshal(website) if err := fileOp.SaveFile(tmpDir+"/website.json", string(remarkInfo), fs.ModePerm); err != nil { return err } - global.LOG.Info("put websitejson into tmp dir successful") + global.LOG.Info("put website.json into tmp dir successful") nginxInfo, err := appInstallRepo.LoadBaseInfo(constant.AppOpenresty, "") if err != nil { @@ -219,21 +184,6 @@ func handleWebsiteBackup(website *model.Website, backupDir, fileName string) err global.LOG.Info("put openresty conf into tmp dir successful") if website.Type == constant.Deployment { - mysqlInfo, err := appInstallRepo.LoadBaseInfo(constant.AppMysql, "") - if err != nil { - return err - } - resource, err := appInstallResourceRepo.GetFirst(appInstallResourceRepo.WithAppInstallId(website.AppInstallID)) - if err != nil { - return err - } - db, err := mysqlRepo.Get(commonRepo.WithByID(resource.ResourceId)) - if err != nil { - return err - } - if err := handleMysqlBackup(mysqlInfo, tmpDir, db.Name, fmt.Sprintf("%s.sql.gz", website.Alias)); err != nil { - return err - } app, err := appInstallRepo.GetFirst(commonRepo.WithByID(website.AppInstallID)) if err != nil { return err @@ -241,13 +191,13 @@ func handleWebsiteBackup(website *model.Website, backupDir, fileName string) err if err := handleAppBackup(&app, tmpDir, fmt.Sprintf("%s.app.tar.gz", website.Alias)); err != nil { return err } - global.LOG.Info("put app tar into tmp dir successful") + global.LOG.Info("put app.tar.gz into tmp dir successful") } websiteDir := fmt.Sprintf("%s/openresty/%s/www/sites/%s", constant.AppInstallDir, nginxInfo.Name, website.Alias) if err := fileOp.Compress([]string{websiteDir}, tmpDir, fmt.Sprintf("%s.web.tar.gz", website.Alias), files.TarGz); err != nil { return err } - global.LOG.Info("put website tar into tmp dir successful, now start to tar tmp dir") + global.LOG.Info("put web.tar.gz into tmp dir successful, now start to tar tmp dir") if err := fileOp.Compress([]string{tmpDir}, backupDir, fileName, files.TarGz); err != nil { return err } diff --git a/backend/app/service/database_mysql.go b/backend/app/service/database_mysql.go index b96b6093c..adca23c30 100644 --- a/backend/app/service/database_mysql.go +++ b/backend/app/service/database_mysql.go @@ -161,7 +161,7 @@ func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error } global.LOG.Info("execute delete database sql successful, now start to drop uploads and records") - uploadDir := fmt.Sprintf("%s/uploads/database/mysql/%s/%s", constant.DataDir, app.Name, db.Name) + uploadDir := fmt.Sprintf("%s/1panel/uploads/database/mysql/%s/%s", global.CONF.System.BaseDir, app.Name, db.Name) if _, err := os.Stat(uploadDir); err == nil { _ = os.RemoveAll(uploadDir) } diff --git a/backend/app/service/entry.go b/backend/app/service/entry.go index 56d3582a5..b022f8731 100644 --- a/backend/app/service/entry.go +++ b/backend/app/service/entry.go @@ -46,7 +46,6 @@ var ServiceGroupApp = new(ServiceGroup) var ( commonRepo = repo.RepoGroupApp.CommonRepo - appInstallBackupRepo = repo.RepoGroupApp.AppInstallBackupRepo appRepo = repo.RepoGroupApp.AppRepo appTagRepo = repo.RepoGroupApp.AppTagRepo appDetailRepo = repo.RepoGroupApp.AppDetailRepo diff --git a/backend/app/service/file.go b/backend/app/service/file.go index 4bdf2d9a7..47c14c020 100644 --- a/backend/app/service/file.go +++ b/backend/app/service/file.go @@ -2,16 +2,17 @@ package service import ( "fmt" - "github.com/1Panel-dev/1Panel/backend/app/dto/request" - "github.com/1Panel-dev/1Panel/backend/app/dto/response" - "github.com/1Panel-dev/1Panel/backend/buserr" - "github.com/1Panel-dev/1Panel/backend/constant" "io/fs" "os" "path/filepath" "strings" "time" + "github.com/1Panel-dev/1Panel/backend/app/dto/request" + "github.com/1Panel-dev/1Panel/backend/app/dto/response" + "github.com/1Panel-dev/1Panel/backend/buserr" + "github.com/1Panel-dev/1Panel/backend/constant" + "github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/utils/common" "github.com/1Panel-dev/1Panel/backend/utils/files" @@ -35,6 +36,37 @@ func (f FileService) GetFileList(op request.FileOption) (response.FileInfo, erro return fileInfo, nil } +func (f FileService) SearchUploadWithPage(req request.SearchUploadWithPage) (int64, interface{}, error) { + var ( + files []response.UploadInfo + backDatas []response.UploadInfo + ) + + _ = filepath.Walk(req.Path, func(path string, info os.FileInfo, err error) error { + if err != nil { + return nil + } + if !info.IsDir() { + files = append(files, response.UploadInfo{ + CreatedAt: info.ModTime().Format("2006-01-02 15:04:05"), + Size: int(info.Size()), + Name: info.Name(), + }) + } + return nil + }) + total, start, end := len(files), (req.Page-1)*req.PageSize, req.Page*req.PageSize + if start > total { + backDatas = make([]response.UploadInfo, 0) + } else { + if end >= total { + end = total + } + backDatas = files[start:end] + } + return int64(total), backDatas, nil +} + func (f FileService) GetFileTree(op request.FileOption) ([]response.FileTree, error) { var treeArray []response.FileTree info, err := files.NewFileInfo(op.FileOption) diff --git a/backend/app/service/website.go b/backend/app/service/website.go index b81ff74f2..3a4883e3c 100644 --- a/backend/app/service/website.go +++ b/backend/app/service/website.go @@ -15,6 +15,7 @@ import ( "github.com/1Panel-dev/1Panel/backend/app/dto/response" "github.com/1Panel-dev/1Panel/backend/app/repo" "github.com/1Panel-dev/1Panel/backend/buserr" + "github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/model" @@ -257,18 +258,23 @@ func (w WebsiteService) DeleteWebsite(ctx context.Context, req request.WebsiteDe } } } - if req.DeleteBackup { - backups, _ := backupRepo.ListRecord(backupRepo.WithByType("website-"+website.Type), commonRepo.WithByName(website.PrimaryDomain)) - if len(backups) > 0 { - fileOp := files.NewFileOp() - for _, b := range backups { - _ = fileOp.DeleteDir(b.FileDir) - } - if err := backupRepo.DeleteRecord(ctx, backupRepo.WithByType("website-"+website.Type), commonRepo.WithByName(website.PrimaryDomain)); err != nil { - return err - } - } + + uploadDir := fmt.Sprintf("%s/1panel/uploads/website/%s", global.CONF.System.BaseDir, website.Alias) + if _, err := os.Stat(uploadDir); err == nil { + _ = os.RemoveAll(uploadDir) } + if req.DeleteBackup { + localDir, err := loadLocalDir() + if err != nil && !req.ForceDelete { + return err + } + backupDir := fmt.Sprintf("%s/website/%s", localDir, website.Alias) + if _, err := os.Stat(backupDir); err == nil { + _ = os.RemoveAll(backupDir) + } + global.LOG.Infof("delete website %s backups successful", website.Alias) + } + _ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType("website"), commonRepo.WithByName(website.Alias)) if err := websiteRepo.DeleteBy(ctx, commonRepo.WithByID(req.ID)); err != nil { return err diff --git a/backend/init/migration/migrations/init.go b/backend/init/migration/migrations/init.go index 9655c0dc0..1adf6a779 100644 --- a/backend/init/migration/migrations/init.go +++ b/backend/init/migration/migrations/init.go @@ -178,7 +178,7 @@ var AddTableCronjob = &gormigrate.Migration{ var AddTableApp = &gormigrate.Migration{ ID: "20200921-add-table-app", Migrate: func(tx *gorm.DB) error { - return tx.AutoMigrate(&model.App{}, &model.AppDetail{}, &model.Tag{}, &model.AppTag{}, &model.AppInstall{}, &model.AppInstallResource{}, &model.AppInstallBackup{}) + return tx.AutoMigrate(&model.App{}, &model.AppDetail{}, &model.Tag{}, &model.AppTag{}, &model.AppInstall{}, &model.AppInstallResource{}) }, } diff --git a/backend/router/ro_app.go b/backend/router/ro_app.go index 01184c322..79144d425 100644 --- a/backend/router/ro_app.go +++ b/backend/router/ro_app.go @@ -29,8 +29,6 @@ func (a *AppRouter) InitAppRouter(Router *gin.RouterGroup) { appRouter.POST("/installed/search", baseApi.SearchAppInstalled) appRouter.POST("/installed/op", baseApi.OperateInstalled) appRouter.POST("/installed/sync", baseApi.SyncInstalled) - appRouter.POST("/installed/backups", baseApi.SearchInstalledBackup) - appRouter.POST("/installed/backups/del", baseApi.DeleteAppBackup) appRouter.POST("/installed/port/change", baseApi.ChangeAppPort) appRouter.GET("/services/:key", baseApi.GetServices) appRouter.GET("/installed/conf/:key", baseApi.GetDefaultConfig) diff --git a/backend/router/ro_file.go b/backend/router/ro_file.go index 9edef8215..00eaf9f19 100644 --- a/backend/router/ro_file.go +++ b/backend/router/ro_file.go @@ -15,6 +15,7 @@ func (f *FileRouter) InitFileRouter(Router *gin.RouterGroup) { baseApi := v1.ApiGroupApp.BaseApi { fileRouter.POST("/search", baseApi.ListFiles) + fileRouter.POST("/upload/search", baseApi.SearchUploadWithPage) fileRouter.POST("/tree", baseApi.GetFileTree) fileRouter.POST("", baseApi.CreateFile) fileRouter.POST("/del", baseApi.DeleteFile) diff --git a/cmd/server/docs/docs.go b/cmd/server/docs/docs.go index 7a65cd1aa..03099dcc5 100644 --- a/cmd/server/docs/docs.go +++ b/cmd/server/docs/docs.go @@ -3117,49 +3117,6 @@ var doc = `{ } } }, - "/databases/backup": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "备份 mysql 数据库", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Backup mysql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BackupDB" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "mysqlName", - "dbName" - ], - "formatEN": "backup mysql database [mysqlName][dbName]", - "formatZH": "备份 mysql 数据库 [mysqlName][dbName]", - "paramKeys": [] - } - } - }, "/databases/baseinfo": { "get": { "security": [ @@ -3499,121 +3456,6 @@ var doc = `{ } } }, - "/databases/recover": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Mysql 数据库恢复", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Recover mysql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.RecoverDB" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "mysqlName", - "dbName", - "backupName" - ], - "formatEN": "恢复 mysql 数据库 [mysqlName][dbName] [backupName]", - "formatZH": "恢复 mysql 数据库 [mysqlName][dbName] [backupName]", - "paramKeys": [] - } - } - }, - "/databases/recover/byupload": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Mysql 数据库从上传文件恢复", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Recover mysql database by upload file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.UploadRecover" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "fileDir", - "fileName", - "mysqlName", - "dbName" - ], - "formatEN": "mysql database recover [fileDir]/[fileName] from [mysqlName][dbName]", - "formatZH": "mysql 数据库从 [fileDir]/[fileName] 恢复 [mysqlName][dbName]", - "paramKeys": [] - } - } - }, - "/databases/redis/backup": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "备份 redis 数据库", - "tags": [ - "Database Redis" - ], - "summary": "Backup redis", - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [], - "formatEN": "backup redis database", - "formatZH": "备份 redis 数据库", - "paramKeys": [] - } - } - }, "/databases/redis/backup/search": { "post": { "security": [ @@ -3854,35 +3696,6 @@ var doc = `{ } } }, - "/databases/redis/recover": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "恢复 redis 数据库", - "tags": [ - "Database Redis" - ], - "summary": "Recover redis", - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "fileDir", - "fileName" - ], - "formatEN": "redis database recover from [fileDir]/[fileName]", - "formatZH": "redis 数据库从 [fileDir]/[fileName] 恢复", - "paramKeys": [] - } - } - }, "/databases/redis/status": { "get": { "security": [ @@ -4711,6 +4524,42 @@ var doc = `{ } } }, + "/files/upload/search": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "分页获取上传文件", + "consumes": [ + "application/json" + ], + "tags": [ + "File" + ], + "summary": "Page file", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.SearchUploadWithPage" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "anrry" + } + } + } + } + }, "/files/wget": { "post": { "security": [ @@ -5046,7 +4895,7 @@ var doc = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.OperateByID" + "$ref": "#/definitions/dto.BatchDeleteReq" } } ], @@ -5060,17 +4909,17 @@ var doc = `{ { "db": "hosts", "input_colume": "id", - "input_value": "id", - "isList": false, + "input_value": "ids", + "isList": true, "output_colume": "addr", - "output_value": "addr" + "output_value": "addrs" } ], "bodyKeys": [ - "id" + "ids" ], - "formatEN": "delete host [addr]", - "formatZH": "删除主机 [addr]", + "formatEN": "delete host [addrs]", + "formatZH": "删除主机 [addrs]", "paramKeys": [] } } @@ -5255,14 +5104,14 @@ var doc = `{ "ApiKeyAuth": [] } ], - "description": "加载主机树", + "description": "获取主机列表分页", "consumes": [ "application/json" ], "tags": [ "Host" ], - "summary": "Load host tree", + "summary": "Page host", "parameters": [ { "description": "request", @@ -5270,7 +5119,7 @@ var doc = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.SearchForTree" + "$ref": "#/definitions/dto.SearchHostWithPage" } } ], @@ -5351,21 +5200,21 @@ var doc = `{ } } }, - "/hosts/update": { + "/hosts/tree": { "post": { "security": [ { "ApiKeyAuth": [] } ], - "description": "更新主机", + "description": "加载主机树", "consumes": [ "application/json" ], "tags": [ "Host" ], - "summary": "Update host", + "summary": "Load host tree", "parameters": [ { "description": "request", @@ -5373,7 +5222,43 @@ var doc = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.HostOperate" + "$ref": "#/definitions/dto.SearchForTree" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "anrry" + } + } + } + } + }, + "/hosts/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "切换分组", + "consumes": [ + "application/json" + ], + "tags": [ + "Host" + ], + "summary": "Update host group", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.ChangeHostGroup" } } ], @@ -5383,13 +5268,22 @@ var doc = `{ } }, "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "name", - "addr" + "BeforeFuntions": [ + { + "db": "hosts", + "input_colume": "id", + "input_value": "id", + "isList": false, + "output_colume": "addr", + "output_value": "addr" + } ], - "formatEN": "update host [name][addr]", - "formatZH": "更新主机信息 [name][addr]", + "bodyKeys": [ + "id", + "group" + ], + "formatEN": "change host [addr] group =\u003e [group]", + "formatZH": "切换主机[addr]分组 =\u003e [group]", "paramKeys": [] } } @@ -5724,6 +5618,50 @@ var doc = `{ } } }, + "/settings/backup/": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "备份系统数据", + "consumes": [ + "application/json" + ], + "tags": [ + "Backup Account" + ], + "summary": "Backup system data", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.CommonBackup" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "type", + "name", + "detailName" + ], + "formatEN": "backup [type] data [name][detailName]", + "formatZH": "备份 [type] 数据 [name][detailName]", + "paramKeys": [] + } + } + }, "/settings/backup/del": { "post": { "security": [ @@ -5902,6 +5840,96 @@ var doc = `{ } } }, + "/settings/backup/recover": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "恢复系统数据", + "consumes": [ + "application/json" + ], + "tags": [ + "Backup Account" + ], + "summary": "Recover system data", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.CommonRecover" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "type", + "name", + "detailName", + "file" + ], + "formatEN": "recover [type] data [name][detailName] from [file]", + "formatZH": "从 [file] 恢复 [type] 数据 [name][detailName]", + "paramKeys": [] + } + } + }, + "/settings/backup/recover/byupload": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "从上传恢复系统数据", + "consumes": [ + "application/json" + ], + "tags": [ + "Backup Account" + ], + "summary": "Recover system data by upload", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.CommonRecover" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "type", + "name", + "detailName", + "file" + ], + "formatEN": "recover [type] data [name][detailName] from [file]", + "formatZH": "从 [file] 恢复 [type] 数据 [name][detailName]", + "paramKeys": [] + } + } + }, "/settings/backup/search": { "get": { "security": [ @@ -7098,57 +7126,6 @@ var doc = `{ } } }, - "/websites/backup": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "备份网站", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Backup website", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteResourceReq" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [ - { - "db": "websites", - "input_colume": "id", - "input_value": "id", - "isList": false, - "output_colume": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Backup website [domain]", - "formatZH": "备份网站 [domain]", - "paramKeys": [] - } - } - }, "/websites/check": { "post": { "security": [ @@ -8033,93 +8010,6 @@ var doc = `{ } } }, - "/websites/recover": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "从备份恢复网站", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Recover website", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteRecover" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "websiteName", - "backupName" - ], - "formatEN": "[websiteName] recover from backups [backupName]", - "formatZH": "[websiteName] 从备份恢复 [backupName]", - "paramKeys": [] - } - } - }, - "/websites/recover/byupload": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "从上传恢复网站", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Recover website by upload", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteRecoverByFile" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "websiteName", - "fileDir", - "fileName" - ], - "formatEN": "[websiteName] recover from uploads [fileDir]/[fileName]", - "formatZH": "[websiteName] 从上传恢复 [fileDir]/[fileName]", - "paramKeys": [] - } - } - }, "/websites/search": { "post": { "security": [ @@ -8565,21 +8455,6 @@ var doc = `{ } }, "definitions": { - "dto.BackupDB": { - "type": "object", - "required": [ - "dbName", - "mysqlName" - ], - "properties": { - "dbName": { - "type": "string" - }, - "mysqlName": { - "type": "string" - } - } - }, "dto.BackupOperate": { "type": "object", "required": [ @@ -8671,6 +8546,21 @@ var doc = `{ } } }, + "dto.ChangeHostGroup": { + "type": "object", + "required": [ + "group", + "id" + ], + "properties": { + "group": { + "type": "string" + }, + "id": { + "type": "integer" + } + } + }, "dto.CleanLog": { "type": "object", "required": [ @@ -8718,6 +8608,55 @@ var doc = `{ } } }, + "dto.CommonBackup": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "detailName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "app", + "mysql", + "redis", + "website" + ] + } + } + }, + "dto.CommonRecover": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "detailName": { + "type": "string" + }, + "file": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "app", + "mysql", + "redis", + "website" + ] + } + } + }, "dto.ComposeCreate": { "type": "object", "required": [ @@ -10183,25 +10122,6 @@ var doc = `{ } } }, - "dto.RecoverDB": { - "type": "object", - "required": [ - "backupName", - "dbName", - "mysqlName" - ], - "properties": { - "backupName": { - "type": "string" - }, - "dbName": { - "type": "string" - }, - "mysqlName": { - "type": "string" - } - } - }, "dto.RedisConf": { "type": "object", "properties": { @@ -10343,6 +10263,27 @@ var doc = `{ } } }, + "dto.SearchHostWithPage": { + "type": "object", + "required": [ + "page", + "pageSize" + ], + "properties": { + "group": { + "type": "string" + }, + "info": { + "type": "string" + }, + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + } + } + }, "dto.SearchLgLogWithPage": { "type": "object", "required": [ @@ -10608,27 +10549,6 @@ var doc = `{ } } }, - "dto.UploadRecover": { - "type": "object", - "required": [ - "dbName", - "mysqlName" - ], - "properties": { - "dbName": { - "type": "string" - }, - "fileDir": { - "type": "string" - }, - "fileName": { - "type": "string" - }, - "mysqlName": { - "type": "string" - } - } - }, "dto.UserLoginInfo": { "type": "object", "properties": { @@ -11565,6 +11485,25 @@ var doc = `{ } } }, + "request.SearchUploadWithPage": { + "type": "object", + "required": [ + "page", + "pageSize", + "path" + ], + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "path": { + "type": "string" + } + } + }, "request.WebsiteAcmeAccountCreate": { "type": "object", "required": [ @@ -11890,48 +11829,6 @@ var doc = `{ } } }, - "request.WebsiteRecover": { - "type": "object", - "required": [ - "backupName", - "type", - "websiteName" - ], - "properties": { - "backupName": { - "type": "string" - }, - "type": { - "type": "string" - }, - "websiteName": { - "type": "string" - } - } - }, - "request.WebsiteRecoverByFile": { - "type": "object", - "required": [ - "fileDir", - "fileName", - "type", - "websiteName" - ], - "properties": { - "fileDir": { - "type": "string" - }, - "fileName": { - "type": "string" - }, - "type": { - "type": "string" - }, - "websiteName": { - "type": "string" - } - } - }, "request.WebsiteResourceReq": { "type": "object", "required": [ diff --git a/cmd/server/docs/swagger.json b/cmd/server/docs/swagger.json index 0bdac1a9d..a3fc60f14 100644 --- a/cmd/server/docs/swagger.json +++ b/cmd/server/docs/swagger.json @@ -3103,49 +3103,6 @@ } } }, - "/databases/backup": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "备份 mysql 数据库", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Backup mysql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.BackupDB" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "mysqlName", - "dbName" - ], - "formatEN": "backup mysql database [mysqlName][dbName]", - "formatZH": "备份 mysql 数据库 [mysqlName][dbName]", - "paramKeys": [] - } - } - }, "/databases/baseinfo": { "get": { "security": [ @@ -3485,121 +3442,6 @@ } } }, - "/databases/recover": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Mysql 数据库恢复", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Recover mysql database", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.RecoverDB" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "mysqlName", - "dbName", - "backupName" - ], - "formatEN": "恢复 mysql 数据库 [mysqlName][dbName] [backupName]", - "formatZH": "恢复 mysql 数据库 [mysqlName][dbName] [backupName]", - "paramKeys": [] - } - } - }, - "/databases/recover/byupload": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "Mysql 数据库从上传文件恢复", - "consumes": [ - "application/json" - ], - "tags": [ - "Database Mysql" - ], - "summary": "Recover mysql database by upload file", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/dto.UploadRecover" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "fileDir", - "fileName", - "mysqlName", - "dbName" - ], - "formatEN": "mysql database recover [fileDir]/[fileName] from [mysqlName][dbName]", - "formatZH": "mysql 数据库从 [fileDir]/[fileName] 恢复 [mysqlName][dbName]", - "paramKeys": [] - } - } - }, - "/databases/redis/backup": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "备份 redis 数据库", - "tags": [ - "Database Redis" - ], - "summary": "Backup redis", - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [], - "formatEN": "backup redis database", - "formatZH": "备份 redis 数据库", - "paramKeys": [] - } - } - }, "/databases/redis/backup/search": { "post": { "security": [ @@ -3840,35 +3682,6 @@ } } }, - "/databases/redis/recover": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "恢复 redis 数据库", - "tags": [ - "Database Redis" - ], - "summary": "Recover redis", - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "fileDir", - "fileName" - ], - "formatEN": "redis database recover from [fileDir]/[fileName]", - "formatZH": "redis 数据库从 [fileDir]/[fileName] 恢复", - "paramKeys": [] - } - } - }, "/databases/redis/status": { "get": { "security": [ @@ -4697,6 +4510,42 @@ } } }, + "/files/upload/search": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "分页获取上传文件", + "consumes": [ + "application/json" + ], + "tags": [ + "File" + ], + "summary": "Page file", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.SearchUploadWithPage" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "anrry" + } + } + } + } + }, "/files/wget": { "post": { "security": [ @@ -5032,7 +4881,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.OperateByID" + "$ref": "#/definitions/dto.BatchDeleteReq" } } ], @@ -5046,17 +4895,17 @@ { "db": "hosts", "input_colume": "id", - "input_value": "id", - "isList": false, + "input_value": "ids", + "isList": true, "output_colume": "addr", - "output_value": "addr" + "output_value": "addrs" } ], "bodyKeys": [ - "id" + "ids" ], - "formatEN": "delete host [addr]", - "formatZH": "删除主机 [addr]", + "formatEN": "delete host [addrs]", + "formatZH": "删除主机 [addrs]", "paramKeys": [] } } @@ -5241,14 +5090,14 @@ "ApiKeyAuth": [] } ], - "description": "加载主机树", + "description": "获取主机列表分页", "consumes": [ "application/json" ], "tags": [ "Host" ], - "summary": "Load host tree", + "summary": "Page host", "parameters": [ { "description": "request", @@ -5256,7 +5105,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.SearchForTree" + "$ref": "#/definitions/dto.SearchHostWithPage" } } ], @@ -5337,21 +5186,21 @@ } } }, - "/hosts/update": { + "/hosts/tree": { "post": { "security": [ { "ApiKeyAuth": [] } ], - "description": "更新主机", + "description": "加载主机树", "consumes": [ "application/json" ], "tags": [ "Host" ], - "summary": "Update host", + "summary": "Load host tree", "parameters": [ { "description": "request", @@ -5359,7 +5208,43 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.HostOperate" + "$ref": "#/definitions/dto.SearchForTree" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "anrry" + } + } + } + } + }, + "/hosts/update": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "切换分组", + "consumes": [ + "application/json" + ], + "tags": [ + "Host" + ], + "summary": "Update host group", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.ChangeHostGroup" } } ], @@ -5369,13 +5254,22 @@ } }, "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "name", - "addr" + "BeforeFuntions": [ + { + "db": "hosts", + "input_colume": "id", + "input_value": "id", + "isList": false, + "output_colume": "addr", + "output_value": "addr" + } ], - "formatEN": "update host [name][addr]", - "formatZH": "更新主机信息 [name][addr]", + "bodyKeys": [ + "id", + "group" + ], + "formatEN": "change host [addr] group =\u003e [group]", + "formatZH": "切换主机[addr]分组 =\u003e [group]", "paramKeys": [] } } @@ -5710,6 +5604,50 @@ } } }, + "/settings/backup/": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "备份系统数据", + "consumes": [ + "application/json" + ], + "tags": [ + "Backup Account" + ], + "summary": "Backup system data", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.CommonBackup" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "type", + "name", + "detailName" + ], + "formatEN": "backup [type] data [name][detailName]", + "formatZH": "备份 [type] 数据 [name][detailName]", + "paramKeys": [] + } + } + }, "/settings/backup/del": { "post": { "security": [ @@ -5888,6 +5826,96 @@ } } }, + "/settings/backup/recover": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "恢复系统数据", + "consumes": [ + "application/json" + ], + "tags": [ + "Backup Account" + ], + "summary": "Recover system data", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.CommonRecover" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "type", + "name", + "detailName", + "file" + ], + "formatEN": "recover [type] data [name][detailName] from [file]", + "formatZH": "从 [file] 恢复 [type] 数据 [name][detailName]", + "paramKeys": [] + } + } + }, + "/settings/backup/recover/byupload": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "从上传恢复系统数据", + "consumes": [ + "application/json" + ], + "tags": [ + "Backup Account" + ], + "summary": "Recover system data by upload", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.CommonRecover" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "x-panel-log": { + "BeforeFuntions": [], + "bodyKeys": [ + "type", + "name", + "detailName", + "file" + ], + "formatEN": "recover [type] data [name][detailName] from [file]", + "formatZH": "从 [file] 恢复 [type] 数据 [name][detailName]", + "paramKeys": [] + } + } + }, "/settings/backup/search": { "get": { "security": [ @@ -7084,57 +7112,6 @@ } } }, - "/websites/backup": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "备份网站", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Backup website", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteResourceReq" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [ - { - "db": "websites", - "input_colume": "id", - "input_value": "id", - "isList": false, - "output_colume": "primary_domain", - "output_value": "domain" - } - ], - "bodyKeys": [ - "id" - ], - "formatEN": "Backup website [domain]", - "formatZH": "备份网站 [domain]", - "paramKeys": [] - } - } - }, "/websites/check": { "post": { "security": [ @@ -8019,93 +7996,6 @@ } } }, - "/websites/recover": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "从备份恢复网站", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Recover website", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteRecover" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "websiteName", - "backupName" - ], - "formatEN": "[websiteName] recover from backups [backupName]", - "formatZH": "[websiteName] 从备份恢复 [backupName]", - "paramKeys": [] - } - } - }, - "/websites/recover/byupload": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "从上传恢复网站", - "consumes": [ - "application/json" - ], - "tags": [ - "Website" - ], - "summary": "Recover website by upload", - "parameters": [ - { - "description": "request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/request.WebsiteRecoverByFile" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "websiteName", - "fileDir", - "fileName" - ], - "formatEN": "[websiteName] recover from uploads [fileDir]/[fileName]", - "formatZH": "[websiteName] 从上传恢复 [fileDir]/[fileName]", - "paramKeys": [] - } - } - }, "/websites/search": { "post": { "security": [ @@ -8551,21 +8441,6 @@ } }, "definitions": { - "dto.BackupDB": { - "type": "object", - "required": [ - "dbName", - "mysqlName" - ], - "properties": { - "dbName": { - "type": "string" - }, - "mysqlName": { - "type": "string" - } - } - }, "dto.BackupOperate": { "type": "object", "required": [ @@ -8657,6 +8532,21 @@ } } }, + "dto.ChangeHostGroup": { + "type": "object", + "required": [ + "group", + "id" + ], + "properties": { + "group": { + "type": "string" + }, + "id": { + "type": "integer" + } + } + }, "dto.CleanLog": { "type": "object", "required": [ @@ -8704,6 +8594,55 @@ } } }, + "dto.CommonBackup": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "detailName": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "app", + "mysql", + "redis", + "website" + ] + } + } + }, + "dto.CommonRecover": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "detailName": { + "type": "string" + }, + "file": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "app", + "mysql", + "redis", + "website" + ] + } + } + }, "dto.ComposeCreate": { "type": "object", "required": [ @@ -10169,25 +10108,6 @@ } } }, - "dto.RecoverDB": { - "type": "object", - "required": [ - "backupName", - "dbName", - "mysqlName" - ], - "properties": { - "backupName": { - "type": "string" - }, - "dbName": { - "type": "string" - }, - "mysqlName": { - "type": "string" - } - } - }, "dto.RedisConf": { "type": "object", "properties": { @@ -10329,6 +10249,27 @@ } } }, + "dto.SearchHostWithPage": { + "type": "object", + "required": [ + "page", + "pageSize" + ], + "properties": { + "group": { + "type": "string" + }, + "info": { + "type": "string" + }, + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + } + } + }, "dto.SearchLgLogWithPage": { "type": "object", "required": [ @@ -10594,27 +10535,6 @@ } } }, - "dto.UploadRecover": { - "type": "object", - "required": [ - "dbName", - "mysqlName" - ], - "properties": { - "dbName": { - "type": "string" - }, - "fileDir": { - "type": "string" - }, - "fileName": { - "type": "string" - }, - "mysqlName": { - "type": "string" - } - } - }, "dto.UserLoginInfo": { "type": "object", "properties": { @@ -11551,6 +11471,25 @@ } } }, + "request.SearchUploadWithPage": { + "type": "object", + "required": [ + "page", + "pageSize", + "path" + ], + "properties": { + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "path": { + "type": "string" + } + } + }, "request.WebsiteAcmeAccountCreate": { "type": "object", "required": [ @@ -11876,48 +11815,6 @@ } } }, - "request.WebsiteRecover": { - "type": "object", - "required": [ - "backupName", - "type", - "websiteName" - ], - "properties": { - "backupName": { - "type": "string" - }, - "type": { - "type": "string" - }, - "websiteName": { - "type": "string" - } - } - }, - "request.WebsiteRecoverByFile": { - "type": "object", - "required": [ - "fileDir", - "fileName", - "type", - "websiteName" - ], - "properties": { - "fileDir": { - "type": "string" - }, - "fileName": { - "type": "string" - }, - "type": { - "type": "string" - }, - "websiteName": { - "type": "string" - } - } - }, "request.WebsiteResourceReq": { "type": "object", "required": [ diff --git a/cmd/server/docs/swagger.yaml b/cmd/server/docs/swagger.yaml index 10dd14d52..27de7219c 100644 --- a/cmd/server/docs/swagger.yaml +++ b/cmd/server/docs/swagger.yaml @@ -1,15 +1,5 @@ basePath: /api/v1 definitions: - dto.BackupDB: - properties: - dbName: - type: string - mysqlName: - type: string - required: - - dbName - - mysqlName - type: object dto.BackupOperate: properties: accessKey: @@ -69,6 +59,16 @@ definitions: required: - value type: object + dto.ChangeHostGroup: + properties: + group: + type: string + id: + type: integer + required: + - group + - id + type: object dto.CleanLog: properties: logType: @@ -100,6 +100,40 @@ definitions: - command - name type: object + dto.CommonBackup: + properties: + detailName: + type: string + name: + type: string + type: + enum: + - app + - mysql + - redis + - website + type: string + required: + - type + type: object + dto.CommonRecover: + properties: + detailName: + type: string + file: + type: string + name: + type: string + type: + enum: + - app + - mysql + - redis + - website + type: string + required: + - type + type: object dto.ComposeCreate: properties: file: @@ -1089,19 +1123,6 @@ definitions: - pageSize - type type: object - dto.RecoverDB: - properties: - backupName: - type: string - dbName: - type: string - mysqlName: - type: string - required: - - backupName - - dbName - - mysqlName - type: object dto.RedisConf: properties: containerName: @@ -1194,6 +1215,20 @@ definitions: info: type: string type: object + dto.SearchHostWithPage: + properties: + group: + type: string + info: + type: string + page: + type: integer + pageSize: + type: integer + required: + - page + - pageSize + type: object dto.SearchLgLogWithPage: properties: ip: @@ -1369,20 +1404,6 @@ definitions: releaseNote: type: string type: object - dto.UploadRecover: - properties: - dbName: - type: string - fileDir: - type: string - fileName: - type: string - mysqlName: - type: string - required: - - dbName - - mysqlName - type: object dto.UserLoginInfo: properties: mfaSecret: @@ -2003,6 +2024,19 @@ definitions: port: type: integer type: object + request.SearchUploadWithPage: + properties: + page: + type: integer + pageSize: + type: integer + path: + type: string + required: + - page + - pageSize + - path + type: object request.WebsiteAcmeAccountCreate: properties: email: @@ -2221,35 +2255,6 @@ definitions: required: - id type: object - request.WebsiteRecover: - properties: - backupName: - type: string - type: - type: string - websiteName: - type: string - required: - - backupName - - type - - websiteName - type: object - request.WebsiteRecoverByFile: - properties: - fileDir: - type: string - fileName: - type: string - type: - type: string - websiteName: - type: string - required: - - fileDir - - fileName - - type - - websiteName - type: object request.WebsiteResourceReq: properties: id: @@ -4593,34 +4598,6 @@ paths: formatEN: create mysql database [name] formatZH: 创建 mysql 数据库 [name] paramKeys: [] - /databases/backup: - post: - consumes: - - application/json - description: 备份 mysql 数据库 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.BackupDB' - responses: - "200": - description: "" - security: - - ApiKeyAuth: [] - summary: Backup mysql database - tags: - - Database Mysql - x-panel-log: - BeforeFuntions: [] - bodyKeys: - - mysqlName - - dbName - formatEN: backup mysql database [mysqlName][dbName] - formatZH: 备份 mysql 数据库 [mysqlName][dbName] - paramKeys: [] /databases/baseinfo: get: description: 获取 mysql 基础信息 @@ -4837,82 +4814,6 @@ paths: summary: List mysql database names tags: - Database Mysql - /databases/recover: - post: - consumes: - - application/json - description: Mysql 数据库恢复 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.RecoverDB' - responses: - "200": - description: "" - security: - - ApiKeyAuth: [] - summary: Recover mysql database - tags: - - Database Mysql - x-panel-log: - BeforeFuntions: [] - bodyKeys: - - mysqlName - - dbName - - backupName - formatEN: 恢复 mysql 数据库 [mysqlName][dbName] [backupName] - formatZH: 恢复 mysql 数据库 [mysqlName][dbName] [backupName] - paramKeys: [] - /databases/recover/byupload: - post: - consumes: - - application/json - description: Mysql 数据库从上传文件恢复 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.UploadRecover' - responses: - "200": - description: "" - security: - - ApiKeyAuth: [] - summary: Recover mysql database by upload file - tags: - - Database Mysql - x-panel-log: - BeforeFuntions: [] - bodyKeys: - - fileDir - - fileName - - mysqlName - - dbName - formatEN: mysql database recover [fileDir]/[fileName] from [mysqlName][dbName] - formatZH: mysql 数据库从 [fileDir]/[fileName] 恢复 [mysqlName][dbName] - paramKeys: [] - /databases/redis/backup: - post: - description: 备份 redis 数据库 - responses: - "200": - description: "" - security: - - ApiKeyAuth: [] - summary: Backup redis - tags: - - Database Redis - x-panel-log: - BeforeFuntions: [] - bodyKeys: [] - formatEN: backup redis database - formatZH: 备份 redis 数据库 - paramKeys: [] /databases/redis/backup/search: post: consumes: @@ -5065,25 +4966,6 @@ paths: formatEN: redis database persistence configuration update formatZH: redis 数据库持久化配置更新 paramKeys: [] - /databases/redis/recover: - post: - description: 恢复 redis 数据库 - responses: - "200": - description: "" - security: - - ApiKeyAuth: [] - summary: Recover redis - tags: - - Database Redis - x-panel-log: - BeforeFuntions: [] - bodyKeys: - - fileDir - - fileName - formatEN: redis database recover from [fileDir]/[fileName] - formatZH: redis 数据库从 [fileDir]/[fileName] 恢复 - paramKeys: [] /databases/redis/status: get: description: 获取 redis 状态信息 @@ -5610,6 +5492,28 @@ paths: formatEN: Upload file [path] formatZH: 上传文件 [path] paramKeys: [] + /files/upload/search: + post: + consumes: + - application/json + description: 分页获取上传文件 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/request.SearchUploadWithPage' + responses: + "200": + description: OK + schema: + type: anrry + security: + - ApiKeyAuth: [] + summary: Page file + tags: + - File /files/wget: post: consumes: @@ -5821,7 +5725,7 @@ paths: name: request required: true schema: - $ref: '#/definitions/dto.OperateByID' + $ref: '#/definitions/dto.BatchDeleteReq' responses: "200": description: "" @@ -5834,14 +5738,14 @@ paths: BeforeFuntions: - db: hosts input_colume: id - input_value: id - isList: false + input_value: ids + isList: true output_colume: addr - output_value: addr + output_value: addrs bodyKeys: - - id - formatEN: delete host [addr] - formatZH: 删除主机 [addr] + - ids + formatEN: delete host [addrs] + formatZH: 删除主机 [addrs] paramKeys: [] /hosts/group: post: @@ -5958,14 +5862,14 @@ paths: post: consumes: - application/json - description: 加载主机树 + description: 获取主机列表分页 parameters: - description: request in: body name: request required: true schema: - $ref: '#/definitions/dto.SearchForTree' + $ref: '#/definitions/dto.SearchHostWithPage' responses: "200": description: OK @@ -5973,7 +5877,7 @@ paths: type: anrry security: - ApiKeyAuth: [] - summary: Load host tree + summary: Page host tags: - Host /hosts/test/byid/:id: @@ -6017,33 +5921,61 @@ paths: summary: Test host conn by info tags: - Host - /hosts/update: + /hosts/tree: post: consumes: - application/json - description: 更新主机 + description: 加载主机树 parameters: - description: request in: body name: request required: true schema: - $ref: '#/definitions/dto.HostOperate' + $ref: '#/definitions/dto.SearchForTree' + responses: + "200": + description: OK + schema: + type: anrry + security: + - ApiKeyAuth: [] + summary: Load host tree + tags: + - Host + /hosts/update: + post: + consumes: + - application/json + description: 切换分组 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.ChangeHostGroup' responses: "200": description: "" security: - ApiKeyAuth: [] - summary: Update host + summary: Update host group tags: - Host x-panel-log: - BeforeFuntions: [] + BeforeFuntions: + - db: hosts + input_colume: id + input_value: id + isList: false + output_colume: addr + output_value: addr bodyKeys: - - name - - addr - formatEN: update host [name][addr] - formatZH: 更新主机信息 [name][addr] + - id + - group + formatEN: change host [addr] group => [group] + formatZH: 切换主机[addr]分组 => [group] paramKeys: [] /logs/clean: post: @@ -6252,6 +6184,35 @@ paths: formatEN: create backup account [type] formatZH: 创建备份账号 [type] paramKeys: [] + /settings/backup/: + post: + consumes: + - application/json + description: 备份系统数据 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.CommonBackup' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Backup system data + tags: + - Backup Account + x-panel-log: + BeforeFuntions: [] + bodyKeys: + - type + - name + - detailName + formatEN: backup [type] data [name][detailName] + formatZH: 备份 [type] 数据 [name][detailName] + paramKeys: [] /settings/backup/del: post: consumes: @@ -6366,6 +6327,66 @@ paths: summary: Page backup records tags: - Backup Account + /settings/backup/recover: + post: + consumes: + - application/json + description: 恢复系统数据 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.CommonRecover' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Recover system data + tags: + - Backup Account + x-panel-log: + BeforeFuntions: [] + bodyKeys: + - type + - name + - detailName + - file + formatEN: recover [type] data [name][detailName] from [file] + formatZH: 从 [file] 恢复 [type] 数据 [name][detailName] + paramKeys: [] + /settings/backup/recover/byupload: + post: + consumes: + - application/json + description: 从上传恢复系统数据 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.CommonRecover' + responses: + "200": + description: "" + security: + - ApiKeyAuth: [] + summary: Recover system data by upload + tags: + - Backup Account + x-panel-log: + BeforeFuntions: [] + bodyKeys: + - type + - name + - detailName + - file + formatEN: recover [type] data [name][detailName] from [file] + formatZH: 从 [file] 恢复 [type] 数据 [name][detailName] + paramKeys: [] /settings/backup/search: get: description: 获取备份账号列表 @@ -7126,39 +7147,6 @@ paths: summary: Page website acme accounts tags: - Website Acme - /websites/backup: - post: - consumes: - - application/json - description: 备份网站 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteResourceReq' - responses: - "200": - description: "" - security: - - ApiKeyAuth: [] - summary: Backup website - tags: - - Website - x-panel-log: - BeforeFuntions: - - db: websites - input_colume: id - input_value: id - isList: false - output_colume: primary_domain - output_value: domain - bodyKeys: - - id - formatEN: Backup website [domain] - formatZH: 备份网站 [domain] - paramKeys: [] /websites/check: post: consumes: @@ -7723,63 +7711,6 @@ paths: summary: List website names tags: - Website - /websites/recover: - post: - consumes: - - application/json - description: 从备份恢复网站 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteRecover' - responses: - "200": - description: "" - security: - - ApiKeyAuth: [] - summary: Recover website - tags: - - Website - x-panel-log: - BeforeFuntions: [] - bodyKeys: - - websiteName - - backupName - formatEN: '[websiteName] recover from backups [backupName]' - formatZH: '[websiteName] 从备份恢复 [backupName]' - paramKeys: [] - /websites/recover/byupload: - post: - consumes: - - application/json - description: 从上传恢复网站 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/request.WebsiteRecoverByFile' - responses: - "200": - description: "" - security: - - ApiKeyAuth: [] - summary: Recover website by upload - tags: - - Website - x-panel-log: - BeforeFuntions: [] - bodyKeys: - - websiteName - - fileDir - - fileName - formatEN: '[websiteName] recover from uploads [fileDir]/[fileName]' - formatZH: '[websiteName] 从上传恢复 [fileDir]/[fileName]' - paramKeys: [] /websites/search: post: consumes: diff --git a/frontend/components.d.ts b/frontend/components.d.ts index 5ba5ae001..cad4b1ef6 100644 --- a/frontend/components.d.ts +++ b/frontend/components.d.ts @@ -83,6 +83,7 @@ declare module 'vue' { SubItem: typeof import('./src/components/app-layout/menu/components/sub-item.vue')['default'] SvgIcon: typeof import('./src/components/svg-icon/svg-icon.vue')['default'] TableSetting: typeof import('./src/components/table-setting/index.vue')['default'] + Upload: typeof import('./src/components/upload/index.vue')['default'] } } diff --git a/frontend/src/api/interface/app.ts b/frontend/src/api/interface/app.ts index 2f36cf2cf..279cca192 100644 --- a/frontend/src/api/interface/app.ts +++ b/frontend/src/api/interface/app.ts @@ -126,21 +126,6 @@ export namespace App { config?: Object; } - export interface AppBackupReq extends ReqPage { - appInstallId: number; - } - - export interface AppBackupDelReq { - ids: number[]; - } - - export interface AppBackup extends CommonModel { - name: string; - path: string; - appInstallId: string; - appDetail: AppDetail; - } - export interface VersionDetail { version: string; detailId: number; diff --git a/frontend/src/api/interface/database.ts b/frontend/src/api/interface/database.ts index ad8247a85..51cd0c7af 100644 --- a/frontend/src/api/interface/database.ts +++ b/frontend/src/api/interface/database.ts @@ -5,17 +5,6 @@ export namespace Database { mysqlName: string; dbName: string; } - export interface Recover { - mysqlName: string; - dbName: string; - backupName: string; - } - export interface RecoverByUpload { - mysqlName: string; - dbName: string; - fileName: string; - fileDir: string; - } export interface MysqlDBInfo { id: number; createdAt: Date; diff --git a/frontend/src/api/interface/file.ts b/frontend/src/api/interface/file.ts index 8724c9d2c..a8e26cdd9 100644 --- a/frontend/src/api/interface/file.ts +++ b/frontend/src/api/interface/file.ts @@ -30,6 +30,15 @@ export namespace File { containSub?: boolean; } + export interface SearchUploadInfo extends ReqPage { + path: string; + } + export interface UploadInfo { + name: string; + size: number; + createdAt: string; + } + export interface FileTree { id: string; name: string; diff --git a/frontend/src/api/interface/website.ts b/frontend/src/api/interface/website.ts index 92b75595d..b290abc56 100644 --- a/frontend/src/api/interface/website.ts +++ b/frontend/src/api/interface/website.ts @@ -34,18 +34,6 @@ export namespace Website { websiteGroupId: number; } - export interface WebSiteRecover { - websiteName: string; - type: string; - backupName: string; - } - export interface WebsiteRecoverByUpload { - websiteName: string; - type: string; - fileDir: string; - fileName: string; - } - export interface WebSiteDel { id: number; deleteApp: boolean; @@ -267,10 +255,6 @@ export namespace Website { id: number; } - export interface BackupReq { - id: number; - } - export interface NginxUpdate { id: number; content: string; diff --git a/frontend/src/api/modules/app.ts b/frontend/src/api/modules/app.ts index f6324f259..caef4ed69 100644 --- a/frontend/src/api/modules/app.ts +++ b/frontend/src/api/modules/app.ts @@ -66,14 +66,6 @@ export const GetAppService = (key: string | undefined) => { return http.get(`apps/services/${key}`); }; -export const GetAppBackups = (info: App.AppBackupReq) => { - return http.post>('apps/installed/backups', info); -}; - -export const DelAppBackups = (req: App.AppBackupDelReq) => { - return http.post('apps/installed/backups/del', req); -}; - export const GetAppUpdateVersions = (id: number) => { return http.get(`apps/installed/${id}/versions`); }; diff --git a/frontend/src/api/modules/files.ts b/frontend/src/api/modules/files.ts index 6a58f7eed..ea7b67447 100644 --- a/frontend/src/api/modules/files.ts +++ b/frontend/src/api/modules/files.ts @@ -1,11 +1,16 @@ import { File } from '@/api/interface/file'; import http from '@/api'; import { AxiosRequestConfig } from 'axios'; +import { ResPage } from '../interface'; export const GetFilesList = (params: File.ReqFile) => { return http.post('files/search', params, 200000); }; +export const GetUploadList = (params: File.SearchUploadInfo) => { + return http.post>('files/upload/search', params); +}; + export const GetFilesTree = (params: File.ReqFile) => { return http.post('files/tree', params); }; diff --git a/frontend/src/components/backup/index.vue b/frontend/src/components/backup/index.vue index cd4ae0e93..5bf341dbe 100644 --- a/frontend/src/components/backup/index.vue +++ b/frontend/src/components/backup/index.vue @@ -27,7 +27,9 @@ - + + + +
+ + +
+ + +
+ {{ $t('database.dropHelper') }} + {{ $t('database.clickHelper') }} +
+ +
+ + {{ $t('commons.button.upload') }} + + + + + + + + + + + + + + + +
+
+
+ + + diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 48b4cbf02..6153b36cb 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -922,8 +922,9 @@ export default { type: 'Type', static: 'Static', deployment: 'Deployment', - supportUpType: 'Only support tar.gz files', - zipFormat: 'tar.gz compressed package structure: test.tar.gz compressed package must contain website.json file', + supportUpType: 'Only .tar.gz files within 50 MB are supported', + zipFormat: + '.tar.gz compressed package structure: test.tar.gz compressed package must contain website.json file', proxy: 'Reverse Proxy', alias: 'Path Name', remark: 'Remark', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 86655da19..7e4035635 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -296,6 +296,8 @@ export default { unSupportType: '不支持当前文件类型!', unSupportSize: '上传文件超过 10M,请确认!', selectFile: '选择文件', + dropHelper: '将上传文件拖拽到此处,或者', + clickHelper: '点击上传', supportUpType: '仅支持 10M 以内 sql、zip、sql.gz、(tar.gz gz tgz) 文件', zipFormat: 'zip、tar.gz 压缩包结构:test.zip 或 test.tar.gz 压缩包内,必需包含 test.sql', @@ -930,8 +932,8 @@ export default { type: '类型', static: '静态网站', deployment: '一键部署', - supportUpType: '仅支持 tar.gz 文件', - zipFormat: 'tar.gz 压缩包结构:test.tar.gz 压缩包内,必需包含 website.json 文件', + supportUpType: '仅支持 50M 以内 .tar.gz 文件', + zipFormat: '.tar.gz 压缩包结构:test.tar.gz 压缩包内,必需包含 website.json 文件', proxy: '反向代理', alias: '代号', remark: '备注', diff --git a/frontend/src/views/app-store/installed/index.vue b/frontend/src/views/app-store/installed/index.vue index 73626f59f..97a4ec65a 100644 --- a/frontend/src/views/app-store/installed/index.vue +++ b/frontend/src/views/app-store/installed/index.vue @@ -89,6 +89,17 @@ + + {{ $t('database.loadBackup') }} + + @@ -164,6 +176,7 @@ import { onMounted, onUnmounted, reactive, ref } from 'vue'; import i18n from '@/lang'; import { ElMessageBox } from 'element-plus'; import Backups from '@/components/backup/index.vue'; +import Uploads from '@/components/upload/index.vue'; import AppResources from './check/index.vue'; import AppDelete from './delete/index.vue'; import AppParams from './detail/index.vue'; @@ -189,6 +202,7 @@ let operateReq = reactive({ detailId: 0, }); const backupRef = ref(); +const uploadRef = ref(); const checkRef = ref(); const deleteRef = ref(); const appParamRef = ref(); @@ -350,6 +364,15 @@ const openBackups = (key: string, name: string) => { backupRef.value.acceptParams(params); }; +const openUploads = (key: string, name: string) => { + let params = { + type: 'app', + name: key, + detailName: name, + }; + uploadRef.value.acceptParams(params); +}; + const openParam = (installId: number) => { appParamRef.value.acceptParams({ id: installId }); }; diff --git a/frontend/src/views/database/mysql/index.vue b/frontend/src/views/database/mysql/index.vue index 3ffee0009..0f9cb0199 100644 --- a/frontend/src/views/database/mysql/index.vue +++ b/frontend/src/views/database/mysql/index.vue @@ -155,11 +155,11 @@ import DeleteDialog from '@/views/database/mysql/delete/index.vue'; import PasswordDialog from '@/views/database/mysql/password/index.vue'; import RootPasswordDialog from '@/views/database/mysql/root-password/index.vue'; import RemoteAccessDialog from '@/views/database/mysql/remote/index.vue'; -import UploadDialog from '@/views/database/mysql/upload/index.vue'; import AppResources from '@/views/database/mysql/check/index.vue'; import Setting from '@/views/database/mysql/setting/index.vue'; import AppStatus from '@/components/app-status/index.vue'; import Backups from '@/components/backup/index.vue'; +import UploadDialog from '@/components/upload/index.vue'; import { dateFormat } from '@/utils/util'; import { reactive, ref } from 'vue'; import { deleteCheckMysqlDB, loadRemoteAccess, searchMysqlDBs, updateMysqlDescription } from '@/api/modules/database'; @@ -350,8 +350,9 @@ const buttons = [ label: i18n.global.t('database.loadBackup'), click: (row: Database.MysqlDBInfo) => { let params = { - mysqlName: mysqlName.value, - dbName: row.name, + type: 'mysql', + name: mysqlName.value, + detailName: row.name, }; uploadRef.value!.acceptParams(params); }, diff --git a/frontend/src/views/database/mysql/upload/index.vue b/frontend/src/views/database/mysql/upload/index.vue deleted file mode 100644 index beee2815e..000000000 --- a/frontend/src/views/database/mysql/upload/index.vue +++ /dev/null @@ -1,210 +0,0 @@ - - - diff --git a/frontend/src/views/host/file-management/upload/index.vue b/frontend/src/views/host/file-management/upload/index.vue index 6e44a4515..ba2d4c957 100644 --- a/frontend/src/views/host/file-management/upload/index.vue +++ b/frontend/src/views/host/file-management/upload/index.vue @@ -1,30 +1,40 @@