fix: 处理数据库遮罩问题 (#5215)

This commit is contained in:
ssongliu 2024-05-30 15:13:21 +08:00 committed by GitHub
parent c62232e648
commit e5bcb07cf6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 166 additions and 54 deletions

View File

@ -73,6 +73,7 @@ type AppInstalledDTO struct {
}
type DatabaseConn struct {
Status string `json:"status"`
Username string `json:"username"`
Password string `json:"password"`
ContainerName string `json:"containerName"`

View File

@ -3,6 +3,7 @@ package repo
import (
"context"
"encoding/json"
"github.com/1Panel-dev/1Panel/backend/constant"
"gorm.io/gorm/clause"
@ -160,6 +161,7 @@ func (a *AppInstallRepo) BatchUpdateBy(maps map[string]interface{}, opts ...DBOp
type RootInfo struct {
ID uint `json:"id"`
Name string `json:"name"`
Status string `json:"status"`
Port int64 `json:"port"`
HttpsPort int64 `json:"httpsPort"`
UserName string `json:"userName"`
@ -234,5 +236,6 @@ func (a *AppInstallRepo) LoadBaseInfo(key string, name string) (*RootInfo, error
info.Key = app.Key
appInstall.App = app
info.AppPath = appInstall.GetAppPath()
info.Status = appInstall.Status
return &info, nil
}

View File

@ -184,6 +184,7 @@ func (a *AppInstallService) LoadConnInfo(req dto.OperationWithNameAndType) (resp
if err != nil {
return data, nil
}
data.Status = app.Status
data.Username = app.UserName
data.Password = app.Password
data.ServiceName = app.ServiceName

View File

@ -70,6 +70,9 @@ func (u *DatabaseService) Get(name string) (dto.DatabaseInfo, error) {
func (u *DatabaseService) List(dbType string) ([]dto.DatabaseOption, error) {
dbs, err := databaseRepo.GetList(databaseRepo.WithTypeList(dbType))
if err != nil {
return nil, err
}
var datas []dto.DatabaseOption
for _, db := range dbs {
var item dto.DatabaseOption

View File

@ -363,6 +363,17 @@ func (u *MysqlService) ChangePassword(req dto.ChangeDBInfo) error {
if err := updateInstallInfoInDB(req.Type, req.Database, "password", req.Value); err != nil {
return err
}
if req.From == "local" {
remote, err := databaseRepo.Get(commonRepo.WithByName(req.Database))
if err != nil {
return err
}
pass, err := encrypt.StringEncrypt(req.Value)
if err != nil {
return fmt.Errorf("decrypt database password failed, err: %v", err)
}
_ = databaseRepo.Update(remote.ID, map[string]interface{}{"password": pass})
}
return nil
}

View File

@ -414,5 +414,16 @@ func (u *PostgresqlService) ChangePassword(req dto.ChangeDBInfo) error {
if err := updateInstallInfoInDB(req.Type, req.Database, "password", req.Value); err != nil {
return err
}
if req.From == "local" {
remote, err := databaseRepo.Get(commonRepo.WithByName(req.Database))
if err != nil {
return err
}
pass, err := encrypt.StringEncrypt(req.Value)
if err != nil {
return fmt.Errorf("decrypt database password failed, err: %v", err)
}
_ = databaseRepo.Update(remote.ID, map[string]interface{}{"password": pass})
}
return nil
}

View File

@ -13,6 +13,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/utils/compose"
"github.com/1Panel-dev/1Panel/backend/utils/docker"
"github.com/1Panel-dev/1Panel/backend/utils/encrypt"
"github.com/docker/docker/api/types/container"
_ "github.com/go-sql-driver/mysql"
)
@ -87,9 +88,17 @@ func (u *RedisService) ChangePassword(req dto.ChangeRedisPass) error {
if err := updateInstallInfoInDB("redis", req.Database, "password", req.Value); err != nil {
return err
}
if err := updateInstallInfoInDB("redis-commander", "", "password", req.Value); err != nil {
remote, err := databaseRepo.Get(commonRepo.WithByName(req.Database))
if err != nil {
return err
}
if remote.From == "local" {
pass, err := encrypt.StringEncrypt(req.Value)
if err != nil {
return fmt.Errorf("decrypt database password failed, err: %v", err)
}
_ = databaseRepo.Update(remote.ID, map[string]interface{}{"password": pass})
}
return nil
}

View File

@ -143,6 +143,7 @@ export namespace App {
}
export interface DatabaseConnInfo {
status: string;
username: string;
password: string;
privilege: boolean;

View File

@ -185,6 +185,7 @@ const onCheck = async () => {
.then((res) => {
data.value = res.data;
em('isExist', res.data);
em('update:maskShow', res.data.status !== 'Running');
operateReq.installId = res.data.appInstallId;
httpPort.value = res.data.httpPort;
httpsPort.value = res.data.httpsPort;

View File

@ -68,7 +68,11 @@
<div v-if="form.from === 'local'">
<el-form-item :label="$t('database.remoteAccess')" prop="privilege">
<el-switch v-model="form.privilege" @change="onSaveAccess" />
<el-switch
v-model="form.privilege"
:disabled="form.status !== 'Running'"
@change="onSaveAccess"
/>
<span class="input-help">{{ $t('database.remoteConnHelper') }}</span>
</el-form-item>
<el-form-item
@ -109,7 +113,7 @@
<el-button :disabled="loading" @click="dialogVisible = false">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button :disabled="loading" type="primary" @click="onSave(formRef)">
<el-button :disabled="loading || form.status !== 'Running'" type="primary" @click="onSave(formRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
@ -134,6 +138,7 @@ const loading = ref(false);
const dialogVisible = ref(false);
const form = reactive({
status: '',
systemIP: '',
password: '',
serviceName: '',
@ -201,6 +206,7 @@ const loadSystemIP = async () => {
const loadPassword = async () => {
if (form.from === 'local') {
const res = await GetAppConnInfo(form.type, form.database);
form.status = res.data.status;
form.password = res.data.password || '';
form.port = res.data.port || 3306;
form.serviceName = res.data.serviceName || '';

View File

@ -70,12 +70,7 @@
>
{{ $t('database.create') }}
</el-button>
<el-button
v-if="currentDB && (currentDB.from !== 'local' || mysqlStatus === 'Running')"
@click="onChangeConn"
type="primary"
plain
>
<el-button v-if="currentDB" @click="onChangeConn" type="primary" plain>
{{ $t('database.databaseConnInfo') }}
</el-button>
<el-button
@ -114,7 +109,7 @@
<template #main v-if="currentDB">
<ComplexTable
:pagination-config="paginationConfig"
:class="{ mask: maskShow && currentDB.from !== 'local' }"
:class="{ mask: maskShow }"
@sort-change="search"
@search="search"
:data="data"
@ -394,6 +389,7 @@ const changeDatabase = async () => {
}
for (const item of dbOptionsRemote.value) {
if (item.database == currentDBName.value) {
maskShow.value = false;
currentDB.value = item;
break;
}

View File

@ -112,7 +112,7 @@
<el-button :disabled="loading" @click="dialogVisible = false">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button :disabled="loading" type="primary" @click="onSave(formRef)">
<el-button :disabled="loading || form.status !== 'Running'" type="primary" @click="onSave(formRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
@ -137,6 +137,7 @@ const loading = ref(false);
const dialogVisible = ref(false);
const form = reactive({
status: '',
systemIP: '',
password: '',
containerName: '',
@ -202,6 +203,7 @@ const loadSystemIP = async () => {
const loadPassword = async () => {
if (form.from === 'local') {
const res = await GetAppConnInfo(form.type, form.database);
form.status = res.data.status;
form.username = res.data.username || '';
form.password = res.data.password || '';
form.port = res.data.port || 5432;

View File

@ -62,12 +62,7 @@
>
{{ $t('database.create') }}
</el-button>
<el-button
v-if="currentDB && (currentDB.from !== 'local' || postgresqlStatus === 'Running')"
@click="onChangeConn"
type="primary"
plain
>
<el-button v-if="currentDB" @click="onChangeConn" type="primary" plain>
{{ $t('database.databaseConnInfo') }}
</el-button>
<el-button
@ -90,7 +85,7 @@
</template>
<template #main v-if="currentDB">
<ComplexTable
:class="{ mask: maskShow && currentDB.from !== 'local' }"
:class="{ mask: maskShow }"
:pagination-config="paginationConfig"
@sort-change="search"
@search="search"
@ -364,6 +359,7 @@ const changeDatabase = async () => {
}
for (const item of dbOptionsRemote.value) {
if (item.database == currentDBName.value) {
maskShow.value = false;
currentDB.value = item;
break;
}

View File

@ -12,12 +12,21 @@
<el-form @submit.prevent v-loading="loading" ref="formRef" :model="form" label-position="top">
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item :label="$t('database.containerConn')">
<el-form-item :label="$t('database.containerConn')" v-if="form.from === 'local'">
<el-card class="mini-border-card">
<el-descriptions :column="1">
<el-descriptions-item :label="$t('database.connAddress')">
{{ form.containerName }}
<CopyButton :content="form.containerName" type="icon" />
<el-tooltip
v-if="loadRedisInfo(true).length > 48"
:content="loadRedisInfo(true)"
placement="top"
>
{{ loadRedisInfo(true).substring(0, 48) }}...
</el-tooltip>
<span else>
{{ loadRedisInfo(true) }}
</span>
<CopyButton :content="loadRedisInfo(true)" type="icon" />
</el-descriptions-item>
<el-descriptions-item :label="$t('database.connPort')">
6379
@ -33,8 +42,17 @@
<el-card class="mini-border-card">
<el-descriptions :column="1">
<el-descriptions-item :label="$t('database.connAddress')">
{{ form.systemIP }}
<CopyButton :content="form.systemIP" type="icon" />
<el-tooltip
v-if="loadRedisInfo(false).length > 48"
:content="loadRedisInfo(false)"
placement="top"
>
{{ loadRedisInfo(false).substring(0, 48) }}...
</el-tooltip>
<span else>
{{ loadRedisInfo(false) }}
</span>
<CopyButton :content="loadRedisInfo(false)" type="icon" />
</el-descriptions-item>
<el-descriptions-item :label="$t('database.connPort')">
{{ form.port }}
@ -48,7 +66,12 @@
</el-form-item>
<el-divider border-style="dashed" />
<el-form-item :label="$t('commons.login.password')" :rules="Rules.paramComplexity" prop="password">
<el-form-item
:label="$t('commons.login.password')"
v-if="form.from === 'local'"
:rules="Rules.paramComplexity"
prop="password"
>
<el-input type="password" show-password clearable v-model="form.password">
<template #append>
<CopyButton :content="form.password" />
@ -58,6 +81,13 @@
</template>
</el-input>
</el-form-item>
<div v-if="form.from !== 'local'">
<el-form-item :label="$t('commons.login.password')">
<el-tag>{{ form.password }}</el-tag>
<CopyButton :content="form.password" type="icon" />
</el-form-item>
</div>
</el-col>
</el-row>
</el-form>
@ -69,7 +99,7 @@
<el-button :disabled="loading" @click="dialogVisible = false">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button :disabled="loading" type="primary" @click="onSave(formRef)">
<el-button :disabled="loading || form.status !== 'Running'" type="primary" @click="onSave(formRef)">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
@ -82,7 +112,7 @@ import { reactive, ref } from 'vue';
import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
import { ElForm } from 'element-plus';
import { changeRedisPassword } from '@/api/modules/database';
import { changeRedisPassword, getDatabase } from '@/api/modules/database';
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import { GetAppConnInfo } from '@/api/modules/app';
import { MsgSuccess } from '@/utils/message';
@ -94,11 +124,16 @@ const loading = ref(false);
const dialogVisible = ref(false);
const form = reactive({
database: '',
password: '',
containerName: '',
status: '',
systemIP: '',
password: '',
serviceName: '',
containerName: '',
port: 0,
from: '',
database: '',
remoteIP: '',
});
const confirmDialogRef = ref();
@ -109,11 +144,13 @@ type FormInstance = InstanceType<typeof ElForm>;
const formRef = ref<FormInstance>();
interface DialogProps {
from: string;
database: string;
}
const acceptParams = (params: DialogProps): void => {
form.database = params.database;
form.password = '';
form.from = params.from;
form.database = params.database;
loadPassword();
dialogVisible.value = true;
};
@ -126,14 +163,36 @@ const random = async () => {
};
const loadPassword = async () => {
const res = await GetAppConnInfo('redis', form.database);
form.containerName = res.data.containerName;
if (form.from === 'local') {
const res = await GetAppConnInfo('redis', form.database);
form.status = res.data.status;
form.password = res.data.password || '';
form.port = res.data.port || 3306;
form.serviceName = res.data.serviceName || '';
form.containerName = res.data.containerName || '';
loadSystemIP();
return;
}
const res = await getDatabase(form.database);
form.password = res.data.password || '';
form.port = res.data.port || 3306;
form.password = res.data.password;
form.port = res.data.port;
const settingInfoRes = await getSettingInfo();
form.systemIP = settingInfoRes.data.systemIP || i18n.global.t('database.localIP');
form.remoteIP = res.data.address;
};
const loadSystemIP = async () => {
const res = await getSettingInfo();
form.systemIP = res.data.systemIP || i18n.global.t('database.localIP');
};
function loadRedisInfo(isContainer: boolean) {
if (isContainer) {
return form.from === 'local' ? form.containerName : form.systemIP;
} else {
return form.from === 'local' ? form.systemIP : form.remoteIP;
}
}
const onSubmit = async () => {
loading.value = true;
emit('closeTerminal');

View File

@ -51,15 +51,13 @@
</el-option-group>
</el-select>
</template>
<template #toolbar v-if="!isOnSetting && currentDB">
<div :class="{ mask: redisStatus != 'Running' && currentDB.from === 'local' }">
<el-button type="primary" plain @click="onChangePassword">
{{ $t('database.databaseConnInfo') }}
</el-button>
<el-button @click="goRemoteDB" type="primary" plain>
{{ $t('database.remoteDB') }}
</el-button>
</div>
<template #toolbar v-if="!isOnSetting">
<el-button v-if="currentDB" type="primary" plain @click="onLoadConn">
{{ $t('database.databaseConnInfo') }}
</el-button>
<el-button @click="goRemoteDB" type="primary" plain>
{{ $t('database.remoteDB') }}
</el-button>
</template>
</LayoutContent>
@ -71,13 +69,10 @@
v-show="redisStatus === 'Running' && terminalShow"
/>
<el-empty
:class="{ mask: maskShow }"
v-if="redisStatus !== 'Running' || (currentDB.from === 'remote' && !redisCliExist)"
:style="{ height: `calc(100vh - ${loadHeight()})`, 'background-color': '#000' }"
:description="
currentDB.from === 'remote'
? $t('commons.service.serviceNotStarted', ['Redis'])
: $t('database.redisCliHelper')
"
:description="loadErrMsg()"
>
<el-button v-if="currentDB.from === 'remote'" type="primary" @click="installCli">
{{ $t('commons.button.enable') }}
@ -94,8 +89,15 @@
</div>
</div>
<el-card
v-if="redisStatus != 'Running' && currentDB && !loading && maskShow && currentDB?.from === 'local'"
class="mask-prompt"
>
<span>{{ $t('commons.service.serviceNotStarted', ['Redis']) }}</span>
</el-card>
<Setting ref="settingRef" style="margin-top: 30px" />
<Password ref="passwordRef" @check-exist="reOpenTerminal" @close-terminal="closeTerminal(true)" />
<Conn ref="connRef" @check-exist="reOpenTerminal" @close-terminal="closeTerminal(true)" />
<el-dialog
v-model="commandVisible"
:title="$t('app.checkTitle')"
@ -121,7 +123,7 @@
<script lang="ts" setup>
import Setting from '@/views/database/redis/setting/index.vue';
import Password from '@/views/database/redis/password/index.vue';
import Conn from '@/views/database/redis/conn/index.vue';
import Terminal from '@/components/terminal/index.vue';
import AppStatus from '@/components/app-status/index.vue';
import QuickCmd from '@/views/database/redis/command/index.vue';
@ -184,9 +186,13 @@ const goRemoteDB = async () => {
router.push({ name: 'Redis-Remote' });
};
const passwordRef = ref();
const onChangePassword = async () => {
passwordRef.value!.acceptParams({ database: currentDBName.value });
const connRef = ref();
const onLoadConn = async () => {
connRef.value!.acceptParams({
from: currentDB.value.from,
type: currentDB.value.type,
database: currentDBName.value,
});
};
const goRouter = async (target: string) => {
@ -209,6 +215,7 @@ const changeDatabase = async () => {
}
for (const item of dbOptionsRemote.value) {
if (item.database == currentDBName.value) {
maskShow.value = false;
currentDB.value = item;
break;
}
@ -255,6 +262,11 @@ const loadDBOptions = async () => {
}
};
const loadErrMsg = () => {
return currentDB.value.from === 'local'
? i18n.global.t('commons.service.serviceNotStarted', ['Redis'])
: i18n.global.t('database.redisCliHelper');
};
const reOpenTerminal = async () => {
closeTerminal(false);
initTerminal();