mirror of https://github.com/1Panel-dev/1Panel
ssongliu
11 months ago
committed by
GitHub
31 changed files with 804 additions and 935 deletions
@ -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) |
||||
} |
@ -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 |
||||
} |
@ -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> |
Loading…
Reference in new issue