From 9d0eca723c299237d91772b338fa3c4890382eb0 Mon Sep 17 00:00:00 2001 From: ssongliu <73214554+ssongliu@users.noreply.github.com> Date: Sun, 8 Oct 2023 14:52:14 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=BF=9C=E7=A8=8B=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93=E5=A2=9E=E5=8A=A0=E5=88=A0=E9=99=A4=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=20(#2454)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/v1/database.go | 41 ++++++-- backend/app/dto/database.go | 6 ++ backend/app/service/database.go | 45 ++++++++- backend/router/ro_database.go | 1 + cmd/server/docs/docs.go | 61 +++++++++++- cmd/server/docs/swagger.json | 61 +++++++++++- cmd/server/docs/swagger.yaml | 39 +++++++- frontend/src/api/interface/database.ts | 5 + frontend/src/api/modules/database.ts | 7 +- frontend/src/lang/modules/en.ts | 1 + frontend/src/lang/modules/tw.ts | 1 + frontend/src/lang/modules/zh.ts | 1 + .../src/views/database/mysql/delete/index.vue | 2 +- .../database/mysql/remote/delete/index.vue | 95 +++++++++++++++++++ .../src/views/database/mysql/remote/index.vue | 22 ++++- 15 files changed, 365 insertions(+), 23 deletions(-) create mode 100644 frontend/src/views/database/mysql/remote/delete/index.vue diff --git a/backend/app/api/v1/database.go b/backend/app/api/v1/database.go index fecfca06e..5cc30f96d 100644 --- a/backend/app/api/v1/database.go +++ b/backend/app/api/v1/database.go @@ -126,15 +126,14 @@ func (b *BaseApi) GetDatabase(c *gin.Context) { } // @Tags Database -// @Summary Delete database -// @Description 删除远程数据库 +// @Summary Check before delete remote database +// @Description Mysql 远程数据库删除前检查 // @Accept json // @Param request body dto.OperateByID true "request" -// @Success 200 +// @Success 200 {array} string // @Security ApiKeyAuth -// @Router /databases/db/del [post] -// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"databases","output_column":"name","output_value":"names"}],"formatZH":"删除远程数据库 [names]","formatEN":"delete database [names]"} -func (b *BaseApi) DeleteDatabase(c *gin.Context) { +// @Router /db/remote/del/check [post] +func (b *BaseApi) DeleteCheckDatabase(c *gin.Context) { var req dto.OperateByID if err := c.ShouldBindJSON(&req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) @@ -145,7 +144,35 @@ func (b *BaseApi) DeleteDatabase(c *gin.Context) { return } - if err := databaseService.Delete(req.ID); err != nil { + apps, err := databaseService.DeleteCheck(req.ID) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, apps) +} + +// @Tags Database +// @Summary Delete database +// @Description 删除远程数据库 +// @Accept json +// @Param request body dto.DatabaseDelete true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /databases/db/del [post] +// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"databases","output_column":"name","output_value":"names"}],"formatZH":"删除远程数据库 [names]","formatEN":"delete database [names]"} +func (b *BaseApi) DeleteDatabase(c *gin.Context) { + var req dto.DatabaseDelete + 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 + } + + if err := databaseService.Delete(req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } diff --git a/backend/app/dto/database.go b/backend/app/dto/database.go index 6687debba..50e5d058d 100644 --- a/backend/app/dto/database.go +++ b/backend/app/dto/database.go @@ -271,3 +271,9 @@ type DatabaseUpdate struct { Password string `json:"password" validate:"required"` Description string `json:"description"` } + +type DatabaseDelete struct { + ID uint `json:"id" validate:"required"` + ForceDelete bool `json:"forceDelete"` + DeleteBackup bool `json:"deleteBackup"` +} diff --git a/backend/app/service/database.go b/backend/app/service/database.go index e7f2e6f8b..60f4125f1 100644 --- a/backend/app/service/database.go +++ b/backend/app/service/database.go @@ -3,10 +3,13 @@ package service import ( "context" "fmt" + "os" + "path" "github.com/1Panel-dev/1Panel/backend/app/dto" "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/encrypt" "github.com/1Panel-dev/1Panel/backend/utils/mysql" "github.com/1Panel-dev/1Panel/backend/utils/mysql/client" @@ -22,7 +25,8 @@ type IDatabaseService interface { CheckDatabase(req dto.DatabaseCreate) bool Create(req dto.DatabaseCreate) error Update(req dto.DatabaseUpdate) error - Delete(id uint) error + DeleteCheck(id uint) ([]string, error) + Delete(req dto.DatabaseDelete) error List(dbType string) ([]dto.DatabaseOption, error) } @@ -114,16 +118,47 @@ func (u *DatabaseService) Create(req dto.DatabaseCreate) error { return nil } -func (u *DatabaseService) Delete(id uint) error { - db, _ := databaseRepo.Get(commonRepo.WithByID(id)) +func (u *DatabaseService) DeleteCheck(id uint) ([]string, error) { + var appInUsed []string + apps, _ := appInstallResourceRepo.GetBy(databaseRepo.WithByFrom("remote"), appInstallResourceRepo.WithLinkId(id)) + for _, app := range apps { + appInstall, _ := appInstallRepo.GetFirst(commonRepo.WithByID(app.AppInstallId)) + if appInstall.ID != 0 { + appInUsed = append(appInUsed, appInstall.Name) + } + } + + return appInUsed, nil +} + +func (u *DatabaseService) Delete(req dto.DatabaseDelete) error { + db, _ := databaseRepo.Get(commonRepo.WithByID(req.ID)) if db.ID == 0 { return constant.ErrRecordNotFound } - if err := databaseRepo.Delete(context.Background(), commonRepo.WithByID(id)); err != nil { + + if req.DeleteBackup { + uploadDir := path.Join(global.CONF.System.BaseDir, fmt.Sprintf("1panel/uploads/database/%s/%s", db.Type, db.Name)) + if _, err := os.Stat(uploadDir); err == nil { + _ = os.RemoveAll(uploadDir) + } + localDir, err := loadLocalDir() + if err != nil && !req.ForceDelete { + return err + } + backupDir := path.Join(localDir, fmt.Sprintf("database/%s/%s", db.Type, db.Name)) + if _, err := os.Stat(backupDir); err == nil { + _ = os.RemoveAll(backupDir) + } + _ = backupRepo.DeleteRecord(context.Background(), commonRepo.WithByType(db.Type), commonRepo.WithByName(db.Name)) + global.LOG.Infof("delete database %s-%s backups successful", db.Type, db.Name) + } + + if err := databaseRepo.Delete(context.Background(), commonRepo.WithByID(req.ID)); err != nil && !req.ForceDelete { return err } if db.From != "local" { - if err := mysqlRepo.Delete(context.Background(), mysqlRepo.WithByMysqlName(db.Name)); err != nil { + if err := mysqlRepo.Delete(context.Background(), mysqlRepo.WithByMysqlName(db.Name)); err != nil && !req.ForceDelete { return err } } diff --git a/backend/router/ro_database.go b/backend/router/ro_database.go index 518077ca9..6f149307b 100644 --- a/backend/router/ro_database.go +++ b/backend/router/ro_database.go @@ -49,6 +49,7 @@ func (s *DatabaseRouter) InitDatabaseRouter(Router *gin.RouterGroup) { cmdRouter.GET("/db/list/:type", baseApi.ListDatabase) cmdRouter.POST("/db/update", baseApi.UpdateDatabase) cmdRouter.POST("/db/search", baseApi.SearchDatabase) + cmdRouter.POST("/db/del/check", baseApi.DeleteCheckDatabase) cmdRouter.POST("/db/del", baseApi.DeleteDatabase) } } diff --git a/cmd/server/docs/docs.go b/cmd/server/docs/docs.go index c01f0e45d..995d2103e 100644 --- a/cmd/server/docs/docs.go +++ b/cmd/server/docs/docs.go @@ -4068,7 +4068,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.OperateByID" + "$ref": "#/definitions/dto.DatabaseDelete" } } ], @@ -4889,6 +4889,45 @@ const docTemplate = `{ } } }, + "/db/remote/del/check": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Mysql 远程数据库删除前检查", + "consumes": [ + "application/json" + ], + "tags": [ + "Database" + ], + "summary": "Check before delete remote database", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperateByID" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, "/files": { "post": { "security": [ @@ -13117,6 +13156,23 @@ const docTemplate = `{ } } }, + "dto.DatabaseDelete": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "deleteBackup": { + "type": "boolean" + }, + "forceDelete": { + "type": "boolean" + }, + "id": { + "type": "integer" + } + } + }, "dto.DatabaseInfo": { "type": "object", "properties": { @@ -17729,6 +17785,9 @@ const docTemplate = `{ "type": "object", "properties": { "config": {}, + "from": { + "type": "string" + }, "label": { "type": "string" }, diff --git a/cmd/server/docs/swagger.json b/cmd/server/docs/swagger.json index 3e948c7d1..63ba15e56 100644 --- a/cmd/server/docs/swagger.json +++ b/cmd/server/docs/swagger.json @@ -4061,7 +4061,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.OperateByID" + "$ref": "#/definitions/dto.DatabaseDelete" } } ], @@ -4882,6 +4882,45 @@ } } }, + "/db/remote/del/check": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "Mysql 远程数据库删除前检查", + "consumes": [ + "application/json" + ], + "tags": [ + "Database" + ], + "summary": "Check before delete remote database", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperateByID" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, "/files": { "post": { "security": [ @@ -13110,6 +13149,23 @@ } } }, + "dto.DatabaseDelete": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "deleteBackup": { + "type": "boolean" + }, + "forceDelete": { + "type": "boolean" + }, + "id": { + "type": "integer" + } + } + }, "dto.DatabaseInfo": { "type": "object", "properties": { @@ -17722,6 +17778,9 @@ "type": "object", "properties": { "config": {}, + "from": { + "type": "string" + }, "label": { "type": "string" }, diff --git a/cmd/server/docs/swagger.yaml b/cmd/server/docs/swagger.yaml index 011ef614c..388261960 100644 --- a/cmd/server/docs/swagger.yaml +++ b/cmd/server/docs/swagger.yaml @@ -786,6 +786,17 @@ definitions: - username - version type: object + dto.DatabaseDelete: + properties: + deleteBackup: + type: boolean + forceDelete: + type: boolean + id: + type: integer + required: + - id + type: object dto.DatabaseInfo: properties: address: @@ -3879,6 +3890,8 @@ definitions: response.AppService: properties: config: {} + from: + type: string label: type: string value: @@ -6716,7 +6729,7 @@ paths: name: request required: true schema: - $ref: '#/definitions/dto.OperateByID' + $ref: '#/definitions/dto.DatabaseDelete' responses: "200": description: OK @@ -7234,6 +7247,30 @@ paths: formatEN: adjust mysql database performance parameters formatZH: 调整 mysql 数据库性能参数 paramKeys: [] + /db/remote/del/check: + post: + consumes: + - application/json + description: Mysql 远程数据库删除前检查 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.OperateByID' + responses: + "200": + description: OK + schema: + items: + type: string + type: array + security: + - ApiKeyAuth: [] + summary: Check before delete remote database + tags: + - Database /files: post: consumes: diff --git a/frontend/src/api/interface/database.ts b/frontend/src/api/interface/database.ts index c94203187..47fda5ed2 100644 --- a/frontend/src/api/interface/database.ts +++ b/frontend/src/api/interface/database.ts @@ -250,4 +250,9 @@ export namespace Database { password: string; description: string; } + export interface DatabaseDelete { + id: number; + forceDelete: boolean; + deleteBackup: boolean; + } } diff --git a/frontend/src/api/modules/database.ts b/frontend/src/api/modules/database.ts index 363c308d8..b8bec3fea 100644 --- a/frontend/src/api/modules/database.ts +++ b/frontend/src/api/modules/database.ts @@ -109,6 +109,9 @@ export const addDatabase = (params: Database.DatabaseCreate) => { export const editDatabase = (params: Database.DatabaseUpdate) => { return http.post(`/databases/db/update`, params, TimeoutEnum.T_40S); }; -export const deleteDatabase = (id: number) => { - return http.post(`/databases/db/del`, { id: id }); +export const deleteCheckDatabase = (id: number) => { + return http.post>(`/databases/db/del/check`, { id: id }); +}; +export const deleteDatabase = (params: Database.DatabaseDelete) => { + return http.post(`/databases/db/del`, params); }; diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 77e358567..1cc668a61 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -327,6 +327,7 @@ const message = { }, database: { database: 'database', + deleteBackupHelper: 'Delete database backups simultaneously', delete: 'Delete operation cannot be rolled back, please input "', deleteHelper: '" to delete this database', create: 'Create database', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index 350d5396a..187e74af8 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -323,6 +323,7 @@ const message = { }, database: { database: '數據庫', + deleteBackupHelper: '同時刪除數據庫備份', delete: '刪除操作無法回滾,請輸入 "', deleteHelper: '" 刪除此數據庫', create: '創建數據庫', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 6d3aac672..33af9a461 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -323,6 +323,7 @@ const message = { }, database: { database: '数据库', + deleteBackupHelper: '同时删除数据库备份', delete: '删除操作无法回滚,请输入 "', deleteHelper: '" 删除此数据库', create: '创建数据库', diff --git a/frontend/src/views/database/mysql/delete/index.vue b/frontend/src/views/database/mysql/delete/index.vue index dd71f064e..1d5d39565 100644 --- a/frontend/src/views/database/mysql/delete/index.vue +++ b/frontend/src/views/database/mysql/delete/index.vue @@ -15,7 +15,7 @@ - {{ $t('app.deleteBackupHelper') }} + {{ $t('database.deleteBackupHelper') }} diff --git a/frontend/src/views/database/mysql/remote/delete/index.vue b/frontend/src/views/database/mysql/remote/delete/index.vue new file mode 100644 index 000000000..10904f6a9 --- /dev/null +++ b/frontend/src/views/database/mysql/remote/delete/index.vue @@ -0,0 +1,95 @@ + + diff --git a/frontend/src/views/database/mysql/remote/index.vue b/frontend/src/views/database/mysql/remote/index.vue index c1b337826..06150ab3b 100644 --- a/frontend/src/views/database/mysql/remote/index.vue +++ b/frontend/src/views/database/mysql/remote/index.vue @@ -84,25 +84,30 @@ + +