Browse Source

feat: PostgreSQL 支持从服务器获取功能 (#3526)

pull/3530/head
ssongliu 11 months ago committed by GitHub
parent
commit
39818b8424
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 28
      backend/app/api/v1/database.go
  2. 75
      backend/app/api/v1/database_common.go
  3. 46
      backend/app/api/v1/database_mysql.go
  4. 79
      backend/app/api/v1/database_postgresql.go
  5. 46
      backend/app/api/v1/database_redis.go
  6. 1
      backend/app/api/v1/entry.go
  7. 39
      backend/app/dto/database.go
  8. 7
      backend/app/dto/database_postgresql.go
  9. 94
      backend/app/service/database_common.go
  10. 62
      backend/app/service/database_mysql.go
  11. 95
      backend/app/service/database_postgresql.go
  12. 8
      backend/init/migration/migrations/v_1_9.go
  13. 14
      backend/router/ro_database.go
  14. 1
      backend/utils/postgresql/client.go
  15. 339
      cmd/server/docs/docs.go
  16. 339
      cmd/server/docs/swagger.json
  17. 232
      cmd/server/docs/swagger.yaml
  18. 9
      frontend/src/api/interface/database.ts
  19. 40
      frontend/src/api/modules/database.ts
  20. 1
      frontend/src/lang/modules/en.ts
  21. 1
      frontend/src/lang/modules/tw.ts
  22. 1
      frontend/src/lang/modules/zh.ts
  23. 4
      frontend/src/views/database/mysql/bind/index.vue
  24. 1
      frontend/src/views/database/mysql/index.vue
  25. 8
      frontend/src/views/database/mysql/setting/index.vue
  26. 4
      frontend/src/views/database/mysql/setting/slow-log/index.vue
  27. 103
      frontend/src/views/database/postgresql/bind/index.vue
  28. 41
      frontend/src/views/database/postgresql/index.vue
  29. 8
      frontend/src/views/database/postgresql/setting/index.vue
  30. 9
      frontend/src/views/database/redis/setting/index.vue
  31. 4
      go.mod

28
backend/app/api/v1/database.go

@ -227,31 +227,3 @@ func (b *BaseApi) UpdateDatabase(c *gin.Context) {
}
helper.SuccessWithData(c, nil)
}
// @Tags Database
// @Summary Load Database file
// @Description 获取数据库文件
// @Accept json
// @Param request body dto.OperationWithNameAndType true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /databases/load/file [post]
func (b *BaseApi) LoadDatabaseFile(c *gin.Context) {
var req dto.OperationWithNameAndType
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
var content string
var err error
switch req.Name {
case constant.AppPostgresql:
content, err = postgresqlService.LoadDatabaseFile(req)
default:
content, err = mysqlService.LoadDatabaseFile(req)
}
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, content)
}

75
backend/app/api/v1/database_common.go

@ -0,0 +1,75 @@
package v1
import (
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/gin-gonic/gin"
)
// @Tags Database Common
// @Summary Load base info
// @Description 获取数据库基础信息
// @Accept json
// @Param request body dto.OperationWithNameAndType true "request"
// @Success 200 {object} dto.DBBaseInfo
// @Security ApiKeyAuth
// @Router /databases/common/info [post]
func (b *BaseApi) LoadDBBaseInfo(c *gin.Context) {
var req dto.OperationWithNameAndType
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := dbCommonService.LoadBaseInfo(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags Database Common
// @Summary Load Database conf
// @Description 获取数据库配置文件
// @Accept json
// @Param request body dto.OperationWithNameAndType true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /databases/common/load/file [post]
func (b *BaseApi) LoadDBFile(c *gin.Context) {
var req dto.OperationWithNameAndType
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
content, err := dbCommonService.LoadDatabaseFile(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, content)
}
// @Tags Database Common
// @Summary Update conf by upload file
// @Description 上传替换配置文件
// @Accept json
// @Param request body dto.DBConfUpdateByFile true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /databases/common/update/conf [post]
// @x-panel-log {"bodyKeys":["type","database"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 [type] 数据库 [database] 配置信息","formatEN":"update the [type] [database] database configuration information"}
func (b *BaseApi) UpdateDBConfByFile(c *gin.Context) {
var req dto.DBConfUpdateByFile
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := dbCommonService.UpdateConfByFile(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}

46
backend/app/api/v1/database_mysql.go

@ -169,29 +169,6 @@ func (b *BaseApi) UpdateMysqlVariables(c *gin.Context) {
helper.SuccessWithData(c, nil)
}
// @Tags Database Mysql
// @Summary Update mysql conf by upload file
// @Description 上传替换 mysql 配置文件
// @Accept json
// @Param request body dto.MysqlConfUpdateByFile true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /databases/conffile/update [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 mysql 数据库配置信息","formatEN":"update the mysql database configuration information"}
func (b *BaseApi) UpdateMysqlConfByFile(c *gin.Context) {
var req dto.MysqlConfUpdateByFile
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := mysqlService.UpdateConfByFile(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
// @Tags Database Mysql
// @Summary Page mysql databases
// @Description 获取 mysql 数据库列表分页
@ -304,29 +281,6 @@ func (b *BaseApi) DeleteMysql(c *gin.Context) {
helper.SuccessWithData(c, nil)
}
// @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 [post]
func (b *BaseApi) LoadBaseinfo(c *gin.Context) {
var req dto.OperationWithNameAndType
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := mysqlService.LoadBaseInfo(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, data)
}
// @Tags Database Mysql
// @Summary Load mysql remote access
// @Description 获取 mysql 远程访问权限

79
backend/app/api/v1/database_postgresql.go

@ -41,6 +41,28 @@ func (b *BaseApi) CreatePostgresql(c *gin.Context) {
helper.SuccessWithData(c, nil)
}
// @Tags Database Postgresql
// @Summary Bind postgresql user
// @Description 绑定 postgresql 数据库用户
// @Accept json
// @Param request body dto.PostgresqlBindUser true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /databases/pg/bind [post]
// @x-panel-log {"bodyKeys":["name", "username"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"绑定 postgresql 数据库 [name] 用户 [username]","formatEN":"bind postgresql database [name] user [username]"}
func (b *BaseApi) BindPostgresqlUser(c *gin.Context) {
var req dto.PostgresqlBindUser
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := postgresqlService.BindUser(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
// @Tags Database Postgresql
// @Summary Update postgresql database description
// @Description 更新 postgresql 数据库库描述信息
@ -94,29 +116,6 @@ func (b *BaseApi) ChangePostgresqlPassword(c *gin.Context) {
helper.SuccessWithData(c, nil)
}
// @Tags Database Postgresql
// @Summary Update postgresql conf by upload file
// @Description 上传替换 postgresql 配置文件
// @Accept json
// @Param request body dto.PostgresqlConfUpdateByFile true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /databases/pg/conf [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 postgresql 数据库配置信息","formatEN":"update the postgresql database configuration information"}
func (b *BaseApi) UpdatePostgresqlConfByFile(c *gin.Context) {
var req dto.PostgresqlConfUpdateByFile
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
if err := postgresqlService.UpdateConfByFile(req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
}
// @Tags Database Postgresql
// @Summary Page postgresql databases
// @Description 获取 postgresql 数据库列表分页
@ -167,21 +166,20 @@ func (b *BaseApi) ListPostgresqlDBName(c *gin.Context) {
// @Accept json
// @Param request body dto.PostgresqlLoadDB true "request"
// @Security ApiKeyAuth
// @Router /databases/pg/load [post]
// @Router /databases/pg/:database/load [post]
func (b *BaseApi) LoadPostgresqlDBFromRemote(c *gin.Context) {
var req dto.PostgresqlLoadDB
if err := helper.CheckBindAndValidate(&req, c); err != nil {
database, err := helper.GetStrParamByKey(c, "database")
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return
}
if err := postgresqlService.LoadFromRemote(req); err != nil {
if err := postgresqlService.LoadFromRemote(database); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, nil)
helper.SuccessWithData(c, nil)
}
// @Tags Database Postgresql
@ -229,26 +227,3 @@ func (b *BaseApi) DeletePostgresql(c *gin.Context) {
tx.Commit()
helper.SuccessWithData(c, nil)
}
// @Tags Database Postgresql
// @Summary Load postgresql base info
// @Description 获取 postgresql 基础信息
// @Accept json
// @Param request body dto.OperationWithNameAndType true "request"
// @Success 200 {object} dto.DBBaseInfo
// @Security ApiKeyAuth
// @Router /databases/pg/baseinfo [post]
func (b *BaseApi) LoadPostgresqlBaseinfo(c *gin.Context) {
var req dto.OperationWithNameAndType
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
data, err := postgresqlService.LoadBaseInfo(req)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, data)
}

46
backend/app/api/v1/database_redis.go

@ -1,15 +1,11 @@
package v1
import (
"bufio"
"encoding/base64"
"fmt"
"os"
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/utils/compose"
"github.com/gin-gonic/gin"
)
@ -161,45 +157,3 @@ func (b *BaseApi) RedisBackupList(c *gin.Context) {
Total: total,
})
}
// @Tags Database Redis
// @Summary Update redis conf by file
// @Description 上传更新 redis 配置信息
// @Accept json
// @Param request body dto.RedisConfUpdateByFile true "request"
// @Success 200
// @Security ApiKeyAuth
// @Router /databases/redis/conffile/update [post]
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新 redis 数据库配置信息","formatEN":"update the redis database configuration information"}
func (b *BaseApi) UpdateRedisConfByFile(c *gin.Context) {
var req dto.RedisConfUpdateByFile
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
redisInfo, err := redisService.LoadConf()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
path := fmt.Sprintf("%s/redis/%s/conf/redis.conf", constant.AppInstallDir, redisInfo.Name)
file, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0640)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
defer file.Close()
write := bufio.NewWriter(file)
_, _ = write.WriteString(req.File)
write.Flush()
if req.RestartNow {
composeDir := fmt.Sprintf("%s/redis/%s/docker-compose.yml", constant.AppInstallDir, redisInfo.Name)
if _, err := compose.Restart(composeDir); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
}
helper.SuccessWithData(c, nil)
}

1
backend/app/api/v1/entry.go

@ -21,6 +21,7 @@ var (
imageService = service.NewIImageService()
dockerService = service.NewIDockerService()
dbCommonService = service.NewIDBCommonService()
mysqlService = service.NewIMysqlService()
postgresqlService = service.NewIPostgresqlService()
databaseService = service.NewIDatabaseService()

39
backend/app/dto/database.go

@ -2,6 +2,27 @@ package dto
import "time"
// common
type DBConfUpdateByFile struct {
Type string `json:"type" validate:"required,oneof=mysql mariadb postgresql redis"`
Database string `json:"database" validate:"required"`
File string `json:"file"`
}
type ChangeDBInfo struct {
ID uint `json:"id"`
From string `json:"from" validate:"required,oneof=local remote"`
Type string `json:"type" validate:"required,oneof=mysql mariadb postgresql"`
Database string `json:"database" validate:"required"`
Value string `json:"value" validate:"required"`
}
type DBBaseInfo struct {
Name string `json:"name"`
ContainerName string `json:"containerName"`
Port int64 `json:"port"`
}
// mysql
type MysqlDBSearch struct {
PageInfo
Info string `json:"info"`
@ -141,24 +162,6 @@ type MysqlVariablesUpdateHelper struct {
Param string `json:"param"`
Value interface{} `json:"value"`
}
type MysqlConfUpdateByFile struct {
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" validate:"required,oneof=local remote"`
Type string `json:"type" validate:"required,oneof=mysql mariadb postgresql"`
Database string `json:"database" validate:"required"`
Value string `json:"value" validate:"required"`
}
type DBBaseInfo struct {
Name string `json:"name"`
ContainerName string `json:"containerName"`
Port int64 `json:"port"`
}
// redis
type ChangeRedisPass struct {

7
backend/app/dto/database_postgresql.go

@ -43,6 +43,13 @@ type PostgresqlDBCreate struct {
Description string `json:"description"`
}
type PostgresqlBindUser struct {
Name string `json:"name" validate:"required"`
Database string `json:"database" validate:"required"`
Username string `json:"username" validate:"required"`
Password string `json:"password" validate:"required"`
}
type PostgresqlLoadDB struct {
From string `json:"from" validate:"required,oneof=local remote"`
Type string `json:"type" validate:"required,oneof=postgresql"`

94
backend/app/service/database_common.go

@ -0,0 +1,94 @@
package service
import (
"bufio"
"fmt"
"os"
"path"
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/buserr"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/compose"
)
type DBCommonService struct{}
type IDBCommonService interface {
LoadBaseInfo(req dto.OperationWithNameAndType) (*dto.DBBaseInfo, error)
LoadDatabaseFile(req dto.OperationWithNameAndType) (string, error)
UpdateConfByFile(req dto.DBConfUpdateByFile) error
}
func NewIDBCommonService() IDBCommonService {
return &DBCommonService{}
}
func (u *DBCommonService) LoadBaseInfo(req dto.OperationWithNameAndType) (*dto.DBBaseInfo, error) {
var data dto.DBBaseInfo
app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name)
if err != nil {
return nil, err
}
data.ContainerName = app.ContainerName
data.Name = app.Name
data.Port = int64(app.Port)
return &data, nil
}
func (u *DBCommonService) LoadDatabaseFile(req dto.OperationWithNameAndType) (string, error) {
filePath := ""
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 "postgresql-conf":
filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/postgresql/%s/data/postgresql.conf", req.Name))
case "redis-conf":
filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/redis/%s/conf/redis.conf", req.Name))
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")
}
content, err := os.ReadFile(filePath)
if err != nil {
return "", err
}
return string(content), nil
}
func (u *DBCommonService) UpdateConfByFile(req dto.DBConfUpdateByFile) error {
app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database)
if err != nil {
return err
}
path := ""
switch req.Type {
case constant.AppMariaDB, constant.AppMysql:
path = fmt.Sprintf("%s/%s/%s/conf/my.cnf", constant.AppInstallDir, req.Type, app.Name)
case constant.AppPostgresql:
path = fmt.Sprintf("%s/%s/%s/data/postgresql.conf", constant.AppInstallDir, req.Type, app.Name)
case constant.AppRedis:
path = fmt.Sprintf("%s/%s/%s/conf/redis.conf", 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(req.File)
write.Flush()
if _, err := compose.Restart(fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, req.Type, app.Name)); err != nil {
return err
}
return nil
}

62
backend/app/service/database_mysql.go

@ -1,7 +1,6 @@
package service
import (
"bufio"
"context"
"encoding/json"
"fmt"
@ -40,17 +39,13 @@ type IMysqlService interface {
ChangeAccess(info dto.ChangeDBInfo) error
ChangePassword(info dto.ChangeDBInfo) error
UpdateVariables(req dto.MysqlVariablesUpdate) error
UpdateConfByFile(info dto.MysqlConfUpdateByFile) error
UpdateDescription(req dto.UpdateDescription) error
DeleteCheck(req dto.MysqlDBDeleteCheck) ([]string, error)
Delete(ctx context.Context, req dto.MysqlDBDelete) 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)
}
func NewIMysqlService() IMysqlService {
@ -406,26 +401,6 @@ func (u *MysqlService) ChangeAccess(req dto.ChangeDBInfo) error {
return nil
}
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/%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(req.File)
write.Flush()
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(req dto.MysqlVariablesUpdate) error {
app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database)
if err != nil {
@ -471,19 +446,6 @@ func (u *MysqlService) UpdateVariables(req dto.MysqlVariablesUpdate) error {
return nil
}
func (u *MysqlService) LoadBaseInfo(req dto.OperationWithNameAndType) (*dto.DBBaseInfo, error) {
var data dto.DBBaseInfo
app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name)
if err != nil {
return nil, err
}
data.ContainerName = app.ContainerName
data.Name = app.Name
data.Port = int64(app.Port)
return &data, nil
}
func (u *MysqlService) LoadRemoteAccess(req dto.OperationWithNameAndType) (bool, error) {
app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name)
if err != nil {
@ -565,30 +527,6 @@ func (u *MysqlService) LoadStatus(req dto.OperationWithNameAndType) (*dto.MysqlS
return &info, nil
}
func (u *MysqlService) LoadDatabaseFile(req dto.OperationWithNameAndType) (string, error) {
filePath := ""
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 "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")
}
content, err := os.ReadFile(filePath)
if err != nil {
return "", err
}
return string(content), nil
}
func executeSqlForMaps(containerName, password, command string) (map[string]string, error) {
cmd := exec.Command("docker", "exec", containerName, "mysql", "-uroot", "-p"+password, "-e", command)
stdout, err := cmd.CombinedOutput()

95
backend/app/service/database_postgresql.go

@ -1,7 +1,6 @@
package service
import (
"bufio"
"context"
"fmt"
"os"
@ -14,7 +13,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
"github.com/1Panel-dev/1Panel/backend/utils/compose"
"github.com/1Panel-dev/1Panel/backend/utils/encrypt"
"github.com/1Panel-dev/1Panel/backend/utils/postgresql"
"github.com/1Panel-dev/1Panel/backend/utils/postgresql/client"
@ -28,16 +26,13 @@ type PostgresqlService struct{}
type IPostgresqlService interface {
SearchWithPage(search dto.PostgresqlDBSearch) (int64, interface{}, error)
ListDBOption() ([]dto.PostgresqlOption, error)
BindUser(req dto.PostgresqlBindUser) error
Create(ctx context.Context, req dto.PostgresqlDBCreate) (*model.DatabasePostgresql, error)
LoadFromRemote(req dto.PostgresqlLoadDB) error
LoadFromRemote(database string) error
ChangePassword(info dto.ChangeDBInfo) error
UpdateConfByFile(info dto.PostgresqlConfUpdateByFile) error
UpdateDescription(req dto.UpdateDescription) error
DeleteCheck(req dto.PostgresqlDBDeleteCheck) ([]string, error)
Delete(ctx context.Context, req dto.PostgresqlDBDelete) error
LoadBaseInfo(req dto.OperationWithNameAndType) (*dto.DBBaseInfo, error)
LoadDatabaseFile(req dto.OperationWithNameAndType) (string, error)
}
func NewIPostgresqlService() IPostgresqlService {
@ -88,6 +83,37 @@ func (u *PostgresqlService) ListDBOption() ([]dto.PostgresqlOption, error) {
return dbs, err
}
func (u *PostgresqlService) BindUser(req dto.PostgresqlBindUser) error {
dbItem, err := postgresqlRepo.Get(postgresqlRepo.WithByPostgresqlName(req.Database), commonRepo.WithByName(req.Name))
if err != nil {
return err
}
pgClient, err := LoadPostgresqlClientByFrom(req.Database)
if err != nil {
return err
}
if err := pgClient.CreateUser(client.CreateInfo{
Name: req.Name,
Username: req.Username,
Password: req.Password,
Timeout: 300,
}, false); err != nil {
return err
}
pass, err := encrypt.StringEncrypt(req.Password)
if err != nil {
return fmt.Errorf("decrypt database db password failed, err: %v", err)
}
if err := postgresqlRepo.Update(dbItem.ID, map[string]interface{}{
"username": req.Username,
"password": pass,
}); err != nil {
return err
}
return nil
}
func (u *PostgresqlService) Create(ctx context.Context, req dto.PostgresqlDBCreate) (*model.DatabasePostgresql, error) {
if cmd.CheckIllegal(req.Name, req.Username, req.Password, req.Format) {
return nil, buserr.New(constant.ErrCmdIllegal)
@ -168,14 +194,14 @@ func LoadPostgresqlClientByFrom(database string) (postgresql.PostgresqlClient, e
return cli, nil
}
func (u *PostgresqlService) LoadFromRemote(req dto.PostgresqlLoadDB) error {
client, err := LoadPostgresqlClientByFrom(req.Database)
func (u *PostgresqlService) LoadFromRemote(database string) error {
client, err := LoadPostgresqlClientByFrom(database)
if err != nil {
return err
}
defer client.Close()
databases, err := postgresqlRepo.List(postgresqlRepo.WithByPostgresqlName(req.Database))
databases, err := postgresqlRepo.List(postgresqlRepo.WithByPostgresqlName(database))
if err != nil {
return err
}
@ -353,52 +379,3 @@ func (u *PostgresqlService) ChangePassword(req dto.ChangeDBInfo) error {
}
return nil
}
func (u *PostgresqlService) UpdateConfByFile(req dto.PostgresqlConfUpdateByFile) error {
app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Database)
if err != nil {
return err
}
conf := fmt.Sprintf("%s/%s/%s/data/postgresql.conf", constant.AppInstallDir, req.Type, app.Name)
file, err := os.OpenFile(conf, os.O_WRONLY|os.O_TRUNC, 0640)
if err != nil {
return err
}
defer file.Close()
write := bufio.NewWriter(file)
_, _ = write.WriteString(req.File)
write.Flush()
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 *PostgresqlService) LoadBaseInfo(req dto.OperationWithNameAndType) (*dto.DBBaseInfo, error) {
var data dto.DBBaseInfo
app, err := appInstallRepo.LoadBaseInfo(req.Type, req.Name)
if err != nil {
return nil, err
}
data.ContainerName = app.ContainerName
data.Name = app.Name
data.Port = int64(app.Port)
return &data, nil
}
func (u *PostgresqlService) LoadDatabaseFile(req dto.OperationWithNameAndType) (string, error) {
filePath := ""
switch req.Type {
case "postgresql-conf":
filePath = path.Join(global.CONF.System.DataDir, fmt.Sprintf("apps/postgresql/%s/data/postgresql.conf", req.Name))
}
if _, err := os.Stat(filePath); err != nil {
return "", buserr.New("ErrHttpReqNotFound")
}
content, err := os.ReadFile(filePath)
if err != nil {
return "", err
}
return string(content), nil
}

8
backend/init/migration/migrations/v_1_9.go

@ -5,6 +5,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/app/repo"
"github.com/1Panel-dev/1Panel/backend/app/service"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/go-gormigrate/gormigrate/v2"
"gorm.io/gorm"
)
@ -133,14 +134,15 @@ var AddTableDatabasePostgresql = &gormigrate.Migration{
for _, job := range jobs {
var db model.DatabaseMysql
if err := tx.Where("id == ?", job.DBName).First(&db).Error; err != nil {
return err
continue
}
var database model.Database
if err := tx.Where("name == ?", db.MysqlName).First(&database).Error; err != nil {
return err
continue
}
if err := tx.Model(&model.Cronjob{}).Where("id = ?", job.ID).Update("db_type", database.Type).Error; err != nil {
return err
global.LOG.Errorf("update db type of cronjob %s failed, err: %v", job.Name, err)
continue
}
}
return nil

14
backend/router/ro_database.go

@ -16,6 +16,10 @@ func (s *DatabaseRouter) InitRouter(Router *gin.RouterGroup) {
Use(middleware.PasswordExpired())
baseApi := v1.ApiGroupApp.BaseApi
{
cmdRouter.POST("/common/info", baseApi.LoadDBBaseInfo)
cmdRouter.POST("/common/load/file", baseApi.LoadDBFile)
cmdRouter.POST("/common/update/conf", baseApi.UpdateDBConfByFile)
cmdRouter.POST("", baseApi.CreateMysql)
cmdRouter.POST("/bind", baseApi.BindUser)
cmdRouter.POST("load", baseApi.LoadDBFromRemote)
@ -25,12 +29,9 @@ func (s *DatabaseRouter) InitRouter(Router *gin.RouterGroup) {
cmdRouter.POST("/del", baseApi.DeleteMysql)
cmdRouter.POST("/description/update", baseApi.UpdateMysqlDescription)
cmdRouter.POST("/variables/update", baseApi.UpdateMysqlVariables)
cmdRouter.POST("/conffile/update", baseApi.UpdateMysqlConfByFile)
cmdRouter.POST("/search", baseApi.SearchMysql)
cmdRouter.POST("/load/file", baseApi.LoadDatabaseFile)
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)
@ -41,7 +42,6 @@ func (s *DatabaseRouter) InitRouter(Router *gin.RouterGroup) {
cmdRouter.POST("/redis/password", baseApi.ChangeRedisPassword)
cmdRouter.POST("/redis/backup/search", baseApi.RedisBackupList)
cmdRouter.POST("/redis/conf/update", baseApi.UpdateRedisConf)
cmdRouter.POST("/redis/conffile/update", baseApi.UpdateRedisConfByFile)
cmdRouter.POST("/redis/persistence/update", baseApi.UpdateRedisPersistenceConf)
cmdRouter.POST("/db/check", baseApi.CheckDatabase)
@ -56,11 +56,11 @@ func (s *DatabaseRouter) InitRouter(Router *gin.RouterGroup) {
cmdRouter.POST("/pg", baseApi.CreatePostgresql)
cmdRouter.POST("/pg/search", baseApi.SearchPostgresql)
cmdRouter.POST("/pg/load", baseApi.LoadPostgresqlDBFromRemote)
cmdRouter.POST("/pg/:database/load", baseApi.LoadPostgresqlDBFromRemote)
cmdRouter.POST("/pg/bind", baseApi.BindPostgresqlUser)
cmdRouter.POST("/pg/del/check", baseApi.DeleteCheckPostgresql)
cmdRouter.POST("/pg/del", baseApi.DeletePostgresql)
cmdRouter.POST("/pg/password", baseApi.ChangePostgresqlPassword)
cmdRouter.POST("/pg/description", baseApi.UpdatePostgresqlDescription)
cmdRouter.POST("/pg/del", baseApi.DeletePostgresql)
cmdRouter.POST("/pg/conf", baseApi.UpdatePostgresqlConfByFile)
}
}

1
backend/utils/postgresql/client.go

@ -14,6 +14,7 @@ import (
type PostgresqlClient interface {
Create(info client.CreateInfo) error
CreateUser(info client.CreateInfo, withDeleteDB bool) error
Delete(info client.DeleteInfo) error
ChangePassword(info client.PasswordChangeInfo) error

339
cmd/server/docs/docs.go

@ -3916,42 +3916,6 @@ const docTemplate = `{
}
}
},
"/databases/baseinfo": {
"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",
"schema": {
"$ref": "#/definitions/dto.DBBaseInfo"
}
}
}
}
},
"/databases/bind": {
"post": {
"security": [
@ -4097,21 +4061,21 @@ const docTemplate = `{
}
}
},
"/databases/conffile/update": {
"/databases/common/info": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "上传替换 mysql 配置文件",
"description": "获取数据库基础信息",
"consumes": [
"application/json"
],
"tags": [
"Database Mysql"
"Database Common"
],
"summary": "Update mysql conf by upload file",
"summary": "Load base info",
"parameters": [
{
"description": "request",
@ -4119,7 +4083,76 @@ const docTemplate = `{
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.MysqlConfUpdateByFile"
"$ref": "#/definitions/dto.OperationWithNameAndType"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/dto.DBBaseInfo"
}
}
}
}
},
"/databases/common/load/file": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "获取数据库配置文件",
"consumes": [
"application/json"
],
"tags": [
"Database Common"
],
"summary": "Load Database conf",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.OperationWithNameAndType"
}
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/databases/common/update/conf": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "上传替换配置文件",
"consumes": [
"application/json"
],
"tags": [
"Database Common"
],
"summary": "Update conf by upload file",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.DBConfUpdateByFile"
}
}
],
@ -4130,9 +4163,12 @@ const docTemplate = `{
},
"x-panel-log": {
"BeforeFunctions": [],
"bodyKeys": [],
"formatEN": "update the mysql database configuration information",
"formatZH": "更新 mysql 数据库配置信息",
"bodyKeys": [
"type",
"database"
],
"formatEN": "update the [type] [database] database configuration information",
"formatZH": "更新 [type] 数据库 [database] 配置信息",
"paramKeys": []
}
}
@ -4595,39 +4631,6 @@ const docTemplate = `{
"responses": {}
}
},
"/databases/load/file": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "获取数据库文件",
"consumes": [
"application/json"
],
"tags": [
"Database"
],
"summary": "Load Database file",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.OperationWithNameAndType"
}
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/databases/options": {
"get": {
"security": [
@ -4709,21 +4712,21 @@ const docTemplate = `{
}
}
},
"/databases/pg/baseinfo": {
"/databases/pg/:database/load": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "获取 postgresql 基础信息",
"description": "从服务器获取",
"consumes": [
"application/json"
],
"tags": [
"Database Postgresql"
],
"summary": "Load postgresql base info",
"summary": "Load postgresql database from remote",
"parameters": [
{
"description": "request",
@ -4731,35 +4734,28 @@ const docTemplate = `{
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.OperationWithNameAndType"
"$ref": "#/definitions/dto.PostgresqlLoadDB"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/dto.DBBaseInfo"
}
}
}
"responses": {}
}
},
"/databases/pg/conf": {
"/databases/pg/bind": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "上传替换 postgresql 配置文件",
"description": "绑定 postgresql 数据库用户",
"consumes": [
"application/json"
],
"tags": [
"Database Postgresql"
],
"summary": "Update postgresql conf by upload file",
"summary": "Bind postgresql user",
"parameters": [
{
"description": "request",
@ -4767,7 +4763,7 @@ const docTemplate = `{
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.PostgresqlConfUpdateByFile"
"$ref": "#/definitions/dto.PostgresqlBindUser"
}
}
],
@ -4778,9 +4774,12 @@ const docTemplate = `{
},
"x-panel-log": {
"BeforeFunctions": [],
"bodyKeys": [],
"formatEN": "update the postgresql database configuration information",
"formatZH": "更新 postgresql 数据库配置信息",
"bodyKeys": [
"name",
"username"
],
"formatEN": "bind postgresql database [name] user [username]",
"formatZH": "绑定 postgresql 数据库 [name] 用户 [username]",
"paramKeys": []
}
}
@ -4927,35 +4926,6 @@ const docTemplate = `{
}
}
},
"/databases/pg/load": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "从服务器获取",
"consumes": [
"application/json"
],
"tags": [
"Database Postgresql"
],
"summary": "Load postgresql database from remote",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.PostgresqlLoadDB"
}
}
],
"responses": {}
}
},
"/databases/pg/options": {
"get": {
"security": [
@ -5180,46 +5150,6 @@ const docTemplate = `{
}
}
},
"/databases/redis/conffile/update": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "上传更新 redis 配置信息",
"consumes": [
"application/json"
],
"tags": [
"Database Redis"
],
"summary": "Update redis conf by file",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.RedisConfUpdateByFile"
}
}
],
"responses": {
"200": {
"description": "OK"
}
},
"x-panel-log": {
"BeforeFunctions": [],
"bodyKeys": [],
"formatEN": "update the redis database configuration information",
"formatZH": "更新 redis 数据库配置信息",
"paramKeys": []
}
}
},
"/databases/redis/password": {
"post": {
"security": [
@ -15084,6 +15014,30 @@ const docTemplate = `{
}
}
},
"dto.DBConfUpdateByFile": {
"type": "object",
"required": [
"database",
"type"
],
"properties": {
"database": {
"type": "string"
},
"file": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"mysql",
"mariadb",
"postgresql",
"redis"
]
}
}
},
"dto.DaemonJsonConf": {
"type": "object",
"properties": {
@ -16289,28 +16243,6 @@ const docTemplate = `{
}
}
},
"dto.MysqlConfUpdateByFile": {
"type": "object",
"required": [
"database",
"type"
],
"properties": {
"database": {
"type": "string"
},
"file": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"mysql",
"mariadb"
]
}
}
},
"dto.MysqlDBCreate": {
"type": "object",
"required": [
@ -16992,25 +16924,26 @@ const docTemplate = `{
}
}
},
"dto.PostgresqlConfUpdateByFile": {
"dto.PostgresqlBindUser": {
"type": "object",
"required": [
"database",
"type"
"name",
"password",
"username"
],
"properties": {
"database": {
"type": "string"
},
"file": {
"name": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"postgresql",
"mariadb"
]
"password": {
"type": "string"
},
"username": {
"type": "string"
}
}
},
@ -17268,20 +17201,6 @@ const docTemplate = `{
}
}
},
"dto.RedisConfUpdateByFile": {
"type": "object",
"required": [
"file"
],
"properties": {
"file": {
"type": "string"
},
"restartNow": {
"type": "boolean"
}
}
},
"dto.RedisPersistence": {
"type": "object",
"properties": {

339
cmd/server/docs/swagger.json

@ -3909,42 +3909,6 @@
}
}
},
"/databases/baseinfo": {
"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",
"schema": {
"$ref": "#/definitions/dto.DBBaseInfo"
}
}
}
}
},
"/databases/bind": {
"post": {
"security": [
@ -4090,21 +4054,21 @@
}
}
},
"/databases/conffile/update": {
"/databases/common/info": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "上传替换 mysql 配置文件",
"description": "获取数据库基础信息",
"consumes": [
"application/json"
],
"tags": [
"Database Mysql"
"Database Common"
],
"summary": "Update mysql conf by upload file",
"summary": "Load base info",
"parameters": [
{
"description": "request",
@ -4112,7 +4076,76 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.MysqlConfUpdateByFile"
"$ref": "#/definitions/dto.OperationWithNameAndType"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/dto.DBBaseInfo"
}
}
}
}
},
"/databases/common/load/file": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "获取数据库配置文件",
"consumes": [
"application/json"
],
"tags": [
"Database Common"
],
"summary": "Load Database conf",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.OperationWithNameAndType"
}
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/databases/common/update/conf": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "上传替换配置文件",
"consumes": [
"application/json"
],
"tags": [
"Database Common"
],
"summary": "Update conf by upload file",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.DBConfUpdateByFile"
}
}
],
@ -4123,9 +4156,12 @@
},
"x-panel-log": {
"BeforeFunctions": [],
"bodyKeys": [],
"formatEN": "update the mysql database configuration information",
"formatZH": "更新 mysql 数据库配置信息",
"bodyKeys": [
"type",
"database"
],
"formatEN": "update the [type] [database] database configuration information",
"formatZH": "更新 [type] 数据库 [database] 配置信息",
"paramKeys": []
}
}
@ -4588,39 +4624,6 @@
"responses": {}
}
},
"/databases/load/file": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "获取数据库文件",
"consumes": [
"application/json"
],
"tags": [
"Database"
],
"summary": "Load Database file",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.OperationWithNameAndType"
}
}
],
"responses": {
"200": {
"description": "OK"
}
}
}
},
"/databases/options": {
"get": {
"security": [
@ -4702,21 +4705,21 @@
}
}
},
"/databases/pg/baseinfo": {
"/databases/pg/:database/load": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "获取 postgresql 基础信息",
"description": "从服务器获取",
"consumes": [
"application/json"
],
"tags": [
"Database Postgresql"
],
"summary": "Load postgresql base info",
"summary": "Load postgresql database from remote",
"parameters": [
{
"description": "request",
@ -4724,35 +4727,28 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.OperationWithNameAndType"
"$ref": "#/definitions/dto.PostgresqlLoadDB"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/dto.DBBaseInfo"
}
}
}
"responses": {}
}
},
"/databases/pg/conf": {
"/databases/pg/bind": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "上传替换 postgresql 配置文件",
"description": "绑定 postgresql 数据库用户",
"consumes": [
"application/json"
],
"tags": [
"Database Postgresql"
],
"summary": "Update postgresql conf by upload file",
"summary": "Bind postgresql user",
"parameters": [
{
"description": "request",
@ -4760,7 +4756,7 @@
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.PostgresqlConfUpdateByFile"
"$ref": "#/definitions/dto.PostgresqlBindUser"
}
}
],
@ -4771,9 +4767,12 @@
},
"x-panel-log": {
"BeforeFunctions": [],
"bodyKeys": [],
"formatEN": "update the postgresql database configuration information",
"formatZH": "更新 postgresql 数据库配置信息",
"bodyKeys": [
"name",
"username"
],
"formatEN": "bind postgresql database [name] user [username]",
"formatZH": "绑定 postgresql 数据库 [name] 用户 [username]",
"paramKeys": []
}
}
@ -4920,35 +4919,6 @@
}
}
},
"/databases/pg/load": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "从服务器获取",
"consumes": [
"application/json"
],
"tags": [
"Database Postgresql"
],
"summary": "Load postgresql database from remote",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.PostgresqlLoadDB"
}
}
],
"responses": {}
}
},
"/databases/pg/options": {
"get": {
"security": [
@ -5173,46 +5143,6 @@
}
}
},
"/databases/redis/conffile/update": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "上传更新 redis 配置信息",
"consumes": [
"application/json"
],
"tags": [
"Database Redis"
],
"summary": "Update redis conf by file",
"parameters": [
{
"description": "request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/dto.RedisConfUpdateByFile"
}
}
],
"responses": {
"200": {
"description": "OK"
}
},
"x-panel-log": {
"BeforeFunctions": [],
"bodyKeys": [],
"formatEN": "update the redis database configuration information",
"formatZH": "更新 redis 数据库配置信息",
"paramKeys": []
}
}
},
"/databases/redis/password": {
"post": {
"security": [
@ -15077,6 +15007,30 @@
}
}
},
"dto.DBConfUpdateByFile": {
"type": "object",
"required": [
"database",
"type"
],
"properties": {
"database": {
"type": "string"
},
"file": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"mysql",
"mariadb",
"postgresql",
"redis"
]
}
}
},
"dto.DaemonJsonConf": {
"type": "object",
"properties": {
@ -16282,28 +16236,6 @@
}
}
},
"dto.MysqlConfUpdateByFile": {
"type": "object",
"required": [
"database",
"type"
],
"properties": {
"database": {
"type": "string"
},
"file": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"mysql",
"mariadb"
]
}
}
},
"dto.MysqlDBCreate": {
"type": "object",
"required": [
@ -16985,25 +16917,26 @@
}
}
},
"dto.PostgresqlConfUpdateByFile": {
"dto.PostgresqlBindUser": {
"type": "object",
"required": [
"database",
"type"
"name",
"password",
"username"
],
"properties": {
"database": {
"type": "string"
},
"file": {
"name": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"postgresql",
"mariadb"
]
"password": {
"type": "string"
},
"username": {
"type": "string"
}
}
},
@ -17261,20 +17194,6 @@
}
}
},
"dto.RedisConfUpdateByFile": {
"type": "object",
"required": [
"file"
],
"properties": {
"file": {
"type": "string"
},
"restartNow": {
"type": "boolean"
}
}
},
"dto.RedisPersistence": {
"type": "object",
"properties": {

232
cmd/server/docs/swagger.yaml

@ -705,6 +705,23 @@ definitions:
port:
type: integer
type: object
dto.DBConfUpdateByFile:
properties:
database:
type: string
file:
type: string
type:
enum:
- mysql
- mariadb
- postgresql
- redis
type: string
required:
- database
- type
type: object
dto.DaemonJsonConf:
properties:
cgroupDriver:
@ -1518,21 +1535,6 @@ definitions:
- interval
- secret
type: object
dto.MysqlConfUpdateByFile:
properties:
database:
type: string
file:
type: string
type:
enum:
- mysql
- mariadb
type: string
required:
- database
- type
type: object
dto.MysqlDBCreate:
properties:
database:
@ -1998,20 +2000,21 @@ definitions:
required:
- serverPort
type: object
dto.PostgresqlConfUpdateByFile:
dto.PostgresqlBindUser:
properties:
database:
type: string
file:
name:
type: string
type:
enum:
- postgresql
- mariadb
password:
type: string
username:
type: string
required:
- database
- type
- name
- password
- username
type: object
dto.PostgresqlDBCreate:
properties:
@ -2185,15 +2188,6 @@ definitions:
timeout:
type: string
type: object
dto.RedisConfUpdateByFile:
properties:
file:
type: string
restartNow:
type: boolean
required:
- file
type: object
dto.RedisPersistence:
properties:
appendfsync:
@ -7466,28 +7460,6 @@ paths:
formatEN: create mysql database [name]
formatZH: 创建 mysql 数据库 [name]
paramKeys: []
/databases/baseinfo:
post:
consumes:
- application/json
description: 获取 mysql 基础信息
parameters:
- description: request
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.OperationWithNameAndType'
responses:
"200":
description: OK
schema:
$ref: '#/definitions/dto.DBBaseInfo'
security:
- ApiKeyAuth: []
summary: Load mysql base info
tags:
- Database Mysql
/databases/bind:
post:
consumes:
@ -7582,31 +7554,75 @@ paths:
formatEN: Update database [name] password
formatZH: 更新数据库 [name] 密码
paramKeys: []
/databases/conffile/update:
/databases/common/info:
post:
consumes:
- application/json
description: 上传替换 mysql 配置文件
description: 获取数据库基础信息
parameters:
- description: request
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.MysqlConfUpdateByFile'
$ref: '#/definitions/dto.OperationWithNameAndType'
responses:
"200":
description: OK
schema:
$ref: '#/definitions/dto.DBBaseInfo'
security:
- ApiKeyAuth: []
summary: Update mysql conf by upload file
summary: Load base info
tags:
- Database Mysql
- Database Common
/databases/common/load/file:
post:
consumes:
- application/json
description: 获取数据库配置文件
parameters:
- description: request
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.OperationWithNameAndType'
responses:
"200":
description: OK
security:
- ApiKeyAuth: []
summary: Load Database conf
tags:
- Database Common
/databases/common/update/conf:
post:
consumes:
- application/json
description: 上传替换配置文件
parameters:
- description: request
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.DBConfUpdateByFile'
responses:
"200":
description: OK
security:
- ApiKeyAuth: []
summary: Update conf by upload file
tags:
- Database Common
x-panel-log:
BeforeFunctions: []
bodyKeys: []
formatEN: update the mysql database configuration information
formatZH: 更新 mysql 数据库配置信息
bodyKeys:
- type
- database
formatEN: update the [type] [database] database configuration information
formatZH: 更新 [type] 数据库 [database] 配置信息
paramKeys: []
/databases/db:
post:
@ -7898,26 +7914,6 @@ paths:
summary: Load mysql database from remote
tags:
- Database Mysql
/databases/load/file:
post:
consumes:
- application/json
description: 获取数据库文件
parameters:
- description: request
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.OperationWithNameAndType'
responses:
"200":
description: OK
security:
- ApiKeyAuth: []
summary: Load Database file
tags:
- Database
/databases/options:
get:
consumes:
@ -7969,53 +7965,51 @@ paths:
formatEN: create postgresql database [name]
formatZH: 创建 postgresql 数据库 [name]
paramKeys: []
/databases/pg/baseinfo:
/databases/pg/:database/load:
post:
consumes:
- application/json
description: 获取 postgresql 基础信息
description: 从服务器获取
parameters:
- description: request
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.OperationWithNameAndType'
responses:
"200":
description: OK
schema:
$ref: '#/definitions/dto.DBBaseInfo'
$ref: '#/definitions/dto.PostgresqlLoadDB'
responses: {}
security:
- ApiKeyAuth: []
summary: Load postgresql base info
summary: Load postgresql database from remote
tags:
- Database Postgresql
/databases/pg/conf:
/databases/pg/bind:
post:
consumes:
- application/json
description: 上传替换 postgresql 配置文件
description: 绑定 postgresql 数据库用户
parameters:
- description: request
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.PostgresqlConfUpdateByFile'
$ref: '#/definitions/dto.PostgresqlBindUser'
responses:
"200":
description: OK
security:
- ApiKeyAuth: []
summary: Update postgresql conf by upload file
summary: Bind postgresql user
tags:
- Database Postgresql
x-panel-log:
BeforeFunctions: []
bodyKeys: []
formatEN: update the postgresql database configuration information
formatZH: 更新 postgresql 数据库配置信息
bodyKeys:
- name
- username
formatEN: bind postgresql database [name] user [username]
formatZH: 绑定 postgresql 数据库 [name] 用户 [username]
paramKeys: []
/databases/pg/del:
post:
@ -8109,24 +8103,6 @@ paths:
[description]
formatZH: postgresql 数据库 [name] 描述信息修改 [description]
paramKeys: []
/databases/pg/load:
post:
consumes:
- application/json
description: 从服务器获取
parameters:
- description: request
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.PostgresqlLoadDB'
responses: {}
security:
- ApiKeyAuth: []
summary: Load postgresql database from remote
tags:
- Database Postgresql
/databases/pg/options:
get:
consumes:
@ -8267,32 +8243,6 @@ paths:
formatEN: update the redis database configuration information
formatZH: 更新 redis 数据库配置信息
paramKeys: []
/databases/redis/conffile/update:
post:
consumes:
- application/json
description: 上传更新 redis 配置信息
parameters:
- description: request
in: body
name: request
required: true
schema:
$ref: '#/definitions/dto.RedisConfUpdateByFile'
responses:
"200":
description: OK
security:
- ApiKeyAuth: []
summary: Update redis conf by file
tags:
- Database Redis
x-panel-log:
BeforeFunctions: []
bodyKeys: []
formatEN: update the redis database configuration information
formatZH: 更新 redis 数据库配置信息
paramKeys: []
/databases/redis/password:
post:
consumes:

9
frontend/src/api/interface/database.ts

@ -33,7 +33,7 @@ export namespace Database {
mysqlKey: string;
containerName: string;
}
export interface MysqlConfUpdateByFile {
export interface DBConfUpdate {
type: string;
database: string;
file: string;
@ -146,10 +146,11 @@ export namespace Database {
type: string;
database: string;
}
export interface PgLoadDB {
from: string;
type: string;
export interface PgBind {
name: string;
database: string;
username: string;
password: string;
}
export interface PostgresqlDBDelete {
id: number;

40
frontend/src/api/modules/database.ts

@ -5,22 +5,27 @@ import { ResPage, DescriptionUpdate } from '../interface';
import { Database } from '../interface/database';
import { TimeoutEnum } from '@/enums/http-enum';
export const searchMysqlDBs = (params: Database.SearchDBWithPage) => {
return http.post<ResPage<Database.MysqlDBInfo>>(`/databases/search`, params);
// common
export const loadDBBaseInfo = (type: string, database: string) => {
return http.post<Database.BaseInfo>(`/databases/common/info`, { type: type, name: database });
};
export const loadDatabaseFile = (type: string, database: string) => {
return http.post<string>(`/databases/load/file`, { type: type, name: database });
export const loadDBFile = (type: string, database: string) => {
return http.post<string>(`/databases/common/load/file`, { type: type, name: database });
};
export const updateDBFile = (params: Database.DBConfUpdate) => {
return http.post(`/databases/common/update/conf`, params);
};
// pg
export const addPostgresqlDB = (params: Database.PostgresqlDBCreate) => {
let request = deepCopy(params) as Database.PostgresqlDBCreate;
if (request.password) {
request.password = Base64.encode(request.password);
}
return http.post(`/databases/pg`, request);
return http.post(`/databases/pg`, request, TimeoutEnum.T_40S);
};
export const updatePostgresqlConfByFile = (params: Database.PostgresqlConfUpdateByFile) => {
return http.post(`/databases/pg/conf`, params);
export const bindPostgresqlUser = (params: Database.PgBind) => {
return http.post(`/databases/pg/bind`, params, TimeoutEnum.T_40S);
};
export const searchPostgresqlDBs = (params: Database.SearchDBWithPage) => {
return http.post<ResPage<Database.PostgresqlDBInfo>>(`/databases/pg/search`, params);
@ -28,24 +33,27 @@ export const searchPostgresqlDBs = (params: Database.SearchDBWithPage) => {
export const updatePostgresqlDescription = (params: DescriptionUpdate) => {
return http.post(`/databases/pg/description`, params);
};
export const loadPgFromRemote = (params: Database.PgLoadDB) => {
return http.post(`/databases/pg/load`, params);
export const loadPgFromRemote = (database: string) => {
return http.post(`/databases/pg/${database}/load`);
};
export const deleteCheckPostgresqlDB = (params: Database.PostgresqlDBDeleteCheck) => {
return http.post<Array<string>>(`/databases/pg/del/check`, params);
return http.post<Array<string>>(`/databases/pg/del/check`, params, TimeoutEnum.T_40S);
};
export const updatePostgresqlPassword = (params: Database.ChangeInfo) => {
let request = deepCopy(params) as Database.ChangeInfo;
if (request.value) {
request.value = Base64.encode(request.value);
}
return http.post(`/databases/pg/password`, request);
return http.post(`/databases/pg/password`, request, TimeoutEnum.T_40S);
};
export const deletePostgresqlDB = (params: Database.PostgresqlDBDelete) => {
return http.post(`/databases/pg/del`, params);
return http.post(`/databases/pg/del`, params, TimeoutEnum.T_40S);
};
// mysql
export const searchMysqlDBs = (params: Database.SearchDBWithPage) => {
return http.post<ResPage<Database.MysqlDBInfo>>(`/databases/search`, params);
};
export const addMysqlDB = (params: Database.MysqlDBCreate) => {
let request = deepCopy(params) as Database.MysqlDBCreate;
if (request.password) {
@ -79,9 +87,6 @@ export const updateMysqlDescription = (params: DescriptionUpdate) => {
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 = (params: Database.MysqlDBDeleteCheck) => {
return http.post<Array<string>>(`/databases/del/check`, params);
};
@ -89,9 +94,6 @@ export const deleteMysqlDB = (params: Database.MysqlDBDelete) => {
return http.post(`/databases/del`, params);
};
export const loadMysqlBaseInfo = (type: string, database: string) => {
return http.post<Database.BaseInfo>(`/databases/baseinfo`, { type: type, name: database });
};
export const loadMysqlVariables = (type: string, database: string) => {
return http.post<Database.MysqlVariables>(`/databases/variables`, { type: type, name: database });
};

1
frontend/src/lang/modules/en.ts

@ -383,6 +383,7 @@ const message = {
loadFromRemote: 'Load from server',
userBind: 'Bind User',
pgBind: 'Bind User (Binding existing users is not currently supported)',
loadFromRemoteHelper:
'This action will synchronize the database info on the server to 1Panel, do you want to continue?',
passwordHelper: 'Unable to retrieve, please modify',

1
frontend/src/lang/modules/tw.ts

@ -376,6 +376,7 @@ const message = {
loadFromRemote: '從服務器獲取',
userBind: '綁定使用者',
pgBind: '綁定用戶(暫不支持綁定已有用戶)',
loadFromRemoteHelper: '此操作將同步服務器上數據庫信息到 1Panel是否繼續',
passwordHelper: '無法獲取密碼請修改',
local: '本地',

1
frontend/src/lang/modules/zh.ts

@ -376,6 +376,7 @@ const message = {
loadFromRemote: '从服务器获取',
userBind: '绑定用户',
pgBind: '绑定用户(暂不支持绑定已有用户)',
loadFromRemoteHelper: '此操作将同步服务器上数据库信息到 1Panel是否继续',
passwordHelper: '无法获取密码请修改',
local: '本地',

4
frontend/src/views/database/mysql/bind/index.vue

@ -66,6 +66,7 @@ const bindVisible = ref(false);
type FormInstance = InstanceType<typeof ElForm>;
const changeFormRef = ref<FormInstance>();
const form = reactive({
from: '',
database: '',
mysqlName: '',
username: '',
@ -93,13 +94,14 @@ function checkIPs(rule: any, value: any, callback: any) {
}
interface DialogProps {
from: string;
database: string;
mysqlName: string;
}
const acceptParams = (params: DialogProps): void => {
form.id = params.id;
form.database = params.database;
form.mysqlName = params.mysqlName;
form.from = params.from;
bindVisible.value = true;
};
const emit = defineEmits<{ (e: 'search'): void }>();

1
frontend/src/views/database/mysql/index.vue

@ -529,6 +529,7 @@ const onBind = async (row: Database.MysqlDBInfo) => {
let param = {
database: currentDBName.value,
mysqlName: row.name,
from: row.from,
};
bindRef.value.acceptParams(param);
};

8
frontend/src/views/database/mysql/setting/index.vue

@ -147,7 +147,7 @@ import { onMounted, reactive, ref } from 'vue';
import { Codemirror } from 'vue-codemirror';
import { javascript } from '@codemirror/lang-javascript';
import { oneDark } from '@codemirror/theme-one-dark';
import { loadDatabaseFile, loadMysqlBaseInfo, loadMysqlVariables, updateMysqlConfByFile } from '@/api/modules/database';
import { loadDBFile, loadDBBaseInfo, loadMysqlVariables, updateDBFile } from '@/api/modules/database';
import { ChangePort, CheckAppInstalled, GetAppDefaultConfig } from '@/api/modules/app';
import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
@ -260,7 +260,7 @@ const onSubmitChangeConf = async () => {
file: mysqlConf.value,
};
loading.value = true;
await updateMysqlConfByFile(param)
await updateDBFile(param)
.then(() => {
useOld.value = false;
loading.value = false;
@ -286,7 +286,7 @@ const loadContainerLog = async (containerID: string) => {
};
const loadBaseInfo = async () => {
const res = await loadMysqlBaseInfo(props.type, props.database);
const res = await loadDBBaseInfo(props.type, props.database);
mysqlName.value = res.data?.name;
baseInfo.port = res.data?.port;
baseInfo.containerID = res.data?.containerName;
@ -323,7 +323,7 @@ const loadSlowLogs = async () => {
const loadMysqlConf = async () => {
useOld.value = false;
await loadDatabaseFile(props.type + '-conf', props.database)
await loadDBFile(props.type + '-conf', props.database)
.then((res) => {
loading.value = false;
mysqlConf.value = res.data;

4
frontend/src/views/database/mysql/setting/slow-log/index.vue

@ -52,7 +52,7 @@ import { oneDark } from '@codemirror/theme-one-dark';
import { nextTick, onBeforeUnmount, reactive, ref, shallowRef } from 'vue';
import { Database } from '@/api/interface/database';
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import { loadDatabaseFile, updateMysqlVariables } from '@/api/modules/database';
import { loadDBFile, updateMysqlVariables } from '@/api/modules/database';
import { dateFormatForName, downloadWithContent } from '@/utils/util';
import i18n from '@/lang';
import { MsgError, MsgInfo, MsgSuccess } from '@/utils/message';
@ -175,7 +175,7 @@ const onDownload = async () => {
};
const loadMysqlSlowlogs = async () => {
const res = await loadDatabaseFile(currentDB.type + '-slow-logs', currentDB.database);
const res = await loadDBFile(currentDB.type + '-slow-logs', currentDB.database);
slowLogs.value = res.data || '';
nextTick(() => {
const state = view.value.state;

103
frontend/src/views/database/postgresql/bind/index.vue

@ -0,0 +1,103 @@
<template>
<div>
<el-drawer v-model="bindVisible" :destroy-on-close="true" :close-on-click-modal="false" width="30%">
<template #header>
<DrawerHeader :header="$t('database.userBind')" :resource="form.name" :back="handleClose" />
</template>
<el-form v-loading="loading" ref="changeFormRef" :model="form" :rules="rules" label-position="top">
<el-row type="flex" justify="center">
<el-col :span="22">
<el-alert type="warning" :description="$t('database.pgBindHelper')" :closable="false" />
<el-form-item class="mt-5" :label="$t('commons.login.username')" prop="username">
<el-input v-model="form.username" />
</el-form-item>
<el-form-item :label="$t('commons.login.password')" prop="password">
<el-input type="password" clearable show-password v-model="form.password" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button :disabled="loading" @click="bindVisible = false">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button :disabled="loading" type="primary" @click="onSubmit(changeFormRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</el-drawer>
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmit"></ConfirmDialog>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import i18n from '@/lang';
import { ElForm } from 'element-plus';
import { bindPostgresqlUser } from '@/api/modules/database';
import DrawerHeader from '@/components/drawer-header/index.vue';
import { Rules } from '@/global/form-rules';
import { MsgSuccess } from '@/utils/message';
const loading = ref();
const bindVisible = ref(false);
type FormInstance = InstanceType<typeof ElForm>;
const changeFormRef = ref<FormInstance>();
const form = reactive({
database: '',
name: '',
username: '',
password: '',
});
const confirmDialogRef = ref();
const rules = reactive({
username: [Rules.requiredInput, Rules.name],
password: [Rules.paramComplexity],
});
interface DialogProps {
database: string;
name: string;
}
const acceptParams = (params: DialogProps): void => {
form.database = params.database;
form.name = params.name;
bindVisible.value = true;
};
const emit = defineEmits<{ (e: 'search'): void }>();
const handleClose = () => {
bindVisible.value = false;
};
const onSubmit = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) return;
let param = {
name: form.name,
database: form.database,
username: form.username,
password: form.password,
};
loading.value = true;
await bindPostgresqlUser(param)
.then(() => {
loading.value = false;
emit('search');
bindVisible.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
})
.catch(() => {
loading.value = false;
});
});
};
defineExpose({
acceptParams,
});
</script>

41
frontend/src/views/database/postgresql/index.vue

@ -101,10 +101,24 @@
<template #main v-if="currentDB">
<ComplexTable :pagination-config="paginationConfig" @sort-change="search" @search="search" :data="data">
<el-table-column :label="$t('commons.table.name')" prop="name" sortable />
<el-table-column :label="$t('commons.login.username')" prop="username" />
<el-table-column :label="$t('commons.login.username')" prop="username">
<template #default="{ row }">
<div class="flex items-center" v-if="row.username">
<span>
{{ row.username }}
</span>
</div>
<div v-else>
<el-button style="margin-left: -3px" type="primary" link @click="onBind(row)">
{{ $t('database.userBind') }}
</el-button>
</div>
</template>
</el-table-column>
<el-table-column :label="$t('commons.login.password')" prop="password">
<template #default="{ row }">
<div class="flex items-center" v-if="row.password">
<span v-if="row.username === '' || row.password === ''">-</span>
<div class="flex items-center" v-else>
<div class="star-center" v-if="!row.showPassword">
<span>**********</span>
</div>
@ -131,11 +145,6 @@
<CopyButton :content="row.password" type="icon" />
</div>
</div>
<div v-else>
<el-link @click="onChangePassword(row)">
<span style="font-size: 12px">{{ $t('database.passwordHelper') }}</span>
</el-link>
</div>
</template>
</el-table-column>
<el-table-column :label="$t('commons.table.description')" prop="description">
@ -198,6 +207,7 @@
</template>
</el-dialog>
<BindDialog ref="bindRef" @search="search" />
<PasswordDialog ref="passwordRef" @search="search" />
<RootPasswordDialog ref="connRef" />
<UploadDialog ref="uploadRef" />
@ -212,6 +222,7 @@
</template>
<script lang="ts" setup>
import BindDialog from '@/views/database/postgresql/bind/index.vue';
import OperateDialog from '@/views/database/postgresql/create/index.vue';
import DeleteDialog from '@/views/database/postgresql/delete/index.vue';
import PasswordDialog from '@/views/database/postgresql/password/index.vue';
@ -252,6 +263,7 @@ const currentDBName = ref();
const checkRef = ref();
const deleteRef = ref();
const bindRef = ref();
const pgadminPort = ref();
const dashboardName = ref();
@ -352,6 +364,14 @@ const search = async (column?: any) => {
paginationConfig.total = res.data.total;
};
const onBind = async (row: Database.PostgresqlDBInfo) => {
let param = {
name: row.name,
database: currentDBName.value,
};
bindRef.value.acceptParams(param);
};
const loadDB = async () => {
ElMessageBox.confirm(i18n.global.t('database.loadFromRemoteHelper'), i18n.global.t('commons.msg.infoTitle'), {
confirmButtonText: i18n.global.t('commons.button.confirm'),
@ -359,12 +379,7 @@ const loadDB = async () => {
type: 'info',
}).then(async () => {
loading.value = true;
let params = {
from: currentDB.value.from,
type: currentDB.value.type,
database: currentDBName.value,
};
await loadPgFromRemote(params)
await loadPgFromRemote(currentDBName.value)
.then(() => {
loading.value = false;
search();

8
frontend/src/views/database/postgresql/setting/index.vue

@ -98,7 +98,7 @@ import { onMounted, reactive, ref } from 'vue';
import { Codemirror } from 'vue-codemirror';
import { javascript } from '@codemirror/lang-javascript';
import { oneDark } from '@codemirror/theme-one-dark';
import { loadDatabaseFile, loadMysqlBaseInfo, updatePostgresqlConfByFile } from '@/api/modules/database';
import { loadDBFile, loadDBBaseInfo, updateDBFile } from '@/api/modules/database';
import { ChangePort, CheckAppInstalled } from '@/api/modules/app';
import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
@ -186,7 +186,7 @@ const onSubmitChangeConf = async () => {
file: postgresqlConf.value,
};
loading.value = true;
await updatePostgresqlConfByFile(param)
await updateDBFile(param)
.then(() => {
loading.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
@ -211,7 +211,7 @@ const loadContainerLog = async (containerID: string) => {
};
const loadBaseInfo = async () => {
const res = await loadMysqlBaseInfo(props.type, props.database);
const res = await loadDBBaseInfo(props.type, props.database);
postgresqlName.value = res.data?.name;
baseInfo.port = res.data?.port;
baseInfo.containerID = res.data?.containerName;
@ -220,7 +220,7 @@ const loadBaseInfo = async () => {
};
const loadPostgresqlConf = async () => {
await loadDatabaseFile(props.type + '-conf', props.database)
await loadDBFile(props.type + '-conf', props.database)
.then((res) => {
loading.value = false;
postgresqlConf.value = res.data;

9
frontend/src/views/database/redis/setting/index.vue

@ -135,7 +135,7 @@ import { oneDark } from '@codemirror/theme-one-dark';
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import Status from '@/views/database/redis/setting/status/index.vue';
import Persistence from '@/views/database/redis/setting/persistence/index.vue';
import { loadDatabaseFile, loadRedisConf, updateRedisConf, updateRedisConfByFile } from '@/api/modules/database';
import { loadDBFile, loadRedisConf, updateRedisConf, updateDBFile } from '@/api/modules/database';
import i18n from '@/lang';
import { checkNumberRange, Rules } from '@/global/form-rules';
import { ChangePort, GetAppDefaultConfig } from '@/api/modules/app';
@ -313,11 +313,12 @@ const onSaveFile = async () => {
};
const submtiFile = async () => {
let param = {
type: 'redis',
database: '',
file: redisConf.value,
restartNow: true,
};
loading.value = true;
await updateRedisConfByFile(param)
await updateDBFile(param)
.then(() => {
useOld.value = false;
loading.value = false;
@ -340,7 +341,7 @@ const loadform = async () => {
const loadConfFile = async () => {
useOld.value = false;
loading.value = true;
await loadDatabaseFile('redis-conf', redisName.value)
await loadDBFile('redis-conf', redisName.value)
.then((res) => {
loading.value = false;
redisConf.value = res.data;

4
go.mod

@ -29,7 +29,6 @@ require (
github.com/jinzhu/gorm v1.9.2
github.com/joho/godotenv v1.5.1
github.com/klauspost/compress v1.16.5
github.com/mattn/go-sqlite3 v1.14.19
github.com/mholt/archiver/v4 v4.0.0-alpha.8
github.com/minio/minio-go/v7 v7.0.36
github.com/mojocn/base64Captcha v1.3.6
@ -61,7 +60,6 @@ require (
gopkg.in/ini.v1 v1.67.0
gopkg.in/square/go-jose.v2 v2.6.0
gopkg.in/yaml.v3 v3.0.1
gorm.io/driver/sqlite v1.5.4
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55
)
@ -160,6 +158,7 @@ require (
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-shellwords v1.0.12 // indirect
github.com/mattn/go-sqlite3 v1.14.19 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/miekg/dns v1.1.55 // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect
@ -240,6 +239,7 @@ require (
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gorm.io/driver/sqlite v1.5.4 // indirect
k8s.io/api v0.26.3 // indirect
k8s.io/apimachinery v0.26.3 // indirect
k8s.io/client-go v0.26.2 // indirect

Loading…
Cancel
Save