fix: Optimize database password verification and password change (#8294)

This commit is contained in:
ssongliu 2025-04-02 16:03:44 +08:00 committed by GitHub
parent d96fe49993
commit 47d135ecca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 150 additions and 130 deletions

View file

@ -839,6 +839,9 @@ func updateInstallInfoInDB(appKey, appName, param string, value interface{}) err
"param": strings.ReplaceAll(appInstall.Param, oldVal, newVal),
"env": strings.ReplaceAll(appInstall.Env, oldVal, newVal),
}, commonRepo.WithByID(appInstall.ID))
if appKey == "mysql" || appKey == "postgresql" {
return nil
}
}
if param == "user-password" {
oldVal = fmt.Sprintf("\"PANEL_DB_USER_PASSWORD\":\"%v\"", appInstall.UserPassword)

View file

@ -121,7 +121,8 @@ const checkIllegal = (rule: any, value: any, callback: any) => {
value.indexOf('`') !== -1 ||
value.indexOf('(') !== -1 ||
value.indexOf(')') !== -1 ||
value.indexOf("'") !== -1
value.indexOf('>') !== -1 ||
value.indexOf('<') !== -1
) {
callback(new Error(i18n.global.t('commons.rule.illegalInput')));
} else {

View file

@ -191,6 +191,7 @@ const message = {
rePassword: 'Confirm password is inconsistent with the password.',
requiredInput: 'This field is required.',
requiredSelect: 'Select an item in the list',
illegalChar: 'Injection of characters & ; $ \' ` ( ) " > < | is currently not supported',
illegalInput: `This field mustn't contains illegal characters.`,
commonName:
'This field must start with non-special characters and must consist of English, Chinese, numbers, ".", "-", and "_" characters with a length of 1-128.',
@ -427,6 +428,8 @@ const message = {
permission: 'Permissions',
permissionForIP: 'IP',
permissionAll: 'All of them(%)',
localhostHelper:
'Configuring database permissions as "localhost" for container deployment will prevent external access to the container. Please choose carefully!',
databaseConnInfo: 'Connection info',
rootPassword: 'Root password',
serviceName: 'Service Name',
@ -438,6 +441,7 @@ const message = {
remoteConnHelper:
'Remote connection to MySQL as user root may have security risks. Therefore, perform this operation with caution.',
changePassword: 'Password',
changeConnHelper: 'This operation will modify the current database {0}. Do you want to continue?',
changePasswordHelper:
'The database has been associated with an application. Changing the password will change the database password of the application at the same time. The change takes effect after the application restarts.',

View file

@ -190,6 +190,7 @@ const message = {
rePassword: 'パスワードがパスワードと矛盾することを確認してください',
requiredInput: 'この項目は必須です',
requiredSelect: 'リスト内のアイテムを選択します',
illegalChar: '現在文字 & ; $ \' ` ( ) " > < | の注入はサポートされていません',
illegalInput: `このフィールドには違法なキャラクターが含まれてはなりません。`,
commonName:
'このフィールドは特別なキャラクターではなく英語中国語数字で構成されている必要がありますおよび_文字が1128の文字で構成されている必要があります',
@ -427,6 +428,8 @@ const message = {
permission: '権限',
permissionForIP: 'ip',
permissionAll: 'それらすべて',
localhostHelper:
'コンテナ展開でデータベース権限を"localhost"に設定するとコンテナ外部からのアクセスができなくなります慎重に選択してください',
databaseConnInfo: '接続情報',
rootPassword: 'ルートパスワード',
serviceName: 'サービス名',
@ -438,6 +441,7 @@ const message = {
remoteConnHelper:
'ユーザールートとしてのMySQLへのリモート接続にはセキュリティリスクがある場合がありますしたがってこの操作を慎重に実行します',
changePassword: 'パスワード',
changeConnHelper: 'この操作は現在のデータベース {0} を変更します続行しますか',
changePasswordHelper:
'データベースはアプリケーションに関連付けられていますパスワードを変更するとアプリケーションのデータベースパスワードが同時に変更されますアプリケーションが再起動した後変更は有効になります',

View file

@ -190,6 +190,7 @@ const message = {
rePassword: '확인 비밀번호가 비밀번호와 일치하지 않습니다.',
requiredInput: ' 필드는 필수 항목입니다.',
requiredSelect: '목록에서 항목을 선택하세요',
illegalChar: '현재 & ; $ \' ` ( ) " > < | 문자 주입은 지원되지 않습니다',
illegalInput: ' 필드에는 유효하지 않은 문자가 포함될 없습니다.',
commonName:
' 필드는 특수 문자로 시작할 없으며, 영어, 한자, 숫자, ".", "-", "_" 문자로 구성되어야 하며 길이는 1-128자여야 합니다.',
@ -429,6 +430,8 @@ const message = {
permission: '권한',
permissionForIP: 'IP',
permissionAll: '모두(%)',
localhostHelper:
'컨테이너 배포 데이터베이스 권한을 "localhost" 설정하면 컨테이너 외부에서 접근할 없게 됩니다. 신중하게 선택하세요!',
databaseConnInfo: '연결 정보',
rootPassword: '루트 비밀번호',
serviceName: '서비스 이름',
@ -440,6 +443,7 @@ const message = {
remoteConnHelper:
'MySQL root 사용자로 원격 접속은 보안 위험을 초래할 있습니다. 따라서 작업은 신중히 수행해야 합니다.',
changePassword: '비밀번호',
changeConnHelper: ' 작업은 현재 데이터베이스 {0}() 수정합니다. 계속하시겠습니까?',
changePasswordHelper:
'데이터베이스가 애플리케이션과 연결되어 있습니다. 비밀번호를 변경하면 애플리케이션의 데이터베이스 비밀번호도 변경됩니다. 변경 사항은 애플리케이션이 재시작된 후에 적용됩니다.',
confChange: '설정',

View file

@ -193,6 +193,7 @@ const message = {
rePassword: 'Pengesahan kata laluan tidak sepadan dengan kata laluan.',
requiredInput: 'Ruangan ini wajib diisi.',
requiredSelect: 'Pilih satu item dalam senarai',
illegalChar: 'Suntikan aksara & ; $ \' ` ( ) " > < | tidak disokong buat masa ini',
illegalInput: 'Ruangan ini tidak boleh mengandungi aksara tidak sah.',
commonName:
'Ruangan ini mesti bermula dengan aksara bukan khas dan mesti terdiri daripada aksara rumi, Cina, nombor, ".", "-", dan "_" dengan panjang 1-128 aksara.',
@ -435,6 +436,8 @@ const message = {
permission: 'Kebenaran',
permissionForIP: 'IP',
permissionAll: 'Kesemuanya(%)',
localhostHelper:
'Mengkonfigurasi kebenaran pangkalan data sebagai "localhost" untuk penyebaran kontena akan menghalang akses luar ke kontena. Sila pilih dengan teliti!',
databaseConnInfo: 'Maklumat sambungan',
rootPassword: 'Kata laluan root',
serviceName: 'Nama Perkhidmatan',
@ -446,6 +449,7 @@ const message = {
remoteConnHelper:
'Sambungan jauh ke MySQL sebagai pengguna root mungkin mempunyai risiko keselamatan. Oleh itu, lakukan operasi ini dengan berhati-hati.',
changePassword: 'Kata laluan',
changeConnHelper: 'Operasi ini akan mengubah pangkalan data semasa {0}. Adakah anda ingin meneruskan?',
changePasswordHelper:
'Pangkalan data telah dikaitkan dengan aplikasi. Menukar kata laluan akan menukar kata laluan pangkalan data aplikasi pada masa yang sama. Perubahan ini akan berkuat kuasa selepas aplikasi dimulakan semula.',

View file

@ -192,6 +192,7 @@ const message = {
rePassword: 'A confirmação da senha não corresponde à senha.',
requiredInput: 'Este campo é obrigatório.',
requiredSelect: 'Selecione um item na lista',
illegalChar: 'Atualmente não suporte para injeção dos caracteres & ; $ \' ` ( ) " > < |',
illegalInput: 'Este campo não deve conter caracteres ilegais.',
commonName:
'Este campo deve começar com caracteres não especiais e consistir em letras, números, ".", "-", e "_" com comprimento de 1-128.',
@ -433,6 +434,8 @@ const message = {
permission: 'Permissões',
permissionForIP: 'IP',
permissionAll: 'Todos (% de)',
localhostHelper:
'Configurar permissões de banco de dados como "localhost" para implantação em contêiner impedirá o acesso externo ao contêiner. Por favor, escolha com cuidado!',
databaseConnInfo: 'Informações de conexão',
rootPassword: 'Senha root',
serviceName: 'Nome do serviço',
@ -444,6 +447,7 @@ const message = {
remoteConnHelper:
'Conectar-se ao MySQL como usuário root pode representar riscos de segurança. Realize esta operação com cautela.',
changePassword: 'Senha',
changeConnHelper: 'Esta operação modificará o banco de dados atual {0}. Deseja continuar?',
changePasswordHelper:
'O banco de dados está associado a um aplicativo. Alterar a senha alterará a senha do banco de dados do aplicativo ao mesmo tempo. A mudança surtirá efeito após a reinicialização do aplicativo.',

View file

@ -191,6 +191,7 @@ const message = {
rePassword: 'Подтверждение пароля не совпадает с паролем.',
requiredInput: 'Это поле обязательно для заполнения.',
requiredSelect: 'Выберите элемент из списка',
illegalChar: 'В настоящее время не поддерживается вставка символов & ; $ \' ` ( ) " > < |',
illegalInput: 'Это поле не должно содержать недопустимых символов.',
commonName:
'Это поле должно начинаться с неспециальных символов и должно состоять из английских букв, китайских иероглифов, цифр, ".", "-" и "_" длиной 1-128.',
@ -429,6 +430,8 @@ const message = {
permission: 'Разрешения',
permissionForIP: 'IP',
permissionAll: 'Все (%)',
localhostHelper:
'Настройка разрешений базы данных как "localhost" для развертывания контейнера предотвратит внешний доступ к контейнеру. Пожалуйста, выбирайте внимательно!',
databaseConnInfo: 'Информация о подключении',
rootPassword: 'Пароль root',
serviceName: 'Имя сервиса',
@ -440,6 +443,7 @@ const message = {
remoteConnHelper:
'Удаленное подключение к MySQL как пользователь root может иметь риски безопасности. Поэтому выполняйте эту операцию с осторожностью.',
changePassword: 'Пароль',
changeConnHelper: 'Эта операция изменит текущую базу данных {0}. Продолжить?',
changePasswordHelper:
'База данных была связана с приложением. Изменение пароля изменит пароль базы данных приложения одновременно. Изменение вступит в силу после перезапуска приложения.',

View file

@ -192,6 +192,7 @@ const message = {
rePassword: '密碼不一致請檢查後重新輸入',
requiredInput: '請填寫必填項',
requiredSelect: '請選擇必選項',
illegalChar: '暫不支援注入字元 & ; $ \' ` ( ) " > < |',
illegalInput: '輸入框中存在不合法字元',
commonName: '支援非特殊字元開頭,英文中文數字.-和_,長度1-128',
userName: '支援英文中文數字和_,長度3-30',
@ -418,6 +419,7 @@ const message = {
permission: '權限',
permissionForIP: '指定 IP',
permissionAll: '所有人(%)',
localhostHelper: '將容器部署的資料庫權限配置為"localhost"會導致容器外部無法存取請謹慎選擇',
databaseConnInfo: '連接資訊',
rootPassword: 'root 密碼',
serviceName: '服務名稱',
@ -428,6 +430,7 @@ const message = {
remoteHelper: '多個 ip 以逗號分隔172.16.10.111,172.16.10.112',
remoteConnHelper: 'root 帳號遠端連接 MySQL 有安全風險開啟需謹慎',
changePassword: '改密',
changeConnHelper: '此操作將修改當前資料庫 {0}是否繼續',
changePasswordHelper: '目前資料庫已經關聯應用修改密碼將同步修改應用中資料庫密碼修改後重啟生效',
portHelper: '該埠為容器對外暴露埠修改需要單獨儲存並且重啟容器',

View file

@ -191,6 +191,7 @@ const message = {
rePassword: '密码不一致请检查后重新输入',
requiredInput: '请填写必填项',
requiredSelect: '请选择必选项',
illegalChar: '暂不支持注入字符 & ; $ \' ` ( ) " > < |',
illegalInput: '输入框中存在不合法字符',
commonName: '支持非特殊字符开头,英文中文数字.-和_,长度1-128',
userName: '支持英文中文数字和_,长度3-30',
@ -419,6 +420,7 @@ const message = {
permission: '权限',
permissionForIP: '指定 IP',
permissionAll: '所有人(%)',
localhostHelper: '将容器部署的数据库权限配置为 localhost 会导致容器外部无法访问请谨慎选择',
databaseConnInfo: '连接信息',
rootPassword: 'root 密码',
serviceName: '服务名称',
@ -429,6 +431,7 @@ const message = {
remoteHelper: '多个 ip 以逗号分隔172.16.10.111,172.16.10.112',
remoteConnHelper: 'root 帐号远程连接 MySQL 有安全风险开启需谨慎',
changePassword: '改密',
changeConnHelper: '此操作将修改当前数据库 {0}是否继续',
changePasswordHelper: '当前数据库已经关联应用修改密码将同步修改应用中数据库密码修改后重启生效',
portHelper: '该端口为容器对外暴露端口修改需要单独保存并且重启容器',

View file

@ -9,7 +9,7 @@
<template #header>
<DrawerHeader :header="$t('database.databaseConnInfo')" :back="handleClose" />
</template>
<el-form @submit.prevent v-loading="loading" ref="formRef" :model="form" label-position="top">
<el-form @submit.prevent v-loading="loading" ref="formRef" :rules="rules" :model="form" label-position="top">
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item :label="$t('database.containerConn')" v-if="form.from === 'local'">
@ -75,11 +75,7 @@
/>
<span class="input-help">{{ $t('database.remoteConnHelper') }}</span>
</el-form-item>
<el-form-item
:label="$t('database.rootPassword')"
:rules="Rules.paramComplexity"
prop="password"
>
<el-form-item :label="$t('database.rootPassword')" prop="password">
<el-input
style="width: calc(100% - 205px)"
type="password"
@ -93,6 +89,7 @@
{{ $t('commons.button.random') }}
</el-button>
</el-button-group>
<span class="input-help">{{ $t('commons.rule.illegalChar') }}</span>
</el-form-item>
</div>
@ -110,9 +107,6 @@
</el-row>
</el-form>
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmit" @cancel="loadPassword"></ConfirmDialog>
<ConfirmDialog ref="confirmAccessDialogRef" @confirm="onSubmitAccess" @cancel="loadAccess"></ConfirmDialog>
<template #footer>
<span class="dialog-footer">
<el-button :disabled="loading" @click="dialogVisible = false">
@ -132,7 +126,6 @@ import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
import { ElForm } from 'element-plus';
import { getDatabase, loadRemoteAccess, updateMysqlAccess, updateMysqlPassword } from '@/api/modules/database';
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import { GetAppConnInfo } from '@/api/modules/app';
import DrawerHeader from '@/components/drawer-header/index.vue';
import { MsgSuccess } from '@/utils/message';
@ -148,6 +141,7 @@ const form = reactive({
password: '',
serviceName: '',
containerName: '',
oldPrivilege: false,
privilege: false,
port: 0,
@ -158,8 +152,9 @@ const form = reactive({
remoteIP: '',
});
const confirmDialogRef = ref();
const confirmAccessDialogRef = ref();
const rules = reactive({
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
});
type FormInstance = InstanceType<typeof ElForm>;
const formRef = ref<FormInstance>();
@ -200,6 +195,7 @@ const loadAccess = async () => {
if (form.from === 'local') {
const res = await loadRemoteAccess(form.type, form.database);
form.privilege = res.data;
form.oldPrivilege = res.data;
}
};
@ -227,68 +223,72 @@ const loadPassword = async () => {
form.remoteIP = res.data.address;
};
const onSubmit = async () => {
let param = {
id: 0,
from: form.from,
type: form.type,
database: form.database,
value: form.password,
};
loading.value = true;
await updateMysqlPassword(param)
.then(() => {
loading.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
dialogVisible.value = false;
})
.catch(() => {
loading.value = false;
});
};
const onSave = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) return;
let params = {
header: i18n.global.t('database.confChange'),
operationInfo: i18n.global.t('database.restartNowHelper'),
submitInputInfo: i18n.global.t('database.restartNow'),
};
confirmDialogRef.value!.acceptParams(params);
ElMessageBox.confirm(
i18n.global.t('database.changeConnHelper', [i18n.global.t('commons.login.password')]),
i18n.global.t('commons.msg.infoTitle'),
{
confirmButtonText: i18n.global.t('commons.button.confirm'),
cancelButtonText: i18n.global.t('commons.button.cancel'),
},
).then(async () => {
let param = {
id: 0,
from: form.from,
type: form.type,
database: form.database,
value: form.password,
};
loading.value = true;
await updateMysqlPassword(param)
.then(() => {
loading.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
dialogVisible.value = false;
})
.catch(() => {
loading.value = false;
});
});
});
};
const onSubmitAccess = async () => {
let param = {
id: 0,
from: form.from,
type: form.type,
database: form.database,
value: form.privilege ? '%' : 'localhost',
};
loading.value = true;
await updateMysqlAccess(param)
.then(() => {
loading.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
dialogVisible.value = false;
const onSaveAccess = async () => {
ElMessageBox.confirm(
i18n.global.t('database.changeConnHelper', [i18n.global.t('database.remoteAccess')]),
i18n.global.t('commons.msg.infoTitle'),
{
confirmButtonText: i18n.global.t('commons.button.confirm'),
cancelButtonText: i18n.global.t('commons.button.cancel'),
},
)
.then(async () => {
let param = {
id: 0,
from: form.from,
type: form.type,
database: form.database,
value: form.privilege ? '%' : 'localhost',
};
loading.value = true;
await updateMysqlAccess(param)
.then(() => {
loading.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
dialogVisible.value = false;
})
.catch(() => {
loading.value = false;
});
})
.catch(() => {
loading.value = false;
form.privilege = form.oldPrivilege;
});
};
const onSaveAccess = () => {
let params = {
header: i18n.global.t('database.confChange'),
operationInfo: i18n.global.t('database.restartNowHelper'),
submitInputInfo: i18n.global.t('database.restartNow'),
};
confirmAccessDialogRef.value!.acceptParams(params);
};
defineExpose({
acceptParams,
});

View file

@ -34,6 +34,7 @@
<el-button @click="random">{{ $t('commons.button.random') }}</el-button>
</template>
</el-input>
<span class="input-help">{{ $t('commons.rule.illegalChar') }}</span>
</el-form-item>
<el-form-item :label="$t('database.permission')" prop="permission">
@ -104,7 +105,7 @@ const form = reactive({
const rules = reactive({
name: [Rules.requiredInput, Rules.dbName],
username: [Rules.requiredInput, Rules.name],
password: [Rules.paramComplexity],
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
permission: [Rules.requiredSelect],
permissionIPs: [{ validator: checkIPs, trigger: 'blur', required: true }],
});

View file

@ -24,6 +24,7 @@
show-password
v-model="changeForm.password"
></el-input>
<span class="input-help">{{ $t('commons.rule.illegalChar') }}</span>
</el-form-item>
</div>
<div v-if="changeForm.operation === 'privilege'">
@ -33,10 +34,11 @@
<el-option
v-if="changeForm.from !== 'local'"
value="localhost"
:label="$t('terminal.localhost')"
:label="$t('terminal.localhost') + '(localhost)'"
/>
<el-option value="ip" :label="$t('database.permissionForIP')" />
</el-select>
<span class="input-help">{{ $t('database.localhostHelper') }}</span>
</el-form-item>
<el-form-item v-if="changeForm.privilege === 'ip'" prop="privilegeIPs">
<el-input clearable :rows="3" type="textarea" v-model="changeForm.privilegeIPs" />
@ -69,7 +71,6 @@ import { deleteCheckMysqlDB, updateMysqlAccess, updateMysqlPassword } from '@/ap
import DrawerHeader from '@/components/drawer-header/index.vue';
import { Rules } from '@/global/form-rules';
import { MsgSuccess } from '@/utils/message';
import { checkIp } from '@/utils/util';
const loading = ref();
const changeVisible = ref(false);
@ -92,20 +93,10 @@ const changeForm = reactive({
const confirmDialogRef = ref();
const rules = reactive({
password: [Rules.paramComplexity],
privilegeIPs: [{ validator: checkIPs, trigger: 'blur', required: true }],
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
privilegeIPs: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
});
function checkIPs(rule: any, value: any, callback: any) {
let ips = changeForm.privilegeIPs.split(',');
for (const item of ips) {
if (checkIp(item)) {
return callback(new Error(i18n.global.t('commons.rule.ip')));
}
}
callback();
}
interface DialogProps {
id: number;
from: string;

View file

@ -9,7 +9,7 @@
<template #header>
<DrawerHeader :header="$t('database.databaseConnInfo')" :back="handleClose" />
</template>
<el-form @submit.prevent v-loading="loading" ref="formRef" :model="form" label-position="top">
<el-form @submit.prevent v-loading="loading" ref="formRef" :rules="rules" :model="form" label-position="top">
<el-row type="flex" justify="center">
<el-col :span="22">
<el-form-item :label="$t('database.containerConn')" v-if="form.from === 'local'">
@ -68,7 +68,13 @@
<el-divider border-style="dashed" />
<div v-if="form.from === 'local'">
<el-form-item :label="$t('commons.login.username')" prop="username">
<el-input type="text" readonly disabled v-model="form.username">
<el-input
type="text"
style="width: calc(100% - 60px)"
readonly
disabled
v-model="form.username"
>
<template #append>
<el-button-group>
<CopyButton :content="form.username" />
@ -76,11 +82,7 @@
</template>
</el-input>
</el-form-item>
<el-form-item
:label="$t('commons.login.password')"
:rules="Rules.paramComplexity"
prop="password"
>
<el-form-item :label="$t('commons.login.password')" prop="password">
<el-input
style="width: calc(100% - 205px)"
type="password"
@ -94,6 +96,7 @@
{{ $t('commons.button.random') }}
</el-button>
</el-button-group>
<span class="input-help">{{ $t('commons.rule.illegalChar') }}</span>
</el-form-item>
</div>
<div v-if="form.from !== 'local'">
@ -110,8 +113,6 @@
</el-row>
</el-form>
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmit" @cancel="loadPassword"></ConfirmDialog>
<template #footer>
<span class="dialog-footer">
<el-button :disabled="loading" @click="dialogVisible = false">
@ -131,7 +132,6 @@ import { Rules } from '@/global/form-rules';
import i18n from '@/lang';
import { ElForm } from 'element-plus';
import { getDatabase, updatePostgresqlPassword } from '@/api/modules/database';
import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import { GetAppConnInfo } from '@/api/modules/app';
import DrawerHeader from '@/components/drawer-header/index.vue';
import { MsgSuccess } from '@/utils/message';
@ -157,7 +157,9 @@ const form = reactive({
remoteIP: '',
});
const confirmDialogRef = ref();
const rules = reactive({
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
});
type FormInstance = InstanceType<typeof ElForm>;
const formRef = ref<FormInstance>();
@ -225,36 +227,36 @@ const loadPassword = async () => {
form.remoteIP = res.data.address;
};
const onSubmit = async () => {
let param = {
id: 0,
from: form.from,
type: form.type,
database: form.database,
value: form.password,
};
loading.value = true;
await updatePostgresqlPassword(param)
.then(() => {
loading.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
dialogVisible.value = false;
})
.catch(() => {
loading.value = false;
});
};
const onSave = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(async (valid) => {
if (!valid) return;
let params = {
header: i18n.global.t('database.confChange'),
operationInfo: i18n.global.t('database.restartNowHelper'),
submitInputInfo: i18n.global.t('database.restartNow'),
};
confirmDialogRef.value!.acceptParams(params);
ElMessageBox.confirm(
i18n.global.t('database.changeConnHelper', [i18n.global.t('commons.login.password')]),
i18n.global.t('commons.msg.infoTitle'),
{
confirmButtonText: i18n.global.t('commons.button.confirm'),
cancelButtonText: i18n.global.t('commons.button.cancel'),
},
).then(async () => {
let param = {
id: 0,
from: form.from,
type: form.type,
database: form.database,
value: form.password,
};
loading.value = true;
await updatePostgresqlPassword(param)
.then(() => {
loading.value = false;
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
dialogVisible.value = false;
})
.catch(() => {
loading.value = false;
});
});
});
};

View file

@ -25,6 +25,7 @@
<el-button @click="random">{{ $t('commons.button.random') }}</el-button>
</template>
</el-input>
<span class="input-help">{{ $t('commons.rule.illegalChar') }}</span>
</el-form-item>
<el-form-item :label="$t('database.permission')" prop="superUser">
<el-checkbox v-model="form.superUser">{{ $t('database.pgSuperUser') }}</el-checkbox>
@ -81,7 +82,7 @@ const form = reactive({
const rules = reactive({
name: [Rules.requiredInput, Rules.dbName],
username: [Rules.requiredInput, Rules.name],
password: [Rules.paramComplexity],
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
});
type FormInstance = InstanceType<typeof ElForm>;

View file

@ -24,6 +24,7 @@
show-password
v-model="changeForm.password"
></el-input>
<span class="input-help">{{ $t('commons.rule.illegalChar') }}</span>
</el-form-item>
</div>
</el-col>
@ -71,7 +72,7 @@ const changeForm = reactive({
});
const confirmDialogRef = ref();
const rules = reactive({
password: [Rules.paramComplexity],
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
});
interface DialogProps {

View file

@ -80,6 +80,7 @@
{{ $t('commons.button.random') }}
</el-button>
</el-button-group>
<span class="input-help">{{ $t('commons.rule.illegalChar') }}</span>
</el-form-item>
<div v-if="form.from !== 'local'">
@ -118,6 +119,7 @@ import { MsgSuccess } from '@/utils/message';
import DrawerHeader from '@/components/drawer-header/index.vue';
import { getRandomStr } from '@/utils/util';
import { getSettingInfo } from '@/api/modules/setting';
import { Rules } from '@/global/form-rules';
const loading = ref(false);
@ -135,21 +137,9 @@ const form = reactive({
remoteIP: '',
});
const rules = reactive({
password: [{ validator: checkPassword, trigger: 'blur' }],
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
});
function checkPassword(rule: any, value: any, callback: any) {
if (form.password !== '') {
const reg = /^[a-zA-Z0-9]{1}[a-zA-Z0-9.%@!~_-]{4,126}[a-zA-Z0-9]{1}$/;
if (!reg.test(value) && value !== '') {
callback(new Error(i18n.global.t('commons.rule.paramComplexity', ['.%@!~_-'])));
} else {
callback();
}
}
callback();
}
const confirmDialogRef = ref();
const emit = defineEmits(['checkExist', 'closeTerminal']);