fix: 修改部分字段校验 (#1881)

This commit is contained in:
ssongliu 2023-08-08 22:30:16 +08:00 committed by GitHub
parent ce258cf157
commit f4d5b5437e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 144 additions and 75 deletions

View file

@ -117,7 +117,7 @@ type MysqlConfUpdateByFile struct {
type ChangeDBInfo struct { type ChangeDBInfo struct {
ID uint `json:"id"` ID uint `json:"id"`
From string `json:"from" validate:"required"` From string `json:"from"`
Value string `json:"value" validate:"required"` Value string `json:"value" validate:"required"`
} }

View file

@ -15,8 +15,8 @@ type ImageRepoUpdate struct {
ID uint `json:"id"` ID uint `json:"id"`
DownloadUrl string `json:"downloadUrl"` DownloadUrl string `json:"downloadUrl"`
Protocol string `json:"protocol"` Protocol string `json:"protocol"`
Username string `json:"username"` Username string `json:"username" validate:"max=256"`
Password string `json:"password"` Password string `json:"password" validate:"max=256"`
Auth bool `json:"auth"` Auth bool `json:"auth"`
} }

View file

@ -13,7 +13,7 @@ type RemoteDBSearch struct {
type RemoteDBInfo struct { type RemoteDBInfo struct {
ID uint `json:"id"` ID uint `json:"id"`
CreatedAt time.Time `json:"createdAt"` CreatedAt time.Time `json:"createdAt"`
Name string `json:"name"` Name string `json:"name" validate:"max=256"`
From string `json:"from"` From string `json:"from"`
Version string `json:"version"` Version string `json:"version"`
Address string `json:"address"` Address string `json:"address"`

View file

@ -181,6 +181,7 @@ const message = {
appName: 'Support English, numbers, - and _, length 2-30, and cannot start and end with -_', appName: 'Support English, numbers, - and _, length 2-30, and cannot start and end with -_',
containerName: containerName:
'Supports letters, numbers, underscores, hyphens and dots, cannot end with hyphen- or dot.1-127', 'Supports letters, numbers, underscores, hyphens and dots, cannot end with hyphen- or dot.1-127',
mirror: 'Support image accelerator addresses that start with http(s)://, English uppercase and lowercase letters, numbers, periods, and hyphens, and there should be no empty lines.',
disableFunction: 'Only support letters ,underscores,and,', disableFunction: 'Only support letters ,underscores,and,',
leechExts: 'Only support letters, numbers and,', leechExts: 'Only support letters, numbers and,',
paramSimple: 'Support lowercase letters and numbers, length 1-128', paramSimple: 'Support lowercase letters and numbers, length 1-128',

View file

@ -179,6 +179,7 @@ const message = {
nginxDoc: '僅支持英文大小寫數字.', nginxDoc: '僅支持英文大小寫數字.',
appName: '支持英文數字-和_,長度2-30,並且不能以-_開頭和結尾', appName: '支持英文數字-和_,長度2-30,並且不能以-_開頭和結尾',
containerName: '支持字母數字下劃線連字符和點,不能以連字符-或點.結尾,長度1-127', containerName: '支持字母數字下劃線連字符和點,不能以連字符-或點.結尾,長度1-127',
mirror: '支持以 http(s):// 開頭,英文大小寫,數字,. 和 - 的鏡像加速地址,且不能有空行',
disableFunction: '僅支持字母下劃線和,', disableFunction: '僅支持字母下劃線和,',
leechExts: '僅支持字母數字和,', leechExts: '僅支持字母數字和,',
paramSimple: '支持小寫字母和數字,長度 1-128', paramSimple: '支持小寫字母和數字,長度 1-128',

View file

@ -179,6 +179,7 @@ const message = {
nginxDoc: '仅支持英文大小写数字.', nginxDoc: '仅支持英文大小写数字.',
appName: '支持英文数字-和_,长度2-30,并且不能以-_开头和结尾', appName: '支持英文数字-和_,长度2-30,并且不能以-_开头和结尾',
containerName: '支持字母数字下划线连字符和点,不能以连字符-或点.结尾,长度1-127', containerName: '支持字母数字下划线连字符和点,不能以连字符-或点.结尾,长度1-127',
mirror: '支持以 http(s):// 开头,英文大小写,数字,. 和 - 的镜像加速地址,且不能有空行',
disableFunction: '仅支持字母下划线和,', disableFunction: '仅支持字母下划线和,',
leechExts: '仅支持字母数字和,', leechExts: '仅支持字母数字和,',
paramSimple: '支持小写字母和数字,长度1-128', paramSimple: '支持小写字母和数字,长度1-128',

View file

@ -4,15 +4,22 @@
<template #header> <template #header>
<DrawerHeader :header="$t('container.mirrors')" :back="handleClose" /> <DrawerHeader :header="$t('container.mirrors')" :back="handleClose" />
</template> </template>
<el-form label-position="top" @submit.prevent v-loading="loading"> <el-form
ref="formRef"
label-position="top"
:model="form"
@submit.prevent
:rules="rules"
v-loading="loading"
>
<el-row type="flex" justify="center"> <el-row type="flex" justify="center">
<el-col :span="22"> <el-col :span="22">
<el-form-item :label="$t('container.mirrors')"> <el-form-item :label="$t('container.mirrors')" prop="mirrors">
<el-input <el-input
type="textarea" type="textarea"
:placeholder="$t('container.mirrorHelper')" :placeholder="$t('container.mirrorHelper')"
:autosize="{ minRows: 8, maxRows: 10 }" :autosize="{ minRows: 8, maxRows: 10 }"
v-model="mirrors" v-model="form.mirrors"
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -21,7 +28,7 @@
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="drawerVisiable = false">{{ $t('commons.button.cancel') }}</el-button> <el-button @click="drawerVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
<el-button :disabled="loading" type="primary" @click="onSave"> <el-button :disabled="loading" type="primary" @click="onSave(formRef)">
{{ $t('commons.button.confirm') }} {{ $t('commons.button.confirm') }}
</el-button> </el-button>
</span> </span>
@ -32,41 +39,66 @@
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue'; import { reactive, ref } from 'vue';
import i18n from '@/lang'; import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message'; import { MsgSuccess } from '@/utils/message';
import ConfirmDialog from '@/components/confirm-dialog/index.vue'; import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import { updateDaemonJson } from '@/api/modules/container'; import { updateDaemonJson } from '@/api/modules/container';
import DrawerHeader from '@/components/drawer-header/index.vue'; import DrawerHeader from '@/components/drawer-header/index.vue';
import { FormInstance } from 'element-plus';
const emit = defineEmits<{ (e: 'search'): void }>(); const emit = defineEmits<{ (e: 'search'): void }>();
const confirmDialogRef = ref(); const confirmDialogRef = ref();
const mirrors = ref();
interface DialogProps { interface DialogProps {
mirrors: string; mirrors: string;
} }
const drawerVisiable = ref(); const drawerVisiable = ref();
const loading = ref(); const loading = ref();
const form = reactive({
mirrors: '',
});
const formRef = ref<FormInstance>();
const rules = reactive({
mirrors: [{ validator: checkMirrors, trigger: 'blur' }],
});
function checkMirrors(rule: any, value: any, callback: any) {
if (form.mirrors !== '') {
const reg = /^https?:\/\/[a-zA-Z0-9.-]+$/;
let mirrors = form.mirrors.split('\n');
for (const item of mirrors) {
if (!reg.test(item)) {
return callback(new Error(i18n.global.t('commons.rule.mirror')));
}
}
}
callback();
}
const acceptParams = (params: DialogProps): void => { const acceptParams = (params: DialogProps): void => {
mirrors.value = params.mirrors || params.mirrors.replaceAll(',', '\n'); form.mirrors = params.mirrors || params.mirrors.replaceAll(',', '\n');
drawerVisiable.value = true; drawerVisiable.value = true;
}; };
const onSave = async () => { const onSave = async (formEl: FormInstance | undefined) => {
let params = { if (!formEl) return;
header: i18n.global.t('database.confChange'), formEl.validate(async (valid) => {
operationInfo: i18n.global.t('database.restartNowHelper'), if (!valid) return;
submitInputInfo: i18n.global.t('database.restartNow'), let params = {
}; header: i18n.global.t('database.confChange'),
confirmDialogRef.value!.acceptParams(params); operationInfo: i18n.global.t('database.restartNowHelper'),
submitInputInfo: i18n.global.t('database.restartNow'),
};
confirmDialogRef.value!.acceptParams(params);
});
}; };
const onSubmit = async () => { const onSubmit = async () => {
loading.value = true; loading.value = true;
await updateDaemonJson('Mirrors', mirrors.value.replaceAll('\n', ',')) await updateDaemonJson('Mirrors', form.mirrors.replaceAll('\n', ','))
.then(() => { .then(() => {
loading.value = false; loading.value = false;
emit('search'); emit('search');

View file

@ -4,15 +4,22 @@
<template #header> <template #header>
<DrawerHeader :header="$t('container.registries')" :back="handleClose" /> <DrawerHeader :header="$t('container.registries')" :back="handleClose" />
</template> </template>
<el-form label-position="top" @submit.prevent v-loading="loading"> <el-form
ref="formRef"
label-position="top"
:model="form"
:rules="rules"
@submit.prevent
v-loading="loading"
>
<el-row type="flex" justify="center"> <el-row type="flex" justify="center">
<el-col :span="22"> <el-col :span="22">
<el-form-item :label="$t('container.registries')"> <el-form-item :label="$t('container.registries')" prop="registries">
<el-input <el-input
type="textarea" type="textarea"
:placeholder="$t('container.registrieHelper')" :placeholder="$t('container.registrieHelper')"
:autosize="{ minRows: 8, maxRows: 10 }" :autosize="{ minRows: 8, maxRows: 10 }"
v-model="registries" v-model="form.registries"
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -32,26 +39,47 @@
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref } from 'vue'; import { reactive, ref } from 'vue';
import i18n from '@/lang'; import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message'; import { MsgSuccess } from '@/utils/message';
import ConfirmDialog from '@/components/confirm-dialog/index.vue'; import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import { updateDaemonJson } from '@/api/modules/container'; import { updateDaemonJson } from '@/api/modules/container';
import DrawerHeader from '@/components/drawer-header/index.vue'; import DrawerHeader from '@/components/drawer-header/index.vue';
import { FormInstance } from 'element-plus';
const emit = defineEmits<{ (e: 'search'): void }>(); const emit = defineEmits<{ (e: 'search'): void }>();
const confirmDialogRef = ref(); const confirmDialogRef = ref();
const registries = ref();
interface DialogProps { interface DialogProps {
registries: string; registries: string;
} }
const drawerVisiable = ref(); const drawerVisiable = ref();
const loading = ref(); const loading = ref();
const form = reactive({
registries: '',
});
const formRef = ref<FormInstance>();
const rules = reactive({
registries: [{ validator: checkRegistries, trigger: 'blur' }],
});
function checkRegistries(rule: any, value: any, callback: any) {
if (form.registries !== '') {
const reg = /^[a-zA-Z0-9]{1}[a-z:A-Z0-9_/.-]{0,150}$/;
let regis = form.registries.split('\n');
for (const item of regis) {
if (!reg.test(item)) {
return callback(new Error(i18n.global.t('commons.rule.imageName')));
}
}
}
callback();
}
const acceptParams = (params: DialogProps): void => { const acceptParams = (params: DialogProps): void => {
registries.value = params.registries || params.registries.replaceAll(',', '\n'); form.registries = params.registries || params.registries.replaceAll(',', '\n');
drawerVisiable.value = true; drawerVisiable.value = true;
}; };
@ -66,7 +94,7 @@ const onSave = async () => {
const onSubmit = async () => { const onSubmit = async () => {
loading.value = true; loading.value = true;
await updateDaemonJson('Registries', registries.value.replaceAll('\n', ',')) await updateDaemonJson('Registries', form.registries.replaceAll('\n', ','))
.then(() => { .then(() => {
loading.value = false; loading.value = false;
handleClose(); handleClose();

View file

@ -4,56 +4,46 @@
<template #header> <template #header>
<DrawerHeader :header="title" :resource="changeForm.mysqlName" :back="handleClose" /> <DrawerHeader :header="title" :resource="changeForm.mysqlName" :back="handleClose" />
</template> </template>
<el-form> <el-form v-loading="loading" ref="changeFormRef" :model="changeForm" :rules="rules" label-position="top">
<el-form v-loading="loading" ref="changeFormRef" :model="changeForm" label-position="top"> <el-row type="flex" justify="center">
<el-row type="flex" justify="center"> <el-col :span="22">
<el-col :span="22"> <div v-if="changeForm.operation === 'password'">
<div v-if="changeForm.operation === 'password'"> <el-form-item :label="$t('commons.login.username')" prop="userName">
<el-form-item :label="$t('commons.login.username')" prop="userName"> <el-input disabled v-model="changeForm.userName"></el-input>
<el-input disabled v-model="changeForm.userName"></el-input> </el-form-item>
</el-form-item> <el-form-item :label="$t('commons.login.password')" prop="password">
<el-form-item <el-input
:label="$t('commons.login.password')" type="password"
prop="password" clearable
:rules="Rules.paramComplexity" show-password
> v-model="changeForm.password"
<el-input ></el-input>
type="password" </el-form-item>
clearable </div>
show-password <div v-if="changeForm.operation === 'privilege'">
v-model="changeForm.password" <el-form-item :label="$t('database.permission')" prop="privilege">
></el-input> <el-select style="width: 100%" v-model="changeForm.privilege">
</el-form-item> <el-option value="%" :label="$t('database.permissionAll')" />
</div> <el-option
<div v-if="changeForm.operation === 'privilege'"> v-if="changeForm.from !== 'local'"
<el-form-item :label="$t('database.permission')" prop="privilege"> value="localhost"
<el-select style="width: 100%" v-model="changeForm.privilege"> :label="$t('terminal.localhost')"
<el-option value="%" :label="$t('database.permissionAll')" />
<el-option
v-if="changeForm.from !== 'local'"
value="localhost"
:label="$t('terminal.localhost')"
/>
<el-option value="ip" :label="$t('database.permissionForIP')" />
</el-select>
</el-form-item>
<el-form-item
v-if="changeForm.privilege === 'ip'"
prop="privilegeIPs"
:rules="Rules.requiredInput"
>
<el-input
clearable
:autosize="{ minRows: 2, maxRows: 5 }"
type="textarea"
v-model="changeForm.privilegeIPs"
/> />
<span class="input-help">{{ $t('database.remoteHelper') }}</span> <el-option value="ip" :label="$t('database.permissionForIP')" />
</el-form-item> </el-select>
</div> </el-form-item>
</el-col> <el-form-item v-if="changeForm.privilege === 'ip'" prop="privilegeIPs">
</el-row> <el-input
</el-form> clearable
:autosize="{ minRows: 2, maxRows: 5 }"
type="textarea"
v-model="changeForm.privilegeIPs"
/>
<span class="input-help">{{ $t('database.remoteHelper') }}</span>
</el-form-item>
</div>
</el-col>
</el-row>
</el-form> </el-form>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
@ -78,6 +68,7 @@ import { deleteCheckMysqlDB, updateMysqlAccess, updateMysqlPassword } from '@/ap
import DrawerHeader from '@/components/drawer-header/index.vue'; import DrawerHeader from '@/components/drawer-header/index.vue';
import { Rules } from '@/global/form-rules'; import { Rules } from '@/global/form-rules';
import { MsgSuccess } from '@/utils/message'; import { MsgSuccess } from '@/utils/message';
import { checkIp } from '@/utils/util';
const loading = ref(); const loading = ref();
const changeVisiable = ref(false); const changeVisiable = ref(false);
@ -97,6 +88,21 @@ const changeForm = reactive({
}); });
const confirmDialogRef = ref(); const confirmDialogRef = ref();
const rules = reactive({
password: [Rules.paramComplexity],
privilegeIPs: [{ validator: checkIPs, trigger: 'blur', required: true }],
});
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 { interface DialogProps {
id: number; id: number;
from: string; from: string;