diff --git a/backend/app/api/v1/app_install.go b/backend/app/api/v1/app_install.go index dd8256143..6675d801f 100644 --- a/backend/app/api/v1/app_install.go +++ b/backend/app/api/v1/app_install.go @@ -1,7 +1,6 @@ package v1 import ( - "errors" "reflect" "github.com/1Panel-dev/1Panel/backend/app/dto/request" @@ -67,17 +66,21 @@ func (b *BaseApi) ListAppInstalled(c *gin.Context) { // @Summary Check app installed // @Description 检查应用安装情况 // @Accept json -// @Param key path string true "request" +// @Param request body request.AppInstalledInfo true "request" // @Success 200 {object} response.AppInstalledCheck // @Security ApiKeyAuth -// @Router /apps/installed/check/:key [get] +// @Router /apps/installed/check [post] func (b *BaseApi) CheckAppInstalled(c *gin.Context) { - key, ok := c.Params.Get("key") - if !ok { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error key in path")) + var req request.AppInstalledInfo + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - checkData, err := appInstallService.CheckExist(key) + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + checkData, err := appInstallService.CheckExist(req) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -89,17 +92,17 @@ func (b *BaseApi) CheckAppInstalled(c *gin.Context) { // @Summary Search app port by key // @Description 获取应用端口 // @Accept json -// @Param key path string true "request" +// @Param request body dto.OperationWithNameAndType true "request" // @Success 200 {integer} port // @Security ApiKeyAuth -// @Router /apps/installed/loadport/:key [get] +// @Router /apps/installed/loadport [post] func (b *BaseApi) LoadPort(c *gin.Context) { - key, ok := c.Params.Get("key") - if !ok { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error key in path")) + var req dto.OperationWithNameAndType + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - port, err := appInstallService.LoadPort(key) + port, err := appInstallService.LoadPort(req) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -111,17 +114,17 @@ func (b *BaseApi) LoadPort(c *gin.Context) { // @Summary Search app password by key // @Description 获取应用连接信息 // @Accept json -// @Param key path string true "request" +// @Param request body dto.OperationWithNameAndType true "request" // @Success 200 {string} response.DatabaseConn // @Security ApiKeyAuth // @Router /apps/installed/conninfo/:key [get] func (b *BaseApi) LoadConnInfo(c *gin.Context) { - key, ok := c.Params.Get("key") - if !ok { - helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error key in path")) + var req dto.OperationWithNameAndType + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - conn, err := appInstallService.LoadConnInfo(key) + conn, err := appInstallService.LoadConnInfo(req) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return diff --git a/backend/app/api/v1/backup.go b/backend/app/api/v1/backup.go index d9853b5f5..aec5ceed8 100644 --- a/backend/app/api/v1/backup.go +++ b/backend/app/api/v1/backup.go @@ -335,7 +335,7 @@ func (b *BaseApi) Backup(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } - case "mysql": + case "mysql", "mariadb": if err := backupService.MysqlBackup(req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -383,7 +383,7 @@ func (b *BaseApi) Recover(c *gin.Context) { req.File = downloadPath } switch req.Type { - case "mysql": + case "mysql", "mariadb": if err := backupService.MysqlRecover(req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -428,7 +428,7 @@ func (b *BaseApi) RecoverByUpload(c *gin.Context) { } switch req.Type { - case "mysql": + case "mysql", "mariadb": if err := backupService.MysqlRecoverByUpload(req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return diff --git a/backend/app/api/v1/remote_db.go b/backend/app/api/v1/database.go similarity index 81% rename from backend/app/api/v1/remote_db.go rename to backend/app/api/v1/database.go index e0b2f046e..b28c1817f 100644 --- a/backend/app/api/v1/remote_db.go +++ b/backend/app/api/v1/database.go @@ -12,13 +12,13 @@ import ( // @Summary Create remote database // @Description 创建远程数据库 // @Accept json -// @Param request body dto.RemoteDBCreate true "request" +// @Param request body dto.DatabaseCreate true "request" // @Success 200 // @Security ApiKeyAuth // @Router /databases/remote [post] // @x-panel-log {"bodyKeys":["name", "type"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"创建远程数据库 [name][type]","formatEN":"create remote database [name][type]"} -func (b *BaseApi) CreateRemoteDB(c *gin.Context) { - var req dto.RemoteDBCreate +func (b *BaseApi) CreateDatabase(c *gin.Context) { + var req dto.DatabaseCreate if err := c.ShouldBindJSON(&req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return @@ -27,7 +27,7 @@ func (b *BaseApi) CreateRemoteDB(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - if err := remoteDBService.Create(req); err != nil { + if err := databaseService.Create(req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } @@ -38,13 +38,13 @@ func (b *BaseApi) CreateRemoteDB(c *gin.Context) { // @Summary Check remote database // @Description 检测远程数据库连接性 // @Accept json -// @Param request body dto.RemoteDBCreate true "request" +// @Param request body dto.DatabaseCreate true "request" // @Success 200 // @Security ApiKeyAuth // @Router /databases/remote/check [post] // @x-panel-log {"bodyKeys":["name", "type"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"检测远程数据库 [name][type] 连接性","formatEN":"check if remote database [name][type] is connectable"} -func (b *BaseApi) CheckeRemoteDB(c *gin.Context) { - var req dto.RemoteDBCreate +func (b *BaseApi) CheckDatabase(c *gin.Context) { + var req dto.DatabaseCreate if err := c.ShouldBindJSON(&req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return @@ -53,25 +53,25 @@ func (b *BaseApi) CheckeRemoteDB(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - helper.SuccessWithData(c, remoteDBService.CheckeRemoteDB(req)) + helper.SuccessWithData(c, databaseService.CheckDatabase(req)) } // @Tags Database // @Summary Page remote databases // @Description 获取远程数据库列表分页 // @Accept json -// @Param request body dto.RemoteDBSearch true "request" +// @Param request body dto.DatabaseSearch true "request" // @Success 200 {object} dto.PageResult // @Security ApiKeyAuth // @Router /databases/remote/search [post] -func (b *BaseApi) SearchRemoteDB(c *gin.Context) { - var req dto.RemoteDBSearch +func (b *BaseApi) SearchDatabase(c *gin.Context) { + var req dto.DatabaseSearch if err := c.ShouldBindJSON(&req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - total, list, err := remoteDBService.SearchWithPage(req) + total, list, err := databaseService.SearchWithPage(req) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -86,16 +86,16 @@ func (b *BaseApi) SearchRemoteDB(c *gin.Context) { // @Tags Database // @Summary List remote databases // @Description 获取远程数据库列表 -// @Success 200 {array} dto.RemoteDBOption +// @Success 200 {array} dto.DatabaseOption // @Security ApiKeyAuth // @Router /databases/remote/list/:type [get] -func (b *BaseApi) ListRemoteDB(c *gin.Context) { +func (b *BaseApi) ListDatabase(c *gin.Context) { dbType, err := helper.GetStrParamByKey(c, "type") if err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - list, err := remoteDBService.List(dbType) + list, err := databaseService.List(dbType) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -107,16 +107,16 @@ func (b *BaseApi) ListRemoteDB(c *gin.Context) { // @Tags Database // @Summary Get remote databases // @Description 获取远程数据库 -// @Success 200 {object} dto.RemoteDBInfo +// @Success 200 {object} dto.DatabaseInfo // @Security ApiKeyAuth // @Router /databases/remote/:name [get] -func (b *BaseApi) GetRemoteDB(c *gin.Context) { +func (b *BaseApi) GetDatabase(c *gin.Context) { name, err := helper.GetStrParamByKey(c, "name") if err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - data, err := remoteDBService.Get(name) + data, err := databaseService.Get(name) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -134,7 +134,7 @@ func (b *BaseApi) GetRemoteDB(c *gin.Context) { // @Security ApiKeyAuth // @Router /databases/remote/del [post] // @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFuntions":[{"input_column":"id","input_value":"ids","isList":true,"db":"databases","output_column":"name","output_value":"names"}],"formatZH":"删除远程数据库 [names]","formatEN":"delete remote database [names]"} -func (b *BaseApi) DeleteRemoteDB(c *gin.Context) { +func (b *BaseApi) DeleteDatabase(c *gin.Context) { var req dto.OperateByID if err := c.ShouldBindJSON(&req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) @@ -145,7 +145,7 @@ func (b *BaseApi) DeleteRemoteDB(c *gin.Context) { return } - if err := remoteDBService.Delete(req.ID); err != nil { + if err := databaseService.Delete(req.ID); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } @@ -156,13 +156,13 @@ func (b *BaseApi) DeleteRemoteDB(c *gin.Context) { // @Summary Update remote database // @Description 更新远程数据库 // @Accept json -// @Param request body dto.RemoteDBUpdate true "request" +// @Param request body dto.DatabaseUpdate true "request" // @Success 200 // @Security ApiKeyAuth // @Router /databases/remote/update [post] // @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFuntions":[],"formatZH":"更新远程数据库 [name]","formatEN":"update remote database [name]"} -func (b *BaseApi) UpdateRemoteDB(c *gin.Context) { - var req dto.RemoteDBUpdate +func (b *BaseApi) UpdateDatabase(c *gin.Context) { + var req dto.DatabaseUpdate if err := c.ShouldBindJSON(&req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return @@ -172,7 +172,7 @@ func (b *BaseApi) UpdateRemoteDB(c *gin.Context) { return } - if err := remoteDBService.Update(req); err != nil { + if err := databaseService.Update(req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } diff --git a/backend/app/api/v1/database_mysql.go b/backend/app/api/v1/database_mysql.go index e082645d6..84bdf5da4 100644 --- a/backend/app/api/v1/database_mysql.go +++ b/backend/app/api/v1/database_mysql.go @@ -143,7 +143,7 @@ func (b *BaseApi) ChangeMysqlAccess(c *gin.Context) { // @Router /databases/variables/update [post] // @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"调整 mysql 数据库性能参数","formatEN":"adjust mysql database performance parameters"} func (b *BaseApi) UpdateMysqlVariables(c *gin.Context) { - var req []dto.MysqlVariablesUpdate + var req dto.MysqlVariablesUpdate if err := c.ShouldBindJSON(&req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return @@ -232,15 +232,21 @@ func (b *BaseApi) ListDBName(c *gin.Context) { // @Tags Database Mysql // @Summary Load mysql database from remote // @Description 从服务器获取 +// @Accept json +// @Param request body dto.MysqlLodaDB true "request" // @Security ApiKeyAuth -// @Router /databases/load/:from [get] +// @Router /databases/load [post] func (b *BaseApi) LoadDBFromRemote(c *gin.Context) { - from, err := helper.GetStrParamByKey(c, "from") - if err != nil { + var req dto.MysqlLodaDB + if err := c.ShouldBindJSON(&req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return } - if err := mysqlService.LoadFromRemote(from); err != nil { + if err := global.VALID.Struct(req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + if err := mysqlService.LoadFromRemote(req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } @@ -252,12 +258,12 @@ func (b *BaseApi) LoadDBFromRemote(c *gin.Context) { // @Summary Check before delete mysql database // @Description Mysql 数据库删除前检查 // @Accept json -// @Param request body dto.OperateByID true "request" +// @Param request body dto.MysqlDBDeleteCheck true "request" // @Success 200 {array} string // @Security ApiKeyAuth // @Router /databases/del/check [post] func (b *BaseApi) DeleteCheckMysql(c *gin.Context) { - var req dto.OperateByID + var req dto.MysqlDBDeleteCheck if err := c.ShouldBindJSON(&req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return @@ -267,7 +273,7 @@ func (b *BaseApi) DeleteCheckMysql(c *gin.Context) { return } - apps, err := mysqlService.DeleteCheck(req.ID) + apps, err := mysqlService.DeleteCheck(req) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -308,11 +314,18 @@ func (b *BaseApi) DeleteMysql(c *gin.Context) { // @Tags Database Mysql // @Summary Load mysql base info // @Description 获取 mysql 基础信息 +// @Accept json +// @Param request body dto.OperationWithNameAndType true "request" // @Success 200 {object} dto.DBBaseInfo // @Security ApiKeyAuth -// @Router /databases/baseinfo [get] +// @Router /databases/baseinfo [post] func (b *BaseApi) LoadBaseinfo(c *gin.Context) { - data, err := mysqlService.LoadBaseInfo() + var req dto.OperationWithNameAndType + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + data, err := mysqlService.LoadBaseInfo(req) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -346,11 +359,18 @@ func (b *BaseApi) LoadDatabaseFile(c *gin.Context) { // @Tags Database Mysql // @Summary Load mysql remote access // @Description 获取 mysql 远程访问权限 +// @Accept json +// @Param request body dto.OperationWithNameAndType true "request" // @Success 200 {boolean} isRemote // @Security ApiKeyAuth -// @Router /databases/remote [get] +// @Router /databases/remote [post] func (b *BaseApi) LoadRemoteAccess(c *gin.Context) { - isRemote, err := mysqlService.LoadRemoteAccess() + var req dto.OperationWithNameAndType + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + isRemote, err := mysqlService.LoadRemoteAccess(req) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -362,11 +382,18 @@ func (b *BaseApi) LoadRemoteAccess(c *gin.Context) { // @Tags Database Mysql // @Summary Load mysql status info // @Description 获取 mysql 状态信息 +// @Accept json +// @Param request body dto.OperationWithNameAndType true "request" // @Success 200 {object} dto.MysqlStatus // @Security ApiKeyAuth -// @Router /databases/status [get] +// @Router /databases/status [post] func (b *BaseApi) LoadStatus(c *gin.Context) { - data, err := mysqlService.LoadStatus() + var req dto.OperationWithNameAndType + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + data, err := mysqlService.LoadStatus(req) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return @@ -378,11 +405,18 @@ func (b *BaseApi) LoadStatus(c *gin.Context) { // @Tags Database Mysql // @Summary Load mysql variables info // @Description 获取 mysql 性能参数信息 +// @Accept json +// @Param request body dto.OperationWithNameAndType true "request" // @Success 200 {object} dto.MysqlVariables // @Security ApiKeyAuth -// @Router /databases/variables [get] +// @Router /databases/variables [post] func (b *BaseApi) LoadVariables(c *gin.Context) { - data, err := mysqlService.LoadVariables() + var req dto.OperationWithNameAndType + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + data, err := mysqlService.LoadVariables(req) if err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return diff --git a/backend/app/api/v1/entry.go b/backend/app/api/v1/entry.go index 8dcd7db56..0bac385fc 100644 --- a/backend/app/api/v1/entry.go +++ b/backend/app/api/v1/entry.go @@ -22,7 +22,7 @@ var ( dockerService = service.NewIDockerService() mysqlService = service.NewIMysqlService() - remoteDBService = service.NewIRemoteDBService() + databaseService = service.NewIDatabaseService() redisService = service.NewIRedisService() cronjobService = service.NewICronjobService() diff --git a/backend/app/dto/backup.go b/backend/app/dto/backup.go index a3a2d0980..906c5f473 100644 --- a/backend/app/dto/backup.go +++ b/backend/app/dto/backup.go @@ -21,25 +21,18 @@ type BackupInfo struct { Vars string `json:"vars"` } -type BackupSearch struct { - PageInfo - Type string `json:"type" validate:"required,oneof=website mysql"` - Name string `json:"name" validate:"required"` - DetailName string `json:"detailName"` -} - type BackupSearchFile struct { Type string `json:"type" validate:"required"` } type CommonBackup struct { - Type string `json:"type" validate:"required,oneof=app mysql redis website"` + Type string `json:"type" validate:"required,oneof=app mysql mariadb redis website"` Name string `json:"name"` DetailName string `json:"detailName"` } type CommonRecover struct { Source string `json:"source" validate:"required,oneof=OSS S3 SFTP MINIO LOCAL COS KODO OneDrive"` - Type string `json:"type" validate:"required,oneof=app mysql redis website"` + Type string `json:"type" validate:"required,oneof=app mysql mariadb redis website"` Name string `json:"name"` DetailName string `json:"detailName"` File string `json:"file"` diff --git a/backend/app/dto/database.go b/backend/app/dto/database.go index 30233a435..589e79042 100644 --- a/backend/app/dto/database.go +++ b/backend/app/dto/database.go @@ -4,10 +4,10 @@ import "time" type MysqlDBSearch struct { PageInfo - Info string `json:"info"` - From string `json:"from"` - OrderBy string `json:"orderBy"` - Order string `json:"order"` + Info string `json:"info"` + Database string `json:"database" validate:"required"` + OrderBy string `json:"orderBy"` + Order string `json:"order"` } type MysqlDBInfo struct { @@ -25,14 +25,15 @@ type MysqlDBInfo struct { } type MysqlOption struct { - ID uint `json:"id"` - Name string `json:"name"` - From string `json:"from"` + ID uint `json:"id"` + From string `json:"from"` + Database string `json:"database"` } type MysqlDBCreate struct { Name string `json:"name" validate:"required"` - From string `json:"from" validate:"required"` + From string `json:"from" validate:"required,oneof=local remote"` + Database string `json:"database" validate:"required"` Format string `json:"format" validate:"required,oneof=utf8mb4 utf8 gbk big5"` Username string `json:"username" validate:"required"` Password string `json:"password" validate:"required"` @@ -40,10 +41,24 @@ type MysqlDBCreate struct { Description string `json:"description"` } +type MysqlLodaDB struct { + From string `json:"from" validate:"required,oneof=local remote"` + Type string `json:"type" validate:"required,oneof=mysql mariadb"` + Database string `json:"database" validate:"required"` +} + +type MysqlDBDeleteCheck struct { + ID uint `json:"id" validate:"required"` + Type string `json:"type" validate:"required,oneof=mysql mariadb"` + Database string `json:"database" validate:"required"` +} + type MysqlDBDelete struct { - ID uint `json:"id" validate:"required"` - ForceDelete bool `json:"forceDelete"` - DeleteBackup bool `json:"deleteBackup"` + ID uint `json:"id" validate:"required"` + Type string `json:"type" validate:"required,oneof=mysql mariadb"` + Database string `json:"database" validate:"required"` + ForceDelete bool `json:"forceDelete"` + DeleteBackup bool `json:"deleteBackup"` } type MysqlStatus struct { @@ -107,18 +122,27 @@ type MysqlVariables struct { } type MysqlVariablesUpdate struct { + Type string `json:"type" validate:"required,oneof=mysql mariadb"` + Database string `json:"database" validate:"required"` + Variables []MysqlVariablesUpdateHelper `json:"variables"` +} + +type MysqlVariablesUpdateHelper struct { Param string `json:"param"` Value interface{} `json:"value"` } type MysqlConfUpdateByFile struct { - MysqlName string `json:"mysqlName" validate:"required"` - File string `json:"file"` + Type string `json:"type" validate:"required,oneof=mysql mariadb"` + Database string `json:"database" validate:"required"` + File string `json:"file"` } type ChangeDBInfo struct { - ID uint `json:"id"` - From string `json:"from"` - Value string `json:"value" validate:"required"` + ID uint `json:"id"` + From string `json:"from" validate:"required,oneof=local remote"` + Type string `json:"type" validate:"required,oneof=mysql mariadb"` + Database string `json:"database" validate:"required"` + Value string `json:"value" validate:"required"` } type DBBaseInfo struct { @@ -127,11 +151,6 @@ type DBBaseInfo struct { Port int64 `json:"port"` } -type SearchDBWithPage struct { - PageInfo - MysqlName string `json:"mysqlName" validate:"required"` -} - type BackupDB struct { MysqlName string `json:"mysqlName" validate:"required"` DBName string `json:"dbName" validate:"required"` @@ -209,3 +228,56 @@ type RedisBackupRecover struct { FileName string `json:"fileName"` FileDir string `json:"fileDir"` } + +// database +type DatabaseSearch struct { + PageInfo + Info string `json:"info"` + Type string `json:"type"` + OrderBy string `json:"orderBy"` + Order string `json:"order"` +} + +type DatabaseInfo struct { + ID uint `json:"id"` + CreatedAt time.Time `json:"createdAt"` + Name string `json:"name" validate:"max=256"` + From string `json:"from"` + Version string `json:"version"` + Address string `json:"address"` + Port uint `json:"port"` + Username string `json:"username"` + Password string `json:"password"` + Description string `json:"description"` +} + +type DatabaseOption struct { + ID uint `json:"id"` + Type string `json:"type"` + From string `json:"from"` + Database string `json:"database"` + Version string `json:"version"` + Address string `json:"address"` +} + +type DatabaseCreate struct { + Name string `json:"name" validate:"required,max=256"` + Type string `json:"type" validate:"required,oneof=mysql"` + From string `json:"from" validate:"required,oneof=local remote"` + Version string `json:"version" validate:"required"` + Address string `json:"address"` + Port uint `json:"port"` + Username string `json:"username" validate:"required"` + Password string `json:"password" validate:"required"` + Description string `json:"description"` +} + +type DatabaseUpdate struct { + ID uint `json:"id"` + Version string `json:"version" validate:"required"` + Address string `json:"address"` + Port uint `json:"port"` + Username string `json:"username" validate:"required"` + Password string `json:"password" validate:"required"` + Description string `json:"description"` +} diff --git a/backend/app/dto/remote_db.go b/backend/app/dto/remote_db.go deleted file mode 100644 index dda319d17..000000000 --- a/backend/app/dto/remote_db.go +++ /dev/null @@ -1,52 +0,0 @@ -package dto - -import "time" - -type RemoteDBSearch struct { - PageInfo - Info string `json:"info"` - Type string `json:"type"` - OrderBy string `json:"orderBy"` - Order string `json:"order"` -} - -type RemoteDBInfo struct { - ID uint `json:"id"` - CreatedAt time.Time `json:"createdAt"` - Name string `json:"name" validate:"max=256"` - From string `json:"from"` - Version string `json:"version"` - Address string `json:"address"` - Port uint `json:"port"` - Username string `json:"username"` - Password string `json:"password"` - Description string `json:"description"` -} - -type RemoteDBOption struct { - ID uint `json:"id"` - Name string `json:"name"` - Address string `json:"address"` -} - -type RemoteDBCreate struct { - Name string `json:"name" validate:"required,max=256"` - Type string `json:"type" validate:"required,oneof=mysql"` - From string `json:"from" validate:"required,oneof=local remote"` - Version string `json:"version" validate:"required"` - Address string `json:"address"` - Port uint `json:"port"` - Username string `json:"username" validate:"required"` - Password string `json:"password" validate:"required"` - Description string `json:"description"` -} - -type RemoteDBUpdate struct { - ID uint `json:"id"` - Version string `json:"version" validate:"required"` - Address string `json:"address"` - Port uint `json:"port"` - Username string `json:"username" validate:"required"` - Password string `json:"password" validate:"required"` - Description string `json:"description"` -} diff --git a/backend/app/dto/request/app.go b/backend/app/dto/request/app.go index 40ad6b10b..0abe9b6c5 100644 --- a/backend/app/dto/request/app.go +++ b/backend/app/dto/request/app.go @@ -41,6 +41,11 @@ type AppInstalledSearch struct { Unused bool `json:"unused"` } +type AppInstalledInfo struct { + Key string `json:"key" validate:"required"` + Name string `json:"name"` +} + type AppBackupSearch struct { dto.PageInfo AppInstallID uint `json:"appInstallID"` diff --git a/backend/app/model/database.go b/backend/app/model/database.go new file mode 100644 index 000000000..1123bf282 --- /dev/null +++ b/backend/app/model/database.go @@ -0,0 +1,15 @@ +package model + +type Database struct { + BaseModel + AppInstallID uint `json:"appInstallID" gorm:"type:decimal"` + Name string `json:"name" gorm:"type:varchar(64);not null;unique"` + Type string `json:"type" gorm:"type:varchar(64);not null"` + Version string `json:"version" gorm:"type:varchar(64);not null"` + From string `json:"from" gorm:"type:varchar(64);not null"` + Address string `json:"address" gorm:"type:varchar(64);not null"` + Port uint `json:"port" gorm:"type:decimal;not null"` + Username string `json:"username" gorm:"type:varchar(64)"` + Password string `json:"password" gorm:"type:varchar(64)"` + Description string `json:"description" gorm:"type:varchar(256);"` +} diff --git a/backend/app/model/remote_db.go b/backend/app/model/remote_db.go deleted file mode 100644 index 8e442b37e..000000000 --- a/backend/app/model/remote_db.go +++ /dev/null @@ -1,14 +0,0 @@ -package model - -type RemoteDB struct { - BaseModel - Name string `json:"name" gorm:"type:varchar(64);not null"` - Type string `json:"type" gorm:"type:varchar(64);not null"` - Version string `json:"version" gorm:"type:varchar(64);not null"` - From string `json:"from" gorm:"type:varchar(64);not null"` - Address string `json:"address" gorm:"type:varchar(64);not null"` - Port uint `json:"port" gorm:"type:decimal;not null"` - Username string `json:"username" gorm:"type:varchar(64)"` - Password string `json:"password" gorm:"type:varchar(64)"` - Description string `json:"description" gorm:"type:varchar(256);"` -} diff --git a/backend/app/repo/app_install.go b/backend/app/repo/app_install.go index 00bf3742d..03465fc2d 100644 --- a/backend/app/repo/app_install.go +++ b/backend/app/repo/app_install.go @@ -3,6 +3,7 @@ package repo import ( "context" "encoding/json" + "gorm.io/gorm/clause" "github.com/1Panel-dev/1Panel/backend/app/model" @@ -193,7 +194,7 @@ func (a *AppInstallRepo) LoadBaseInfo(key string, name string) (*RootInfo, error return nil, err } switch app.Key { - case "mysql": + case "mysql", "mariadb": password, ok := envMap["PANEL_DB_ROOT_PASSWORD"].(string) if ok { info.Password = password diff --git a/backend/app/repo/database.go b/backend/app/repo/database.go new file mode 100644 index 000000000..96ee6a439 --- /dev/null +++ b/backend/app/repo/database.go @@ -0,0 +1,91 @@ +package repo + +import ( + "github.com/1Panel-dev/1Panel/backend/app/model" + "github.com/1Panel-dev/1Panel/backend/global" + "gorm.io/gorm" +) + +type DatabaseRepo struct{} + +type IDatabaseRepo interface { + GetList(opts ...DBOption) ([]model.Database, error) + Page(limit, offset int, opts ...DBOption) (int64, []model.Database, error) + Create(database *model.Database) error + Update(id uint, vars map[string]interface{}) error + Delete(opts ...DBOption) error + Get(opts ...DBOption) (model.Database, error) + WithByFrom(from string) DBOption + WithoutByFrom(from string) DBOption + WithByMysqlList() DBOption +} + +func NewIDatabaseRepo() IDatabaseRepo { + return &DatabaseRepo{} +} + +func (u *DatabaseRepo) Get(opts ...DBOption) (model.Database, error) { + var database model.Database + db := global.DB + for _, opt := range opts { + db = opt(db) + } + err := db.First(&database).Error + return database, err +} + +func (u *DatabaseRepo) Page(page, size int, opts ...DBOption) (int64, []model.Database, error) { + var users []model.Database + db := global.DB.Model(&model.Database{}) + for _, opt := range opts { + db = opt(db) + } + count := int64(0) + db = db.Count(&count) + err := db.Limit(size).Offset(size * (page - 1)).Find(&users).Error + return count, users, err +} + +func (u *DatabaseRepo) GetList(opts ...DBOption) ([]model.Database, error) { + var databases []model.Database + db := global.DB.Model(&model.Database{}) + for _, opt := range opts { + db = opt(db) + } + err := db.Find(&databases).Error + return databases, err +} + +func (c *DatabaseRepo) WithByMysqlList() DBOption { + return func(g *gorm.DB) *gorm.DB { + return g.Where("type == ? OR type == ?", "mysql", "mariadb") + } +} + +func (c *DatabaseRepo) WithByFrom(from string) DBOption { + return func(g *gorm.DB) *gorm.DB { + return g.Where("`from` == ?", from) + } +} + +func (c *DatabaseRepo) WithoutByFrom(from string) DBOption { + return func(g *gorm.DB) *gorm.DB { + return g.Where("`from` != ?", from) + } +} + +func (u *DatabaseRepo) Create(database *model.Database) error { + return global.DB.Create(database).Error +} + +func (u *DatabaseRepo) Update(id uint, vars map[string]interface{}) error { + return global.DB.Model(&model.Database{}).Where("id = ?", id).Updates(vars).Error +} + +func (u *DatabaseRepo) Delete(opts ...DBOption) error { + db := global.DB + for _, opt := range opts { + db = opt(db) + } + return db.Delete(&model.Database{}).Error +} diff --git a/backend/app/repo/remote_db.go b/backend/app/repo/remote_db.go deleted file mode 100644 index 660b765fa..000000000 --- a/backend/app/repo/remote_db.go +++ /dev/null @@ -1,84 +0,0 @@ -package repo - -import ( - "github.com/1Panel-dev/1Panel/backend/app/model" - "github.com/1Panel-dev/1Panel/backend/global" - "gorm.io/gorm" -) - -type RemoteDBRepo struct{} - -type IRemoteDBRepo interface { - GetList(opts ...DBOption) ([]model.RemoteDB, error) - Page(limit, offset int, opts ...DBOption) (int64, []model.RemoteDB, error) - Create(database *model.RemoteDB) error - Update(id uint, vars map[string]interface{}) error - Delete(opts ...DBOption) error - Get(opts ...DBOption) (model.RemoteDB, error) - WithByFrom(from string) DBOption - WithoutByFrom(from string) DBOption -} - -func NewIRemoteDBRepo() IRemoteDBRepo { - return &RemoteDBRepo{} -} - -func (u *RemoteDBRepo) Get(opts ...DBOption) (model.RemoteDB, error) { - var database model.RemoteDB - db := global.DB - for _, opt := range opts { - db = opt(db) - } - err := db.First(&database).Error - return database, err -} - -func (u *RemoteDBRepo) Page(page, size int, opts ...DBOption) (int64, []model.RemoteDB, error) { - var users []model.RemoteDB - db := global.DB.Model(&model.RemoteDB{}) - for _, opt := range opts { - db = opt(db) - } - count := int64(0) - db = db.Count(&count) - err := db.Limit(size).Offset(size * (page - 1)).Find(&users).Error - return count, users, err -} - -func (u *RemoteDBRepo) GetList(opts ...DBOption) ([]model.RemoteDB, error) { - var databases []model.RemoteDB - db := global.DB.Model(&model.RemoteDB{}) - for _, opt := range opts { - db = opt(db) - } - err := db.Find(&databases).Error - return databases, err -} - -func (c *RemoteDBRepo) WithByFrom(from string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("`from` == ?", from) - } -} - -func (c *RemoteDBRepo) WithoutByFrom(from string) DBOption { - return func(g *gorm.DB) *gorm.DB { - return g.Where("`from` != ?", from) - } -} - -func (u *RemoteDBRepo) Create(database *model.RemoteDB) error { - return global.DB.Create(database).Error -} - -func (u *RemoteDBRepo) Update(id uint, vars map[string]interface{}) error { - return global.DB.Model(&model.RemoteDB{}).Where("id = ?", id).Updates(vars).Error -} - -func (u *RemoteDBRepo) Delete(opts ...DBOption) error { - db := global.DB - for _, opt := range opts { - db = opt(db) - } - return db.Delete(&model.RemoteDB{}).Error -} diff --git a/backend/app/service/app_install.go b/backend/app/service/app_install.go index 967edf1b7..ae0970b0f 100644 --- a/backend/app/service/app_install.go +++ b/backend/app/service/app_install.go @@ -41,9 +41,9 @@ type AppInstallService struct { type IAppInstallService interface { Page(req request.AppInstalledSearch) (int64, []response.AppInstalledDTO, error) - CheckExist(key string) (*response.AppInstalledCheck, error) - LoadPort(key string) (int64, error) - LoadConnInfo(key string) (response.DatabaseConn, error) + CheckExist(req request.AppInstalledInfo) (*response.AppInstalledCheck, error) + LoadPort(req dto.OperationWithNameAndType) (int64, error) + LoadConnInfo(req dto.OperationWithNameAndType) (response.DatabaseConn, error) SearchForWebsite(req request.AppInstalledSearch) ([]response.AppInstalledDTO, error) Operate(req request.AppInstalledOperate) error Update(req request.AppInstalledUpdate) error @@ -130,23 +130,31 @@ func (a *AppInstallService) Page(req request.AppInstalledSearch) (int64, []respo return total, installDTOs, nil } -func (a *AppInstallService) CheckExist(key string) (*response.AppInstalledCheck, error) { +func (a *AppInstallService) CheckExist(req request.AppInstalledInfo) (*response.AppInstalledCheck, error) { res := &response.AppInstalledCheck{ IsExist: false, } - app, err := appRepo.GetFirst(appRepo.WithKey(key)) + + app, err := appRepo.GetFirst(appRepo.WithKey(req.Key)) if err != nil { return res, nil } res.App = app.Name - appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithAppId(app.ID)) - if reflect.DeepEqual(appInstall, model.AppInstall{}) { - return res, nil + + var appInstall model.AppInstall + if len(req.Name) == 0 { + appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithAppId(app.ID)) + if reflect.DeepEqual(appInstall, model.AppInstall{}) { + return res, nil + } + if err := syncById(appInstall.ID); err != nil { + return nil, err + } + appInstall, _ = appInstallRepo.GetFirst(commonRepo.WithByID(appInstall.ID)) + } else { + appInstall, _ = appInstallRepo.GetFirst(commonRepo.WithByName(req.Name)) + } - if err := syncById(appInstall.ID); err != nil { - return nil, err - } - appInstall, _ = appInstallRepo.GetFirst(commonRepo.WithByID(appInstall.ID)) res.ContainerName = appInstall.ContainerName res.Name = appInstall.Name @@ -155,24 +163,24 @@ func (a *AppInstallService) CheckExist(key string) (*response.AppInstalledCheck, res.Status = appInstall.Status res.AppInstallID = appInstall.ID res.IsExist = true - res.InstallPath = path.Join(constant.AppInstallDir, app.Key, appInstall.Name) + res.InstallPath = path.Join(constant.AppInstallDir, appInstall.App.Key, appInstall.Name) res.HttpPort = appInstall.HttpPort res.HttpsPort = appInstall.HttpsPort return res, nil } -func (a *AppInstallService) LoadPort(key string) (int64, error) { - app, err := appInstallRepo.LoadBaseInfo(key, "") +func (a *AppInstallService) LoadPort(req dto.OperationWithNameAndType) (int64, error) { + app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name) if err != nil { return int64(0), nil } return app.Port, nil } -func (a *AppInstallService) LoadConnInfo(key string) (response.DatabaseConn, error) { +func (a *AppInstallService) LoadConnInfo(req dto.OperationWithNameAndType) (response.DatabaseConn, error) { var data response.DatabaseConn - app, err := appInstallRepo.LoadBaseInfo(key, "") + app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name) if err != nil { return data, nil } @@ -748,7 +756,7 @@ func updateInstallInfoInDB(appKey, appName, param string, isRestart bool, value envKey := "" switch param { case "password": - if appKey == "mysql" { + if appKey == "mysql" || appKey == "mariadb" { envKey = "PANEL_DB_ROOT_PASSWORD=" } else { envKey = "PANEL_REDIS_ROOT_PASSWORD=" diff --git a/backend/app/service/backup_app.go b/backend/app/service/backup_app.go index 412d8f3fb..0d823e4f0 100644 --- a/backend/app/service/backup_app.go +++ b/backend/app/service/backup_app.go @@ -106,7 +106,7 @@ func handleAppBackup(install *model.AppInstall, backupDir, fileName string) erro resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID)) for _, resource := range resources { - if resource.Key == "mysql" { + if resource.Key == "mysql" || resource.Key == "mariadb" { db, err := mysqlRepo.Get(commonRepo.WithByID(resource.ResourceId)) if err != nil { return err @@ -173,7 +173,7 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback newEnvFile := "" resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID)) for _, resource := range resources { - if resource.Key == "mysql" { + if resource.Key == "mysql" || resource.Key == "maraidb" { mysqlInfo, err := appInstallRepo.LoadBaseInfo(resource.Key, "") if err != nil { return err diff --git a/backend/app/service/backup_mysql.go b/backend/app/service/backup_mysql.go index 4ddb26c48..be4b409a6 100644 --- a/backend/app/service/backup_mysql.go +++ b/backend/app/service/backup_mysql.go @@ -23,7 +23,7 @@ func (u *BackupService) MysqlBackup(req dto.CommonBackup) error { } timeNow := time.Now().Format("20060102150405") - targetDir := path.Join(localDir, fmt.Sprintf("database/mysql/%s/%s", req.Name, req.DetailName)) + targetDir := path.Join(localDir, fmt.Sprintf("database/%s/%s/%s", req.Type, req.Name, req.DetailName)) fileName := fmt.Sprintf("%s_%s.sql.gz", req.DetailName, timeNow) if err := handleMysqlBackup(req.Name, req.DetailName, targetDir, fileName); err != nil { @@ -31,7 +31,7 @@ func (u *BackupService) MysqlBackup(req dto.CommonBackup) error { } record := &model.BackupRecord{ - Type: "mysql", + Type: req.Type, Name: req.Name, DetailName: req.DetailName, Source: "LOCAL", @@ -97,12 +97,12 @@ func (u *BackupService) MysqlRecoverByUpload(req dto.CommonRecover) error { return nil } -func handleMysqlBackup(name, dbName, targetDir, fileName string) error { - dbInfo, err := mysqlRepo.Get(commonRepo.WithByName(dbName), mysqlRepo.WithByMysqlName(name)) +func handleMysqlBackup(database, dbName, targetDir, fileName string) error { + dbInfo, err := mysqlRepo.Get(commonRepo.WithByName(dbName), mysqlRepo.WithByMysqlName(database)) if err != nil { return err } - cli, _, err := LoadMysqlClientByFrom(dbInfo.From) + cli, _, err := LoadMysqlClientByFrom(database) if err != nil { return err } @@ -131,13 +131,13 @@ func handleMysqlRecover(req dto.CommonRecover, isRollback bool) error { if err != nil { return err } - cli, _, err := LoadMysqlClientByFrom(dbInfo.From) + cli, _, err := LoadMysqlClientByFrom(req.Name) if err != nil { return err } if !isRollback { - rollbackFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("database/mysql/%s_%s.sql.gz", req.DetailName, time.Now().Format("20060102150405"))) + rollbackFile := path.Join(global.CONF.System.TmpDir, fmt.Sprintf("database/%s/%s_%s.sql.gz", req.Type, req.DetailName, time.Now().Format("20060102150405"))) if err := cli.Backup(client.BackupInfo{ Name: req.DetailName, Format: dbInfo.Format, diff --git a/backend/app/service/cronjob_helper.go b/backend/app/service/cronjob_helper.go index cc63261c6..aaabd50a6 100644 --- a/backend/app/service/cronjob_helper.go +++ b/backend/app/service/cronjob_helper.go @@ -293,12 +293,13 @@ func (u *CronjobService) handleDatabase(cronjob model.Cronjob, backup model.Back for _, dbInfo := range dbs { var record model.BackupRecord - record.Type = "mysql" + database, _ := databaseRepo.Get(commonRepo.WithByName(dbInfo.MysqlName)) + record.Type = database.Type record.Source = "LOCAL" record.BackupType = backup.Type record.Name = dbInfo.MysqlName - backupDir := path.Join(localDir, fmt.Sprintf("database/mysql/%s/%s", record.Name, dbInfo.Name)) + backupDir := path.Join(localDir, fmt.Sprintf("database/%s/%s/%s", database.Type, record.Name, dbInfo.Name)) record.FileName = fmt.Sprintf("db_%s_%s.sql.gz", dbInfo.Name, startTime.Format("20060102150405")) if err = handleMysqlBackup(dbInfo.MysqlName, dbInfo.Name, backupDir, record.FileName); err != nil { return paths, err diff --git a/backend/app/service/remote_db.go b/backend/app/service/database.go similarity index 57% rename from backend/app/service/remote_db.go rename to backend/app/service/database.go index 64bf129c7..71b0fc689 100644 --- a/backend/app/service/remote_db.go +++ b/backend/app/service/database.go @@ -4,6 +4,7 @@ import ( "context" "github.com/1Panel-dev/1Panel/backend/app/dto" + "github.com/1Panel-dev/1Panel/backend/app/repo" "github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/utils/mysql" "github.com/1Panel-dev/1Panel/backend/utils/mysql/client" @@ -11,31 +12,31 @@ import ( "github.com/pkg/errors" ) -type RemoteDBService struct{} +type DatabaseService struct{} -type IRemoteDBService interface { - Get(name string) (dto.RemoteDBInfo, error) - SearchWithPage(search dto.RemoteDBSearch) (int64, interface{}, error) - CheckeRemoteDB(req dto.RemoteDBCreate) bool - Create(req dto.RemoteDBCreate) error - Update(req dto.RemoteDBUpdate) error +type IDatabaseService interface { + Get(name string) (dto.DatabaseInfo, error) + SearchWithPage(search dto.DatabaseSearch) (int64, interface{}, error) + CheckDatabase(req dto.DatabaseCreate) bool + Create(req dto.DatabaseCreate) error + Update(req dto.DatabaseUpdate) error Delete(id uint) error - List(dbType string) ([]dto.RemoteDBOption, error) + List(dbType string) ([]dto.DatabaseOption, error) } -func NewIRemoteDBService() IRemoteDBService { - return &RemoteDBService{} +func NewIDatabaseService() IDatabaseService { + return &DatabaseService{} } -func (u *RemoteDBService) SearchWithPage(search dto.RemoteDBSearch) (int64, interface{}, error) { - total, dbs, err := remoteDBRepo.Page(search.Page, search.PageSize, +func (u *DatabaseService) SearchWithPage(search dto.DatabaseSearch) (int64, interface{}, error) { + total, dbs, err := databaseRepo.Page(search.Page, search.PageSize, commonRepo.WithByType(search.Type), commonRepo.WithLikeName(search.Info), - remoteDBRepo.WithoutByFrom("local"), + databaseRepo.WithoutByFrom("local"), ) - var datas []dto.RemoteDBInfo + var datas []dto.DatabaseInfo for _, db := range dbs { - var item dto.RemoteDBInfo + var item dto.DatabaseInfo if err := copier.Copy(&item, &db); err != nil { return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) } @@ -44,9 +45,9 @@ func (u *RemoteDBService) SearchWithPage(search dto.RemoteDBSearch) (int64, inte return total, datas, err } -func (u *RemoteDBService) Get(name string) (dto.RemoteDBInfo, error) { - var data dto.RemoteDBInfo - remote, err := remoteDBRepo.Get(commonRepo.WithByName(name)) +func (u *DatabaseService) Get(name string) (dto.DatabaseInfo, error) { + var data dto.DatabaseInfo + remote, err := databaseRepo.Get(commonRepo.WithByName(name)) if err != nil { return data, err } @@ -56,20 +57,27 @@ func (u *RemoteDBService) Get(name string) (dto.RemoteDBInfo, error) { return data, nil } -func (u *RemoteDBService) List(dbType string) ([]dto.RemoteDBOption, error) { - dbs, err := remoteDBRepo.GetList(commonRepo.WithByType(dbType)) - var datas []dto.RemoteDBOption +func (u *DatabaseService) List(dbType string) ([]dto.DatabaseOption, error) { + var opts []repo.DBOption + if dbType == "mysql" { + opts = append(opts, databaseRepo.WithByMysqlList()) + } else { + opts = append(opts, commonRepo.WithByType(dbType)) + } + dbs, err := databaseRepo.GetList(opts...) + var datas []dto.DatabaseOption for _, db := range dbs { - var item dto.RemoteDBOption + var item dto.DatabaseOption if err := copier.Copy(&item, &db); err != nil { return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) } + item.Database = db.Name datas = append(datas, item) } return datas, err } -func (u *RemoteDBService) CheckeRemoteDB(req dto.RemoteDBCreate) bool { +func (u *DatabaseService) CheckDatabase(req dto.DatabaseCreate) bool { if _, err := mysql.NewMysqlClient(client.DBInfo{ From: "remote", Address: req.Address, @@ -83,8 +91,8 @@ func (u *RemoteDBService) CheckeRemoteDB(req dto.RemoteDBCreate) bool { return true } -func (u *RemoteDBService) Create(req dto.RemoteDBCreate) error { - db, _ := remoteDBRepo.Get(commonRepo.WithByName(req.Name)) +func (u *DatabaseService) Create(req dto.DatabaseCreate) error { + db, _ := databaseRepo.Get(commonRepo.WithByName(req.Name)) if db.ID != 0 { return constant.ErrRecordExist } @@ -101,29 +109,29 @@ func (u *RemoteDBService) Create(req dto.RemoteDBCreate) error { if err := copier.Copy(&db, &req); err != nil { return errors.WithMessage(constant.ErrStructTransform, err.Error()) } - if err := remoteDBRepo.Create(&db); err != nil { + if err := databaseRepo.Create(&db); err != nil { return err } return nil } -func (u *RemoteDBService) Delete(id uint) error { - db, _ := remoteDBRepo.Get(commonRepo.WithByID(id)) +func (u *DatabaseService) Delete(id uint) error { + db, _ := databaseRepo.Get(commonRepo.WithByID(id)) if db.ID == 0 { return constant.ErrRecordNotFound } - if err := remoteDBRepo.Delete(commonRepo.WithByID(id)); err != nil { + if err := databaseRepo.Delete(commonRepo.WithByID(id)); err != nil { return err } if db.From != "local" { - if err := mysqlRepo.Delete(context.Background(), remoteDBRepo.WithByFrom(db.Name)); err != nil { + if err := mysqlRepo.Delete(context.Background(), databaseRepo.WithByFrom(db.Name)); err != nil { return err } } return nil } -func (u *RemoteDBService) Update(req dto.RemoteDBUpdate) error { +func (u *DatabaseService) Update(req dto.DatabaseUpdate) error { if _, err := mysql.NewMysqlClient(client.DBInfo{ From: "remote", Address: req.Address, @@ -142,5 +150,5 @@ func (u *RemoteDBService) Update(req dto.RemoteDBUpdate) error { upMap["username"] = req.Username upMap["password"] = req.Password upMap["description"] = req.Description - return remoteDBRepo.Update(req.ID, upMap) + return databaseRepo.Update(req.ID, upMap) } diff --git a/backend/app/service/database_mysql.go b/backend/app/service/database_mysql.go index ea3f89dea..b8408ce64 100644 --- a/backend/app/service/database_mysql.go +++ b/backend/app/service/database_mysql.go @@ -34,18 +34,19 @@ type IMysqlService interface { SearchWithPage(search dto.MysqlDBSearch) (int64, interface{}, error) ListDBOption() ([]dto.MysqlOption, error) Create(ctx context.Context, req dto.MysqlDBCreate) (*model.DatabaseMysql, error) - LoadFromRemote(from string) error + LoadFromRemote(req dto.MysqlLodaDB) error ChangeAccess(info dto.ChangeDBInfo) error ChangePassword(info dto.ChangeDBInfo) error - UpdateVariables(updates []dto.MysqlVariablesUpdate) error + UpdateVariables(req dto.MysqlVariablesUpdate) error UpdateConfByFile(info dto.MysqlConfUpdateByFile) error UpdateDescription(req dto.UpdateDescription) error - DeleteCheck(id uint) ([]string, error) + DeleteCheck(req dto.MysqlDBDeleteCheck) ([]string, error) Delete(ctx context.Context, req dto.MysqlDBDelete) error - LoadStatus() (*dto.MysqlStatus, error) - LoadVariables() (*dto.MysqlVariables, error) - LoadBaseInfo() (*dto.DBBaseInfo, error) - LoadRemoteAccess() (bool, error) + + LoadStatus(req dto.OperationWithNameAndType) (*dto.MysqlStatus, error) + LoadVariables(req dto.OperationWithNameAndType) (*dto.MysqlVariables, error) + LoadBaseInfo(req dto.OperationWithNameAndType) (*dto.DBBaseInfo, error) + LoadRemoteAccess(req dto.OperationWithNameAndType) (bool, error) LoadDatabaseFile(req dto.OperationWithNameAndType) (string, error) } @@ -56,7 +57,7 @@ func NewIMysqlService() IMysqlService { func (u *MysqlService) SearchWithPage(search dto.MysqlDBSearch) (int64, interface{}, error) { total, mysqls, err := mysqlRepo.Page(search.Page, search.PageSize, - mysqlRepo.WithByFrom(search.From), + mysqlRepo.WithByMysqlName(search.Database), commonRepo.WithLikeName(search.Info), commonRepo.WithOrderRuleBy(search.OrderBy, search.Order), ) @@ -89,7 +90,7 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode return nil, buserr.New(constant.ErrCmdIllegal) } - mysql, _ := mysqlRepo.Get(commonRepo.WithByName(req.Name), remoteDBRepo.WithByFrom(req.From)) + mysql, _ := mysqlRepo.Get(commonRepo.WithByName(req.Name), databaseRepo.WithByFrom(req.From)) if mysql.ID != 0 { return nil, constant.ErrRecordExist } @@ -103,20 +104,11 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode return nil, errors.New("Cannot set root as user name") } - cli, version, err := LoadMysqlClientByFrom(req.From) + cli, version, err := LoadMysqlClientByFrom(req.Database) if err != nil { return nil, err } - - if req.From == "local" { - app, err := appInstallRepo.LoadBaseInfo("mysql", "") - if err != nil { - return nil, err - } - createItem.MysqlName = app.Name - } else { - createItem.MysqlName = req.From - } + createItem.MysqlName = req.Database defer cli.Close() if err := cli.Create(client.CreateInfo{ Name: req.Name, @@ -137,22 +129,22 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode return &createItem, nil } -func (u *MysqlService) LoadFromRemote(from string) error { - client, version, err := LoadMysqlClientByFrom(from) +func (u *MysqlService) LoadFromRemote(req dto.MysqlLodaDB) error { + client, version, err := LoadMysqlClientByFrom(req.Database) if err != nil { return err } - mysqlName := from - if from == "local" { - app, err := appInstallRepo.LoadBaseInfo("mysql", "") + mysqlName := req.From + if req.From == "local" { + app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database) if err != nil { return err } mysqlName = app.Name } - databases, err := mysqlRepo.List(remoteDBRepo.WithByFrom(from)) + databases, err := mysqlRepo.List(databaseRepo.WithByFrom(req.From)) if err != nil { return err } @@ -186,15 +178,15 @@ func (u *MysqlService) UpdateDescription(req dto.UpdateDescription) error { return mysqlRepo.Update(req.ID, map[string]interface{}{"description": req.Description}) } -func (u *MysqlService) DeleteCheck(id uint) ([]string, error) { +func (u *MysqlService) DeleteCheck(req dto.MysqlDBDeleteCheck) ([]string, error) { var appInUsed []string - db, err := mysqlRepo.Get(commonRepo.WithByID(id)) + db, err := mysqlRepo.Get(commonRepo.WithByID(req.ID)) if err != nil { return appInUsed, err } if db.From == "local" { - app, err := appInstallRepo.LoadBaseInfo("mysql", "") + app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database) if err != nil { return appInUsed, err } @@ -223,7 +215,7 @@ func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error if err != nil && !req.ForceDelete { return err } - cli, version, err := LoadMysqlClientByFrom(db.From) + cli, version, err := LoadMysqlClientByFrom(req.Database) if err != nil { return err } @@ -238,12 +230,7 @@ func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error return err } - app, err := appInstallRepo.LoadBaseInfo("mysql", "") - if err != nil && !req.ForceDelete { - return err - } - - uploadDir := path.Join(global.CONF.System.BaseDir, fmt.Sprintf("1panel/uploads/database/mysql/%s/%s", app.Name, db.Name)) + uploadDir := path.Join(global.CONF.System.BaseDir, fmt.Sprintf("1panel/uploads/database/%s/%s/%s", req.Type, req.Database, db.Name)) if _, err := os.Stat(uploadDir); err == nil { _ = os.RemoveAll(uploadDir) } @@ -252,23 +239,23 @@ func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error if err != nil && !req.ForceDelete { return err } - backupDir := path.Join(localDir, fmt.Sprintf("database/mysql/%s/%s", db.MysqlName, db.Name)) + backupDir := path.Join(localDir, fmt.Sprintf("database/%s/%s/%s", req.Type, db.MysqlName, db.Name)) if _, err := os.Stat(backupDir); err == nil { _ = os.RemoveAll(backupDir) } - global.LOG.Infof("delete database %s-%s backups successful", app.Name, db.Name) + global.LOG.Infof("delete database %s-%s backups successful", req.Database, db.Name) } - _ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType("mysql"), commonRepo.WithByName(app.Name), backupRepo.WithByDetailName(db.Name)) + _ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType(req.Type), commonRepo.WithByName(req.Database), backupRepo.WithByDetailName(db.Name)) _ = mysqlRepo.Delete(ctx, commonRepo.WithByID(db.ID)) return nil } -func (u *MysqlService) ChangePassword(info dto.ChangeDBInfo) error { - if cmd.CheckIllegal(info.Value) { +func (u *MysqlService) ChangePassword(req dto.ChangeDBInfo) error { + if cmd.CheckIllegal(req.Value) { return buserr.New(constant.ErrCmdIllegal) } - cli, version, err := LoadMysqlClientByFrom(info.From) + cli, version, err := LoadMysqlClientByFrom(req.Database) if err != nil { return err } @@ -277,12 +264,12 @@ func (u *MysqlService) ChangePassword(info dto.ChangeDBInfo) error { mysqlData model.DatabaseMysql passwordInfo client.PasswordChangeInfo ) - passwordInfo.Password = info.Value + passwordInfo.Password = req.Value passwordInfo.Timeout = 300 passwordInfo.Version = version - if info.ID != 0 { - mysqlData, err = mysqlRepo.Get(commonRepo.WithByID(info.ID)) + if req.ID != 0 { + mysqlData, err = mysqlRepo.Get(commonRepo.WithByID(req.ID)) if err != nil { return err } @@ -296,10 +283,10 @@ func (u *MysqlService) ChangePassword(info dto.ChangeDBInfo) error { return err } - if info.ID != 0 { + if req.ID != 0 { var appRess []model.AppInstallResource - if info.From == "local" { - app, err := appInstallRepo.LoadBaseInfo("mysql", "") + if req.From == "local" { + app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database) if err != nil { return err } @@ -318,29 +305,26 @@ func (u *MysqlService) ChangePassword(info dto.ChangeDBInfo) error { } global.LOG.Infof("start to update mysql password used by app %s-%s", appModel.Key, appInstall.Name) - if err := updateInstallInfoInDB(appModel.Key, appInstall.Name, "user-password", true, info.Value); err != nil { + if err := updateInstallInfoInDB(appModel.Key, appInstall.Name, "user-password", true, req.Value); err != nil { return err } } global.LOG.Info("excute password change sql successful") - _ = mysqlRepo.Update(mysqlData.ID, map[string]interface{}{"password": info.Value}) + _ = mysqlRepo.Update(mysqlData.ID, map[string]interface{}{"password": req.Value}) return nil } - if err := updateInstallInfoInDB("mysql", "", "password", false, info.Value); err != nil { - return err - } - if err := updateInstallInfoInDB("phpmyadmin", "", "password", true, info.Value); err != nil { + if err := updateInstallInfoInDB(req.Type, req.Database, "password", false, req.Value); err != nil { return err } return nil } -func (u *MysqlService) ChangeAccess(info dto.ChangeDBInfo) error { - if cmd.CheckIllegal(info.Value) { +func (u *MysqlService) ChangeAccess(req dto.ChangeDBInfo) error { + if cmd.CheckIllegal(req.Value) { return buserr.New(constant.ErrCmdIllegal) } - cli, version, err := LoadMysqlClientByFrom(info.From) + cli, version, err := LoadMysqlClientByFrom(req.Database) if err != nil { return err } @@ -349,12 +333,12 @@ func (u *MysqlService) ChangeAccess(info dto.ChangeDBInfo) error { mysqlData model.DatabaseMysql accessInfo client.AccessChangeInfo ) - accessInfo.Permission = info.Value + accessInfo.Permission = req.Value accessInfo.Timeout = 300 accessInfo.Version = version - if info.ID != 0 { - mysqlData, err = mysqlRepo.Get(commonRepo.WithByID(info.ID)) + if req.ID != 0 { + mysqlData, err = mysqlRepo.Get(commonRepo.WithByID(req.ID)) if err != nil { return err } @@ -370,40 +354,40 @@ func (u *MysqlService) ChangeAccess(info dto.ChangeDBInfo) error { } if mysqlData.ID != 0 { - _ = mysqlRepo.Update(mysqlData.ID, map[string]interface{}{"permission": info.Value}) + _ = mysqlRepo.Update(mysqlData.ID, map[string]interface{}{"permission": req.Value}) } return nil } -func (u *MysqlService) UpdateConfByFile(info dto.MysqlConfUpdateByFile) error { - app, err := appInstallRepo.LoadBaseInfo("mysql", "") +func (u *MysqlService) UpdateConfByFile(req dto.MysqlConfUpdateByFile) error { + app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database) if err != nil { return err } - path := fmt.Sprintf("%s/mysql/%s/conf/my.cnf", constant.AppInstallDir, app.Name) + path := fmt.Sprintf("%s/%s/%s/conf/my.cnf", constant.AppInstallDir, req.Type, app.Name) file, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0640) if err != nil { return err } defer file.Close() write := bufio.NewWriter(file) - _, _ = write.WriteString(info.File) + _, _ = write.WriteString(req.File) write.Flush() - if _, err := compose.Restart(fmt.Sprintf("%s/mysql/%s/docker-compose.yml", constant.AppInstallDir, app.Name)); err != nil { + if _, err := compose.Restart(fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, req.Type, app.Name)); err != nil { return err } return nil } -func (u *MysqlService) UpdateVariables(updates []dto.MysqlVariablesUpdate) error { - app, err := appInstallRepo.LoadBaseInfo("mysql", "") +func (u *MysqlService) UpdateVariables(req dto.MysqlVariablesUpdate) error { + app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database) if err != nil { return err } var files []string - path := fmt.Sprintf("%s/mysql/%s/conf/my.cnf", constant.AppInstallDir, app.Name) + path := fmt.Sprintf("%s/%s/%s/conf/my.cnf", constant.AppInstallDir, req.Type, app.Name) lineBytes, err := os.ReadFile(path) if err != nil { return err @@ -411,7 +395,7 @@ func (u *MysqlService) UpdateVariables(updates []dto.MysqlVariablesUpdate) error files = strings.Split(string(lineBytes), "\n") group := "[mysqld]" - for _, info := range updates { + for _, info := range req.Variables { if !strings.HasPrefix(app.Version, "5.7") && !strings.HasPrefix(app.Version, "5.6") { if info.Param == "query_cache_size" { continue @@ -434,16 +418,16 @@ func (u *MysqlService) UpdateVariables(updates []dto.MysqlVariablesUpdate) error return err } - if _, err := compose.Restart(fmt.Sprintf("%s/mysql/%s/docker-compose.yml", constant.AppInstallDir, app.Name)); err != nil { + if _, err := compose.Restart(fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, req.Type, app.Name)); err != nil { return err } return nil } -func (u *MysqlService) LoadBaseInfo() (*dto.DBBaseInfo, error) { +func (u *MysqlService) LoadBaseInfo(req dto.OperationWithNameAndType) (*dto.DBBaseInfo, error) { var data dto.DBBaseInfo - app, err := appInstallRepo.LoadBaseInfo("mysql", "") + app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name) if err != nil { return nil, err } @@ -454,8 +438,8 @@ func (u *MysqlService) LoadBaseInfo() (*dto.DBBaseInfo, error) { return &data, nil } -func (u *MysqlService) LoadRemoteAccess() (bool, error) { - app, err := appInstallRepo.LoadBaseInfo("mysql", "") +func (u *MysqlService) LoadRemoteAccess(req dto.OperationWithNameAndType) (bool, error) { + app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name) if err != nil { return false, err } @@ -472,8 +456,8 @@ func (u *MysqlService) LoadRemoteAccess() (bool, error) { return false, nil } -func (u *MysqlService) LoadVariables() (*dto.MysqlVariables, error) { - app, err := appInstallRepo.LoadBaseInfo("mysql", "") +func (u *MysqlService) LoadVariables(req dto.OperationWithNameAndType) (*dto.MysqlVariables, error) { + app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name) if err != nil { return nil, err } @@ -490,8 +474,8 @@ func (u *MysqlService) LoadVariables() (*dto.MysqlVariables, error) { return &info, nil } -func (u *MysqlService) LoadStatus() (*dto.MysqlStatus, error) { - app, err := appInstallRepo.LoadBaseInfo("mysql", "") +func (u *MysqlService) LoadStatus(req dto.OperationWithNameAndType) (*dto.MysqlStatus, error) { + app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name) if err != nil { return nil, err } @@ -540,10 +524,14 @@ func (u *MysqlService) LoadDatabaseFile(req dto.OperationWithNameAndType) (strin switch req.Type { case "mysql-conf": filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mysql/%s/conf/my.cnf", req.Name)) + case "mariadb-conf": + filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mariadb/%s/conf/my.cnf", req.Name)) case "redis-conf": filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/redis/%s/conf/redis.conf", req.Name)) - case "slow-logs": + case "mysql-slow-logs": filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mysql/%s/data/1Panel-slow.log", req.Name)) + case "mariadb-slow-logs": + filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/mariadb/%s/db/data/1Panel-slow.log", req.Name)) } if _, err := os.Stat(filePath); err != nil { return "", buserr.New("ErrHttpReqNotFound") @@ -625,20 +613,20 @@ func updateMyCnf(oldFiles []string, group string, param string, value interface{ return newFiles } -func LoadMysqlClientByFrom(from string) (mysql.MysqlClient, string, error) { +func LoadMysqlClientByFrom(database string) (mysql.MysqlClient, string, error) { var ( dbInfo client.DBInfo version string err error ) - dbInfo.From = from dbInfo.Timeout = 300 - if from != "local" { - databaseItem, err := remoteDBRepo.Get(commonRepo.WithByName(from)) - if err != nil { - return nil, "", err - } + databaseItem, err := databaseRepo.Get(commonRepo.WithByName(database)) + if err != nil { + return nil, "", err + } + dbInfo.From = databaseItem.From + if dbInfo.From != "local" { dbInfo.Address = databaseItem.Address dbInfo.Port = databaseItem.Port dbInfo.Username = databaseItem.Username @@ -646,7 +634,7 @@ func LoadMysqlClientByFrom(from string) (mysql.MysqlClient, string, error) { version = databaseItem.Version } else { - app, err := appInstallRepo.LoadBaseInfo("mysql", "") + app, err := appInstallRepo.LoadBaseInfo(databaseItem.Type, database) if err != nil { return nil, "", err } diff --git a/backend/app/service/entry.go b/backend/app/service/entry.go index fa8f9f238..e085513cd 100644 --- a/backend/app/service/entry.go +++ b/backend/app/service/entry.go @@ -13,7 +13,7 @@ var ( appInstallResourceRepo = repo.NewIAppInstallResourceRpo() mysqlRepo = repo.NewIMysqlRepo() - remoteDBRepo = repo.NewIRemoteDBRepo() + databaseRepo = repo.NewIDatabaseRepo() imageRepoRepo = repo.NewIImageRepoRepo() composeRepo = repo.NewIComposeTemplateRepo() diff --git a/backend/init/hook/hook.go b/backend/init/hook/hook.go index aeaa40615..1baa76350 100644 --- a/backend/init/hook/hook.go +++ b/backend/init/hook/hook.go @@ -82,33 +82,33 @@ func handleSnapStatus() { status, _ := snapRepo.GetStatusList() for _, statu := range status { - updatas := make(map[string]interface{}) + updates := make(map[string]interface{}) if statu.Panel == constant.StatusRunning { - updatas["panel"] = constant.StatusFailed + updates["panel"] = constant.StatusFailed } if statu.PanelInfo == constant.StatusRunning { - updatas["panel_info"] = constant.StatusFailed + updates["panel_info"] = constant.StatusFailed } if statu.DaemonJson == constant.StatusRunning { - updatas["daemon_json"] = constant.StatusFailed + updates["daemon_json"] = constant.StatusFailed } if statu.AppData == constant.StatusRunning { - updatas["app_data"] = constant.StatusFailed + updates["app_data"] = constant.StatusFailed } if statu.PanelData == constant.StatusRunning { - updatas["panel_data"] = constant.StatusFailed + updates["panel_data"] = constant.StatusFailed } if statu.BackupData == constant.StatusRunning { - updatas["backup_data"] = constant.StatusFailed + updates["backup_data"] = constant.StatusFailed } if statu.Compress == constant.StatusRunning { - updatas["compress"] = constant.StatusFailed + updates["compress"] = constant.StatusFailed } if statu.Upload == constant.StatusUploading { - updatas["upload"] = constant.StatusFailed + updates["upload"] = constant.StatusFailed } - if len(updatas) != 0 { - _ = snapRepo.UpdateStatus(statu.ID, updatas) + if len(updates) != 0 { + _ = snapRepo.UpdateStatus(statu.ID, updates) } } } diff --git a/backend/init/migration/migrate.go b/backend/init/migration/migrate.go index 00a31ec75..3b119e62b 100644 --- a/backend/init/migration/migrate.go +++ b/backend/init/migration/migrate.go @@ -39,6 +39,7 @@ func Init() { migrations.UpdateRedisParam, migrations.UpdateCronjobWithDb, migrations.AddTableFirewall, + migrations.UpdateDatabase, }) if err := m.Migrate(); err != nil { global.LOG.Error(err) diff --git a/backend/init/migration/migrations/init.go b/backend/init/migration/migrations/init.go index cecce5dc4..5fb19bfb2 100644 --- a/backend/init/migration/migrations/init.go +++ b/backend/init/migration/migrations/init.go @@ -485,7 +485,7 @@ var EncryptHostPassword = &gormigrate.Migration{ var AddRemoteDB = &gormigrate.Migration{ ID: "20230724-add-remote-db", Migrate: func(tx *gorm.DB) error { - if err := tx.AutoMigrate(&model.RemoteDB{}, &model.DatabaseMysql{}); err != nil { + if err := tx.AutoMigrate(&model.DatabaseMysql{}); err != nil { return err } var ( @@ -509,7 +509,7 @@ var AddRemoteDB = &gormigrate.Migration{ if !ok { return errors.New("error password in app env") } - if err := tx.Create(&model.RemoteDB{ + if err := tx.Create(&model.Database{ Name: "local", Type: "mysql", Version: appInstall.Version, @@ -572,11 +572,90 @@ var UpdateCronjobWithDb = &gormigrate.Migration{ } var AddTableFirewall = &gormigrate.Migration{ - ID: "20230823-add-table-firewall", + ID: "20230825-add-table-firewall", Migrate: func(tx *gorm.DB) error { if err := tx.AutoMigrate(&model.Firewall{}, model.SnapshotStatus{}, &model.Cronjob{}); err != nil { return err } + if err := tx.Exec("alter table remote_dbs rename to databases;").Error; err != nil { + return err + } + return nil + }, +} + +var UpdateDatabase = &gormigrate.Migration{ + ID: "20230828-update-database", + Migrate: func(tx *gorm.DB) error { + var ( + app model.App + appInstall model.AppInstall + ) + if err := tx.AutoMigrate(&model.Database{}); err != nil { + return err + } + if err := global.DB.Where("key = ?", "mariadb").First(&app).Error; err != nil { + return nil + } + if err := global.DB.Where("app_id = ?", app.ID).First(&appInstall).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil + } + return err + } + envMap := make(map[string]interface{}) + if err := json.Unmarshal([]byte(appInstall.Env), &envMap); err != nil { + return err + } + password, ok := envMap["PANEL_DB_ROOT_PASSWORD"].(string) + if !ok { + return errors.New("error password in app env") + } + if err := tx.Create(&model.Database{ + AppInstallID: appInstall.ID, + Name: appInstall.Name, + Type: "mariadb", + Version: appInstall.Version, + From: "local", + Address: appInstall.ServiceName, + Port: uint(appInstall.HttpPort), + Username: "root", + Password: password, + }).Error; err != nil { + return err + } + + if err := global.DB.Model(&model.DatabaseMysql{}).Where("`from` != ?", "local").Updates(map[string]interface{}{ + "from": "remote", + }).Error; err != nil { + return err + } + + var ( + appMysql model.App + appInstallMysql model.AppInstall + localDatabase model.Database + ) + _ = global.DB.Where("name = ? AND address = ?", "local", "127.0.0.1").First(&localDatabase).Error + if localDatabase.ID == 0 { + return nil + } + if err := global.DB.Where("key = ?", "mysql").First(&appMysql).Error; err != nil { + return nil + } + if err := global.DB.Where("app_id = ?", appMysql.ID).First(&appInstallMysql).Error; err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil + } + return err + } + if err := global.DB.Model(&model.Database{}).Where("id = ?", localDatabase.ID).Updates(map[string]interface{}{ + "app_install_id": appInstallMysql.ID, + "name": appInstallMysql.Name, + "address": appInstallMysql.ServiceName, + }).Error; err != nil { + return err + } return nil }, } diff --git a/backend/router/ro_app.go b/backend/router/ro_app.go index a52027099..4aba7d68d 100644 --- a/backend/router/ro_app.go +++ b/backend/router/ro_app.go @@ -24,9 +24,9 @@ func (a *AppRouter) InitAppRouter(Router *gin.RouterGroup) { appRouter.POST("/install", baseApi.InstallApp) appRouter.GET("/tags", baseApi.GetAppTags) appRouter.GET("/installed/:appInstallId/versions", baseApi.GetUpdateVersions) - appRouter.GET("/installed/check/:key", baseApi.CheckAppInstalled) - appRouter.GET("/installed/loadport/:key", baseApi.LoadPort) - appRouter.GET("/installed/conninfo/:key", baseApi.LoadConnInfo) + appRouter.POST("/installed/check", baseApi.CheckAppInstalled) + appRouter.POST("/installed/loadport", baseApi.LoadPort) + appRouter.POST("/installed/conninfo", baseApi.LoadConnInfo) appRouter.GET("/installed/delete/check/:appInstallId", baseApi.DeleteCheck) appRouter.POST("/installed/search", baseApi.SearchAppInstalled) appRouter.GET("/installed/list", baseApi.ListAppInstalled) diff --git a/backend/router/ro_database.go b/backend/router/ro_database.go index eeaf8f0c9..518077ca9 100644 --- a/backend/router/ro_database.go +++ b/backend/router/ro_database.go @@ -17,7 +17,7 @@ func (s *DatabaseRouter) InitDatabaseRouter(Router *gin.RouterGroup) { baseApi := v1.ApiGroupApp.BaseApi { cmdRouter.POST("", baseApi.CreateMysql) - cmdRouter.GET("load/:from", baseApi.LoadDBFromRemote) + cmdRouter.POST("load", baseApi.LoadDBFromRemote) cmdRouter.POST("/change/access", baseApi.ChangeMysqlAccess) cmdRouter.POST("/change/password", baseApi.ChangeMysqlPassword) cmdRouter.POST("/del/check", baseApi.DeleteCheckMysql) @@ -27,10 +27,10 @@ func (s *DatabaseRouter) InitDatabaseRouter(Router *gin.RouterGroup) { cmdRouter.POST("/conffile/update", baseApi.UpdateMysqlConfByFile) cmdRouter.POST("/search", baseApi.SearchMysql) cmdRouter.POST("/load/file", baseApi.LoadDatabaseFile) - cmdRouter.GET("/variables", baseApi.LoadVariables) - cmdRouter.GET("/status", baseApi.LoadStatus) - cmdRouter.GET("/baseinfo", baseApi.LoadBaseinfo) - cmdRouter.GET("/remote", baseApi.LoadRemoteAccess) + cmdRouter.POST("/variables", baseApi.LoadVariables) + cmdRouter.POST("/status", baseApi.LoadStatus) + cmdRouter.POST("/baseinfo", baseApi.LoadBaseinfo) + cmdRouter.POST("/remote", baseApi.LoadRemoteAccess) cmdRouter.GET("/options", baseApi.ListDBName) cmdRouter.GET("/redis/persistence/conf", baseApi.LoadPersistenceConf) @@ -43,12 +43,12 @@ func (s *DatabaseRouter) InitDatabaseRouter(Router *gin.RouterGroup) { cmdRouter.POST("/redis/conffile/update", baseApi.UpdateRedisConfByFile) cmdRouter.POST("/redis/persistence/update", baseApi.UpdateRedisPersistenceConf) - cmdRouter.POST("/remote/check", baseApi.CheckeRemoteDB) - cmdRouter.POST("/remote", baseApi.CreateRemoteDB) - cmdRouter.GET("/remote/:name", baseApi.GetRemoteDB) - cmdRouter.GET("/remote/list/:type", baseApi.ListRemoteDB) - cmdRouter.POST("/remote/update", baseApi.UpdateRemoteDB) - cmdRouter.POST("/remote/search", baseApi.SearchRemoteDB) - cmdRouter.POST("/remote/del", baseApi.DeleteRemoteDB) + cmdRouter.POST("/db/check", baseApi.CheckDatabase) + cmdRouter.POST("/db", baseApi.CreateDatabase) + cmdRouter.GET("/db/:name", baseApi.GetDatabase) + cmdRouter.GET("/db/list/:type", baseApi.ListDatabase) + cmdRouter.POST("/db/update", baseApi.UpdateDatabase) + cmdRouter.POST("/db/search", baseApi.SearchDatabase) + cmdRouter.POST("/db/del", baseApi.DeleteDatabase) } } diff --git a/backend/utils/mysql/client/local.go b/backend/utils/mysql/client/local.go index 431d65c42..f902f9480 100644 --- a/backend/utils/mysql/client/local.go +++ b/backend/utils/mysql/client/local.go @@ -164,7 +164,7 @@ func (r *Local) ChangePassword(info PasswordChangeInfo) error { if host == "%" || host == "localhost" { passwordRootChangeCMD := fmt.Sprintf("set password for 'root'@'%s' = password('%s')", host, info.Password) if !strings.HasPrefix(info.Version, "5.7") && !strings.HasPrefix(info.Version, "5.6") { - passwordRootChangeCMD = fmt.Sprintf("alter user 'root'@'%s' identified with mysql_native_password BY '%s';", host, info.Password) + passwordRootChangeCMD = fmt.Sprintf("alter user 'root'@'%s' identified by '%s';", host, info.Password) } if err := r.ExecSQL(passwordRootChangeCMD, info.Timeout); err != nil { return err diff --git a/backend/utils/mysql/client/remote.go b/backend/utils/mysql/client/remote.go index 810c90a6f..4d67dcc1f 100644 --- a/backend/utils/mysql/client/remote.go +++ b/backend/utils/mysql/client/remote.go @@ -169,7 +169,7 @@ func (r *Remote) ChangePassword(info PasswordChangeInfo) error { if host == "%" || host == "localhost" { passwordRootChangeCMD := fmt.Sprintf("set password for 'root'@'%s' = password('%s')", host, info.Password) if !strings.HasPrefix(info.Version, "5.7") && !strings.HasPrefix(info.Version, "5.6") { - passwordRootChangeCMD = fmt.Sprintf("alter user 'root'@'%s' identified with mysql_native_password BY '%s';", host, info.Password) + passwordRootChangeCMD = fmt.Sprintf("alter user 'root'@'%s' identified by '%s';", host, info.Password) } if err := r.ExecSQL(passwordRootChangeCMD, info.Timeout); err != nil { return err diff --git a/cmd/server/docs/docs.go b/cmd/server/docs/docs.go index 48277d00e..968abdc14 100644 --- a/cmd/server/docs/docs.go +++ b/cmd/server/docs/docs.go @@ -279,8 +279,8 @@ const docTemplate = `{ } } }, - "/apps/installed/check/:key": { - "get": { + "/apps/installed/check": { + "post": { "security": [ { "ApiKeyAuth": [] @@ -296,11 +296,13 @@ const docTemplate = `{ "summary": "Check app installed", "parameters": [ { - "type": "string", "description": "request", - "name": "key", - "in": "path", - "required": true + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.AppInstalledInfo" + } } ], "responses": { @@ -364,11 +366,13 @@ const docTemplate = `{ "summary": "Search app password by key", "parameters": [ { - "type": "string", "description": "request", - "name": "key", - "in": "path", - "required": true + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithNameAndType" + } } ], "responses": { @@ -488,8 +492,8 @@ const docTemplate = `{ } } }, - "/apps/installed/loadport/:key": { - "get": { + "/apps/installed/loadport": { + "post": { "security": [ { "ApiKeyAuth": [] @@ -505,11 +509,13 @@ const docTemplate = `{ "summary": "Search app port by key", "parameters": [ { - "type": "string", "description": "request", - "name": "key", - "in": "path", - "required": true + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithNameAndType" + } } ], "responses": { @@ -3699,17 +3705,31 @@ const docTemplate = `{ } }, "/databases/baseinfo": { - "get": { + "post": { "security": [ { "ApiKeyAuth": [] } ], "description": "获取 mysql 基础信息", + "consumes": [ + "application/json" + ], "tags": [ "Database Mysql" ], "summary": "Load mysql base info", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithNameAndType" + } + } + ], "responses": { "200": { "description": "OK", @@ -3935,7 +3955,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.OperateByID" + "$ref": "#/definitions/dto.MysqlDBDeleteCheck" } } ], @@ -4004,18 +4024,32 @@ const docTemplate = `{ } } }, - "/databases/load/:from": { - "get": { + "/databases/load": { + "post": { "security": [ { "ApiKeyAuth": [] } ], "description": "从服务器获取", + "consumes": [ + "application/json" + ], "tags": [ "Database Mysql" ], "summary": "Load mysql database from remote", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.MysqlLodaDB" + } + } + ], "responses": {} } }, @@ -4354,40 +4388,20 @@ const docTemplate = `{ } }, "/databases/remote": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 mysql 远程访问权限", - "tags": [ - "Database Mysql" - ], - "summary": "Load mysql remote access", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "boolean" - } - } - } - }, "post": { "security": [ { "ApiKeyAuth": [] } ], - "description": "创建远程数据库", + "description": "获取 mysql 远程访问权限", "consumes": [ "application/json" ], "tags": [ - "Database" + "Database Mysql" ], - "summary": "Create remote database", + "summary": "Load mysql remote access", "parameters": [ { "description": "request", @@ -4395,24 +4409,17 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.RemoteDBCreate" + "$ref": "#/definitions/dto.OperationWithNameAndType" } } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "type": "boolean" + } } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "name", - "type" - ], - "formatEN": "create remote database [name][type]", - "formatZH": "创建远程数据库 [name][type]", - "paramKeys": [] } } }, @@ -4432,7 +4439,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.RemoteDBInfo" + "$ref": "#/definitions/dto.DatabaseInfo" } } } @@ -4460,7 +4467,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.RemoteDBCreate" + "$ref": "#/definitions/dto.DatabaseCreate" } } ], @@ -4550,7 +4557,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/dto.RemoteDBOption" + "$ref": "#/definitions/dto.DatabaseOption" } } } @@ -4579,7 +4586,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.RemoteDBSearch" + "$ref": "#/definitions/dto.DatabaseSearch" } } ], @@ -4615,7 +4622,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.RemoteDBUpdate" + "$ref": "#/definitions/dto.DatabaseUpdate" } } ], @@ -4672,17 +4679,31 @@ const docTemplate = `{ } }, "/databases/status": { - "get": { + "post": { "security": [ { "ApiKeyAuth": [] } ], "description": "获取 mysql 状态信息", + "consumes": [ + "application/json" + ], "tags": [ "Database Mysql" ], "summary": "Load mysql status info", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithNameAndType" + } + } + ], "responses": { "200": { "description": "OK", @@ -4694,17 +4715,31 @@ const docTemplate = `{ } }, "/databases/variables": { - "get": { + "post": { "security": [ { "ApiKeyAuth": [] } ], "description": "获取 mysql 性能参数信息", + "consumes": [ + "application/json" + ], "tags": [ "Database Mysql" ], "summary": "Load mysql variables info", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithNameAndType" + } + } + ], "responses": { "200": { "description": "OK", @@ -8910,6 +8945,39 @@ const docTemplate = `{ } } }, + "/settings/snapshot/status": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取快照状态", + "consumes": [ + "application/json" + ], + "tags": [ + "System Setting" + ], + "summary": "Load Snapshot status", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperateByID" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/settings/ssl/download": { "post": { "security": [ @@ -11767,15 +11835,32 @@ const docTemplate = `{ "dto.ChangeDBInfo": { "type": "object", "required": [ + "database", + "from", + "type", "value" ], "properties": { - "from": { + "database": { "type": "string" }, + "from": { + "type": "string", + "enum": [ + "local", + "remote" + ] + }, "id": { "type": "integer" }, + "type": { + "type": "string", + "enum": [ + "mysql", + "mariadb" + ] + }, "value": { "type": "string" } @@ -11860,6 +11945,7 @@ const docTemplate = `{ "enum": [ "app", "mysql", + "mariadb", "redis", "website" ] @@ -11900,6 +11986,7 @@ const docTemplate = `{ "enum": [ "app", "mysql", + "mariadb", "redis", "website" ] @@ -12616,6 +12703,171 @@ const docTemplate = `{ } } }, + "dto.DatabaseCreate": { + "type": "object", + "required": [ + "from", + "name", + "password", + "type", + "username", + "version" + ], + "properties": { + "address": { + "type": "string" + }, + "description": { + "type": "string" + }, + "from": { + "type": "string", + "enum": [ + "local", + "remote" + ] + }, + "name": { + "type": "string", + "maxLength": 256 + }, + "password": { + "type": "string" + }, + "port": { + "type": "integer" + }, + "type": { + "type": "string", + "enum": [ + "mysql" + ] + }, + "username": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "dto.DatabaseInfo": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "from": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string", + "maxLength": 256 + }, + "password": { + "type": "string" + }, + "port": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "dto.DatabaseOption": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "database": { + "type": "string" + }, + "from": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "dto.DatabaseSearch": { + "type": "object", + "required": [ + "page", + "pageSize" + ], + "properties": { + "info": { + "type": "string" + }, + "order": { + "type": "string" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "type": { + "type": "string" + } + } + }, + "dto.DatabaseUpdate": { + "type": "object", + "required": [ + "password", + "username", + "version" + ], + "properties": { + "address": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "password": { + "type": "string" + }, + "port": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, "dto.DiskInfo": { "type": "object", "properties": { @@ -13205,20 +13457,29 @@ const docTemplate = `{ "dto.MysqlConfUpdateByFile": { "type": "object", "required": [ - "mysqlName" + "database", + "type" ], "properties": { + "database": { + "type": "string" + }, "file": { "type": "string" }, - "mysqlName": { - "type": "string" + "type": { + "type": "string", + "enum": [ + "mysql", + "mariadb" + ] } } }, "dto.MysqlDBCreate": { "type": "object", "required": [ + "database", "format", "from", "name", @@ -13227,6 +13488,9 @@ const docTemplate = `{ "username" ], "properties": { + "database": { + "type": "string" + }, "description": { "type": "string" }, @@ -13240,7 +13504,11 @@ const docTemplate = `{ ] }, "from": { - "type": "string" + "type": "string", + "enum": [ + "local", + "remote" + ] }, "name": { "type": "string" @@ -13259,9 +13527,14 @@ const docTemplate = `{ "dto.MysqlDBDelete": { "type": "object", "required": [ - "id" + "database", + "id", + "type" ], "properties": { + "database": { + "type": "string" + }, "deleteBackup": { "type": "boolean" }, @@ -13270,17 +13543,48 @@ const docTemplate = `{ }, "id": { "type": "integer" + }, + "type": { + "type": "string", + "enum": [ + "mysql", + "mariadb" + ] + } + } + }, + "dto.MysqlDBDeleteCheck": { + "type": "object", + "required": [ + "database", + "id", + "type" + ], + "properties": { + "database": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "type": { + "type": "string", + "enum": [ + "mysql", + "mariadb" + ] } } }, "dto.MysqlDBSearch": { "type": "object", "required": [ + "database", "page", "pageSize" ], "properties": { - "from": { + "database": { "type": "string" }, "info": { @@ -13300,17 +13604,44 @@ const docTemplate = `{ } } }, + "dto.MysqlLodaDB": { + "type": "object", + "required": [ + "database", + "from", + "type" + ], + "properties": { + "database": { + "type": "string" + }, + "from": { + "type": "string", + "enum": [ + "local", + "remote" + ] + }, + "type": { + "type": "string", + "enum": [ + "mysql", + "mariadb" + ] + } + } + }, "dto.MysqlOption": { "type": "object", "properties": { + "database": { + "type": "string" + }, "from": { "type": "string" }, "id": { "type": "integer" - }, - "name": { - "type": "string" } } }, @@ -13484,6 +13815,31 @@ const docTemplate = `{ } }, "dto.MysqlVariablesUpdate": { + "type": "object", + "required": [ + "database", + "type" + ], + "properties": { + "database": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "mysql", + "mariadb" + ] + }, + "variables": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.MysqlVariablesUpdateHelper" + } + } + } + }, + "dto.MysqlVariablesUpdateHelper": { "type": "object", "properties": { "param": { @@ -13907,162 +14263,6 @@ const docTemplate = `{ } } }, - "dto.RemoteDBCreate": { - "type": "object", - "required": [ - "from", - "name", - "password", - "type", - "username", - "version" - ], - "properties": { - "address": { - "type": "string" - }, - "description": { - "type": "string" - }, - "from": { - "type": "string", - "enum": [ - "local", - "remote" - ] - }, - "name": { - "type": "string", - "maxLength": 256 - }, - "password": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "type": { - "type": "string", - "enum": [ - "mysql" - ] - }, - "username": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.RemoteDBInfo": { - "type": "object", - "properties": { - "address": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "from": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string", - "maxLength": 256 - }, - "password": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "username": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.RemoteDBOption": { - "type": "object", - "properties": { - "address": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, - "dto.RemoteDBSearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "info": { - "type": "string" - }, - "order": { - "type": "string" - }, - "orderBy": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "type": { - "type": "string" - } - } - }, - "dto.RemoteDBUpdate": { - "type": "object", - "required": [ - "password", - "username", - "version" - ], - "properties": { - "address": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "password": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "username": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, "dto.ResourceLimit": { "type": "object", "properties": { @@ -14484,6 +14684,9 @@ const docTemplate = `{ "KODO", "OneDrive" ] + }, + "id": { + "type": "integer" } } }, @@ -15141,6 +15344,20 @@ const docTemplate = `{ } } }, + "request.AppInstalledInfo": { + "type": "object", + "required": [ + "key" + ], + "properties": { + "key": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "request.AppInstalledOperate": { "type": "object", "required": [ @@ -16938,6 +17155,12 @@ const docTemplate = `{ "createdAt": { "type": "string" }, + "httpPort": { + "type": "integer" + }, + "httpsPort": { + "type": "integer" + }, "installPath": { "type": "string" }, diff --git a/cmd/server/docs/swagger.json b/cmd/server/docs/swagger.json index aafcebab0..f84067e80 100644 --- a/cmd/server/docs/swagger.json +++ b/cmd/server/docs/swagger.json @@ -272,8 +272,8 @@ } } }, - "/apps/installed/check/:key": { - "get": { + "/apps/installed/check": { + "post": { "security": [ { "ApiKeyAuth": [] @@ -289,11 +289,13 @@ "summary": "Check app installed", "parameters": [ { - "type": "string", "description": "request", - "name": "key", - "in": "path", - "required": true + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/request.AppInstalledInfo" + } } ], "responses": { @@ -357,11 +359,13 @@ "summary": "Search app password by key", "parameters": [ { - "type": "string", "description": "request", - "name": "key", - "in": "path", - "required": true + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithNameAndType" + } } ], "responses": { @@ -481,8 +485,8 @@ } } }, - "/apps/installed/loadport/:key": { - "get": { + "/apps/installed/loadport": { + "post": { "security": [ { "ApiKeyAuth": [] @@ -498,11 +502,13 @@ "summary": "Search app port by key", "parameters": [ { - "type": "string", "description": "request", - "name": "key", - "in": "path", - "required": true + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithNameAndType" + } } ], "responses": { @@ -3692,17 +3698,31 @@ } }, "/databases/baseinfo": { - "get": { + "post": { "security": [ { "ApiKeyAuth": [] } ], "description": "获取 mysql 基础信息", + "consumes": [ + "application/json" + ], "tags": [ "Database Mysql" ], "summary": "Load mysql base info", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithNameAndType" + } + } + ], "responses": { "200": { "description": "OK", @@ -3928,7 +3948,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.OperateByID" + "$ref": "#/definitions/dto.MysqlDBDeleteCheck" } } ], @@ -3997,18 +4017,32 @@ } } }, - "/databases/load/:from": { - "get": { + "/databases/load": { + "post": { "security": [ { "ApiKeyAuth": [] } ], "description": "从服务器获取", + "consumes": [ + "application/json" + ], "tags": [ "Database Mysql" ], "summary": "Load mysql database from remote", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.MysqlLodaDB" + } + } + ], "responses": {} } }, @@ -4347,40 +4381,20 @@ } }, "/databases/remote": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "获取 mysql 远程访问权限", - "tags": [ - "Database Mysql" - ], - "summary": "Load mysql remote access", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "boolean" - } - } - } - }, "post": { "security": [ { "ApiKeyAuth": [] } ], - "description": "创建远程数据库", + "description": "获取 mysql 远程访问权限", "consumes": [ "application/json" ], "tags": [ - "Database" + "Database Mysql" ], - "summary": "Create remote database", + "summary": "Load mysql remote access", "parameters": [ { "description": "request", @@ -4388,24 +4402,17 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.RemoteDBCreate" + "$ref": "#/definitions/dto.OperationWithNameAndType" } } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "type": "boolean" + } } - }, - "x-panel-log": { - "BeforeFuntions": [], - "bodyKeys": [ - "name", - "type" - ], - "formatEN": "create remote database [name][type]", - "formatZH": "创建远程数据库 [name][type]", - "paramKeys": [] } } }, @@ -4425,7 +4432,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.RemoteDBInfo" + "$ref": "#/definitions/dto.DatabaseInfo" } } } @@ -4453,7 +4460,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.RemoteDBCreate" + "$ref": "#/definitions/dto.DatabaseCreate" } } ], @@ -4543,7 +4550,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/dto.RemoteDBOption" + "$ref": "#/definitions/dto.DatabaseOption" } } } @@ -4572,7 +4579,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.RemoteDBSearch" + "$ref": "#/definitions/dto.DatabaseSearch" } } ], @@ -4608,7 +4615,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.RemoteDBUpdate" + "$ref": "#/definitions/dto.DatabaseUpdate" } } ], @@ -4665,17 +4672,31 @@ } }, "/databases/status": { - "get": { + "post": { "security": [ { "ApiKeyAuth": [] } ], "description": "获取 mysql 状态信息", + "consumes": [ + "application/json" + ], "tags": [ "Database Mysql" ], "summary": "Load mysql status info", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithNameAndType" + } + } + ], "responses": { "200": { "description": "OK", @@ -4687,17 +4708,31 @@ } }, "/databases/variables": { - "get": { + "post": { "security": [ { "ApiKeyAuth": [] } ], "description": "获取 mysql 性能参数信息", + "consumes": [ + "application/json" + ], "tags": [ "Database Mysql" ], "summary": "Load mysql variables info", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperationWithNameAndType" + } + } + ], "responses": { "200": { "description": "OK", @@ -8903,6 +8938,39 @@ } } }, + "/settings/snapshot/status": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "获取快照状态", + "consumes": [ + "application/json" + ], + "tags": [ + "System Setting" + ], + "summary": "Load Snapshot status", + "parameters": [ + { + "description": "request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.OperateByID" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/settings/ssl/download": { "post": { "security": [ @@ -11760,15 +11828,32 @@ "dto.ChangeDBInfo": { "type": "object", "required": [ + "database", + "from", + "type", "value" ], "properties": { - "from": { + "database": { "type": "string" }, + "from": { + "type": "string", + "enum": [ + "local", + "remote" + ] + }, "id": { "type": "integer" }, + "type": { + "type": "string", + "enum": [ + "mysql", + "mariadb" + ] + }, "value": { "type": "string" } @@ -11853,6 +11938,7 @@ "enum": [ "app", "mysql", + "mariadb", "redis", "website" ] @@ -11893,6 +11979,7 @@ "enum": [ "app", "mysql", + "mariadb", "redis", "website" ] @@ -12609,6 +12696,171 @@ } } }, + "dto.DatabaseCreate": { + "type": "object", + "required": [ + "from", + "name", + "password", + "type", + "username", + "version" + ], + "properties": { + "address": { + "type": "string" + }, + "description": { + "type": "string" + }, + "from": { + "type": "string", + "enum": [ + "local", + "remote" + ] + }, + "name": { + "type": "string", + "maxLength": 256 + }, + "password": { + "type": "string" + }, + "port": { + "type": "integer" + }, + "type": { + "type": "string", + "enum": [ + "mysql" + ] + }, + "username": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "dto.DatabaseInfo": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": "string" + }, + "from": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string", + "maxLength": 256 + }, + "password": { + "type": "string" + }, + "port": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "dto.DatabaseOption": { + "type": "object", + "properties": { + "address": { + "type": "string" + }, + "database": { + "type": "string" + }, + "from": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "type": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "dto.DatabaseSearch": { + "type": "object", + "required": [ + "page", + "pageSize" + ], + "properties": { + "info": { + "type": "string" + }, + "order": { + "type": "string" + }, + "orderBy": { + "type": "string" + }, + "page": { + "type": "integer" + }, + "pageSize": { + "type": "integer" + }, + "type": { + "type": "string" + } + } + }, + "dto.DatabaseUpdate": { + "type": "object", + "required": [ + "password", + "username", + "version" + ], + "properties": { + "address": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "password": { + "type": "string" + }, + "port": { + "type": "integer" + }, + "username": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, "dto.DiskInfo": { "type": "object", "properties": { @@ -13198,20 +13450,29 @@ "dto.MysqlConfUpdateByFile": { "type": "object", "required": [ - "mysqlName" + "database", + "type" ], "properties": { + "database": { + "type": "string" + }, "file": { "type": "string" }, - "mysqlName": { - "type": "string" + "type": { + "type": "string", + "enum": [ + "mysql", + "mariadb" + ] } } }, "dto.MysqlDBCreate": { "type": "object", "required": [ + "database", "format", "from", "name", @@ -13220,6 +13481,9 @@ "username" ], "properties": { + "database": { + "type": "string" + }, "description": { "type": "string" }, @@ -13233,7 +13497,11 @@ ] }, "from": { - "type": "string" + "type": "string", + "enum": [ + "local", + "remote" + ] }, "name": { "type": "string" @@ -13252,9 +13520,14 @@ "dto.MysqlDBDelete": { "type": "object", "required": [ - "id" + "database", + "id", + "type" ], "properties": { + "database": { + "type": "string" + }, "deleteBackup": { "type": "boolean" }, @@ -13263,17 +13536,48 @@ }, "id": { "type": "integer" + }, + "type": { + "type": "string", + "enum": [ + "mysql", + "mariadb" + ] + } + } + }, + "dto.MysqlDBDeleteCheck": { + "type": "object", + "required": [ + "database", + "id", + "type" + ], + "properties": { + "database": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "type": { + "type": "string", + "enum": [ + "mysql", + "mariadb" + ] } } }, "dto.MysqlDBSearch": { "type": "object", "required": [ + "database", "page", "pageSize" ], "properties": { - "from": { + "database": { "type": "string" }, "info": { @@ -13293,17 +13597,44 @@ } } }, + "dto.MysqlLodaDB": { + "type": "object", + "required": [ + "database", + "from", + "type" + ], + "properties": { + "database": { + "type": "string" + }, + "from": { + "type": "string", + "enum": [ + "local", + "remote" + ] + }, + "type": { + "type": "string", + "enum": [ + "mysql", + "mariadb" + ] + } + } + }, "dto.MysqlOption": { "type": "object", "properties": { + "database": { + "type": "string" + }, "from": { "type": "string" }, "id": { "type": "integer" - }, - "name": { - "type": "string" } } }, @@ -13477,6 +13808,31 @@ } }, "dto.MysqlVariablesUpdate": { + "type": "object", + "required": [ + "database", + "type" + ], + "properties": { + "database": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "mysql", + "mariadb" + ] + }, + "variables": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.MysqlVariablesUpdateHelper" + } + } + } + }, + "dto.MysqlVariablesUpdateHelper": { "type": "object", "properties": { "param": { @@ -13900,162 +14256,6 @@ } } }, - "dto.RemoteDBCreate": { - "type": "object", - "required": [ - "from", - "name", - "password", - "type", - "username", - "version" - ], - "properties": { - "address": { - "type": "string" - }, - "description": { - "type": "string" - }, - "from": { - "type": "string", - "enum": [ - "local", - "remote" - ] - }, - "name": { - "type": "string", - "maxLength": 256 - }, - "password": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "type": { - "type": "string", - "enum": [ - "mysql" - ] - }, - "username": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.RemoteDBInfo": { - "type": "object", - "properties": { - "address": { - "type": "string" - }, - "createdAt": { - "type": "string" - }, - "description": { - "type": "string" - }, - "from": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string", - "maxLength": 256 - }, - "password": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "username": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, - "dto.RemoteDBOption": { - "type": "object", - "properties": { - "address": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, - "dto.RemoteDBSearch": { - "type": "object", - "required": [ - "page", - "pageSize" - ], - "properties": { - "info": { - "type": "string" - }, - "order": { - "type": "string" - }, - "orderBy": { - "type": "string" - }, - "page": { - "type": "integer" - }, - "pageSize": { - "type": "integer" - }, - "type": { - "type": "string" - } - } - }, - "dto.RemoteDBUpdate": { - "type": "object", - "required": [ - "password", - "username", - "version" - ], - "properties": { - "address": { - "type": "string" - }, - "description": { - "type": "string" - }, - "id": { - "type": "integer" - }, - "password": { - "type": "string" - }, - "port": { - "type": "integer" - }, - "username": { - "type": "string" - }, - "version": { - "type": "string" - } - } - }, "dto.ResourceLimit": { "type": "object", "properties": { @@ -14477,6 +14677,9 @@ "KODO", "OneDrive" ] + }, + "id": { + "type": "integer" } } }, @@ -15134,6 +15337,20 @@ } } }, + "request.AppInstalledInfo": { + "type": "object", + "required": [ + "key" + ], + "properties": { + "key": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, "request.AppInstalledOperate": { "type": "object", "required": [ @@ -16931,6 +17148,12 @@ "createdAt": { "type": "string" }, + "httpPort": { + "type": "integer" + }, + "httpsPort": { + "type": "integer" + }, "installPath": { "type": "string" }, diff --git a/cmd/server/docs/swagger.yaml b/cmd/server/docs/swagger.yaml index d2e96d15b..e51ee5b3d 100644 --- a/cmd/server/docs/swagger.yaml +++ b/cmd/server/docs/swagger.yaml @@ -131,13 +131,26 @@ definitions: type: object dto.ChangeDBInfo: properties: + database: + type: string from: + enum: + - local + - remote type: string id: type: integer + type: + enum: + - mysql + - mariadb + type: string value: type: string required: + - database + - from + - type - value type: object dto.ChangeHostGroup: @@ -191,6 +204,7 @@ definitions: enum: - app - mysql + - mariadb - redis - website type: string @@ -220,6 +234,7 @@ definitions: enum: - app - mysql + - mariadb - redis - website type: string @@ -703,6 +718,118 @@ definitions: uptime: type: integer type: object + dto.DatabaseCreate: + properties: + address: + type: string + description: + type: string + from: + enum: + - local + - remote + type: string + name: + maxLength: 256 + type: string + password: + type: string + port: + type: integer + type: + enum: + - mysql + type: string + username: + type: string + version: + type: string + required: + - from + - name + - password + - type + - username + - version + type: object + dto.DatabaseInfo: + properties: + address: + type: string + createdAt: + type: string + description: + type: string + from: + type: string + id: + type: integer + name: + maxLength: 256 + type: string + password: + type: string + port: + type: integer + username: + type: string + version: + type: string + type: object + dto.DatabaseOption: + properties: + address: + type: string + database: + type: string + from: + type: string + id: + type: integer + type: + type: string + version: + type: string + type: object + dto.DatabaseSearch: + properties: + info: + type: string + order: + type: string + orderBy: + type: string + page: + type: integer + pageSize: + type: integer + type: + type: string + required: + - page + - pageSize + type: object + dto.DatabaseUpdate: + properties: + address: + type: string + description: + type: string + id: + type: integer + password: + type: string + port: + type: integer + username: + type: string + version: + type: string + required: + - password + - username + - version + type: object dto.DiskInfo: properties: device: @@ -1100,15 +1227,23 @@ definitions: type: object dto.MysqlConfUpdateByFile: properties: + database: + type: string file: type: string - mysqlName: + type: + enum: + - mysql + - mariadb type: string required: - - mysqlName + - database + - type type: object dto.MysqlDBCreate: properties: + database: + type: string description: type: string format: @@ -1119,6 +1254,9 @@ definitions: - big5 type: string from: + enum: + - local + - remote type: string name: type: string @@ -1129,6 +1267,7 @@ definitions: username: type: string required: + - database - format - from - name @@ -1138,18 +1277,43 @@ definitions: type: object dto.MysqlDBDelete: properties: + database: + type: string deleteBackup: type: boolean forceDelete: type: boolean id: type: integer + type: + enum: + - mysql + - mariadb + type: string required: + - database - id + - type + type: object + dto.MysqlDBDeleteCheck: + properties: + database: + type: string + id: + type: integer + type: + enum: + - mysql + - mariadb + type: string + required: + - database + - id + - type type: object dto.MysqlDBSearch: properties: - from: + database: type: string info: type: string @@ -1162,17 +1326,37 @@ definitions: pageSize: type: integer required: + - database - page - pageSize type: object + dto.MysqlLodaDB: + properties: + database: + type: string + from: + enum: + - local + - remote + type: string + type: + enum: + - mysql + - mariadb + type: string + required: + - database + - from + - type + type: object dto.MysqlOption: properties: + database: + type: string from: type: string id: type: integer - name: - type: string type: object dto.MysqlStatus: properties: @@ -1287,6 +1471,23 @@ definitions: type: string type: object dto.MysqlVariablesUpdate: + properties: + database: + type: string + type: + enum: + - mysql + - mariadb + type: string + variables: + items: + $ref: '#/definitions/dto.MysqlVariablesUpdateHelper' + type: array + required: + - database + - type + type: object + dto.MysqlVariablesUpdateHelper: properties: param: type: string @@ -1571,112 +1772,6 @@ definitions: used_memory_rss: type: string type: object - dto.RemoteDBCreate: - properties: - address: - type: string - description: - type: string - from: - enum: - - local - - remote - type: string - name: - maxLength: 256 - type: string - password: - type: string - port: - type: integer - type: - enum: - - mysql - type: string - username: - type: string - version: - type: string - required: - - from - - name - - password - - type - - username - - version - type: object - dto.RemoteDBInfo: - properties: - address: - type: string - createdAt: - type: string - description: - type: string - from: - type: string - id: - type: integer - name: - maxLength: 256 - type: string - password: - type: string - port: - type: integer - username: - type: string - version: - type: string - type: object - dto.RemoteDBOption: - properties: - address: - type: string - id: - type: integer - name: - type: string - type: object - dto.RemoteDBSearch: - properties: - info: - type: string - order: - type: string - orderBy: - type: string - page: - type: integer - pageSize: - type: integer - type: - type: string - required: - - page - - pageSize - type: object - dto.RemoteDBUpdate: - properties: - address: - type: string - description: - type: string - id: - type: integer - password: - type: string - port: - type: integer - username: - type: string - version: - type: string - required: - - password - - username - - version - type: object dto.ResourceLimit: properties: cpu: @@ -1957,6 +2052,8 @@ definitions: - KODO - OneDrive type: string + id: + type: integer required: - from type: object @@ -2391,6 +2488,15 @@ definitions: - detailID - operate type: object + request.AppInstalledInfo: + properties: + key: + type: string + name: + type: string + required: + - key + type: object request.AppInstalledOperate: properties: backup: @@ -3601,6 +3707,10 @@ definitions: type: string createdAt: type: string + httpPort: + type: integer + httpsPort: + type: integer installPath: type: string isExist: @@ -4077,17 +4187,18 @@ paths: summary: Search app update version by install id tags: - App - /apps/installed/check/:key: - get: + /apps/installed/check: + post: consumes: - application/json description: 检查应用安装情况 parameters: - description: request - in: path - name: key + in: body + name: request required: true - type: string + schema: + $ref: '#/definitions/request.AppInstalledInfo' responses: "200": description: OK @@ -4126,10 +4237,11 @@ paths: description: 获取应用连接信息 parameters: - description: request - in: path - name: key + in: body + name: request required: true - type: string + schema: + $ref: '#/definitions/dto.OperationWithNameAndType' responses: "200": description: OK @@ -4207,17 +4319,18 @@ paths: summary: List app installed tags: - App - /apps/installed/loadport/:key: - get: + /apps/installed/loadport: + post: consumes: - application/json description: 获取应用端口 parameters: - description: request - in: path - name: key + in: body + name: request required: true - type: string + schema: + $ref: '#/definitions/dto.OperationWithNameAndType' responses: "200": description: OK @@ -6250,8 +6363,17 @@ paths: formatZH: 创建 mysql 数据库 [name] paramKeys: [] /databases/baseinfo: - get: + post: + consumes: + - application/json description: 获取 mysql 基础信息 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.OperationWithNameAndType' responses: "200": description: OK @@ -6398,7 +6520,7 @@ paths: name: request required: true schema: - $ref: '#/definitions/dto.OperateByID' + $ref: '#/definitions/dto.MysqlDBDeleteCheck' responses: "200": description: OK @@ -6445,9 +6567,18 @@ paths: formatEN: The description of the mysql database [name] is modified => [description] formatZH: mysql 数据库 [name] 描述信息修改 [description] paramKeys: [] - /databases/load/:from: - get: + /databases/load: + post: + consumes: + - application/json description: 从服务器获取 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.MysqlLodaDB' responses: {} security: - ApiKeyAuth: [] @@ -6664,8 +6795,17 @@ paths: tags: - Database Redis /databases/remote: - get: + post: + consumes: + - application/json description: 获取 mysql 远程访问权限 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.OperationWithNameAndType' responses: "200": description: OK @@ -6676,33 +6816,6 @@ paths: summary: Load mysql remote access tags: - Database Mysql - post: - consumes: - - application/json - description: 创建远程数据库 - parameters: - - description: request - in: body - name: request - required: true - schema: - $ref: '#/definitions/dto.RemoteDBCreate' - responses: - "200": - description: OK - security: - - ApiKeyAuth: [] - summary: Create remote database - tags: - - Database - x-panel-log: - BeforeFuntions: [] - bodyKeys: - - name - - type - formatEN: create remote database [name][type] - formatZH: 创建远程数据库 [name][type] - paramKeys: [] /databases/remote/:name: get: description: 获取远程数据库 @@ -6710,7 +6823,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/dto.RemoteDBInfo' + $ref: '#/definitions/dto.DatabaseInfo' security: - ApiKeyAuth: [] summary: Get remote databases @@ -6727,7 +6840,7 @@ paths: name: request required: true schema: - $ref: '#/definitions/dto.RemoteDBCreate' + $ref: '#/definitions/dto.DatabaseCreate' responses: "200": description: OK @@ -6785,7 +6898,7 @@ paths: description: OK schema: items: - $ref: '#/definitions/dto.RemoteDBOption' + $ref: '#/definitions/dto.DatabaseOption' type: array security: - ApiKeyAuth: [] @@ -6803,7 +6916,7 @@ paths: name: request required: true schema: - $ref: '#/definitions/dto.RemoteDBSearch' + $ref: '#/definitions/dto.DatabaseSearch' responses: "200": description: OK @@ -6825,7 +6938,7 @@ paths: name: request required: true schema: - $ref: '#/definitions/dto.RemoteDBUpdate' + $ref: '#/definitions/dto.DatabaseUpdate' responses: "200": description: OK @@ -6864,8 +6977,17 @@ paths: tags: - Database Mysql /databases/status: - get: + post: + consumes: + - application/json description: 获取 mysql 状态信息 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.OperationWithNameAndType' responses: "200": description: OK @@ -6877,8 +6999,17 @@ paths: tags: - Database Mysql /databases/variables: - get: + post: + consumes: + - application/json description: 获取 mysql 性能参数信息 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.OperationWithNameAndType' responses: "200": description: OK @@ -9555,6 +9686,26 @@ paths: summary: Page system snapshot tags: - System Setting + /settings/snapshot/status: + post: + consumes: + - application/json + description: 获取快照状态 + parameters: + - description: request + in: body + name: request + required: true + schema: + $ref: '#/definitions/dto.OperateByID' + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: Load Snapshot status + tags: + - System Setting /settings/ssl/download: post: description: 下载证书 diff --git a/frontend/src/api/interface/database.ts b/frontend/src/api/interface/database.ts index 531064588..f18d17b80 100644 --- a/frontend/src/api/interface/database.ts +++ b/frontend/src/api/interface/database.ts @@ -3,7 +3,7 @@ import { ReqPage } from '.'; export namespace Database { export interface SearchDBWithPage { info: string; - from: string; + database: string; page: number; pageSize: number; orderBy?: string; @@ -34,19 +34,34 @@ export namespace Database { containerName: string; } export interface MysqlConfUpdateByFile { - mysqlName: string; + type: string; + database: string; file: string; } export interface MysqlDBCreate { name: string; + from: string; + database: string; format: string; username: string; password: string; permission: string; description: string; } + export interface MysqlLodaDB { + from: string; + type: string; + database: string; + } + export interface MysqlDBDeleteCheck { + id: number; + type: string; + database: string; + } export interface MysqlDBDelete { id: number; + type: string; + database: string; forceDelete: boolean; deleteBackup: boolean; } @@ -71,6 +86,11 @@ export namespace Database { long_query_time: number; } export interface VariablesUpdate { + type: string; + database: string; + variables: Array; + } + export interface VariablesUpdateHelper { param: string; value: any; } @@ -118,6 +138,9 @@ export namespace Database { } export interface ChangeInfo { id: number; + from: string; + type: string; + database: string; value: string; } @@ -177,7 +200,7 @@ export namespace Database { } // remote - export interface RemoteDBInfo { + export interface DatabaseInfo { id: number; createdAt: Date; name: string; @@ -190,7 +213,7 @@ export namespace Database { password: string; description: string; } - export interface SearchRemoteDBPage { + export interface SearchDatabasePage { info: string; type: string; page: number; @@ -198,12 +221,15 @@ export namespace Database { orderBy?: string; order?: string; } - export interface RemoteDBOption { + export interface DatabaseOption { id: number; - name: string; + from: string; + type: string; + database: string; + version: string; address: string; } - export interface RemoteDBCreate { + export interface DatabaseCreate { name: string; version: string; from: string; @@ -213,7 +239,7 @@ export namespace Database { password: string; description: string; } - export interface RemoteDBUpdate { + export interface DatabaseUpdate { id: number; version: string; address: string; diff --git a/frontend/src/api/modules/app.ts b/frontend/src/api/modules/app.ts index 6315787d1..2de2fc784 100644 --- a/frontend/src/api/modules/app.ts +++ b/frontend/src/api/modules/app.ts @@ -46,16 +46,16 @@ export const ListAppInstalled = () => { return http.get>('apps/installed/list'); }; -export const GetAppPort = (key: string) => { - return http.get(`apps/installed/loadport/${key}`); +export const GetAppPort = (type: string, name: string) => { + return http.post(`apps/installed/loadport`, { type: type, name: name }); }; -export const GetAppConnInfo = (key: string) => { - return http.get(`apps/installed/conninfo/${key}`); +export const GetAppConnInfo = (type: string, name: string) => { + return http.post(`apps/installed/conninfo`, { type: type, name: name }); }; -export const CheckAppInstalled = (key: string) => { - return http.get(`apps/installed/check/${key}`); +export const CheckAppInstalled = (key: string, name: string) => { + return http.post(`apps/installed/check`, { key: key, name: name }); }; export const AppInstalledDeleteCheck = (appInstallId: number) => { diff --git a/frontend/src/api/modules/database.ts b/frontend/src/api/modules/database.ts index 24a52813d..98650dee8 100644 --- a/frontend/src/api/modules/database.ts +++ b/frontend/src/api/modules/database.ts @@ -7,8 +7,8 @@ import { Database } from '../interface/database'; export const searchMysqlDBs = (params: Database.SearchDBWithPage) => { return http.post>(`/databases/search`, params); }; -export const loadDatabaseFile = (type: string, name: string) => { - return http.post(`/databases/load/file`, { type: type, name: name }); +export const loadDatabaseFile = (type: string, database: string) => { + return http.post(`/databases/load/file`, { type: type, name: database }); }; export const addMysqlDB = (params: Database.MysqlDBCreate) => { @@ -18,8 +18,8 @@ export const addMysqlDB = (params: Database.MysqlDBCreate) => { } return http.post(`/databases`, reqest); }; -export const loadDBFromRemote = (from: string) => { - return http.get(`/databases/load/${from}`); +export const loadDBFromRemote = (params: Database.MysqlLodaDB) => { + return http.post(`/databases/load`, params); }; export const updateMysqlAccess = (params: Database.ChangeInfo) => { return http.post(`/databases/change/access`, params); @@ -34,30 +34,30 @@ export const updateMysqlPassword = (params: Database.ChangeInfo) => { export const updateMysqlDescription = (params: DescriptionUpdate) => { return http.post(`/databases/description/update`, params); }; -export const updateMysqlVariables = (params: Array) => { +export const updateMysqlVariables = (params: Database.VariablesUpdate) => { return http.post(`/databases/variables/update`, params); }; export const updateMysqlConfByFile = (params: Database.MysqlConfUpdateByFile) => { return http.post(`/databases/conffile/update`, params); }; -export const deleteCheckMysqlDB = (id: number) => { - return http.post>(`/databases/del/check`, { id: id }); +export const deleteCheckMysqlDB = (params: Database.MysqlDBDeleteCheck) => { + return http.post>(`/databases/del/check`, params); }; export const deleteMysqlDB = (params: Database.MysqlDBDelete) => { return http.post(`/databases/del`, params); }; -export const loadMysqlBaseInfo = () => { - return http.get(`/databases/baseinfo`); +export const loadMysqlBaseInfo = (type: string, database: string) => { + return http.post(`/databases/baseinfo`, { type: type, name: database }); }; -export const loadMysqlVariables = () => { - return http.get(`/databases/variables`); +export const loadMysqlVariables = (type: string, database: string) => { + return http.post(`/databases/variables`, { type: type, name: database }); }; -export const loadMysqlStatus = () => { - return http.get(`/databases/status`); +export const loadMysqlStatus = (type: string, database: string) => { + return http.post(`/databases/status`, { type: type, name: database }); }; -export const loadRemoteAccess = () => { - return http.get(`/databases/remote`); +export const loadRemoteAccess = (type: string, database: string) => { + return http.post(`/databases/remote`, { type: type, name: database }); }; export const loadDBOptions = () => { return http.get>(`/databases/options`); @@ -90,25 +90,25 @@ export const updateRedisConfByFile = (params: Database.RedisConfUpdateByFile) => return http.post(`/databases/redis/conffile/update`, params); }; -// remote -export const getRemoteDB = (name: string) => { - return http.get(`/databases/remote/${name}`); +// databasae +export const getDatabase = (name: string) => { + return http.get(`/databases/db/${name}`); }; -export const searchRemoteDBs = (params: Database.SearchRemoteDBPage) => { - return http.post>(`/databases/remote/search`, params); +export const searchDatabases = (params: Database.SearchDatabasePage) => { + return http.post>(`/databases/db/search`, params); }; -export const listRemoteDBs = (type: string) => { - return http.get>(`/databases/remote/list/${type}`); +export const listDatabases = (type: string) => { + return http.get>(`/databases/db/list/${type}`); }; -export const checkRemoteDB = (params: Database.RemoteDBCreate) => { - return http.post(`/databases/remote/check`, params, 40000); +export const checkDatabase = (params: Database.DatabaseCreate) => { + return http.post(`/databases/db/check`, params, 40000); }; -export const addRemoteDB = (params: Database.RemoteDBCreate) => { - return http.post(`/databases/remote`, params, 40000); +export const addDatabase = (params: Database.DatabaseCreate) => { + return http.post(`/databases/db`, params, 40000); }; -export const editRemoteDB = (params: Database.RemoteDBUpdate) => { - return http.post(`/databases/remote/update`, params, 40000); +export const editDatabase = (params: Database.DatabaseUpdate) => { + return http.post(`/databases/db/update`, params, 40000); }; -export const deleteRemoteDB = (id: number) => { - return http.post(`/databases/remote/del`, { id: id }); +export const deleteDatabase = (id: number) => { + return http.post(`/databases/db/del`, { id: id }); }; diff --git a/frontend/src/components/app-status/index.vue b/frontend/src/components/app-status/index.vue index 04c994d4d..513ac2837 100644 --- a/frontend/src/components/app-status/index.vue +++ b/frontend/src/components/app-status/index.vue @@ -73,7 +73,7 @@ diff --git a/frontend/src/components/upload/index.vue b/frontend/src/components/upload/index.vue index ddc2900fa..eb46f66f3 100644 --- a/frontend/src/components/upload/index.vue +++ b/frontend/src/components/upload/index.vue @@ -126,10 +126,11 @@ const acceptParams = async (params: DialogProps): Promise => { if (type.value === 'website' || type.value === 'app') { title.value = name.value; } + let dir = type.value === 'mysql' || type.value === 'mariadb' ? 'database/' + type.value : type.value; if (detailName.value) { - baseDir.value = `${pathRes.data}/uploads/${type.value}/${name.value}/${detailName.value}/`; + baseDir.value = `${pathRes.data}/uploads/${dir}/${name.value}/${detailName.value}/`; } else { - baseDir.value = `${pathRes.data}/uploads/${type.value}/${name.value}/`; + baseDir.value = `${pathRes.data}/uploads/${dir}/${name.value}/`; } upVisiable.value = true; search(); diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 94d105618..3b81a20fd 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -346,6 +346,7 @@ const message = { loadFromRemoteHelper: 'This action will synchronize the database info on the server to 1Panel, do you want to continue?', passwordHelper: 'Unable to retrieve, please modify', + local: 'Local', remote: 'Remote', remoteDB: 'Remote DB', createRemoteDB: 'Create Remote Server', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index 80ffd370b..02b906350 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -340,6 +340,7 @@ const message = { loadFromRemote: '從服務器獲取', loadFromRemoteHelper: '此操作將同步服務器上數據庫信息到 1Panel,是否繼續?', passwordHelper: '無法獲取密碼,請修改', + local: '本地', remote: '遠程', remoteDB: '遠程服務器', createRemoteDB: '添加遠程服務器', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 9d3ea8590..0eadb2787 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -340,6 +340,7 @@ const message = { loadFromRemote: '从服务器获取', loadFromRemoteHelper: '此操作将同步服务器上数据库信息到 1Panel,是否继续?', passwordHelper: '无法获取密码,请修改', + local: '本地', remote: '远程', remoteDB: '远程服务器', createRemoteDB: '添加远程服务器', diff --git a/frontend/src/routers/modules/database.ts b/frontend/src/routers/modules/database.ts index 2fc320484..38c71b7fe 100644 --- a/frontend/src/routers/modules/database.ts +++ b/frontend/src/routers/modules/database.ts @@ -28,9 +28,10 @@ const databaseRouter = { }, }, { - path: 'mysql/setting', + path: 'mysql/setting/:type/:database', name: 'MySQL-Setting', component: () => import('@/views/database/mysql/setting/index.vue'), + props: true, hidden: true, meta: { activeMenu: '/databases', diff --git a/frontend/src/views/database/mysql/conn/index.vue b/frontend/src/views/database/mysql/conn/index.vue index def3acea3..be7360f26 100644 --- a/frontend/src/views/database/mysql/conn/index.vue +++ b/frontend/src/views/database/mysql/conn/index.vue @@ -97,7 +97,7 @@ import { reactive, ref } from 'vue'; import { Rules } from '@/global/form-rules'; import i18n from '@/lang'; import { ElForm } from 'element-plus'; -import { getRemoteDB, loadRemoteAccess, updateMysqlAccess, updateMysqlPassword } from '@/api/modules/database'; +import { getDatabase, loadRemoteAccess, updateMysqlAccess, updateMysqlPassword } from '@/api/modules/database'; import ConfirmDialog from '@/components/confirm-dialog/index.vue'; import { GetAppConnInfo } from '@/api/modules/app'; import DrawerHeader from '@/components/drawer-header/index.vue'; @@ -118,6 +118,8 @@ const form = reactive({ port: 0, from: '', + type: '', + database: '', username: '', remoteIP: '', }); @@ -130,15 +132,16 @@ const formRef = ref(); interface DialogProps { from: string; - remoteIP: string; + type: string; + database: string; } const acceptParams = (param: DialogProps): void => { form.password = ''; form.from = param.from; - if (form.from === 'local') { - loadAccess(); - } + form.type = param.type; + form.database = param.database; + loadAccess(); loadPassword(); dialogVisiable.value = true; }; @@ -167,8 +170,10 @@ const handleClose = () => { }; const loadAccess = async () => { - const res = await loadRemoteAccess(); - form.privilege = res.data; + if (form.from === 'local') { + const res = await loadRemoteAccess(form.type, form.database); + form.privilege = res.data; + } }; const loadSystemIP = async () => { @@ -178,14 +183,14 @@ const loadSystemIP = async () => { const loadPassword = async () => { if (form.from === 'local') { - const res = await GetAppConnInfo('mysql'); + const res = await GetAppConnInfo(form.type, form.database); form.password = res.data.password || ''; form.port = res.data.port || 3306; form.serviceName = res.data.serviceName || ''; loadSystemIP(); return; } - const res = await getRemoteDB(form.from); + const res = await getDatabase(form.database); form.password = res.data.password || ''; form.port = res.data.port || 3306; form.username = res.data.username; @@ -197,6 +202,8 @@ const onSubmit = async () => { let param = { id: 0, from: form.from, + type: form.type, + database: form.database, value: form.password, }; loading.value = true; @@ -228,6 +235,8 @@ const onSubmitAccess = async () => { let param = { id: 0, from: form.from, + type: form.type, + database: form.database, value: form.privilege ? '%' : 'localhost', }; loading.value = true; diff --git a/frontend/src/views/database/mysql/create/index.vue b/frontend/src/views/database/mysql/create/index.vue index efec6ff0e..5fa477dba 100644 --- a/frontend/src/views/database/mysql/create/index.vue +++ b/frontend/src/views/database/mysql/create/index.vue @@ -91,7 +91,7 @@ const createVisiable = ref(false); const form = reactive({ name: '', from: 'local', - mysqlName: '', + database: '', format: '', username: '', password: '', @@ -111,12 +111,12 @@ const formRef = ref(); interface DialogProps { from: string; - mysqlName: string; + database: string; } const acceptParams = (params: DialogProps): void => { form.name = ''; form.from = params.from; - form.mysqlName = params.mysqlName; + form.database = params.database; form.format = 'utf8mb4'; form.username = ''; form.permission = '%'; diff --git a/frontend/src/views/database/mysql/delete/index.vue b/frontend/src/views/database/mysql/delete/index.vue index aba38730a..9f959330a 100644 --- a/frontend/src/views/database/mysql/delete/index.vue +++ b/frontend/src/views/database/mysql/delete/index.vue @@ -48,6 +48,8 @@ import { MsgSuccess } from '@/utils/message'; let deleteReq = ref({ id: 0, + type: '', + database: '', deleteBackup: false, forceDelete: false, }); @@ -60,13 +62,17 @@ const deleteForm = ref(); interface DialogProps { id: number; + type: string; name: string; + database: string; } const emit = defineEmits<{ (e: 'search'): void }>(); const acceptParams = async (prop: DialogProps) => { deleteReq.value = { id: prop.id, + type: prop.type, + database: prop.database, deleteBackup: false, forceDelete: false, }; diff --git a/frontend/src/views/database/mysql/index.vue b/frontend/src/views/database/mysql/index.vue index b2c3a6eea..209afcedc 100644 --- a/frontend/src/views/database/mysql/index.vue +++ b/frontend/src/views/database/mysql/index.vue @@ -1,9 +1,21 @@