fix: unify database credential validation (#14216)

This commit is contained in:
ssongliu
2026-10-27 23:06:13 +08:00
committed by GitHub
parent bd0bc0079e
commit 3a7cd211af
32 changed files with 98 additions and 64 deletions
+11
View File
@@ -5,12 +5,14 @@ import (
"fmt"
"os"
"path"
"strings"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
"github.com/1Panel-dev/1Panel/agent/utils/mysql"
"github.com/1Panel-dev/1Panel/agent/utils/mysql/client"
@@ -126,6 +128,9 @@ func (u *DatabaseService) LoadItems(dbType string) ([]dto.DatabaseItem, error) {
}
func (u *DatabaseService) CheckDatabase(req dto.DatabaseCreate) bool {
if (req.Type == constant.AppMysql || req.Type == constant.AppMariaDB || req.Type == constant.AppPostgresql || req.Type == constant.AppMongodb) && (cmd.CheckIllegal(req.Username, req.Password) || strings.Contains(req.Password, " ")) {
return false
}
if req.Timeout == 0 {
req.Timeout = 30
}
@@ -180,6 +185,9 @@ func (u *DatabaseService) CheckDatabase(req dto.DatabaseCreate) bool {
}
func (u *DatabaseService) Create(req dto.DatabaseCreate) error {
if (req.Type == constant.AppMysql || req.Type == constant.AppMariaDB || req.Type == constant.AppPostgresql || req.Type == constant.AppMongodb) && (cmd.CheckIllegal(req.Username, req.Password) || strings.Contains(req.Password, " ")) {
return buserr.New("ErrCmdIllegal")
}
if req.Timeout == 0 {
req.Timeout = 30
}
@@ -303,6 +311,9 @@ func (u *DatabaseService) Delete(req dto.DatabaseDelete) error {
}
func (u *DatabaseService) Update(req dto.DatabaseUpdate) error {
if (req.Type == constant.AppMysql || req.Type == constant.AppMariaDB || req.Type == constant.AppPostgresql || req.Type == constant.AppMongodb) && (cmd.CheckIllegal(req.Username, req.Password) || strings.Contains(req.Password, " ")) {
return buserr.New("ErrCmdIllegal")
}
switch req.Type {
case constant.AppPostgresql:
if _, err := postgresql.NewPostgresqlClient(pgclient.DBInfo{
+4 -4
View File
@@ -64,7 +64,7 @@ func (u *MongodbService) UpdateDescription(req dto.UpdateDescription) error {
}
func (u *MongodbService) Create(ctx context.Context, req dto.MongodbDBCreate) (*model.DatabaseMongodb, error) {
if cmd.CheckIllegal(req.Name, req.Username, req.Password) {
if cmd.CheckIllegal(req.Name, req.Username, req.Password) || strings.Contains(req.Password, " ") {
return nil, buserr.New("ErrCmdIllegal")
}
if !isSupportedMongodbPrivilege(req.Permission) {
@@ -146,7 +146,7 @@ func (u *MongodbService) LoadFromRemote(req dto.MongodbLoadDB) error {
}
func (u *MongodbService) BindUser(req dto.MongodbBind) error {
if cmd.CheckIllegal(req.Database, req.Name, req.Username, req.Password) {
if cmd.CheckIllegal(req.Database, req.Name, req.Username, req.Password) || strings.Contains(req.Password, " ") {
return buserr.New("ErrCmdIllegal")
}
@@ -168,7 +168,7 @@ func (u *MongodbService) BindUser(req dto.MongodbBind) error {
}
func (u *MongodbService) ChangePassword(req dto.MongodbPassword) error {
if cmd.CheckIllegal(req.Database, req.Name, req.Password) {
if cmd.CheckIllegal(req.Database, req.Name, req.Password) || strings.Contains(req.Password, " ") {
return buserr.New("ErrCmdIllegal")
}
@@ -190,7 +190,7 @@ func (u *MongodbService) ChangePassword(req dto.MongodbPassword) error {
}
func (u *MongodbService) ChangeRootPassword(req dto.ChangeDBInfo) error {
if cmd.CheckIllegal(req.Value) {
if cmd.CheckIllegal(req.Value) || strings.Contains(req.Value, " ") {
return buserr.New("ErrCmdIllegal")
}
if req.From != constant.AppResourceLocal {
+5 -5
View File
@@ -437,7 +437,7 @@ func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*mode
}
func (u *MysqlService) create(ctx context.Context, req dto.MysqlDBCreate, mcpBounded bool) (*model.DatabaseMysql, error) {
if cmd.CheckIllegal(req.Name, req.Username, req.Password, req.Format, req.Collation, req.Permission) {
if cmd.CheckIllegal(req.Name, req.Username, req.Password, req.Format, req.Collation, req.Permission) || strings.Contains(req.Password, " ") {
return nil, buserr.New("ErrCmdIllegal")
}
if len(req.Username) != 0 && len(req.Password) == 0 {
@@ -680,7 +680,7 @@ func (u *MysqlService) ListGrantSummary(req dto.MysqlGrantSummarySearch) (map[st
}
func (u *MysqlService) CreateUser(req dto.MysqlUserCreate) error {
if cmd.CheckIllegal(req.Username, req.Password, req.Host) {
if cmd.CheckIllegal(req.Username, req.Password, req.Host) || strings.Contains(req.Password, " ") {
return buserr.New("ErrCmdIllegal")
}
dbs := make([]string, 0, len(req.DBs))
@@ -883,7 +883,7 @@ func (u *MysqlService) UpdateUser(req dto.MysqlUserUpdate) error {
}
func (u *MysqlService) ChangeUserPassword(req dto.MysqlUserPassword) error {
if cmd.CheckIllegal(req.Username, req.Host, req.Password) {
if cmd.CheckIllegal(req.Username, req.Host, req.Password) || strings.Contains(req.Password, " ") {
return buserr.New("ErrCmdIllegal")
}
if err := checkMysqlNormalUser(req.Username); err != nil {
@@ -936,7 +936,7 @@ func (u *MysqlService) ChangeUserPassword(req dto.MysqlUserPassword) error {
}
func (u *MysqlService) SaveUserPassword(req dto.MysqlUserPassword) error {
if cmd.CheckIllegal(req.Username, req.Host, req.Password) {
if cmd.CheckIllegal(req.Username, req.Host, req.Password) || strings.Contains(req.Password, " ") {
return buserr.New("ErrCmdIllegal")
}
if err := checkMysqlNormalUser(req.Username); err != nil {
@@ -1302,7 +1302,7 @@ func isMysqlDatabaseResourceInUseError(err error) bool {
}
func (u *MysqlService) ChangePassword(req dto.ChangeDBInfo) error {
if cmd.CheckIllegal(req.Value) {
if cmd.CheckIllegal(req.Value) || strings.Contains(req.Value, " ") {
return buserr.New("ErrCmdIllegal")
}
cli, version, err := LoadMysqlClientByFrom(req.Database)
+3 -3
View File
@@ -87,7 +87,7 @@ func (u *PostgresqlService) ListDBOption() ([]dto.PostgresqlOption, error) {
}
func (u *PostgresqlService) BindUser(req dto.PostgresqlBindUser) error {
if cmd.CheckIllegal(req.Name, req.Username, req.Password) {
if cmd.CheckIllegal(req.Name, req.Username, req.Password) || strings.Contains(req.Password, " ") {
return buserr.New("ErrCmdIllegal")
}
dbItem, err := postgresqlRepo.Get(postgresqlRepo.WithByPostgresqlName(req.Database), repo.WithByName(req.Name))
@@ -123,7 +123,7 @@ func (u *PostgresqlService) BindUser(req dto.PostgresqlBindUser) error {
}
func (u *PostgresqlService) Create(ctx context.Context, req dto.PostgresqlDBCreate) (*model.DatabasePostgresql, error) {
if cmd.CheckIllegal(req.Name, req.Username, req.Password, req.Format) {
if cmd.CheckIllegal(req.Name, req.Username, req.Password, req.Format) || strings.Contains(req.Password, " ") {
return nil, buserr.New("ErrCmdIllegal")
}
@@ -366,7 +366,7 @@ func (u *PostgresqlService) ChangePrivileges(req dto.PostgresqlPrivileges) error
}
func (u *PostgresqlService) ChangePassword(req dto.ChangeDBInfo) error {
if cmd.CheckIllegal(req.Value) {
if cmd.CheckIllegal(req.Value) || strings.Contains(req.Value, " ") {
return buserr.New("ErrCmdIllegal")
}
cli, err := LoadPostgresqlClientByFrom(req.Database)
+34
View File
@@ -151,6 +151,30 @@ const checkIllegal: RuleValidator = (_rule, value, callback) => {
}
};
const checkDatabaseUsername: RuleValidator = (_rule, value, callback) => {
if (value && /[&|;'`$()"><\n\r]/.test(value)) {
callback(new Error(i18n.global.t('commons.rule.illegalInput')));
return;
}
callback();
};
const checkDatabasePassword: RuleValidator = (_rule, value, callback) => {
if (!value) {
callback();
return;
}
if (value.includes(' ')) {
callback(new Error(i18n.global.t('setting.noSpace')));
return;
}
if (/[&|;'`$()"><\n\r]/.test(value)) {
callback(new Error(i18n.global.t('commons.rule.illegalInput')));
return;
}
callback();
};
const complexityPassword: RuleValidator = (_rule, value, callback) => {
if (value === '' || typeof value === 'undefined' || value == null) {
callback(new Error(i18n.global.t('commons.rule.complexityPassword')));
@@ -682,6 +706,8 @@ interface CommonRule {
userName: FormItemRule;
simpleName: FormItemRule;
simplePassword: FormItemRule;
databaseUsername: FormItemRule;
databasePassword: FormItemRule;
dbName: FormItemRule;
imageName: FormItemRule;
composeName: FormItemRule;
@@ -860,6 +886,14 @@ export const Rules: CommonRule = {
required: true,
trigger: 'blur',
},
databaseUsername: {
validator: checkDatabaseUsername,
trigger: 'blur',
},
databasePassword: {
validator: checkDatabasePassword,
trigger: 'blur',
},
port: {
required: true,
trigger: 'blur',
+1 -1
View File
@@ -292,7 +292,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',
illegalChar: "Injection of characters & ; $ ' ` ( ) \" > < {'|'} is currently not supported",
illegalInput: "This field mustn't contains illegal characters.",
duplicate: 'This value must be unique.',
commonName:
+1 -1
View File
@@ -291,7 +291,7 @@ const message = {
rePassword: 'La confirmación de la contraseña no coincide con la contraseña.',
requiredInput: 'Este campo es obligatorio.',
requiredSelect: 'Seleccione un elemento de la lista',
illegalChar: 'Actualmente no se admite la inyección de caracteres & ; $ \' ` ( ) " > < |',
illegalChar: "Actualmente no se admite la inyección de caracteres & ; $ ' ` ( ) \" > < {'|'}",
illegalInput: 'Este campo no debe contener caracteres no permitidos.',
duplicate: 'Este valor debe ser único.',
commonName:
+1 -1
View File
@@ -291,7 +291,7 @@ const message = {
rePassword: 'تکرار رمز عبور با رمز عبور مطابقت ندارد.',
requiredInput: 'این فیلد الزامی است.',
requiredSelect: 'یک مورد از لیست انتخاب کنید',
illegalChar: 'کاراکترهای & ; $ \' ` ( ) " > < | در حال حاضر پشتیبانی نمی‌شوند',
illegalChar: "کاراکترهای & ; $ ' ` ( ) \" > < {'|'} در حال حاضر پشتیبانی نمی‌شوند",
illegalInput: 'این فیلد نباید شامل کاراکترهای غیرمجاز باشد.',
duplicate: 'این مقدار باید یکتا باشد.',
commonName:
+1 -1
View File
@@ -292,7 +292,7 @@ const message = {
rePassword: 'パスワードがパスワードと矛盾することを確認してください。',
requiredInput: 'この項目は必須です。',
requiredSelect: 'リスト内のアイテムを選択します',
illegalChar: '現在、文字 & ; $ \' ` ( ) " > < | の注入はサポートされていません',
illegalChar: "現在、文字 & ; $ ' ` ( ) \" > < {'|'} の注入はサポートされていません",
illegalInput: 'このフィールドには違法なキャラクターが含まれてはなりません。',
duplicate: 'この値は一意である必要があります。',
commonName:
+1 -1
View File
@@ -290,7 +290,7 @@ const message = {
rePassword: '확인 비밀번호가 비밀번호와 일치하지 않습니다.',
requiredInput: '이 필드는 필수 항목입니다.',
requiredSelect: '목록에서 항목을 선택하세요',
illegalChar: '현재 & ; $ \' ` ( ) " > < | 문자 주입은 지원되지 않습니다',
illegalChar: "현재 & ; $ ' ` ( ) \" > < {'|'} 문자 주입은 지원되지 않습니다",
illegalInput: '이 필드에는 유효하지 않은 문자가 포함될 수 없습니다.',
duplicate: '이 값은 고유해야 합니다.',
commonName:
+1 -1
View File
@@ -288,7 +288,7 @@ const message = {
rePassword: 'ຢືນຢັນລະຫັດຜ່ານບໍ່ກົງກັນ.',
requiredInput: 'ຈຳເປັນຕ້ອງປ້ອນຂໍ້ມູນນີ້.',
requiredSelect: 'ເລືອກລາຍການໃນລາຍຊື່',
illegalChar: 'ບໍ່ຮອງຮັບການໃຊ້ຕົວອັກສອນ & ; $ \' ` ( ) " > < | ໃນເວລານີ້',
illegalChar: "ບໍ່ຮອງຮັບການໃຊ້ຕົວອັກສອນ & ; $ ' ` ( ) \" > < {'|'} ໃນເວລານີ້",
illegalInput: 'ຂໍ້ມູນນີ້ຕ້ອງບໍ່ມີຕົວອັກສອນທີ່ບໍ່ຖືກຕ້ອງ.',
duplicate: 'ຄ່ານີ້ຕ້ອງບໍ່ຊ້ຳກັນ.',
commonName:
+1 -1
View File
@@ -295,7 +295,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',
illegalChar: "Suntikan aksara & ; $ ' ` ( ) \" > < {'|'} tidak disokong buat masa ini",
illegalInput: 'Ruangan ini tidak boleh mengandungi aksara tidak sah.',
duplicate: 'Nilai ini mesti unik.',
commonName:
+1 -1
View File
@@ -292,7 +292,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 há suporte para injeção dos caracteres & ; $ \' ` ( ) " > < |',
illegalChar: "Atualmente não há suporte para injeção dos caracteres & ; $ ' ` ( ) \" > < {'|'}",
illegalInput: 'Este campo não deve conter caracteres ilegais.',
duplicate: 'Este valor deve ser único.',
commonName:
+1 -1
View File
@@ -293,7 +293,7 @@ const message = {
rePassword: 'Подтверждение пароля не совпадает с паролем.',
requiredInput: 'Это поле обязательно для заполнения.',
requiredSelect: 'Выберите элемент из списка',
illegalChar: 'В настоящее время не поддерживается вставка символов & ; $ \' ` ( ) " > < |',
illegalChar: "В настоящее время не поддерживается вставка символов & ; $ ' ` ( ) \" > < {'|'}",
illegalInput: 'Это поле не должно содержать недопустимых символов.',
duplicate: 'Значение должно быть уникальным.',
commonName:
+1 -1
View File
@@ -295,7 +295,7 @@ const message = {
rePassword: 'Şifre onayı, şifre ile tutarsız.',
requiredInput: 'Bu alan gereklidir.',
requiredSelect: 'Listeden bir öğe seçin',
illegalChar: '& ; $ ` ( ) " > < | karakterlerinin enjekte edilmesi şu anda desteklenmiyor',
illegalChar: "& ; $ ' ` ( ) \" > < {'|'} karakterlerinin enjekte edilmesi şu anda desteklenmiyor",
illegalInput: 'Bu alan yasadışı karakterler içermemelidir.',
duplicate: 'Bu değer benzersiz olmalıdır.',
commonName:
+1 -1
View File
@@ -284,7 +284,7 @@ const message = {
rePassword: '密碼不一致,請檢查後重新輸入',
requiredInput: '請填寫必填項',
requiredSelect: '請選擇必選項',
illegalChar: '暫不支援注入字元 & ; $ \' ` ( ) " > < |',
illegalChar: "暫不支援注入字元 & ; $ ' ` ( ) \" > < {'|'}",
illegalInput: '輸入框中存在不合法字元',
commonName: '支援非特殊字元開頭,英文、中文、數字、.-和_,長度1-128',
userName: '支援非特殊字元開頭、英文、中文、數字和_,長度3-30',
+1 -1
View File
@@ -284,7 +284,7 @@ const message = {
rePassword: '密码不一致,请检查后重新输入',
requiredInput: '请填写必填项',
requiredSelect: '请选择必选项',
illegalChar: '暂不支持注入字符 & ; $ \' ` ( ) " > < |',
illegalChar: "暂不支持注入字符 & ; $ ' ` ( ) \" > < {'|'}",
illegalInput: '输入框中存在不合法字符',
duplicate: '内容不能重复',
commonName: '支持非特殊字符开头,英文、中文、数字、.-和_,长度1-128',
@@ -50,7 +50,7 @@ const form = reactive({
const rules = reactive({
username: [Rules.requiredInput, Rules.name],
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
password: [Rules.requiredInput, Rules.databasePassword],
});
interface DialogProps {
@@ -162,7 +162,7 @@ const form = reactive({
});
const rules = reactive({
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
password: [Rules.requiredInput, Rules.databasePassword],
});
type FormInstance = InstanceType<typeof ElForm>;
@@ -263,6 +263,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">
<el-select v-model="createForm.permission" class="w-full">
@@ -418,7 +419,7 @@ const createForm = reactive({
const rules = reactive({
name: [Rules.requiredInput, Rules.dbName],
username: [Rules.requiredInput, Rules.name],
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
password: [Rules.requiredInput, Rules.databasePassword],
permission: [Rules.requiredSelect],
});
@@ -49,7 +49,7 @@ const form = reactive({
});
const rules = reactive({
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
password: [Rules.requiredInput, Rules.databasePassword],
});
interface DialogProps {
@@ -38,6 +38,7 @@
show-password
v-model.trim="dialogData.rowData!.password"
/>
<span class="input-help">{{ $t('commons.rule.illegalChar') }}</span>
</el-form-item>
<el-form-item :label="$t('database.timeout')" prop="timeout">
<el-input-number
@@ -122,8 +123,8 @@ const rules = reactive({
version: [Rules.requiredSelect],
address: [Rules.ipV4V6OrDomain],
port: [Rules.port],
username: [Rules.requiredInput],
password: [Rules.requiredInput],
username: [Rules.requiredInput, Rules.databaseUsername],
password: [Rules.requiredInput, Rules.databasePassword],
timeout: [Rules.number, checkNumberRange(1, 600)],
});
@@ -131,6 +131,7 @@
</el-form-item>
<el-form-item :label="$t('commons.login.password')" prop="password" required>
<el-input type="password" clearable show-password v-model.trim="form.password" />
<span class="input-help">{{ $t('commons.rule.illegalChar') }}</span>
</el-form-item>
<el-form-item :label="$t('database.permission')" prop="permission">
<el-select v-model="form.permission" @change="changePermission">
@@ -214,7 +215,7 @@ const rules = reactive({
username: [Rules.requiredInput, Rules.name],
permission: [Rules.requiredSelect],
host: [Rules.requiredInput, Rules.noSpace, Rules.illegal, { validator: checkMysqlHosts, trigger: 'blur' }],
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
password: [Rules.requiredInput, Rules.databasePassword],
});
interface DialogProps {
@@ -161,7 +161,7 @@ const form = reactive({
remoteIP: '',
});
const rules = reactive({
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
password: [Rules.requiredInput, Rules.databasePassword],
});
type FormInstance = InstanceType<typeof ElForm>;
@@ -183,7 +183,7 @@ const rules = reactive({
userMode: [Rules.requiredSelect],
userKey: [Rules.requiredSelect],
username: [Rules.requiredInput, Rules.name],
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
password: [Rules.requiredInput, Rules.databasePassword],
permission: [Rules.requiredSelect],
permissionIPs: [Rules.requiredInput, Rules.noSpace, Rules.illegal, { validator: checkMysqlHosts, trigger: 'blur' }],
});
@@ -48,6 +48,7 @@
show-password
v-model.trim="dialogData.rowData!.password"
/>
<span class="input-help">{{ $t('commons.rule.illegalChar') }}</span>
</el-form-item>
<el-form-item>
<el-checkbox @change="isOK = false" v-model="dialogData.rowData!.ssl" :label="$t('database.ssl')" />
@@ -167,8 +168,8 @@ const rules = reactive({
version: [Rules.requiredSelect],
address: [Rules.ipV4V6OrDomain],
port: [Rules.port],
username: [Rules.requiredInput],
password: [Rules.requiredInput],
username: [Rules.requiredInput, Rules.databaseUsername],
password: [Rules.requiredInput, Rules.databasePassword],
timeout: [Rules.number, checkNumberRange(1, 600)],
});
@@ -110,6 +110,7 @@
</el-form-item>
<el-form-item :label="$t('commons.login.password')" prop="password" :required="userDialogMode === 'create'">
<el-input type="password" clearable show-password v-model.trim="userForm.password" />
<span class="input-help">{{ $t('commons.rule.illegalChar') }}</span>
<span v-if="userDialogMode === 'edit'" class="input-help">
{{ $t('setting.passwordEmptyTip') }}
</span>
@@ -146,6 +147,7 @@
</el-form-item>
<el-form-item :label="$t('commons.login.password')" prop="password">
<el-input type="password" clearable show-password v-model.trim="supplementForm.password" />
<span class="input-help">{{ $t('commons.rule.illegalChar') }}</span>
<span class="input-help">{{ $t('database.supplementPasswordHelper') }}</span>
</el-form-item>
</el-form>
@@ -263,27 +265,8 @@ const supplementForm = reactive({
password: '',
});
const supplementRules = reactive({
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
password: [Rules.requiredInput, Rules.databasePassword],
});
const checkPassword = (_rule: unknown, value: string, callback: (error?: Error) => void) => {
if (!value && userDialogMode.value === 'edit') {
callback();
return;
}
if (!value) {
callback(new Error(i18n.global.t('commons.rule.requiredInput')));
return;
}
if (value.indexOf(' ') !== -1) {
callback(new Error(i18n.global.t('setting.noSpace')));
return;
}
if (/[&|;'`$()><]/.test(value)) {
callback(new Error(i18n.global.t('commons.rule.illegalInput')));
return;
}
callback();
};
const checkUserHosts = (_rule: unknown, value: string, callback: (error?: Error) => void) => {
const hosts = value.split(',').map((item) => item.trim());
if (hosts.length === 0 || hosts.some((item) => !item)) {
@@ -296,12 +279,13 @@ const checkUserHosts = (_rule: unknown, value: string, callback: (error?: Error)
}
callback();
};
const userRules = reactive({
const userRules = computed(() => ({
username: [Rules.requiredInput, Rules.name],
permission: [Rules.requiredSelect],
host: [Rules.requiredInput, Rules.noSpace, Rules.illegal, { validator: checkUserHosts, trigger: 'blur' }],
password: [{ validator: checkPassword, trigger: 'blur' }],
});
password:
userDialogMode.value === 'create' ? [Rules.requiredInput, Rules.databasePassword] : [Rules.databasePassword],
}));
interface DialogProps {
database: string;
@@ -58,7 +58,7 @@ const confirmDialogRef = ref();
const rules = reactive({
username: [Rules.requiredInput, Rules.name],
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
password: [Rules.requiredInput, Rules.databasePassword],
});
interface DialogProps {
@@ -157,7 +157,7 @@ const form = reactive({
remoteIP: '',
});
const rules = reactive({
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
password: [Rules.requiredInput, Rules.databasePassword],
});
type FormInstance = InstanceType<typeof ElForm>;
@@ -66,7 +66,7 @@ const form = reactive({
const rules = reactive({
name: [Rules.requiredInput, Rules.dbName],
username: [Rules.requiredInput, Rules.name],
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
password: [Rules.requiredInput, Rules.databasePassword],
});
type FormInstance = InstanceType<typeof ElForm>;
@@ -59,7 +59,7 @@ const changeForm = reactive({
});
const confirmDialogRef = ref();
const rules = reactive({
password: [Rules.requiredInput, Rules.noSpace, Rules.illegal],
password: [Rules.requiredInput, Rules.databasePassword],
});
interface DialogProps {
@@ -41,6 +41,7 @@
show-password
v-model.trim="dialogData.rowData!.password"
/>
<span class="input-help">{{ $t('commons.rule.illegalChar') }}</span>
</el-form-item>
<el-form-item :label="$t('database.timeout')" prop="timeout">
@@ -111,8 +112,8 @@ const rules = reactive({
version: [Rules.requiredSelect],
address: [Rules.ipV4V6OrDomain],
port: [Rules.port],
username: [Rules.requiredInput],
password: [Rules.requiredInput],
username: [Rules.requiredInput, Rules.databaseUsername],
password: [Rules.requiredInput, Rules.databasePassword],
clientKey: [Rules.requiredInput],
clientCert: [Rules.requiredInput],