mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-03-14 01:34:47 +08:00
feat: 实现远程数据库改密、授权功能
This commit is contained in:
parent
cb7351a9fb
commit
7f79f5f031
@ -68,7 +68,11 @@ func (b *BaseApi) SearchRemoteDB(c *gin.Context) {
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /databases/remote/list/:type [get]
|
||||
func (b *BaseApi) ListRemoteDB(c *gin.Context) {
|
||||
dbType := c.Query("type")
|
||||
dbType, err := helper.GetStrParamByKey(c, "type")
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
list, err := remoteDBService.List(dbType)
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
|
||||
|
@ -6,6 +6,7 @@ type MysqlDBInfo struct {
|
||||
ID uint `json:"id"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
Name string `json:"name"`
|
||||
From string `json:"from"`
|
||||
Format string `json:"format"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
|
@ -122,10 +122,15 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cli.Close()
|
||||
if err := cli.Create(client.CreateInfo{
|
||||
Name: req.Name,
|
||||
Format: req.Format,
|
||||
Version: version,
|
||||
Name: req.Name,
|
||||
Format: req.Format,
|
||||
Username: req.Username,
|
||||
Password: req.Password,
|
||||
Permission: req.Permission,
|
||||
Version: version,
|
||||
Timeout: 300,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -168,6 +173,7 @@ func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cli.Close()
|
||||
db, err := mysqlRepo.Get(commonRepo.WithByID(req.ID))
|
||||
if err != nil && !req.ForceDelete {
|
||||
return err
|
||||
@ -216,6 +222,7 @@ func (u *MysqlService) ChangePassword(info dto.ChangeDBInfo) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cli.Close()
|
||||
var (
|
||||
mysqlData model.DatabaseMysql
|
||||
passwordInfo client.PasswordChangeInfo
|
||||
@ -278,6 +285,7 @@ func (u *MysqlService) ChangeAccess(info dto.ChangeDBInfo) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cli.Close()
|
||||
var (
|
||||
mysqlData model.DatabaseMysql
|
||||
accessInfo client.AccessChangeInfo
|
||||
@ -293,6 +301,7 @@ func (u *MysqlService) ChangeAccess(info dto.ChangeDBInfo) error {
|
||||
}
|
||||
accessInfo.Name = mysqlData.Name
|
||||
accessInfo.Username = mysqlData.Username
|
||||
accessInfo.Password = mysqlData.Password
|
||||
accessInfo.OldPermission = mysqlData.Permission
|
||||
} else {
|
||||
accessInfo.Username = "root"
|
||||
@ -544,14 +553,17 @@ func loadClientByID(id uint) (mysql.MysqlClient, string, error) {
|
||||
version string
|
||||
err error
|
||||
)
|
||||
|
||||
dbInfo.From = "local"
|
||||
if id != 0 {
|
||||
mysqlData, err = mysqlRepo.Get(commonRepo.WithByID(id))
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
dbInfo.From = mysqlData.From
|
||||
}
|
||||
|
||||
if mysqlData.From != "local" {
|
||||
if dbInfo.From != "local" {
|
||||
databaseItem, err := remoteDBRepo.Get(commonRepo.WithByName(mysqlData.From))
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
|
@ -41,7 +41,7 @@ func (u *RemoteDBService) SearchWithPage(search dto.RemoteDBSearch) (int64, inte
|
||||
}
|
||||
|
||||
func (u *RemoteDBService) List(dbType string) ([]dto.RemoteDBOption, error) {
|
||||
dbs, err := remoteDBRepo.GetList(commonRepo.WithByType(dbType), remoteDBRepo.WithoutByFrom("local"))
|
||||
dbs, err := remoteDBRepo.GetList(commonRepo.WithByType(dbType))
|
||||
var datas []dto.RemoteDBOption
|
||||
for _, db := range dbs {
|
||||
var item dto.RemoteDBOption
|
||||
|
@ -437,7 +437,7 @@ func (u *SnapshotService) SnapshotRollback(req dto.SnapshotRecover) error {
|
||||
}
|
||||
}
|
||||
if snap.InterruptStep == "UpdateLiveRestore" {
|
||||
_, _ = cmd.Exec("systemctl restart dockere")
|
||||
_, _ = cmd.Exec("systemctl restart docker")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ func (s *DatabaseRouter) InitDatabaseRouter(Router *gin.RouterGroup) {
|
||||
cmdRouter.POST("/redis/persistence/update", baseApi.UpdateRedisPersistenceConf)
|
||||
|
||||
cmdRouter.POST("/remote", baseApi.CreateRemoteDB)
|
||||
cmdRouter.POST("/remote/list/:type", baseApi.ListRemoteDB)
|
||||
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)
|
||||
|
@ -2,7 +2,6 @@ package mysql
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/buserr"
|
||||
@ -22,23 +21,21 @@ type MysqlClient interface {
|
||||
}
|
||||
|
||||
func NewMysqlClient(conn client.DBInfo) (MysqlClient, error) {
|
||||
if conn.From == "remote" {
|
||||
connArgs := fmt.Sprintf("%s:%s@tcp(%s:%d)/?charset=utf8", conn.Username, conn.Password, conn.Address, conn.Port)
|
||||
db, err := sql.Open("mysql", connArgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := db.Ping(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return client.NewRemote(db), nil
|
||||
}
|
||||
if conn.From == "local" {
|
||||
if cmd.CheckIllegal(conn.Address, conn.Username, conn.Password) {
|
||||
return nil, buserr.New(constant.ErrCmdIllegal)
|
||||
}
|
||||
connArgs := []string{"exec", conn.Address, "mysql", "-u" + conn.Username, "-p" + conn.Password + "-e"}
|
||||
connArgs := []string{"exec", conn.Address, "mysql", "-u" + conn.Username, "-p" + conn.Password, "-e"}
|
||||
return client.NewLocal(connArgs, conn.Address), nil
|
||||
}
|
||||
return nil, errors.New("no such type")
|
||||
|
||||
connArgs := fmt.Sprintf("%s:%s@tcp(%s:%d)/?charset=utf8", conn.Username, conn.Password, conn.Address, conn.Port)
|
||||
db, err := sql.Open("mysql", connArgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := db.Ping(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return client.NewRemote(db), nil
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package client
|
||||
|
||||
type DBInfo struct {
|
||||
From string `json:"from"` // local remote
|
||||
From string `json:"from"`
|
||||
Address string `json:"address"`
|
||||
Port uint `json:"port"`
|
||||
Username string `json:"userName"`
|
||||
@ -45,6 +45,7 @@ type AccessChangeInfo struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Username string `json:"userName"`
|
||||
Password string `json:"password"`
|
||||
OldPermission string `json:"oldPermission"`
|
||||
Permission string `json:"permission"`
|
||||
|
||||
|
@ -31,7 +31,7 @@ func (r *Local) Create(info CreateInfo) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := r.CreateUser(CreateInfo{Name: info.Name, Version: info.Version, Username: info.Username, Permission: info.Permission, Timeout: info.Timeout}); err != nil {
|
||||
if err := r.CreateUser(info); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -185,7 +185,14 @@ func (r *Local) ChangeAccess(info AccessChangeInfo) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if err := r.CreateUser(CreateInfo{Name: info.Name, Version: info.Version, Username: info.Username, Permission: info.Permission, Timeout: info.Timeout}); err != nil {
|
||||
if err := r.CreateUser(CreateInfo{
|
||||
Name: info.Name,
|
||||
Version: info.Version,
|
||||
Username: info.Username,
|
||||
Password: info.Password,
|
||||
Permission: info.Permission,
|
||||
Timeout: info.Timeout,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := r.ExecSQL("flush privileges", 300); err != nil {
|
||||
|
@ -29,7 +29,7 @@ func (r *Remote) Create(info CreateInfo) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := r.CreateUser(CreateInfo{Name: info.Name, Version: info.Version, Username: info.Username, Permission: info.Permission, Timeout: info.Timeout}); err != nil {
|
||||
if err := r.CreateUser(info); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -183,7 +183,14 @@ func (r *Remote) ChangeAccess(info AccessChangeInfo) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if err := r.CreateUser(CreateInfo{Name: info.Name, Version: info.Version, Username: info.Username, Permission: info.Permission, Timeout: info.Timeout}); err != nil {
|
||||
if err := r.CreateUser(CreateInfo{
|
||||
Name: info.Name,
|
||||
Version: info.Version,
|
||||
Username: info.Username,
|
||||
Password: info.Password,
|
||||
Permission: info.Permission,
|
||||
Timeout: info.Timeout,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := r.ExecSQL("flush privileges", 300); err != nil {
|
||||
|
@ -9,6 +9,7 @@ export namespace Database {
|
||||
id: number;
|
||||
createdAt: Date;
|
||||
name: string;
|
||||
from: string;
|
||||
format: string;
|
||||
username: string;
|
||||
password: string;
|
||||
|
@ -45,6 +45,18 @@
|
||||
/>
|
||||
<span class="input-help">{{ $t('database.remoteHelper') }}</span>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('commons.table.name')" prop="name">
|
||||
<el-select v-model="form.from">
|
||||
<el-option
|
||||
v-for="(item, index) in dbOptions"
|
||||
:key="index"
|
||||
:value="item.name"
|
||||
:label="loadLabel(item)"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('commons.table.description')" prop="description">
|
||||
<el-input type="textarea" clearable v-model="form.description" />
|
||||
</el-form-item>
|
||||
@ -71,15 +83,17 @@ import { reactive, ref } from 'vue';
|
||||
import { Rules } from '@/global/form-rules';
|
||||
import i18n from '@/lang';
|
||||
import { ElForm } from 'element-plus';
|
||||
import { addMysqlDB } from '@/api/modules/database';
|
||||
import { addMysqlDB, listRemoteDBs } from '@/api/modules/database';
|
||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { getRandomStr } from '@/utils/util';
|
||||
|
||||
const loading = ref();
|
||||
const dbOptions = ref();
|
||||
const createVisiable = ref(false);
|
||||
const form = reactive({
|
||||
name: '',
|
||||
from: 'local',
|
||||
mysqlName: '',
|
||||
format: '',
|
||||
username: '',
|
||||
@ -110,12 +124,22 @@ const acceptParams = (params: DialogProps): void => {
|
||||
form.permissionIPs = '';
|
||||
form.description = '';
|
||||
random();
|
||||
loadDBOptions();
|
||||
createVisiable.value = true;
|
||||
};
|
||||
const handleClose = () => {
|
||||
createVisiable.value = false;
|
||||
};
|
||||
|
||||
const loadDBOptions = async () => {
|
||||
const res = await listRemoteDBs('mysql');
|
||||
dbOptions.value = res.data;
|
||||
};
|
||||
|
||||
function loadLabel(item: any) {
|
||||
return (item.name === 'local' ? i18n.global.t('database.localDB') : item.name) + '(' + item.address + ')';
|
||||
}
|
||||
|
||||
const random = async () => {
|
||||
form.password = getRandomStr(16);
|
||||
};
|
||||
|
@ -49,6 +49,11 @@
|
||||
:class="{ mask: mysqlStatus != 'Running' }"
|
||||
>
|
||||
<el-table-column :label="$t('commons.table.name')" prop="name" sortable />
|
||||
<el-table-column :label="$t('commons.login.username')" prop="from">
|
||||
<template #default="{ row }">
|
||||
<span>{{ row.from === 'local' ? $t('database.localDB') : row.from }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.login.username')" prop="username" />
|
||||
<el-table-column :label="$t('commons.login.password')" prop="password">
|
||||
<template #default="{ row }">
|
||||
@ -310,6 +315,7 @@ const buttons = [
|
||||
click: (row: Database.MysqlDBInfo) => {
|
||||
let param = {
|
||||
id: row.id,
|
||||
from: row.from,
|
||||
mysqlName: row.name,
|
||||
operation: 'password',
|
||||
username: row.username,
|
||||
@ -323,6 +329,7 @@ const buttons = [
|
||||
click: (row: Database.MysqlDBInfo) => {
|
||||
let param = {
|
||||
id: row.id,
|
||||
from: row.from,
|
||||
mysqlName: row.name,
|
||||
operation: 'privilege',
|
||||
privilege: '',
|
||||
|
@ -81,6 +81,7 @@ const changeFormRef = ref<FormInstance>();
|
||||
const title = ref();
|
||||
const changeForm = reactive({
|
||||
id: 0,
|
||||
from: '',
|
||||
mysqlName: '',
|
||||
userName: '',
|
||||
password: '',
|
||||
@ -93,6 +94,7 @@ const confirmDialogRef = ref();
|
||||
|
||||
interface DialogProps {
|
||||
id: number;
|
||||
from: string;
|
||||
mysqlName: string;
|
||||
username: string;
|
||||
password: string;
|
||||
@ -107,6 +109,7 @@ const acceptParams = (params: DialogProps): void => {
|
||||
? i18n.global.t('database.changePassword')
|
||||
: i18n.global.t('database.permission');
|
||||
changeForm.id = params.id;
|
||||
changeForm.from = params.from === 'local' ? 'local' : 'remote';
|
||||
changeForm.mysqlName = params.mysqlName;
|
||||
changeForm.userName = params.username;
|
||||
changeForm.password = params.password;
|
||||
@ -128,6 +131,7 @@ const submitChangeInfo = async (formEl: FormInstance | undefined) => {
|
||||
if (!valid) return;
|
||||
let param = {
|
||||
id: changeForm.id,
|
||||
from: changeForm.from,
|
||||
value: '',
|
||||
};
|
||||
if (changeForm.operation === 'password') {
|
||||
@ -177,6 +181,7 @@ const submitChangeInfo = async (formEl: FormInstance | undefined) => {
|
||||
const onSubmit = async () => {
|
||||
let param = {
|
||||
id: changeForm.id,
|
||||
from: changeForm.from,
|
||||
value: changeForm.password,
|
||||
};
|
||||
loading.value = true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user